From fa49e78cc199526a9e33b59c5194f8e3bf0f0952 Mon Sep 17 00:00:00 2001 From: huangjian Date: Wed, 31 Aug 2016 16:47:33 +0800 Subject: Add winery source code Change-Id: I1c5088121d79b71098c3cba1996c6f784737532e Issue-id: TOSCA-49 Signed-off-by: huangjian --- .../org/apache/http/impl/cookie/DateUtils.java | 68 + .../org/eclipse/winery/repository/CORSFilter.java | 34 + .../org/eclipse/winery/repository/Constants.java | 67 + .../org/eclipse/winery/repository/JAXBSupport.java | 138 + .../java/org/eclipse/winery/repository/Prefs.java | 332 + .../eclipse/winery/repository/RestDocFilter.java | 26 + .../java/org/eclipse/winery/repository/Utils.java | 787 + .../repository/backend/AbstractRepository.java | 110 + .../winery/repository/backend/BackendUtils.java | 995 ++ .../repository/backend/IGenericRepository.java | 189 + .../winery/repository/backend/IRepository.java | 68 + .../backend/IRepositoryAdministration.java | 43 + .../winery/repository/backend/MockXMLElement.java | 30 + .../winery/repository/backend/Repository.java | 19 + .../repository/backend/ResourceCreationResult.java | 84 + .../repository/backend/constants/Filename.java | 47 + .../repository/backend/constants/MediaTypes.java | 25 + .../backend/filebased/AutoSaveListener.java | 72 + .../repository/backend/filebased/FileUtils.java | 110 + .../backend/filebased/FilebasedRepository.java | 596 + .../backend/filebased/GitBasedRepository.java | 190 + .../filebased/OnlyNonHiddenDirectories.java | 27 + .../backend/filebased/OnlyNonHiddenFiles.java | 33 + .../winery/repository/datatypes/FileMeta.java | 110 + .../repository/datatypes/TypeWithShortName.java | 60 + .../winery/repository/datatypes/ids/IdNames.java | 30 + .../repository/datatypes/ids/admin/AdminId.java | 55 + .../datatypes/ids/admin/ConstraintTypesId.java | 26 + .../datatypes/ids/admin/NamespacesId.java | 26 + .../datatypes/ids/admin/PlanLanguagesId.java | 26 + .../datatypes/ids/admin/PlanTypesId.java | 26 + .../repository/datatypes/ids/admin/TypesId.java | 22 + .../ids/elements/ArtifactTemplateDirectoryId.java | 28 + .../ids/elements/SelfServiceMetaDataId.java | 24 + .../datatypes/ids/elements/VisualAppearanceId.java | 28 + .../datatypes/select2/Select2DataItem.java | 56 + .../select2/Select2DataWithOptGroups.java | 52 + .../datatypes/select2/Select2OptGroup.java | 65 + .../repository/datatypes/select2/package-info.java | 17 + .../winery/repository/export/CSARExporter.java | 299 + .../export/DummyParentForGeneratedXSDRef.java | 43 + ...ummyRepositoryFileReferenceForGeneratedXSD.java | 38 + .../winery/repository/export/ExportedState.java | 67 + .../winery/repository/export/TOSCAExportUtil.java | 802 + .../winery/repository/importing/CSARImporter.java | 1158 ++ .../json/TTopologyTemplateSerializer.java | 81 + .../repository/json/TopologyTemplateModule.java | 24 + .../repository/resources/API/APIResource.java | 107 + .../repository/resources/API/package-info.java | 20 + .../AbstractComponentInstanceResource.java | 516 + ...ceResourceWithNameDerivedFromAbstractFinal.java | 200 + ...actComponentInstanceWithReferencesResource.java | 52 + .../resources/AbstractComponentsResource.java | 279 + ...bstractComponentsWithTypeReferenceResource.java | 71 + .../repository/resources/ConstraintResource.java | 69 + .../repository/resources/ConstraintsResource.java | 39 + .../repository/resources/EntityTypeResource.java | 92 + .../resources/GenericComponentPageData.java | 103 + .../resources/GenericVisualAppearanceResource.java | 123 + .../winery/repository/resources/IHasName.java | 43 + .../repository/resources/IHasTypeReference.java | 39 + ...teResourceOrNodeTypeImplementationResource.java | 19 + ...ceOrRelationshipTypeImplementationResource.java | 23 + ...ceOrRelationshipTypeImplementationResource.java | 19 + .../repository/resources/InheritanceResource.java | 74 + .../winery/repository/resources/MainResource.java | 189 + .../winery/repository/resources/SubMenuData.java | 38 + .../resources/_support/IPersistable.java | 24 + .../_support/collections/CollectionsHelper.java | 42 + .../collections/EntityCollectionResource.java | 206 + .../_support/collections/EntityResource.java | 123 + .../_support/collections/IIdDetermination.java | 20 + .../withid/EntityWithIdCollectionResource.java | 66 + .../collections/withid/EntityWithIdResource.java | 29 + .../EntityWithoutIdCollectionResource.java | 114 + .../withoutid/EntityWithoutIdResource.java | 33 + .../withoutid/IdDeterminationWithHashCode.java | 36 + .../collections/withoutid/package-info.java | 17 + .../resources/admin/AbstractAdminResource.java | 45 + .../resources/admin/AdminTopResource.java | 57 + .../resources/admin/NamespacesResource.java | 253 + .../resources/admin/RepositoryAdminResource.java | 112 + .../admin/types/AbstractTypesManager.java | 204 + .../admin/types/ConstraintTypesManager.java | 25 + .../admin/types/PlanLanguagesManager.java | 29 + .../resources/admin/types/PlanTypesManager.java | 28 + .../artifacts/DeploymentArtifactResource.java | 87 + .../artifacts/DeploymentArtifactsResource.java | 73 + .../artifacts/GenericArtifactResource.java | 42 + .../artifacts/GenericArtifactsResource.java | 572 + .../artifacts/ImplementationArtifactResource.java | 95 + .../artifacts/ImplementationArtifactsResource.java | 93 + .../documentation/DocumentationResource.java | 43 + .../documentation/DocumentationsResource.java | 60 + .../entitytemplates/IEntityTemplateResource.java | 34 + .../entitytemplates/PropertiesResource.java | 66 + .../entitytemplates/TEntityTemplateResource.java | 92 + .../entitytemplates/TEntityTemplatesResource.java | 30 + .../ArtifactTemplateResource.java | 308 + .../ArtifactTemplatesResource.java | 21 + .../artifacttemplates/FilesResource.java | 163 + .../resources/entitytemplates/package-info.java | 27 + .../policytemplates/PolicyTemplateResource.java | 95 + .../policytemplates/PolicyTemplatesResource.java | 23 + .../EntityTypeImplementationResource.java | 29 + .../NodeTypeImplementationResource.java | 105 + .../NodeTypeImplementationsResource.java | 18 + .../entitytypeimplementations/package-info.java | 19 + .../RelationshipTypeImplementationResource.java | 81 + .../RelationshipTypeImplementationsResource.java | 18 + .../entitytypes/ImplementationsOfOneType.java | 74 + .../entitytypes/InstanceStatesResource.java | 133 + .../TopologyGraphElementEntityTypeResource.java | 23 + .../artifacttypes/ArtifactTypeResource.java | 67 + .../artifacttypes/ArtifactTypesResource.java | 90 + .../capabilitytypes/CapabilityTypeResource.java | 47 + .../capabilitytypes/CapabilityTypesResource.java | 22 + .../ImplementationsOfOneNodeTypeResource.java | 101 + .../entitytypes/nodetypes/NodeTypeResource.java | 105 + .../entitytypes/nodetypes/NodeTypesResource.java | 22 + .../nodetypes/VisualAppearanceResource.java | 84 + .../reqandcapdefs/AbstractReqOrCapDefResource.java | 177 + .../CapabilityDefinitionResource.java | 92 + .../CapabilityDefinitionsResource.java | 50 + .../RequirementDefinitionResource.java | 89 + .../RequirementDefinitionsResource.java | 45 + ...RequirementOrCapabilityDefinitionsResource.java | 131 + .../resources/entitytypes/package-info.java | 17 + .../entitytypes/policytypes/AppliesToResource.java | 41 + .../entitytypes/policytypes/LanguageResource.java | 28 + .../policytypes/PolicyTypeResource.java | 66 + .../policytypes/PolicyTypesResource.java | 22 + .../resources/entitytypes/properties/JSPData.java | 85 + .../properties/PropertiesDefinitionResource.java | 161 + .../winery/PropertyDefinitionKVListResource.java | 41 + .../winery/PropertyDefinitionKVResource.java | 59 + .../WinerysPropertiesDefinitionResource.java | 132 + ...plementationsOfOneRelationshipTypeResource.java | 95 + .../RelationshipTypeResource.java | 165 + .../RelationshipTypesResource.java | 17 + .../VisualAppearanceResource.java | 291 + .../RequiredCapabilityTypeResource.java | 83 + .../requirementtypes/RequirementTypeResource.java | 44 + .../requirementtypes/RequirementTypesResource.java | 22 + .../resources/imports/ImportsResource.java | 44 + .../genericimports/GenericImportResource.java | 133 + .../genericimports/GenericImportsResource.java | 38 + .../imports/xsdimports/XSDImportResource.java | 174 + .../imports/xsdimports/XSDImportsResource.java | 124 + .../resources/interfaces/InterfaceResource.java | 46 + .../resources/interfaces/InterfacesResource.java | 140 + .../resources/interfaces/OperationResource.java | 71 + .../resources/interfaces/OperationsResource.java | 69 + .../resources/interfaces/ParameterResource.java | 62 + .../resources/interfaces/ParametersResource.java | 99 + .../winery/repository/resources/package-info.java | 27 + .../servicetemplates/ServiceTemplateResource.java | 263 + .../servicetemplates/ServiceTemplatesResource.java | 18 + .../BoundaryDefinitionsJSPData.java | 113 + .../BoundaryDefinitionsResource.java | 144 + .../PropertyMappingsResource.java | 115 + .../interfaces/ExportedInterfaceResource.java | 34 + .../interfaces/ExportedOperationResource.java | 249 + .../interfaces/ExportedOperationsResource.java | 38 + .../interfaces/InterfacesResource.java | 38 + .../interfaces/package-info.java | 16 + .../policies/PoliciesResource.java | 46 + .../policies/PolicyResource.java | 26 + .../boundarydefinitions/policies/package-info.java | 16 + .../reqscaps/CapabilitiesResource.java | 76 + .../reqscaps/CapabilityResource.java | 26 + .../reqscaps/RequirementResource.java | 26 + .../reqscaps/RequirementsResource.java | 85 + .../boundarydefinitions/reqscaps/package-info.java | 18 + .../servicetemplates/plans/PlanFileResource.java | 115 + .../servicetemplates/plans/PlanResource.java | 203 + .../servicetemplates/plans/PlansResource.java | 205 + .../servicetemplates/plans/PlansResourceData.java | 136 + .../selfserviceportal/OptionResource.java | 96 + .../selfserviceportal/OptionsResource.java | 131 + .../SelfServicePortalResource.java | 223 + .../topologytemplates/NodeTemplateResource.java | 145 + .../topologytemplates/NodeTemplatesResource.java | 39 + .../RelationshipTemplateResource.java | 26 + .../RelationshipTemplatesResource.java | 39 + .../TopologyTemplateResource.java | 280 + .../repository/resources/tags/TagsResource.java | 38 + .../OpenTOSCAContainerConnection.java | 30 + .../runtimeintegration/package-info.java | 16 + .../src/main/resources/.gitignore | 3 + .../src/main/resources/logback-test.xml | 21 + .../src/main/resources/logback.xml | 16 + .../src/main/resources/mime-types.properties | 19 + .../src/main/templates/Version.java | 7 + .../main/webapp/3rdparty/jquery-ui/js/jquery-ui.js | 14987 +++++++++++++++++++ .../webapp/3rdparty/jquery-ui/js/jquery-ui.min.js | 12 + .../src/main/webapp/WEB-INF/.gitignore | 3 + .../src/main/webapp/WEB-INF/appengine-web.xml | 20 + .../src/main/webapp/WEB-INF/functions.tld | 153 + .../src/main/webapp/WEB-INF/jetty-web.xml | 7 + .../src/main/webapp/WEB-INF/tags/about.tag | 65 + .../webapp/WEB-INF/tags/addComponentInstance.tag | 147 + .../src/main/webapp/WEB-INF/tags/colorwheel.tag | 36 + .../main/webapp/WEB-INF/tags/componentinstance.tag | 163 + .../WEB-INF/tags/componentinstancewithName.tag | 33 + ...entinstancewithNameDerivedFromAbstractFinal.tag | 45 + .../webapp/WEB-INF/tags/constraints/constraint.tag | 83 + .../main/webapp/WEB-INF/tags/entitytemplate.tag | 43 + .../src/main/webapp/WEB-INF/tags/entitytype.tag | 49 + .../nodetypes/reqandcapdefs/reqandcapdefs.tag | 334 + .../src/main/webapp/WEB-INF/tags/genericpage.tag | 349 + .../src/main/webapp/WEB-INF/tags/imageUpload.tag | 42 + .../main/webapp/WEB-INF/tags/namespaceChooser.tag | 52 + .../WEB-INF/tags/parameters/parametersHTML.tag | 38 + .../WEB-INF/tags/parameters/parametersInput.tag | 20 + .../WEB-INF/tags/parameters/parametersJS.tag | 177 + .../WEB-INF/tags/parameters/parametersOutput.tag | 20 + .../validnodetypeendingsselect.tag | 43 + .../boundarydefinitions/browseForReqOrCap.tag | 161 + .../browseForServiceTemplatePropertyReqOrCap.tag | 166 + .../boundarydefinitions/browseForX.tag | 49 + .../webapp/WEB-INF/tags/simpleSingleFileUpload.tag | 114 + .../src/main/webapp/WEB-INF/tags/submenu.tag | 26 + .../WEB-INF/tags/topologyTemplateRenderer.tag | 208 + .../WEB-INF/tags/typeswithshortnameasselect.tag | 46 + .../src/main/webapp/WEB-INF/web.xml | 95 + .../main/webapp/css/topologyTemplateRenderer.css | 49 + .../css/topologyTemplateRendererFullscreen.css | 30 + .../css/topologytemplaterendering/CapSelection.css | 15 + .../NodeTemplateSelection.css | 13 + .../RelationshipTemplateSelection.css | 13 + .../css/topologytemplaterendering/ReqSelection.css | 15 + .../propertySelection.css | 15 + .../webapp/css/topologytemplaterendering/small.css | 37 + .../src/main/webapp/css/winery-repository.css | 868 ++ .../src/main/webapp/images/back_disabled.png | Bin 0 -> 1361 bytes .../src/main/webapp/images/back_enabled.png | Bin 0 -> 1379 bytes .../src/main/webapp/images/back_enabled_hover.png | Bin 0 -> 1375 bytes .../webapp/images/containers/admin/FrameBottom.jpg | Bin 0 -> 9642 bytes .../webapp/images/containers/admin/FrameMiddle.jpg | Bin 0 -> 1579 bytes .../webapp/images/containers/admin/FrameTop.jpg | Bin 0 -> 30099 bytes .../containers/admin/styledTabMenuButtonCenter.jpg | Bin 0 -> 1625 bytes .../containers/admin/styledTabMenuButtonLeft.jpg | Bin 0 -> 1549 bytes .../containers/admin/styledTabMenuButtonRight.jpg | Bin 0 -> 1799 bytes .../webapp/images/containers/nt/FrameBottom.jpg | Bin 0 -> 14574 bytes .../webapp/images/containers/nt/FrameMiddle.jpg | Bin 0 -> 1579 bytes .../main/webapp/images/containers/nt/FrameTop.jpg | Bin 0 -> 38952 bytes .../webapp/images/containers/nt/FrameTopLarge.jpg | Bin 0 -> 31898 bytes .../webapp/images/containers/rt/FrameBottom.jpg | Bin 0 -> 16269 bytes .../webapp/images/containers/rt/FrameMiddle.jpg | Bin 0 -> 1579 bytes .../main/webapp/images/containers/rt/FrameTop.jpg | Bin 0 -> 42281 bytes .../webapp/images/containers/rt/FrameTopLarge.jpg | Bin 0 -> 33776 bytes .../webapp/images/containers/st/FrameBottom.jpg | Bin 0 -> 16696 bytes .../webapp/images/containers/st/FrameMiddle.jpg | Bin 0 -> 1579 bytes .../main/webapp/images/containers/st/FrameTop.jpg | Bin 0 -> 43839 bytes .../main/webapp/images/entityBox/admin/center.jpg | Bin 0 -> 494 bytes .../main/webapp/images/entityBox/admin/left.jpg | Bin 0 -> 4377 bytes .../main/webapp/images/entityBox/admin/right.jpg | Bin 0 -> 1257 bytes .../main/webapp/images/entityBox/deleteButton.jpg | Bin 0 -> 2061 bytes .../webapp/images/entityBox/deleteButtonHover.jpg | Bin 0 -> 3011 bytes .../main/webapp/images/entityBox/editButton.jpg | Bin 0 -> 1299 bytes .../webapp/images/entityBox/editButtonHover.jpg | Bin 0 -> 2350 bytes .../main/webapp/images/entityBox/exportButton.jpg | Bin 0 -> 1321 bytes .../webapp/images/entityBox/exportButtonHover.jpg | Bin 0 -> 2459 bytes .../webapp/images/entityBox/nodeType/center.jpg | Bin 0 -> 586 bytes .../main/webapp/images/entityBox/nodeType/left.jpg | Bin 0 -> 6588 bytes .../webapp/images/entityBox/nodeType/right.jpg | Bin 0 -> 1729 bytes .../images/entityBox/relationshipType/center.jpg | Bin 0 -> 584 bytes .../images/entityBox/relationshipType/left.jpg | Bin 0 -> 7282 bytes .../images/entityBox/relationshipType/right.jpg | Bin 0 -> 1676 bytes .../images/entityBox/serviceTemplate/center.jpg | Bin 0 -> 601 bytes .../images/entityBox/serviceTemplate/left.jpg | Bin 0 -> 7774 bytes .../images/entityBox/serviceTemplate/right.jpg | Bin 0 -> 1838 bytes .../src/main/webapp/images/favicon.ico | Bin 0 -> 1150 bytes .../src/main/webapp/images/forward_disabled.png | Bin 0 -> 1363 bytes .../src/main/webapp/images/forward_enabled.png | Bin 0 -> 1380 bytes .../main/webapp/images/forward_enabled_hover.png | Bin 0 -> 1379 bytes .../src/main/webapp/images/header_background.png | Bin 0 -> 36799 bytes .../webapp/images/jquery-fileupload/loading.gif | Bin 0 -> 3897 bytes .../images/jquery-fileupload/progressbar.gif | Bin 0 -> 3323 bytes .../main/webapp/images/overviewShadowBottom.jpg | Bin 0 -> 1401 bytes .../main/webapp/images/overviewShadowMiddle.jpg | Bin 0 -> 345 bytes .../src/main/webapp/images/overviewShadowTop.jpg | Bin 0 -> 1306 bytes .../images/relationshiptype/DiamondSource.png | Bin 0 -> 261 bytes .../images/relationshiptype/DiamondTarget.png | Bin 0 -> 270 bytes .../images/relationshiptype/PlainArrowSource.png | Bin 0 -> 260 bytes .../images/relationshiptype/PlainArrowTarget.png | Bin 0 -> 255 bytes .../images/relationshiptype/circleSource.png | Bin 0 -> 242 bytes .../images/relationshiptype/circleTarget.png | Bin 0 -> 255 bytes .../webapp/images/relationshiptype/dotted2Line.png | Bin 0 -> 247 bytes .../webapp/images/relationshiptype/dottedLine.png | Bin 0 -> 414 bytes .../images/relationshiptype/doubleArrowSource.png | Bin 0 -> 337 bytes .../images/relationshiptype/doubleArrowTarget.png | Bin 0 -> 343 bytes .../webapp/images/relationshiptype/noneSource.png | Bin 0 -> 141 bytes .../webapp/images/relationshiptype/noneTarget.png | Bin 0 -> 146 bytes .../webapp/images/relationshiptype/plainLine.png | Bin 0 -> 139 bytes .../images/relationshiptype/simpleArrowSource.png | Bin 0 -> 265 bytes .../images/relationshiptype/simpleArrowTarget.png | Bin 0 -> 274 bytes .../images/relationshiptype/squareSource.png | Bin 0 -> 193 bytes .../images/relationshiptype/squareTarget.png | Bin 0 -> 198 bytes .../src/main/webapp/images/searchBoxBackground.jpg | Bin 0 -> 5574 bytes .../src/main/webapp/images/sort_asc.png | Bin 0 -> 1118 bytes .../src/main/webapp/images/sort_asc_disabled.png | Bin 0 -> 1050 bytes .../src/main/webapp/images/sort_both.png | Bin 0 -> 1136 bytes .../src/main/webapp/images/sort_desc.png | Bin 0 -> 1127 bytes .../src/main/webapp/images/sort_desc_disabled.png | Bin 0 -> 1045 bytes .../webapp/images/styledTabMenuButtonCenter.jpg | Bin 0 -> 1625 bytes .../main/webapp/images/styledTabMenuButtonLeft.jpg | Bin 0 -> 1549 bytes .../webapp/images/styledTabMenuButtonRight.jpg | Bin 0 -> 1799 bytes .../src/main/webapp/js/.gitignore | 3 + .../webapp/js/boundaryDefinitionsXSelection.js | 96 + .../src/main/webapp/js/jquery.fileupload-audio.js | 12 + .../src/main/webapp/js/jquery.fileupload-image.js | 12 + .../main/webapp/js/jquery.fileupload-validate.js | 12 + .../src/main/webapp/js/jquery.fileupload-video.js | 12 + .../src/main/webapp/js/nextselect.js | 144 + .../src/main/webapp/js/winery-support-non-AMD.js | 223 + .../src/main/webapp/js/winery-support.js | 112 + .../src/main/webapp/jsp/admin/adminindex.jsp | 41 + .../src/main/webapp/jsp/admin/namespaces.jsp | 108 + .../src/main/webapp/jsp/admin/repository.jsp | 101 + .../src/main/webapp/jsp/admin/types/types.jsp | 105 + .../src/main/webapp/jsp/artifacts/artifacts.jsp | 141 + .../src/main/webapp/jsp/componentnaming.jspf | 28 + .../src/main/webapp/jsp/documentation.jsp | 87 + .../artifacttemplates/artifacttemplate.jsp | 32 + .../entitytemplates/artifacttemplates/files.jsp | 18 + .../policytemplates/policytemplate.jsp | 29 + .../main/webapp/jsp/entitytemplates/properties.jsp | 92 + .../nodetypeimplementation.jsp | 33 + .../relationshiptypeimplementation.jsp | 29 + .../jsp/entitytypes/artifacttypes/artifacttype.jsp | 26 + .../entitytypes/capabilitytypes/capabilitytype.jsp | 17 + .../webapp/jsp/entitytypes/implementations.jsp | 63 + .../main/webapp/jsp/entitytypes/instancestates.jsp | 86 + .../webapp/jsp/entitytypes/nodetypes/nodetype.jsp | 44 + .../nodetypes/reqandcapdefs/capdefs.jsp | 17 + .../nodetypes/reqandcapdefs/reqdefs.jsp | 17 + .../jsp/entitytypes/nodetypes/visualappearance.jsp | 68 + .../jsp/entitytypes/policytypes/appliesto.jsp | 25 + .../jsp/entitytypes/policytypes/language.jsp | 21 + .../jsp/entitytypes/policytypes/policytype.jsp | 32 + .../properties/propertiesDefinition.jsp | 320 + .../relationshiptypes/relationshiptype.jsp | 44 + .../entitytypes/relationshiptypes/validendings.jsp | 39 + .../relationshiptypes/visualappearance.jsp | 193 + .../requirementtypes/requiredcapabilitytype.jsp | 56 + .../requirementtypes/requirementtype.jsp | 30 + .../src/main/webapp/jsp/genericcomponentpage.jsp | 209 + .../src/main/webapp/jsp/hashloading.jsp | 140 + .../webapp/jsp/imports/xsdimports/xsdimport.jsp | 50 + .../src/main/webapp/jsp/inheritance.jsp | 55 + .../src/main/webapp/jsp/interfaces/interfaces.jsp | 489 + .../src/main/webapp/jsp/otherElements.jsp | 44 + .../boundarydefinitions/boundarydefinitions.jsp | 1080 ++ .../webapp/jsp/servicetemplates/plans/plans.jsp | 266 + .../selfservicemetadata/selfservicemetadata.jsp | 256 + .../jsp/servicetemplates/servicetemplate.jsp | 43 + .../topologytemplates/topologytemplate.jsp | 23 + .../topologytemplates/topologytemplateview.jsp | 67 + .../main/webapp/jsp/setupTriggerRemoveByDELKey.jsp | 28 + .../src/main/webapp/jsp/tags/tags.jsp | 14 + .../src/main/webapp/jsp/test.jsp | 33 + .../src/main/webapp/jsp/xmlSource.jsp | 20 + .../src/psd/Sorting icons.psd | Bin 0 -> 27490 bytes .../src/psd/header_background_plain.png | Bin 0 -> 36026 bytes .../org/eclipse/winery/librarytests/DateTest.java | 33 + .../librarytests/InheritanceIllustration.java | 48 + .../winery/repository/PrefsTestEnabled.java | 32 + .../PrefsTestEnabledGitBackedRepository.java | 30 + .../PrefsTestEnabledUsingConfiguredRepository.java | 28 + .../repository/TestWithRepositoryConnection.java | 27 + .../org/eclipse/winery/repository/UtilsTest.java | 26 + .../repository/export/TestToscaExporter.java | 81 + .../repository/importing/TestCSARImporter.java | 48 + ...ComponentInstanceResourceDefinitionsBacked.java | 54 + .../winery/repository/resources/TestResource.java | 22 + .../TestArtifactTemplateResource.java | 43 + .../TestCapabilityTypeResource.java | 53 + .../reqandcapdefs/TestRequirementDefinitions.java | 144 + .../src/test/resources/.gitignore | 1 + .../src/test/resources/logback-test.xml | 15 + .../src/test/resources/servicetemplate.tosca | 35 + 383 files changed, 44854 insertions(+) create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/apache/http/impl/cookie/DateUtils.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/CORSFilter.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/Constants.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/JAXBSupport.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/Prefs.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/RestDocFilter.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/Utils.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/AbstractRepository.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/BackendUtils.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/IGenericRepository.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/IRepository.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/IRepositoryAdministration.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/MockXMLElement.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/Repository.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/ResourceCreationResult.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/constants/Filename.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/constants/MediaTypes.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/AutoSaveListener.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/FileUtils.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/FilebasedRepository.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/GitBasedRepository.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/OnlyNonHiddenDirectories.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/OnlyNonHiddenFiles.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/FileMeta.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/TypeWithShortName.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/IdNames.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/AdminId.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/ConstraintTypesId.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/NamespacesId.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/PlanLanguagesId.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/PlanTypesId.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/TypesId.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/elements/ArtifactTemplateDirectoryId.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/elements/SelfServiceMetaDataId.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/elements/VisualAppearanceId.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/select2/Select2DataItem.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/select2/Select2DataWithOptGroups.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/select2/Select2OptGroup.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/select2/package-info.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/CSARExporter.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/DummyParentForGeneratedXSDRef.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/DummyRepositoryFileReferenceForGeneratedXSD.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/ExportedState.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/TOSCAExportUtil.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/importing/CSARImporter.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/json/TTopologyTemplateSerializer.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/json/TopologyTemplateModule.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/API/APIResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/API/package-info.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceWithReferencesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentsWithTypeReferenceResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/ConstraintResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/ConstraintsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/EntityTypeResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/GenericComponentPageData.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/GenericVisualAppearanceResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/IHasName.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/IHasTypeReference.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTemplateResourceOrNodeTypeImplementationResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTypeImplementationResourceOrRelationshipTypeImplementationResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/InheritanceResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/MainResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/SubMenuData.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/IPersistable.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/CollectionsHelper.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityCollectionResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/IIdDetermination.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withid/EntityWithIdCollectionResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withid/EntityWithIdResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/EntityWithoutIdCollectionResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/EntityWithoutIdResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/IdDeterminationWithHashCode.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/package-info.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/AbstractAdminResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/AdminTopResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/NamespacesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/RepositoryAdminResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/AbstractTypesManager.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/ConstraintTypesManager.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/PlanLanguagesManager.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/PlanTypesManager.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/DeploymentArtifactResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/DeploymentArtifactsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/ImplementationArtifactResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/ImplementationArtifactsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/documentation/DocumentationResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/documentation/DocumentationsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/IEntityTemplateResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/PropertiesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/TEntityTemplateResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/TEntityTemplatesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/ArtifactTemplateResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/ArtifactTemplatesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/FilesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/package-info.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/policytemplates/PolicyTemplateResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/policytemplates/PolicyTemplatesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/EntityTypeImplementationResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/nodetypeimplementations/NodeTypeImplementationResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/nodetypeimplementations/NodeTypeImplementationsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/package-info.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/relationshiptypeimplementations/RelationshipTypeImplementationResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/relationshiptypeimplementations/RelationshipTypeImplementationsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/ImplementationsOfOneType.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/InstanceStatesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/TopologyGraphElementEntityTypeResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/artifacttypes/ArtifactTypeResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/artifacttypes/ArtifactTypesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/CapabilityTypeResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/CapabilityTypesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/ImplementationsOfOneNodeTypeResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/NodeTypeResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/NodeTypesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/VisualAppearanceResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/AbstractReqOrCapDefResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/CapabilityDefinitionResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/CapabilityDefinitionsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementDefinitionResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementDefinitionsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementOrCapabilityDefinitionsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/package-info.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/AppliesToResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/LanguageResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/PolicyTypeResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/PolicyTypesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/JSPData.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/PropertiesDefinitionResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/PropertyDefinitionKVListResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/PropertyDefinitionKVResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/WinerysPropertiesDefinitionResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/ImplementationsOfOneRelationshipTypeResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/RelationshipTypeResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/RelationshipTypesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/VisualAppearanceResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequiredCapabilityTypeResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequirementTypeResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequirementTypesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/ImportsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/genericimports/GenericImportResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/genericimports/GenericImportsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/xsdimports/XSDImportResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/xsdimports/XSDImportsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/InterfaceResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/InterfacesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/OperationResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/OperationsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/ParameterResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/ParametersResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/package-info.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/ServiceTemplateResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/ServiceTemplatesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/BoundaryDefinitionsJSPData.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/BoundaryDefinitionsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/PropertyMappingsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedInterfaceResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedOperationResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedOperationsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/InterfacesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/package-info.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/PoliciesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/PolicyResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/package-info.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/CapabilitiesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/CapabilityResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/RequirementResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/RequirementsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/package-info.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlanFileResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlanResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlansResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlansResourceData.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/OptionResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/OptionsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/SelfServicePortalResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/NodeTemplateResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/NodeTemplatesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/RelationshipTemplateResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/RelationshipTemplatesResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/TopologyTemplateResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/tags/TagsResource.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/runtimeintegration/OpenTOSCAContainerConnection.java create mode 100644 winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/runtimeintegration/package-info.java create mode 100644 winery/org.eclipse.winery.repository/src/main/resources/.gitignore create mode 100644 winery/org.eclipse.winery.repository/src/main/resources/logback-test.xml create mode 100644 winery/org.eclipse.winery.repository/src/main/resources/logback.xml create mode 100644 winery/org.eclipse.winery.repository/src/main/resources/mime-types.properties create mode 100644 winery/org.eclipse.winery.repository/src/main/templates/Version.java create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/3rdparty/jquery-ui/js/jquery-ui.js create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/3rdparty/jquery-ui/js/jquery-ui.min.js create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/.gitignore create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/appengine-web.xml create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/functions.tld create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/jetty-web.xml create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/about.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/addComponentInstance.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/colorwheel.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/componentinstance.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/componentinstancewithName.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/componentinstancewithNameDerivedFromAbstractFinal.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/constraints/constraint.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/entitytemplate.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/entitytype.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/entitytypes/nodetypes/reqandcapdefs/reqandcapdefs.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/genericpage.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/imageUpload.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/namespaceChooser.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/parameters/parametersHTML.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/parameters/parametersInput.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/parameters/parametersJS.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/parameters/parametersOutput.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/relationshiptype/validnodetypeendingsselect.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/servicetemplates/boundarydefinitions/browseForReqOrCap.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/servicetemplates/boundarydefinitions/browseForServiceTemplatePropertyReqOrCap.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/servicetemplates/boundarydefinitions/browseForX.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/simpleSingleFileUpload.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/submenu.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/topologyTemplateRenderer.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/typeswithshortnameasselect.tag create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/web.xml create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/css/topologyTemplateRenderer.css create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/css/topologyTemplateRendererFullscreen.css create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/CapSelection.css create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/NodeTemplateSelection.css create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/RelationshipTemplateSelection.css create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/ReqSelection.css create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/propertySelection.css create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/small.css create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/css/winery-repository.css create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/back_disabled.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/back_enabled.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/back_enabled_hover.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/FrameBottom.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/FrameMiddle.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/FrameTop.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/styledTabMenuButtonCenter.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/styledTabMenuButtonLeft.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/styledTabMenuButtonRight.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/nt/FrameBottom.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/nt/FrameMiddle.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/nt/FrameTop.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/nt/FrameTopLarge.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/rt/FrameBottom.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/rt/FrameMiddle.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/rt/FrameTop.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/rt/FrameTopLarge.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/st/FrameBottom.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/st/FrameMiddle.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/containers/st/FrameTop.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/admin/center.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/admin/left.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/admin/right.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/deleteButton.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/deleteButtonHover.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/editButton.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/editButtonHover.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/exportButton.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/exportButtonHover.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/nodeType/center.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/nodeType/left.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/nodeType/right.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/relationshipType/center.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/relationshipType/left.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/relationshipType/right.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/serviceTemplate/center.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/serviceTemplate/left.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/serviceTemplate/right.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/favicon.ico create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/forward_disabled.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/forward_enabled.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/forward_enabled_hover.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/header_background.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/jquery-fileupload/loading.gif create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/jquery-fileupload/progressbar.gif create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/overviewShadowBottom.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/overviewShadowMiddle.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/overviewShadowTop.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/DiamondSource.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/DiamondTarget.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/PlainArrowSource.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/PlainArrowTarget.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/circleSource.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/circleTarget.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/dotted2Line.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/dottedLine.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/doubleArrowSource.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/doubleArrowTarget.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/noneSource.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/noneTarget.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/plainLine.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/simpleArrowSource.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/simpleArrowTarget.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/squareSource.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/squareTarget.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/searchBoxBackground.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/sort_asc.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/sort_asc_disabled.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/sort_both.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/sort_desc.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/sort_desc_disabled.png create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/styledTabMenuButtonCenter.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/styledTabMenuButtonLeft.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/images/styledTabMenuButtonRight.jpg create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/js/.gitignore create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/js/boundaryDefinitionsXSelection.js create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/js/jquery.fileupload-audio.js create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/js/jquery.fileupload-image.js create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/js/jquery.fileupload-validate.js create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/js/jquery.fileupload-video.js create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/js/nextselect.js create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/js/winery-support-non-AMD.js create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/js/winery-support.js create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/admin/adminindex.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/admin/namespaces.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/admin/repository.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/admin/types/types.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/artifacts/artifacts.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/componentnaming.jspf create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/documentation.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytemplates/artifacttemplates/artifacttemplate.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytemplates/artifacttemplates/files.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytemplates/policytemplates/policytemplate.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytemplates/properties.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypeimplementations/nodetypeimplementations/nodetypeimplementation.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypeimplementations/relationshiptypeimplementations/relationshiptypeimplementation.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/artifacttypes/artifacttype.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/capabilitytypes/capabilitytype.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/implementations.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/instancestates.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/nodetypes/nodetype.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/nodetypes/reqandcapdefs/capdefs.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/nodetypes/reqandcapdefs/reqdefs.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/nodetypes/visualappearance.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/policytypes/appliesto.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/policytypes/language.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/policytypes/policytype.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/properties/propertiesDefinition.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/relationshiptypes/relationshiptype.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/relationshiptypes/validendings.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/relationshiptypes/visualappearance.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/requirementtypes/requiredcapabilitytype.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/requirementtypes/requirementtype.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/genericcomponentpage.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/hashloading.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/imports/xsdimports/xsdimport.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/inheritance.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/interfaces/interfaces.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/otherElements.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/boundarydefinitions/boundarydefinitions.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/plans/plans.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/selfservicemetadata/selfservicemetadata.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/servicetemplate.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplate.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplateview.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/setupTriggerRemoveByDELKey.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/tags/tags.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/test.jsp create mode 100644 winery/org.eclipse.winery.repository/src/main/webapp/jsp/xmlSource.jsp create mode 100644 winery/org.eclipse.winery.repository/src/psd/Sorting icons.psd create mode 100644 winery/org.eclipse.winery.repository/src/psd/header_background_plain.png create mode 100644 winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/librarytests/DateTest.java create mode 100644 winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/librarytests/InheritanceIllustration.java create mode 100644 winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/PrefsTestEnabled.java create mode 100644 winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/PrefsTestEnabledGitBackedRepository.java create mode 100644 winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/PrefsTestEnabledUsingConfiguredRepository.java create mode 100644 winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/TestWithRepositoryConnection.java create mode 100644 winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/UtilsTest.java create mode 100644 winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/export/TestToscaExporter.java create mode 100644 winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/importing/TestCSARImporter.java create mode 100644 winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/TestAbstractComponentInstanceResourceDefinitionsBacked.java create mode 100644 winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/TestResource.java create mode 100644 winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/TestArtifactTemplateResource.java create mode 100644 winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/TestCapabilityTypeResource.java create mode 100644 winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/TestRequirementDefinitions.java create mode 100644 winery/org.eclipse.winery.repository/src/test/resources/.gitignore create mode 100644 winery/org.eclipse.winery.repository/src/test/resources/logback-test.xml create mode 100644 winery/org.eclipse.winery.repository/src/test/resources/servicetemplate.tosca (limited to 'winery/org.eclipse.winery.repository/src') diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/apache/http/impl/cookie/DateUtils.java b/winery/org.eclipse.winery.repository/src/main/java/org/apache/http/impl/cookie/DateUtils.java new file mode 100644 index 0000000..33f9c70 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/apache/http/impl/cookie/DateUtils.java @@ -0,0 +1,68 @@ +/* + * $HeadURL: https://svn.apache.org/repos/asf/httpcomponents/httpclient/tags/4.0-beta1/module-client/src/main/java/org/apache/http/impl/cookie/DateUtils.java $ + * $Revision: 677240 $ + * $Date: 2008-07-16 13:25:47 +0200 (Wed, 16 Jul 2008) $ + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.impl.cookie; + +/** + * A utility class for parsing and formatting HTTP dates as used in cookies and + * other headers. This class handles dates as defined by RFC 2616 section + * 3.3.1 as well as some other common non-standard formats. + * + * @author Christopher Brown + * @author Michael Becke + * + * Shortened by Oliver Kopp to contain DEFAULT_PATTERNS and related artifacts only. + */ +public final class DateUtils { + + /** + * Date format pattern used to parse HTTP date headers in RFC 1123 format. + */ + public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz"; + + /** + * Date format pattern used to parse HTTP date headers in RFC 1036 format. + */ + public static final String PATTERN_RFC1036 = "EEEE, dd-MMM-yy HH:mm:ss zzz"; + + /** + * Date format pattern used to parse HTTP date headers in ANSI C + * asctime() format. + */ + public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy"; + + public static final String[] DEFAULT_PATTERNS = new String[] { + PATTERN_RFC1036, + PATTERN_RFC1123, + PATTERN_ASCTIME + }; + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/CORSFilter.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/CORSFilter.java new file mode 100644 index 0000000..966b5f2 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/CORSFilter.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; + +import com.sun.jersey.spi.container.ContainerRequest; +import com.sun.jersey.spi.container.ContainerResponse; +import com.sun.jersey.spi.container.ContainerResponseFilter; + +/** + * Required for the BPMN4TOSCA modeler when not running on the same machine + */ +public class CORSFilter implements ContainerResponseFilter { + + @Override + public ContainerResponse filter(ContainerRequest containerRequest, ContainerResponse containerResponse) { + ResponseBuilder response = Response.fromResponse(containerResponse.getResponse()); + response.header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "GET, PUT, OPTIONS"); + containerResponse.setResponse(response.build()); + return containerResponse; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/Constants.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/Constants.java new file mode 100644 index 0000000..60eacdd --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/Constants.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository; + +import java.util.Calendar; +import java.util.Date; + +public class Constants { + + /** repository specific **/ + public static final String DEFAULT_REPO_NAME = "winery-repository"; + // this directory is checked for existence. If it does not exist + // $HOME/DEFAULT_REPO_NAME is used + public static final String GLOBAL_REPO_PATH_WINDOWS = "C:\\" + Constants.DEFAULT_REPO_NAME; + + /** file-system in general **/ + public static final String newline = System.getProperty("line.separator"); + + // Path to images for extensions + // Currently, we require the format .png + public static final String PATH_MIMETYPEIMAGES = "/images/mime-types/"; + + // suffix for BPMN4TOSCA + public static final String SUFFIX_BPMN4TOSCA = ".bpmn4tosca"; + + // suffix for CSAR files + public static final String SUFFIX_CSAR = ".csar"; + + // suffix for files in the directory PATH_MIMETYPEIMAGES, including "." + public static final String SUFFIX_MIMETYPEIMAGES = ".png"; + + // suffix for files storing the mimetype of the belonging files + // used in implementors if IRepository of no appropriate implementation for storing a mimetype is available + public static final String SUFFIX_MIMETYPE = ".mimetype"; + + // suffix for all property files + public static final String SUFFIX_PROPERTIES = ".properties"; + + // suffix for all files storing Definitions + // following line 2935 of TOSCA cos01 + public static final String SUFFIX_TOSCA_DEFINITIONS = ".tosca"; + + // at each new start of the application, the modified date changes + // reason: the default values of the properties or the JSP could have + // changed + public static final Date LASTMODIFIEDDATE_FOR_404 = Calendar.getInstance().getTime(); + + public static final String TOSCA_PLANTYPE_BUILD_PLAN = "http://docs.oasis-open.org/tosca/ns/2011/12/PlanTypes/BuildPlan"; + public static final String TOSCA_PLANTYPE_TERMINATION_PLAN = "http://docs.oasis-open.org/tosca/ns/2011/12/PlanTypes/TerminationPlan"; + + public static final String DIRNAME_SELF_SERVICE_METADATA = "SELFSERVICE-Metadata"; + + /* used for IA generation */ + //public static final String NAMESPACE_ARTIFACTTYPE_WAR = "http://www.opentosca.org/types"; + public static final String NAMESPACE_ARTIFACTTYPE_WAR = "http://www.example.com/ToscaTypes"; + public static final String LOCALNAME_ARTIFACTTYPE_WAR = "WAR"; + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/JAXBSupport.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/JAXBSupport.java new file mode 100644 index 0000000..876c015 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/JAXBSupport.java @@ -0,0 +1,138 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; + +import org.eclipse.winery.common.propertydefinitionkv.WinerysPropertiesDefinition; +import org.eclipse.winery.model.tosca.TDefinitions; +import org.eclipse.winery.repository.backend.MockXMLElement; +import org.eclipse.winery.repository.resources.admin.NamespacesResource; +import org.eclipse.winery.model.selfservice.Application; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.xml.bind.marshaller.NamespacePrefixMapper; + +// if com.sun.xml.bind.marshaller.NamespacePrefixMapper cannot be resolved, +// possibly +// http://mvnrepository.com/artifact/com.googlecode.jaxb-namespaceprefixmapper-interfaces/JAXBNamespacePrefixMapper/2.2.4 +// helps +// also com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper could be the +// right package + +/** + * Bundles all general JAXB functionality + */ +public class JAXBSupport { + + private static final Logger logger = LoggerFactory.getLogger(JAXBSupport.class); + + // thread-safe JAXB as inspired by https://jaxb.java.net/guide/Performance_and_thread_safety.html + // The other possibility: Each subclass sets JAXBContext.newInstance(theSubClass.class); in its static {} part. + // This seems to be more complicated than listing all subclasses in initContext + public final static JAXBContext context = JAXBSupport.initContext(); + + private final static PrefixMapper prefixMapper = new PrefixMapper(); + + + /** + * Follows + * https://jaxb.java.net/2.2.5/docs/release-documentation.html#marshalling + * -changing-prefixes + * + * See http://www.jarvana.com/jarvana/view/com/sun/xml/bind/jaxb-impl/2.2.2/ + * jaxb-impl-2.2.2-javadoc.jar!/com/sun/xml/bind/marshaller/ + * NamespacePrefixMapper.html for a JavaDoc of the NamespacePrefixMapper + */ + private static class PrefixMapper extends NamespacePrefixMapper { + + @Override + public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) { + if (namespaceUri.equals("")) { + return ""; + } + + // this does not work to get TOSCA elements without prefix + // possibly because the attribute "name" is present without prefix + // if (namespaceUri.equals(Namespaces.TOSCA_NAMESPACE)) { + // return ""; + // } + + String prefix = NamespacesResource.getPrefix(namespaceUri); + return prefix; + } + } + + + private static JAXBContext initContext() { + JAXBContext context; + try { + // For winery classes, eventually the package+jaxb.index method could be better. See http://stackoverflow.com/a/3628525/873282 + // @formatter:off + context = JAXBContext.newInstance( + TDefinitions.class, // all other elements are referred by "@XmlSeeAlso" + WinerysPropertiesDefinition.class, + // for the self-service portal + Application.class, + // MockXMLElement is added for testing purposes only. + MockXMLElement.class); + // @formatter:on + } catch (JAXBException e) { + JAXBSupport.logger.error("Could not initialize JAXBContext", e); + throw new IllegalStateException(e); + } + return context; + } + + /** + * Creates a marshaller + * + * @throws IllegalStateException if marshaller could not be instantiated + */ + public static Marshaller createMarshaller(boolean includeProcessingInstruction) { + Marshaller m; + try { + m = JAXBSupport.context.createMarshaller(); + // pretty printed output is required as the XML is sent 1:1 to the browser for editing + m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + m.setProperty("com.sun.xml.bind.namespacePrefixMapper", JAXBSupport.prefixMapper); + if (!includeProcessingInstruction) { + // side effect of JAXB_FRAGMENT property (when true): processing instruction is not included + m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); + } + } catch (JAXBException e) { + JAXBSupport.logger.error("Could not instantiate marshaller", e); + throw new IllegalStateException(e); + } + + return m; + } + + /** + * Creates an unmarshaller + * + * @throws IllegalStateException if unmarshaller could not be instantiated + */ + public static Unmarshaller createUnmarshaller() { + try { + return JAXBSupport.context.createUnmarshaller(); + } catch (JAXBException e) { + JAXBSupport.logger.error("Could not instantiate unmarshaller", e); + throw new IllegalStateException(e); + } + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/Prefs.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/Prefs.java new file mode 100644 index 0000000..cbb120f --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/Prefs.java @@ -0,0 +1,332 @@ +/******************************************************************************* + * Copyright (c) 2012-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + * C. Timurhan Sungur - jClouds preferences + *******************************************************************************/ +package org.eclipse.winery.repository; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.security.AccessControlException; +import java.util.Locale; +import java.util.Properties; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +import org.eclipse.winery.common.TOSCADocumentBuilderFactory; +import org.eclipse.winery.repository.backend.IRepository; +import org.eclipse.winery.repository.backend.filebased.FilebasedRepository; +import org.eclipse.winery.repository.backend.filebased.GitBasedRepository; +import org.eclipse.winery.repository.runtimeintegration.OpenTOSCAContainerConnection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Prefs implements ServletContextListener { + + // set by the constructors + // We have to do this hack as the servlet container initializes this class + // on its own and we want to have a *single* instance of this class. + public static Prefs INSTANCE; + + private static final Logger logger = LoggerFactory.getLogger(Prefs.class); + + protected IRepository repository = null; + + private ServletContext context; + + private Boolean isContainerLocallyAvailable = null; + + private Boolean isRestDocDocumentationAvailable = null; + + private Boolean isPlanBuilderAvailable = null; + + // location of the winery topology modeler + private String wineryTopologyModelerPath = null; + + // the properties from winery.properties + protected Properties properties = null; + + // package visibility to ease testing + static final String PROP_JCLOUDS_CONTEXT_PROVIDER = "jclouds.context.provider"; + static final String PROP_JCLOUDS_CONTEXT_IDENTITY = "jclouds.context.identity"; + static final String PROP_JCLOUDS_CONTEXT_CREDENTIAL = "jclouds.context.credential"; + static final String PROP_JCLOUDS_BLOBSTORE_LOCATION = "jclouds.blobstore.location"; + static final String PROP_JCLOUDS_CONTAINERNAME = "jclouds.blobstore.container"; + static final String PROP_JCLOUDS_END_POINT = "jclouds.blobstore.endpoint"; + + static final String PROP_BPMN4TOSCA_MODELER_URI = "bpmn4toscamodelerBaseURI"; + + + /** + * This constructor is called at handling at servlets, too. Therefore, we + * make it private. If testing is needed, an additional paramater has to be + * passed + */ + public Prefs() { + Prefs.INSTANCE = this; + } + + /** + * Constructor for Unit testing ONLY! + * + * @param initializeRepository true if the repository should be initialized + * as provided in winery.properties + * @throws IOException + * @warning Do not call! (except from Unit testing code) + */ + protected Prefs(boolean initializeRepository) throws IOException { + this(); + + // emulate behavior of doInitialization(Context) + Properties p = new Properties(); + InputStream is = this.getClass().getClassLoader().getResourceAsStream("winery.properties"); + if (is != null) { + p.load(is); + } + this.properties = p; + + if (initializeRepository) { + this.doRepositoryInitialization(); + } + } + + /** + * Initialization code for the repository. Should go into separate class, + * but being here should be OK for a prototype + * + * Called from both the constructor for JUnit and the servlet-based + * initialization + * + * Pre-Condition: this.properties is set. + */ + private void doRepositoryInitialization() { + assert (this.properties != null); + + String provider = this.properties.getProperty(Prefs.PROP_JCLOUDS_CONTEXT_PROVIDER); + if (provider != null) { + // repository runs via jclouds + // String identity = this.properties.getProperty(Prefs.PROP_JCLOUDS_CONTEXT_IDENTITY); + // String credential = this.properties.getProperty(Prefs.PROP_JCLOUDS_CONTEXT_CREDENTIAL); + // String location = this.properties.getProperty(Prefs.PROP_JCLOUDS_BLOBSTORE_LOCATION); + // String containerName = this.properties.getProperty(Prefs.PROP_JCLOUDS_CONTAINERNAME); + // String endPoint = this.properties.getProperty(Prefs.PROP_JCLOUDS_END_POINT); + Prefs.logger.error("jClouds is currently not supported due to jClouds not yet approved by Eclipse. Falling back to local storages"); + provider = null; + // Prefs.logger.info("Using jclouds as interface to the repository"); + // this.repository = new JCloudsBasedRepository(provider, identity, credential, location, containerName, endPoint); + } // else { + if (provider == null) { + String repositoryLocation = this.properties.getProperty("repositoryPath"); + Prefs.logger.debug("Repository location: {}", repositoryLocation); + Prefs.logger.debug("Trying git-based backend"); + try { + this.repository = new GitBasedRepository(repositoryLocation); + Prefs.logger.debug("git-based backend is used"); + } catch (Throwable e) { + Prefs.logger.trace(e.getMessage()); + Prefs.logger.debug("There seems to be no git repository at the specified location. We fall back to the file-based repository"); + this.repository = new FilebasedRepository(repositoryLocation); + } + } + } + + private void doInitialization(ServletContext ctx) { + if (Locale.getDefault() != Locale.ENGLISH) { + try { + // needed for {@link + // org.eclipse.winery.repository.filesystem.Utils.returnFile(File, + // String)} + Locale.setDefault(Locale.ENGLISH); + } catch (AccessControlException e) { + // Happens at Google App Engine + Prefs.logger.error("Could not switch locale to English", e); + } + } + + this.context = ctx; + + // Reading // + final String fn = "/WEB-INF/classes/winery.properties"; + Prefs.logger.debug("Trying to read ".concat(ctx.getRealPath(fn))); + InputStream inStream = ctx.getResourceAsStream(fn); + // alternative: InputStream inStream = this.getClass().getClassLoader().getResourceAsStream("winery.properties"); + Properties p = new Properties(); + if (inStream == null) { + Prefs.logger.info(fn + " does not exist."); + + // We search for winery.properties on the filesystem in the repository + + File propFile = new File(FilebasedRepository.getDefaultRepositoryFilePath(), "winery.properties"); + Prefs.logger.info("Trying " + propFile.getAbsolutePath()); + if (propFile.exists()) { + Prefs.logger.info("Found"); + // if winery.property exists in the root of the default repository path (~/winery-repository), load it + try (InputStream is2 = new FileInputStream(propFile)) { + p.load(is2); + } catch (IOException e) { + Prefs.logger.error("Could not load winery.properties", e); + } + } else { + Prefs.logger.info("Not found"); + } + } else { + try { + p.load(inStream); + try { + inStream.close(); + } catch (IOException e) { + Prefs.logger.error("Could not close stream of winery.properties", e); + } + } catch (FileNotFoundException e) { + // OK if file does not exist + } catch (IOException e) { + Prefs.logger.error("Could not load winery.properties", e); + } + } + + this.wineryTopologyModelerPath = p.getProperty("topologymodeler"); + + // make the properties known in the class + this.properties = p; + + this.doRepositoryInitialization(); + + // Initialize XSD validation in the background. Takes up a few seconds. + // If we do not do it here, the first save by a user takes a few seconds, which is inconvenient + new Thread() { + + @Override + public void run() { + Prefs.logger.debug("Initializing XML validation"); + @SuppressWarnings("unused") + TOSCADocumentBuilderFactory tdbf = TOSCADocumentBuilderFactory.INSTANCE; + Prefs.logger.debug("Initialized XML validation"); + } + }.start(); + } + + public IRepository getRepository() { + return this.repository; + } + + @Override + public void contextInitialized(ServletContextEvent arg0) { + Prefs.INSTANCE.doInitialization(arg0.getServletContext()); + } + + @Override + public void contextDestroyed(ServletContextEvent arg0) { + // nothing to do at tear down + } + + /** + * @return the path of the root resource + */ + public String getResourcePath() { + return this.context.getContextPath(); + } + + /** + * @return the path to the winery topology modeler. Without trailing slash + */ + public String getWineryTopologyModelerPath() { + if (this.wineryTopologyModelerPath == null) { + // derive the path from the current path + String res = this.getResourcePath(); + if (res.endsWith("/")) { + res = res.substring(0, res.length() - 1); + } + int pos = res.lastIndexOf("/"); + if (pos <= 0) { + res = "/winery-topologymodeler"; + } else { + res = res.substring(0, pos); + res = res + "winery-topologymodeler"; + } + return res; + } else { + assert (this.wineryTopologyModelerPath != null); + return this.wineryTopologyModelerPath; + } + } + + /** + * Returns the read content from winery.properties. + * + * @return the internal object held by this class. Manipulations on this + * object may cause trouble. + */ + public Properties getProperties() { + return this.properties; + } + + /** + * @return the version of winery + */ + public String getVersion() { + return Version.VERSION; + } + + /** + * @return true if the OpenTOSCA container is locally available + */ + public boolean isContainerLocallyAvailable() { + if (this.isContainerLocallyAvailable == null) { + // we initialize the variable at the first read + // The container and Winery are started simultaneously + // Therefore, the container might not be available if Winery is starting + // When checking at the first read, chances are high that the container started + this.isContainerLocallyAvailable = OpenTOSCAContainerConnection.isContainerLocallyAvailable(); + } + return this.isContainerLocallyAvailable; + } + + /** + * @return true if the plan generator is available + */ + public boolean isPlanBuilderAvailable() { + // similar implementation as isContainerLocallyAvailable() + if (this.isPlanBuilderAvailable == null) { + String planBuilderURI = "http://localhost:1339/planbuilder"; + this.isPlanBuilderAvailable = Utils.isResourceAvailable(planBuilderURI); + } + return this.isPlanBuilderAvailable; + } + + /** + * Quick hack to check whether a RestDoc documentation is available at + * /restdoc.html. We do not deliver + */ + public boolean isRestDocDocumentationAvailable() { + String path = "http://localhost:8080/restdoc.html"; + if (this.isRestDocDocumentationAvailable == null) { + // we initialize the variable at the first read + // The container and Winery are started simultaneously + // Therefore, the container might not be available if Winery is starting + // When checking at the first read, chances are high that the container started + this.isRestDocDocumentationAvailable = Utils.isResourceAvailable(path); + } + return this.isRestDocDocumentationAvailable; + } + + /** + * @return the base URL of the BPMN4TOSCA plan modeler. NULL if not + * configured. May also be empty. + */ + public String getBPMN4TOSCABaseURL() { + return this.properties.getProperty(Prefs.PROP_BPMN4TOSCA_MODELER_URI); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/RestDocFilter.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/RestDocFilter.java new file mode 100644 index 0000000..12d84e9 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/RestDocFilter.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ + +package org.eclipse.winery.repository; + +import org.eclipse.winery.repository.resources.MainResource; +import org.restdoc.jersey.server.RestDocFeature; + +public class RestDocFilter extends RestDocFeature { + + @Override + protected Class[] getClasses() { + Class[] res = {MainResource.class}; + return res; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/Utils.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/Utils.java new file mode 100644 index 0000000..e989324 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/Utils.java @@ -0,0 +1,787 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.StringWriter; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.Response.Status.Family; +import javax.ws.rs.core.StreamingOutput; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.namespace.QName; + +import org.apache.taglibs.standard.functions.Functions; +import org.apache.tika.detect.Detector; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.parser.AutoDetectParser; +import org.apache.xerces.xs.XSConstants; +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.common.ids.GenericId; +import org.eclipse.winery.common.ids.Namespace; +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.common.ids.definitions.imports.XSDImportId; +import org.eclipse.winery.model.tosca.TArtifactType; +import org.eclipse.winery.model.tosca.TConstraint; +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.model.tosca.TEntityType; +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.model.tosca.TNodeType; +import org.eclipse.winery.model.tosca.TPolicyType; +import org.eclipse.winery.model.tosca.TRelationshipType; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.datatypes.ids.admin.AdminId; +import org.eclipse.winery.repository.export.CSARExporter; +import org.eclipse.winery.repository.export.TOSCAExportUtil; +import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource; +import org.eclipse.winery.repository.resources.AbstractComponentsResource; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypesResource; +import org.eclipse.winery.repository.resources.entitytypes.relationshiptypes.RelationshipTypeResource; +import org.eclipse.winery.repository.resources.entitytypes.relationshiptypes.RelationshipTypesResource; +import org.eclipse.winery.repository.resources.imports.xsdimports.XSDImportResource; +import org.slf4j.ext.XLogger; +import org.slf4j.ext.XLoggerFactory; +import org.w3c.dom.Element; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; + +/** + * Contains utility functionality concerning with everything that is + * not related only to the repository, but more. For instance, resource + * functionality. Utility functionality for the repository is contained at + * {@link BackendUtils} + */ +public class Utils { + + private static final XLogger logger = XLoggerFactory.getXLogger(Utils.class); + + + public static URI createURI(String uri) { + try { + return new URI(uri); + } catch (URISyntaxException e) { + throw new IllegalStateException(); + } + } + + + // RegExp inspired by http://stackoverflow.com/a/5396246/873282 + // NameStartChar without ":" + // stackoverflow: -dfff, standard: d7fff + private static final String RANGE_NCNAMESTARTCHAR = "A-Z_a-z\\u00C0\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02ff\\u0370-\\u037d" + "\\u037f-\\u1fff\\u200c\\u200d\\u2070-\\u218f\\u2c00-\\u2fef\\u3001-\\ud7ff" + "\\uf900-\\ufdcf\\ufdf0-\\ufffd\\x10000-\\xEFFFF"; + private static final String REGEX_NCNAMESTARTCHAR = "[" + Utils.RANGE_NCNAMESTARTCHAR + "]"; + + private static final String RANGE_NCNAMECHAR = Utils.RANGE_NCNAMESTARTCHAR + "\\-\\.0-9\\u00b7\\u0300-\\u036f\\u203f-\\u2040"; + private static final String REGEX_INVALIDNCNAMESCHAR = "[^" + Utils.RANGE_NCNAMECHAR + "]"; + + + /** + * Creates a (valid) XML ID (NCName) based on the passed name + * + * Valid NCNames: http://www.w3.org/TR/REC-xml-names/#NT-NCName / + * http://www.w3.org/TR/xml/#NT-Name http://www.w3.org/TR/xml/#NT-Name + * + */ + public static XMLId createXMLid(String name) { + return new XMLId(Utils.createXMLidAsString(name), false); + } + + /** + * Creates a (valid) XML ID (NCName) based on the passed name + * + * Valid NCNames: http://www.w3.org/TR/REC-xml-names/#NT-NCName / + * http://www.w3.org/TR/xml/#NT-Name http://www.w3.org/TR/xml/#NT-Name + * + * TODO: this method seems to be equal to {@link + * org.eclipse.winery.common.Util.makeNCName(String)}. The methods should be + * merged into one. + * + */ + public static String createXMLidAsString(String name) { + String id = name; + if (!id.substring(0, 1).matches(Utils.REGEX_NCNAMESTARTCHAR)) { + id = "_".concat(id); + } + // id starts with a valid character + + // before we wipe out all invalid characters, we do a readable + // replacement for appropriate characters + id = id.replace(' ', '_'); + + // keep length of ID, only wipe out invalid characters + // alternative: replace invalid characters by URLencoded version. As the + // ID is visible only in the URL, this quick hack should be OK + // ID is visible only in the URL, this quick hack should be OK + id = id.replaceAll(Utils.REGEX_INVALIDNCNAMESCHAR, "_"); + + return id; + } + + /** + * Returns the plain XML for the selected resource + * + * @param uri + */ + public static Response getDefinitionsOfSelectedResource(final AbstractComponentInstanceResource resource, final URI uri) { + final TOSCAExportUtil exporter = new TOSCAExportUtil(); + StreamingOutput so = new StreamingOutput() { + + @Override + public void write(OutputStream output) throws IOException, WebApplicationException { + Map conf = new HashMap<>(); + conf.put(TOSCAExportUtil.ExportProperties.REPOSITORY_URI.toString(), uri); + try { + exporter.exportTOSCA(resource.getId(), output, conf); + } catch (JAXBException e) { + throw new WebApplicationException(e); + } + output.close(); + } + }; + /* + * this code is for offering a download action // Browser offers save as + * // .tosca is more or less needed for debugging, only a CSAR makes + * sense. // Therefore, we want to have the xml opened in the browser. + * StringBuilder sb = new StringBuilder(); + * sb.append("attachment;filename=\""); + * sb.append(resource.getXmlId().getEncoded()); sb.append(" - "); + * sb.append(resource.getNamespace().getEncoded()); sb.append(".xml"); + * sb.append("\""); return Response.ok().header("Content-Disposition", + * sb + * .toString()).type(MediaType.APPLICATION_XML_TYPE).entity(so).build(); + */ + return Response.ok().type(MediaType.APPLICATION_XML).entity(so).build(); + } + + public static Response getCSARofSelectedResource(final AbstractComponentInstanceResource resource) { + final CSARExporter exporter = new CSARExporter(); + StreamingOutput so = new StreamingOutput() { + + @Override + public void write(OutputStream output) throws IOException, WebApplicationException { + try { + exporter.writeCSAR(resource.getId(), output); + } catch (Exception e) { + throw new WebApplicationException(e); + } + } + }; + StringBuilder sb = new StringBuilder(); + sb.append("attachment;filename=\""); + sb.append(resource.getXmlId().getEncoded()); + sb.append(org.eclipse.winery.repository.Constants.SUFFIX_CSAR); + sb.append("\""); + return Response.ok().header("Content-Disposition", sb.toString()).type(org.eclipse.winery.common.constants.MimeTypes.MIMETYPE_ZIP).entity(so).build(); + } + + /** + * @return Singular type name for the given resource. E.g., + * "ServiceTemplateResource" gets "ServiceTemplate" + */ + public static String getTypeForInstance(Class resClass) { + String res = resClass.getName(); + // Everything between the last "." and before "Resource" is the Type + int dotIndex = res.lastIndexOf('.'); + assert (dotIndex >= 0); + return res.substring(dotIndex + 1, res.length() - "Resource".length()); + } + + /** + * @return Singular type name for the given id. E.g., "ServiceTemplateId" + * gets "ServiceTemplate" + */ + public static String getTypeForAdminId(Class idClass) { + return Util.getEverythingBetweenTheLastDotAndBeforeId(idClass); + } + + /** + * @return Singular type name for given AbstractComponentsResource. E.g, + * "ServiceTemplatesResource" gets "ServiceTemplate" + */ + public static String getTypeForComponentContainer(Class containerClass) { + String res = containerClass.getName(); + // Everything between the last "." and before "sResource" is the Type + int dotIndex = res.lastIndexOf('.'); + assert (dotIndex >= 0); + return res.substring(dotIndex + 1, res.length() - "sResource".length()); + } + + @SuppressWarnings("unchecked") + public static Class getComponentIdClass(String idClassName) { + String pkg = "org.eclipse.winery.common.ids.definitions."; + if (idClassName.contains("Import")) { + // quick hack to handle imports, which reside in their own package + pkg = pkg + "imports."; + } + String fullClassName = pkg + idClassName; + try { + return (Class) Class.forName(fullClassName); + } catch (ClassNotFoundException e) { + // quick hack for Ids local to winery repository + try { + fullClassName = "org.eclipse.winery.repository.datatypes.ids.admin." + idClassName; + return (Class) Class.forName(fullClassName); + } catch (ClassNotFoundException e2) { + String errorMsg = "Could not find id class for component container, " + fullClassName; + Utils.logger.error(errorMsg); + throw new IllegalStateException(errorMsg); + } + } + } + + /** + * Returns a class object for ids of components nested in the given + * AbstractComponentsResource + */ + public static Class getComponentIdClassForComponentContainer(Class containerClass) { + // the name of the id class is the type + "Id" + String idClassName = Utils.getTypeForComponentContainer(containerClass) + "Id"; + + return Utils.getComponentIdClass(idClassName); + } + + public static Class getComponentIdClassForTExtensibleElements(Class clazz) { + // we assume that the clazzName always starts with a T. + // Therefore, we fetch everything after the last dot (plus offest 1) + String idClassName = clazz.getName(); + int dotIndex = idClassName.lastIndexOf('.'); + assert (dotIndex >= 0); + idClassName = idClassName.substring(dotIndex + 2) + "Id"; + + return Utils.getComponentIdClass(idClassName); + } + + + private static final String slashEncoded = Util.URLencode("/"); + + + public static String getURLforPathInsideRepo(String pathInsideRepo) { + // first encode the whole string + String res = Util.URLencode(pathInsideRepo); + // issue: "/" is also encoded. This has to be undone: + res = res.replaceAll(Utils.slashEncoded, "/"); + return res; + } + + + /** + * Shared object to map JSONs + */ + public static final ObjectMapper mapper = new ObjectMapper(); + + + public static String Object2JSON(Object o) { + String res; + try { + res = Utils.mapper.writeValueAsString(o); + } catch (Exception e) { + Utils.logger.error(e.getMessage(), e); + return null; + } + return res; + } + + @SuppressWarnings("unchecked") + public static Class getGenericIdClassForType(String typeIdType) { + Class res; + // quick hack - we only need definitions right now + String pkg = "org.eclipse.winery.repository.datatypes.ids.definitions."; + String className = typeIdType; + className = pkg + className; + try { + res = (Class) Class.forName(className); + } catch (ClassNotFoundException e) { + Utils.logger.error("Could not find id class for id type", e); + res = null; + } + return res; + } + + /** + * @return the absolute path for the given id + */ + public static String getAbsoluteURL(GenericId id) { + return Prefs.INSTANCE.getResourcePath() + "/" + Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(id)); + } + + /** + * @param baseURI the URI from which the path should start + * @param id the generic id to resolve + * + * @return the relative path for the given id + */ + public static String getRelativeURL(URI baseURI, GenericId id) { + String absolutePath = Prefs.INSTANCE.getResourcePath() + "/" + Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(id)); + return baseURI.relativize(URI.create(absolutePath)).toString(); + } + + /** + * @return the absolute path for the given id + */ + public static String getAbsoluteURL(RepositoryFileReference ref) { + return Prefs.INSTANCE.getResourcePath() + "/" + Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(ref)); + } + + public static URI getAbsoluteURI(GenericId id) { + return Utils.createURI(Utils.getAbsoluteURL(id)); + } + + public static String doubleEscapeHTMLAndThenConvertNL2BR(String txt) { + String res = Functions.escapeXml(txt); + res = Functions.escapeXml(res); + res = res.replaceAll("\\n", "
"); + return res; + } + + /** + * This method is similar to {@link + * org.eclipse.winery.common.Util.qname2href()}, but treats winery's + * internal ID model instead of the global TOSCA model + * + * @param id the id to create an a href element for + * @return an a HTML element pointing to the given id + */ + public static String getHREF(TOSCAComponentId id) { + String res = "" + Functions.escapeXml(id.getXmlId().getDecoded()) + ""; + return res; + } + + public static String artifactTypeQName2href(QName qname) { + return Util.qname2href(Prefs.INSTANCE.getResourcePath(), TArtifactType.class, qname); + } + + public static String nodeTypeQName2href(QName qname) { + return Util.qname2href(Prefs.INSTANCE.getResourcePath(), TNodeType.class, qname); + } + + public static String relationshipTypeQName2href(QName qname) { + return Util.qname2href(Prefs.INSTANCE.getResourcePath(), TRelationshipType.class, qname); + } + + public static String policyTypeQName2href(QName qname) { + return Util.qname2href(Prefs.INSTANCE.getResourcePath(), TPolicyType.class, qname); + } + + /** + * Returns the middle part of the package name or the JSP location + * + * @param type the type + * @param separator the separator to be used, "." or "/" + * @return string which can be used "in the middle" of a package or of a + * path to a JSP + */ + public static String getIntermediateLocationStringForType(String type, String separator) { + String location; + if (type.contains("ServiceTemplate")) { + location = "servicetemplates"; + } else { + if (type.contains("TypeImplementation")) { + location = "entitytypeimplementations"; + } else if (type.contains("Type")) { + location = "entitytypes"; + } else if (type.contains("Import")) { + location = "imports"; + } else { + assert (type.contains("Template")); + location = "entitytemplates"; + } + // location now is the super pkg, we have to add a pkg of the type + location = location + separator + type.toLowerCase() + "s"; + } + return location; + } + + /** + * Required by topologyedit.jsp + * + * @return all known nodetype resources + */ + public static Collection getAllNodeTypeResources() { + @SuppressWarnings("unchecked") + Collection res = (Collection) (Collection) new NodeTypesResource().getAll(); + return res; + } + + /** + * Required by topologyedit.jsp + * + * @return all known relation ship type resources + */ + public static Collection getAllRelationshipTypeResources() { + @SuppressWarnings("unchecked") + Collection res = (Collection) (Collection) new RelationshipTypesResource().getAll(); + return res; + } + + /** + * @return the path to the Winery topology modeler. Required by + * functions.tld + */ + public static String getWineryTopologyModelerPath() { + return Prefs.INSTANCE.getWineryTopologyModelerPath(); + } + + /** + * Detect the mime type of the stream. The stream is marked at the beginning + * and reset at the end + * + * @param is the stream + * @param fileName the fileName of the file belonging to the stream + */ + public static String getMimeType(BufferedInputStream bis, String fn) throws IOException { + AutoDetectParser parser = new AutoDetectParser(); + Detector detector = parser.getDetector(); + Metadata md = new Metadata(); + md.add(Metadata.RESOURCE_NAME_KEY, fn); + org.apache.tika.mime.MediaType mediaType = detector.detect(bis, md); + return mediaType.toString(); + } + + + private static final MediaType MEDIATYPE_APPLICATION_OCTET_STREAM = MediaType.valueOf("application/octet-stream"); + + + /** + * Fixes the mediaType if it is too vague (such as application/octet-stream) + * + * @return a more fitting MediaType or the original one if it is appropriate + * enough + */ + public static MediaType getFixedMimeType(BufferedInputStream is, String fileName, MediaType mediaType) { + if (mediaType.equals(Utils.MEDIATYPE_APPLICATION_OCTET_STREAM)) { + // currently, we fix application/octet-stream only + + // TODO: instead of using apache tika, we could hve a user-configured map storing + // * media type + // * file extension + + try { + return MediaType.valueOf(Utils.getMimeType(is, fileName)); + } catch (Exception e) { + Utils.logger.debug("Could not determine mimetype for " + fileName, e); + // just keep the old one + return mediaType; + } + } else { + return mediaType; + } + } + + /** + * Converts the given object to XML. + * + * Used in cases the given element is not annotated with @XmlRoot + * + * We cannot use {@literal Class} as, for + * instance, {@link TConstraint} does not inherit from + * {@link TExtensibleElements} + * + * @param clazz the Class of the passed object, required if obj is null + * @param obj the object to serialize + */ + public static Response getXML(Class clazz, T obj) { + // see commit ab4b5c547619c058990 for an implementation using getJAXBElement, + // which can be directly passed as entity + // the issue is that we want to have a *formatted* XML + // Therefore, we serialize "by hand". + String xml = Utils.getXMLAsString(clazz, obj, false); + + return Response.ok().type(MediaType.TEXT_XML).entity(xml).build(); + } + + public static String getXMLAsString(Class clazz, T obj, boolean includeProcessingInstruction) { + JAXBElement rootElement = Util.getJAXBElement(clazz, obj); + Marshaller m = JAXBSupport.createMarshaller(includeProcessingInstruction); + StringWriter w = new StringWriter(); + try { + m.marshal(rootElement, w); + } catch (JAXBException e) { + Utils.logger.error("Could not put content to string", e); + throw new IllegalStateException(e); + } + String res = w.toString(); + return res; + } + + public static String getXMLAsString(Object obj) { + if (obj instanceof Element) { + // in case the object is a DOM element, we use the DOM functionality + return Util.getXMLAsString((Element) obj); + } else { + return Utils.getXMLAsString(obj, false); + } + } + + public static String getXMLAsString(T obj, boolean includeProcessingInstruction) { + if (obj == null) { + return ""; + } + @SuppressWarnings("unchecked") + Class clazz = (Class) obj.getClass(); + return Utils.getXMLAsString(clazz, obj, includeProcessingInstruction); + } + + public static String getAllXSDElementDefinitionsForTypeAheadSelection() { + Utils.logger.entry(); + try { + return Utils.getAllXSDefinitionsForTypeAheadSelection(XSConstants.ELEMENT_DECLARATION); + } finally { + Utils.logger.exit(); + } + } + + public static String getAllXSDTypeDefinitionsForTypeAheadSelection() { + Utils.logger.entry(); + try { + return Utils.getAllXSDefinitionsForTypeAheadSelection(XSConstants.TYPE_DEFINITION); + } finally { + Utils.logger.exit(); + } + } + + public static String getAllXSDefinitionsForTypeAheadSelection(short type) { + SortedSet allImports = Repository.INSTANCE.getAllTOSCAComponentIds(XSDImportId.class); + + Map> data = new HashMap>(); + + for (XSDImportId id : allImports) { + XSDImportResource resource = new XSDImportResource(id); + Collection allLocalNames = resource.getAllDefinedLocalNames(type); + + Collection list; + if ((list = data.get(id.getNamespace())) == null) { + // list does not yet exist + list = new ArrayList(); + data.put(id.getNamespace(), list); + } + assert (list != null); + + list.addAll(allLocalNames); + } + + ArrayNode rootNode = Utils.mapper.createArrayNode(); + + // ensure ordering in JSON object + Collection allns = new TreeSet(); + allns.addAll(data.keySet()); + + for (Namespace ns : allns) { + Collection localNames = data.get(ns); + if (!localNames.isEmpty()) { + ObjectNode groupEntry = Utils.mapper.createObjectNode(); + rootNode.add(groupEntry); + groupEntry.put("text", ns.getDecoded()); + ArrayNode children = Utils.mapper.createArrayNode(); + groupEntry.put("children", children); + Collection sortedLocalNames = new TreeSet(); + sortedLocalNames.addAll(localNames); + for (String localName : sortedLocalNames) { + String value = "{" + ns.getDecoded() + "}" + localName; + String text = localName; + ObjectNode o = Utils.mapper.createObjectNode(); + o.put("text", text); + o.put("value", value); + children.add(o); + } + } + } + + try { + return Utils.mapper.writeValueAsString(rootNode); + } catch (JsonProcessingException e) { + throw new IllegalStateException("Could not create JSON", e); + } + } + + public static Response getResponseForException(Exception e) { + String msg; + if (e.getCause() != null) { + msg = e.getCause().getMessage(); + } else { + msg = e.getMessage(); + } + Response res = Response.status(Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + return res; + } + + /** + * Returns the stored type for the given template + * + * Goes to the repository to retrieve stored data + * + * @param template the template to determine the type for + */ + // we suppress "unchecked" as we use Class.forName + @SuppressWarnings("unchecked") + public static TEntityType getTypeForTemplate(TEntityTemplate template) { + QName type = template.getType(); + + // Possibilities: + // a) try all possibly types whether an appropriate QName exists + // b) derive type class from template class. Determine appropriate resource afterwards. + // We go for b) + + String instanceResourceClassName = template.getClass().toString(); + int idx = instanceResourceClassName.lastIndexOf('.'); + // get everything from ".T", where "." is the last dot + instanceResourceClassName = instanceResourceClassName.substring(idx + 2); + // strip off "Template" + instanceResourceClassName = instanceResourceClassName.substring(0, instanceResourceClassName.length() - "Template".length()); + // add "Type" + instanceResourceClassName += "Type"; + + // an id is required to instantiate the resource + String idClassName = "org.eclipse.winery.common.ids.definitions." + instanceResourceClassName + "Id"; + + String packageName = "org.eclipse.winery.repository.resources.entitytypes." + instanceResourceClassName.toLowerCase() + "s"; + // convert from NodeType to NodeTypesResource + instanceResourceClassName += "Resource"; + instanceResourceClassName = packageName + "." + instanceResourceClassName; + + Utils.logger.debug("idClassName: {}", idClassName); + Utils.logger.debug("className: {}", instanceResourceClassName); + + // Get instance of id class having "type" as id + Class idClass; + try { + idClass = (Class) Class.forName(idClassName); + } catch (ClassNotFoundException e) { + throw new IllegalStateException("Could not determine id class", e); + } + Constructor idConstructor; + try { + idConstructor = idClass.getConstructor(QName.class); + } catch (NoSuchMethodException | SecurityException e) { + throw new IllegalStateException("Could not get QName id constructor", e); + } + TOSCAComponentId typeId; + try { + typeId = idConstructor.newInstance(type); + } catch (InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { + throw new IllegalStateException("Could not instantiate type", e); + } + + // now instantiate the resource, where the type belongs to + Class instanceResourceClass; + try { + instanceResourceClass = (Class) Class.forName(instanceResourceClassName); + } catch (ClassNotFoundException e) { + throw new IllegalStateException("Could not determine component instance resource class", e); + } + Constructor resConstructor; + try { + resConstructor = instanceResourceClass.getConstructor(typeId.getClass()); + } catch (NoSuchMethodException | SecurityException e) { + throw new IllegalStateException("Could not get contructor", e); + } + AbstractComponentInstanceResource typeResource; + try { + typeResource = resConstructor.newInstance(typeId); + } catch (InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { + throw new IllegalStateException("Could not instantiate resoruce", e); + } + + // read the data from the resource and store it + TEntityType entityType = (TEntityType) typeResource.getElement(); + + return entityType; + } + + /** + * referenced by functions.tld + */ + public static Boolean isContainerLocallyAvailable() { + return Prefs.INSTANCE.isContainerLocallyAvailable(); + } + + /** + * referenced by functions.tld + * + * We need the bridge as functions (at tld) require a static method. We did + * not want to put two methods in Prefs and therefore, we put the method + * here. + */ + public static Boolean isRestDocDocumentationAvailable() { + return Prefs.INSTANCE.isRestDocDocumentationAvailable(); + } + + public static boolean isSuccessFulResponse(Response res) { + return Status.fromStatusCode(res.getStatus()).getFamily().equals(Family.SUCCESSFUL); + } + + /** + * Converts the given String to an integer. Fallback if String is a float. + * If String is an invalid number, "0" is returned + */ + public static int convertStringToInt(String number) { + int intTop = 0; + try { + intTop = Integer.parseInt(number); + } catch (NumberFormatException e) { + try { + float floatTop = Float.parseFloat(number); + intTop = Math.round(floatTop); + } catch (NumberFormatException e2) { + // do nothing + } + } + + return intTop; + } + + /** + * Checks whether a given resource (with absolute URL!) is available with a + * HEAD request on it. + */ + public static boolean isResourceAvailable(String path) { + Client client = Client.create(); + WebResource wr = client.resource(path); + boolean res; + try { + ClientResponse response = wr.head(); + res = (response.getClientResponseStatus().getFamily().equals(Family.SUCCESSFUL)); + } catch (com.sun.jersey.api.client.ClientHandlerException ex) { + // In the case of a java.net.ConnectException, return false + res = false; + } + return res; + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/AbstractRepository.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/AbstractRepository.java new file mode 100644 index 0000000..6417df6 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/AbstractRepository.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.backend; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Date; + +import javax.ws.rs.core.MediaType; + +import org.apache.commons.configuration.Configuration; +import org.apache.commons.io.IOUtils; +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.ids.GenericId; +import org.eclipse.winery.repository.Constants; +import org.eclipse.winery.repository.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provides basic implementations for {@link IRepository} + */ +public abstract class AbstractRepository implements IRepository { + + private static final Logger logger = LoggerFactory.getLogger(AbstractRepository.class); + + + /** + * + * @param ref the file reference to store the mime type for + * @return a reference to the file holding the mime type + */ + private RepositoryFileReference getMimeFileRef(RepositoryFileReference ref) { + String fileName = ref.getFileName() + Constants.SUFFIX_MIMETYPE; + RepositoryFileReference mimeFileRef = new RepositoryFileReference(ref.getParent(), fileName); + return mimeFileRef; + } + + /** + * {@inheritDoc} + * + * This is a simple implementation using the information put by + * setMimeType(RepositoryFileReference ref) or determining the mime type + * using Utils.getMimeType. If the latter is done, the mime type is + * persisted using setMimeType + */ + @Override + public String getMimeType(RepositoryFileReference ref) throws IOException { + RepositoryFileReference mimeFileRef = this.getMimeFileRef(ref); + String mimeType; + if (this.exists(mimeFileRef)) { + InputStream is = this.newInputStream(mimeFileRef); + mimeType = IOUtils.toString(is, "UTF-8"); + is.close(); + } else { + // repository has been manipulated manually, + // create mimetype information + mimeType = null; + try (InputStream is = this.newInputStream(ref); + BufferedInputStream bis = new BufferedInputStream(is);) { + mimeType = Utils.getMimeType(bis, ref.getFileName()); + } + if (mimeType != null) { + // successful execution + this.setMimeType(ref, MediaType.valueOf(mimeType)); + } else { + AbstractRepository.logger.debug("Could not determine mimetype"); + } + } + return mimeType; + } + + /** + * Stores the mime type of the given file reference in a separate file + * + * This method calls putContentToFile(), where the filename is appended with + * Constants.SUFFIX_MIMETYPE and a null mime type. The latter indicates that + * no "normal" file is stored. + * + * @param ref the file reference + * @param mediaType the mimeType + */ + protected void setMimeType(RepositoryFileReference ref, MediaType mediaType) throws IOException { + RepositoryFileReference mimeFileRef = this.getMimeFileRef(ref); + this.putContentToFile(mimeFileRef, mediaType.toString(), null); + } + + @Override + public Date getConfigurationLastUpdate(GenericId id) { + RepositoryFileReference ref = BackendUtils.getRefOfConfiguration(id); + return this.getLastUpdate(ref); + } + + @Override + public Configuration getConfiguration(GenericId id) { + RepositoryFileReference ref = BackendUtils.getRefOfConfiguration(id); + return this.getConfiguration(ref); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/BackendUtils.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/BackendUtils.java new file mode 100644 index 0000000..eeddfba --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/BackendUtils.java @@ -0,0 +1,995 @@ +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.backend; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.net.URI; +import java.nio.file.attribute.FileTime; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.SortedSet; + +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; +import javax.xml.XMLConstants; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.namespace.QName; + +import org.apache.commons.configuration.Configuration; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.time.DateUtils; +import org.apache.xerces.impl.dv.XSSimpleType; +import org.apache.xerces.impl.xs.XSImplementationImpl; +import org.apache.xerces.xs.XSComplexTypeDefinition; +import org.apache.xerces.xs.XSElementDeclaration; +import org.apache.xerces.xs.XSImplementation; +import org.apache.xerces.xs.XSLoader; +import org.apache.xerces.xs.XSModel; +import org.apache.xerces.xs.XSModelGroup; +import org.apache.xerces.xs.XSObjectList; +import org.apache.xerces.xs.XSParticle; +import org.apache.xerces.xs.XSTerm; +import org.apache.xerces.xs.XSTypeDefinition; +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.common.ids.GenericId; +import org.eclipse.winery.common.ids.IdUtil; +import org.eclipse.winery.common.ids.Namespace; +import org.eclipse.winery.common.ids.definitions.EntityTypeId; +import org.eclipse.winery.common.ids.definitions.NodeTypeImplementationId; +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.common.ids.definitions.imports.GenericImportId; +import org.eclipse.winery.common.ids.elements.PlansId; +import org.eclipse.winery.common.ids.elements.TOSCAElementId; +import org.eclipse.winery.common.propertydefinitionkv.PropertyDefinitionKV; +import org.eclipse.winery.common.propertydefinitionkv.PropertyDefinitionKVList; +import org.eclipse.winery.common.propertydefinitionkv.WinerysPropertiesDefinition; +import org.eclipse.winery.model.tosca.Definitions; +import org.eclipse.winery.model.tosca.ObjectFactory; +import org.eclipse.winery.model.tosca.TDeploymentArtifact; +import org.eclipse.winery.model.tosca.TDeploymentArtifacts; +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.model.tosca.TEntityType; +import org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition; +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.model.tosca.TImplementationArtifacts; +import org.eclipse.winery.model.tosca.TImplementationArtifacts.ImplementationArtifact; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TServiceTemplate; +import org.eclipse.winery.model.tosca.TTopologyTemplate; +import org.eclipse.winery.repository.Constants; +import org.eclipse.winery.repository.JAXBSupport; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.constants.Filename; +import org.eclipse.winery.repository.datatypes.ids.admin.AdminId; +import org.eclipse.winery.repository.datatypes.ids.elements.VisualAppearanceId; +import org.eclipse.winery.repository.resources.AbstractComponentsResource; +import org.eclipse.winery.repository.resources.IHasTypeReference; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources.admin.NamespacesResource; +import org.eclipse.winery.repository.resources.entitytypeimplementations.nodetypeimplementations.NodeTypeImplementationResource; +import org.eclipse.winery.repository.resources.entitytypes.TopologyGraphElementEntityTypeResource; +import org.eclipse.winery.repository.resources.imports.xsdimports.XSDImportsResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.ls.LSInput; + +import com.sun.jersey.core.header.ContentDisposition; + +/** + * Contains generic utility functions for the Backend + * + * Contains everything that is useful for our ids etc. Does not contain + * anything that has to do with resources + */ +public class BackendUtils { + + private static final Logger logger = LoggerFactory.getLogger(BackendUtils.class); + + + /** + * Deletes given file/dir and returns appropriate response code + */ + public static Response delete(GenericId id) { + if (!Repository.INSTANCE.exists(id)) { + return Response.status(Status.NOT_FOUND).build(); + } + try { + Repository.INSTANCE.forceDelete(id); + } catch (IOException e) { + BackendUtils.logger.error(e.getMessage(), e); + return Response.serverError().entity(e.getMessage()).build(); + } + return Response.noContent().build(); + } + + /** + * Deletes given file and returns appropriate response code + */ + public static Response delete(RepositoryFileReference ref) { + if (!Repository.INSTANCE.exists(ref)) { + return Response.status(Status.NOT_FOUND).build(); + } + try { + Repository.INSTANCE.forceDelete(ref); + } catch (IOException e) { + BackendUtils.logger.error(e.getMessage(), e); + return Response.serverError().entity(e.getMessage()).build(); + } + return Response.ok().build(); + } + + /** + * Generates given TOSCA element and returns appropriate response code
+ * + * In the case of an existing resource, the other possible return code is + * 302. This code has no Status constant, therefore we use Status.CONFLICT, + * which is also possible. + * + * @return
    + *
  • + *
      + *
    • Status.CREATED (201) if the resource has been created,
    • + *
    • Status.CONFLICT if the resource already exists,
    • + *
    • Status.INTERNAL_SERVER_ERROR (500) if something went wrong
    • + *
    + *
  • + *
  • URI: the absolute URI of the newly created resource
  • + *
+ */ + public static ResourceCreationResult create(GenericId id) { + ResourceCreationResult res = new ResourceCreationResult(); + if (Repository.INSTANCE.exists(id)) { + // res.setStatus(302); + res.setStatus(Status.CONFLICT); + } else { + if (Repository.INSTANCE.flagAsExisting(id)) { + res.setStatus(Status.CREATED); + // @formatter:off + // This method is a generic method + // We cannot return an "absolute" URL as the URL is always + // relative to the caller + // Does not work: String path = Prefs.INSTANCE.getResourcePath() + // + "/" + + // Utils.getURLforPathInsideRepo(id.getPathInsideRepo()); + // We distinguish between two cases: TOSCAcomponentId and + // TOSCAelementId + // @formatter:on + String path; + if (id instanceof TOSCAComponentId) { + // here, we return namespace + id, as it is only possible to + // post on the TOSCA component*s* resource to create an + // instance of a TOSCA component + TOSCAComponentId tcId = (TOSCAComponentId) id; + path = tcId.getNamespace().getEncoded() + "/" + tcId.getXmlId().getEncoded() + "/"; + } else { + assert (id instanceof TOSCAElementId); + // We just return the id as we assume that only the parent + // of this id may create sub elements + path = id.getXmlId().getEncoded() + "/"; + } + // we have to encode it twice to get correct URIs + path = Utils.getURLforPathInsideRepo(path); + URI uri = Utils.createURI(path); + res.setUri(uri); + res.setId(id); + } else { + res.setStatus(Status.INTERNAL_SERVER_ERROR); + } + } + return res; + } + + /** + * + * Sends the file if modified and "not modified" if not modified future work + * may put each file with a unique id in a separate folder in tomcat * use + * that static URL for each file * if file is modified, URL of file changes + * * -> client always fetches correct file + * + * additionally "Vary: Accept" header is added (enables caching of the + * response) + * + * method header for calling method public
+ * Response getXY(@HeaderParam("If-Modified-Since") String modified) {...} + * + * + * @param ref references the file to be send + * @param modified - HeaderField "If-Modified-Since" - may be "null" + * @return Response to be sent to the client + */ + public static Response returnRepoPath(RepositoryFileReference ref, String modified) { + return BackendUtils.returnRefAsResponseBuilder(ref, modified).build(); + } + + /** + * @return true if given fileDate is newer then the modified date (or + * modified is null) + */ + public static boolean isFileNewerThanModifiedDate(long millis, String modified) { + if (modified == null) { + return true; + } + + Date modifiedDate = null; + + assert (Locale.getDefault() == Locale.ENGLISH); + try { + modifiedDate = DateUtils.parseDate(modified, org.apache.http.impl.cookie.DateUtils.DEFAULT_PATTERNS); + } catch (ParseException e) { + BackendUtils.logger.error(e.getMessage(), e); + } + + if (modifiedDate != null) { + // modifiedDate does not carry milliseconds, but fileDate does + // therefore we have to do a range-based comparison + if ((millis - modifiedDate.getTime()) < DateUtils.MILLIS_PER_SECOND) { + return false; + } + } + + return true; + } + + /** + * This is not repository specific, but we leave it close to the only caller + * + * If the passed ref is newer than the modified date (or the modified date + * is null), an OK response with an inputstream pointing to the path is + * returned + */ + private static ResponseBuilder returnRefAsResponseBuilder(RepositoryFileReference ref, String modified) { + if (!Repository.INSTANCE.exists(ref)) { + return Response.status(Status.NOT_FOUND); + } + + FileTime lastModified; + try { + lastModified = Repository.INSTANCE.getLastModifiedTime(ref); + } catch (IOException e1) { + BackendUtils.logger.debug("Could not get lastModifiedTime", e1); + return Response.serverError(); + } + + // do we really need to send the file or can send "not modified"? + if (!BackendUtils.isFileNewerThanModifiedDate(lastModified.toMillis(), modified)) { + return Response.status(Status.NOT_MODIFIED); + } + + ResponseBuilder res; + try { + res = Response.ok(Repository.INSTANCE.newInputStream(ref)); + } catch (IOException e) { + BackendUtils.logger.debug("Could not open input stream", e); + return Response.serverError(); + } + res = res.lastModified(new Date(lastModified.toMillis())); + // vary:accept header is always set to be safe + res = res.header(HttpHeaders.VARY, HttpHeaders.ACCEPT); + // determine and set MIME content type + try { + res = res.header(HttpHeaders.CONTENT_TYPE, Repository.INSTANCE.getMimeType(ref)); + } catch (IOException e) { + BackendUtils.logger.debug("Could not determine mime type", e); + return Response.serverError(); + } + // set filename + ContentDisposition contentDisposition = ContentDisposition.type("attachment").fileName(ref.getFileName()).modificationDate(new Date(lastModified.toMillis())).build(); + res.header("Content-Disposition", contentDisposition); + return res; + } + + /** + * Updates the given property in the given configuration. Currently always + * returns "no content", because the underlying class does not report any + * errors during updating.
+ * + * If null or "" is passed as value, the property is cleared + * + * @return Status.NO_CONTENT + */ + public static Response updateProperty(Configuration configuration, String property, String val) { + if (StringUtils.isBlank(val)) { + configuration.clearProperty(property); + } else { + configuration.setProperty(property, val); + } + return Response.noContent().build(); + } + + /** + * Persists the resource and returns appropriate response + */ + public static Response persist(IPersistable res) { + Response r; + try { + res.persist(); + } catch (IOException e) { + BackendUtils.logger.debug("Could not persist resource", e); + r = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e).build(); + return r; + } + r = Response.noContent().build(); + return r; + } + + /** + * Writes data to file. Replaces the file's content with the given content. + * The file does not need to exist + * + * @param ref Reference to the File to write to (overwrite) + * @param content the data to write + * @return a JAX-RS Response containing the result. NOCONTENT if successful, + * InternalSeverError otherwise + */ + public static Response putContentToFile(RepositoryFileReference ref, String content, MediaType mediaType) { + try { + Repository.INSTANCE.putContentToFile(ref, content, mediaType); + } catch (IOException e) { + BackendUtils.logger.error(e.getMessage(), e); + return Response.serverError().entity(e.getMessage()).build(); + } + return Response.noContent().build(); + } + + public static Response putContentToFile(RepositoryFileReference ref, InputStream inputStream, MediaType mediaType) { + try { + Repository.INSTANCE.putContentToFile(ref, inputStream, mediaType); + } catch (IOException e) { + BackendUtils.logger.error(e.getMessage(), e); + return Response.serverError().entity(e.getMessage()).build(); + } + return Response.noContent().build(); + } + + public static T getTOSCAcomponentId(Class idClass, String qnameStr) { + QName qname = QName.valueOf(qnameStr); + return BackendUtils.getTOSCAcomponentId(idClass, qname.getNamespaceURI(), qname.getLocalPart(), false); + } + + public static T getTOSCAcomponentId(Class idClass, QName qname) { + // we got two implementation possibilities: one is to directly use the + // QName constructor, + // the other is to use a namespace, localname, urlencoded constructor + // we opt for the latter one, which forces the latter constructor to + // exist at all ids + return BackendUtils.getTOSCAcomponentId(idClass, qname.getNamespaceURI(), qname.getLocalPart(), false); + } + + public static T getTOSCAcomponentId(Class idClass, String namespace, String id, boolean URLencoded) { + Constructor constructor; + try { + constructor = idClass.getConstructor(String.class, String.class, boolean.class); + } catch (NoSuchMethodException | SecurityException e) { + BackendUtils.logger.error("Could not get constructor for id " + idClass.getName(), e); + throw new IllegalStateException(e); + } + T tcId; + try { + tcId = constructor.newInstance(namespace, id, URLencoded); + } catch (InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { + BackendUtils.logger.error("Could not create id instance", e); + throw new IllegalStateException(e); + } + return tcId; + } + + /** + * @param id the id to determine the namespace of the parent for + * @return the namespace of the first TOSCAcomponentId found in the ID + * hierarchy + */ + public static Namespace getNamespace(TOSCAElementId id) { + GenericId parent = id.getParent(); + while (!(parent instanceof TOSCAComponentId)) { + parent = parent.getParent(); + } + return ((TOSCAComponentId) parent).getNamespace(); + } + + public static String getName(TOSCAComponentId instanceId) { + // TODO: Here is a performance issue as we don't use caching or a database + // Bad, but without performance loss: Use "text = instanceId.getXmlId().getDecoded();" + TExtensibleElements instanceElement = AbstractComponentsResource.getComponentInstaceResource(instanceId).getElement(); + return ModelUtilities.getNameWithIdFallBack(instanceElement); + } + +/** + * Do not use this for creating URLs. Use + * + * {@link org.eclipse.winery.repository.Utils.getURLforPathInsideRepo(String)} + * + * or + * + * {@link org.eclipse.winery.repository.Utils.getAbsoluteURL(GenericId) + * instead. + * + * @return the path starting from the root element to the current element. + * Separated by "/", URLencoded, but not double encoded. With + * trailing slash if sub-resources can exist + * @throws IllegalStateException if id is of an unknown subclass of id + */ + public static String getPathInsideRepo(GenericId id) { + if (id == null) { + throw new NullPointerException("id is null"); + } + + // for creating paths see also org.eclipse.winery.repository.Utils.getIntermediateLocationStringForType(String, String) + // and org.eclipse.winery.common.Util.getRootPathFragment(Class) + if (id instanceof AdminId) { + return "admin/" + id.getXmlId().getEncoded() + "/"; + } else if (id instanceof GenericImportId) { + GenericImportId i = (GenericImportId) id; + String res = "imports/"; + res = res + Util.URLencode(i.getType()) + "/"; + res = res + i.getNamespace().getEncoded() + "/"; + res = res + i.getXmlId().getEncoded() + "/"; + return res; + } else if (id instanceof TOSCAComponentId) { + return IdUtil.getPathFragment(id); + } else if (id instanceof TOSCAElementId) { + // we cannot reuse IdUtil.getPathFragment(id) as this TOSCAelementId + // might be nested in an AdminId + return BackendUtils.getPathInsideRepo(id.getParent()) + id.getXmlId().getEncoded() + "/"; + } else { + throw new IllegalStateException("Unknown subclass of GenericId " + id.getClass()); + } + } + +/** + * Do not use this for creating URLs. Use + * + * {@link org.eclipse.winery.repository.Utils.getURLforPathInsideRepo(String)} + * + * or + * + * {@link org.eclipse.winery.repository.Utils.getAbsoluteURL(GenericId) + * instead. + * + * @return the path starting from the root element to the current element. + * Separated by "/", parent URLencoded. Without trailing slash. + */ + public static String getPathInsideRepo(RepositoryFileReference ref) { + return BackendUtils.getPathInsideRepo(ref.getParent()) + ref.getFileName(); + } + + /** + * Returns the reference to the definitions XML storing the TOSCA for the + * given id + * + * @param id the id to lookup + * @return the reference + */ + public static RepositoryFileReference getRefOfDefinitions(TOSCAComponentId id) { + String name = Util.getTypeForComponentId(id.getClass()); + name = name + Constants.SUFFIX_TOSCA_DEFINITIONS; + RepositoryFileReference ref = new RepositoryFileReference(id, name); + return ref; + } + + /** + * Returns the reference to the properties file storing the TOSCA + * information for the given id + * + * @param id the id to lookup + * @return the reference + */ + public static RepositoryFileReference getRefOfConfiguration(GenericId id) { + String name; + // Hack to determine file name + if (id instanceof TOSCAComponentId) { + name = Util.getTypeForComponentId(((TOSCAComponentId) id).getClass()); + name = name + Constants.SUFFIX_PROPERTIES; + } else if (id instanceof AdminId) { + name = Utils.getTypeForAdminId(((AdminId) id).getClass()); + name = name + Constants.SUFFIX_PROPERTIES; + } else { + assert (id instanceof TOSCAElementId); + TOSCAElementId tId = (TOSCAElementId) id; + if (tId instanceof PlansId) { + name = Filename.FILENAME_PROPERTIES_PLANCONTAINER; + } else if (tId instanceof VisualAppearanceId) { + // quick hack for special name here + name = Filename.FILENAME_PROPERTIES_VISUALAPPEARANCE; + } else { + name = Util.getTypeForElementId(tId.getClass()) + Constants.SUFFIX_PROPERTIES; + } + } + + RepositoryFileReference ref = new RepositoryFileReference(id, name); + return ref; + } + + /** + * @param qNameOfTheType the QName of the type, where all TOSCAComponentIds, + * where the associated element points to the type + * @param clazz the Id class of the entities to discover + */ + public static Collection getAllElementsRelatedWithATypeAttribute(Class clazz, QName qNameOfTheType) { + // we do not use any database system, + // therefore we have to crawl through each node type implementation by ourselves + SortedSet allIds = Repository.INSTANCE.getAllTOSCAComponentIds(clazz); + Collection res = new HashSet<>(); + for (X id : allIds) { + IHasTypeReference resource; + try { + resource = (IHasTypeReference) AbstractComponentsResource.getComponentInstaceResource(id); + } catch (ClassCastException e) { + String error = "Requested following the type, but the component instance does not implmenet IHasTypeReference"; + BackendUtils.logger.error(error); + throw new IllegalStateException(error); + } + // The resource may have been freshly initialized due to existence of a directory + // then it has no node type assigned leading to ntiRes.getType() being null + // we ignore this error here + if (qNameOfTheType.equals(resource.getType())) { + // the component instance is an implementation of the associated node type + res.add(id); + } + } + return res; + } + + /** + * Returns a list of the topology template nested in the given service + * template + */ + public static List getAllNestedNodeTemplates(TServiceTemplate serviceTemplate) { + List l = new ArrayList(); + TTopologyTemplate topologyTemplate = serviceTemplate.getTopologyTemplate(); + if (topologyTemplate == null) { + return Collections.emptyList(); + } + for (TEntityTemplate t : topologyTemplate.getNodeTemplateOrRelationshipTemplate()) { + if (t instanceof TNodeTemplate) { + l.add((TNodeTemplate) t); + } + } + return l; + } + + private static Collection getAllReferencedArtifactTemplates(TDeploymentArtifacts tDeploymentArtifacts) { + if (tDeploymentArtifacts == null) { + return Collections.emptyList(); + } + List deploymentArtifacts = tDeploymentArtifacts.getDeploymentArtifact(); + if (deploymentArtifacts == null) { + return Collections.emptyList(); + } + Collection res = new ArrayList<>(); + for (TDeploymentArtifact da : deploymentArtifacts) { + QName artifactRef = da.getArtifactRef(); + if (artifactRef != null) { + res.add(artifactRef); + } + } + return res; + } + + private static Collection getAllReferencedArtifactTemplates(TImplementationArtifacts tImplementationArtifacts) { + if (tImplementationArtifacts == null) { + return Collections.emptyList(); + } + List implementationArtifacts = tImplementationArtifacts.getImplementationArtifact(); + if (implementationArtifacts == null) { + return Collections.emptyList(); + } + Collection res = new ArrayList<>(); + for (ImplementationArtifact ia : implementationArtifacts) { + QName artifactRef = ia.getArtifactRef(); + if (artifactRef != null) { + res.add(artifactRef); + } + } + return res; + } + + public static Collection getArtifactTemplatesOfReferencedDeploymentArtifacts(TNodeTemplate nodeTemplate) { + List l = new ArrayList(); + + // DAs may be assigned directly to a node template + Collection allReferencedArtifactTemplates = BackendUtils.getAllReferencedArtifactTemplates(nodeTemplate.getDeploymentArtifacts()); + l.addAll(allReferencedArtifactTemplates); + + // DAs may be assigned via node type implementations + QName nodeTypeQName = nodeTemplate.getType(); + Collection allNodeTypeImplementations = BackendUtils.getAllElementsRelatedWithATypeAttribute(NodeTypeImplementationId.class, nodeTypeQName); + for (NodeTypeImplementationId nodeTypeImplementationId : allNodeTypeImplementations) { + NodeTypeImplementationResource ntiRes = new NodeTypeImplementationResource(nodeTypeImplementationId); + allReferencedArtifactTemplates = BackendUtils.getAllReferencedArtifactTemplates(ntiRes.getNTI().getDeploymentArtifacts()); + l.addAll(allReferencedArtifactTemplates); + } + + return l; + } + + public static Collection getArtifactTemplatesOfReferencedImplementationArtifacts(TNodeTemplate nodeTemplate) { + List l = new ArrayList(); + + // IAs may be assigned via node type implementations + QName nodeTypeQName = nodeTemplate.getType(); + Collection allNodeTypeImplementations = BackendUtils.getAllElementsRelatedWithATypeAttribute(NodeTypeImplementationId.class, nodeTypeQName); + for (NodeTypeImplementationId nodeTypeImplementationId : allNodeTypeImplementations) { + NodeTypeImplementationResource ntiRes = new NodeTypeImplementationResource(nodeTypeImplementationId); + Collection allReferencedArtifactTemplates = BackendUtils.getAllReferencedArtifactTemplates(ntiRes.getNTI().getImplementationArtifacts()); + l.addAll(allReferencedArtifactTemplates); + } + + return l; + } + + /** + * Creates a new TDefintions element wrapping a TOSCA Component instance. + * The namespace of the tosca component is used as namespace and + * {@code winery-defs-for-} concatenated with the (unique) ns prefix and + * idOfContainedElement is used as id + * + * @param toscAcomponentId the id of the element the wrapper is used for + * + * @return a definitions element prepared for wrapping a TOSCA component + * instance + */ + public static Definitions createWrapperDefinitions(TOSCAComponentId tcId) { + ObjectFactory of = new ObjectFactory(); + Definitions defs = of.createDefinitions(); + + // set target namespace + // an internal namespace is not possible + // a) tPolicyTemplate and tArtfactTemplate do NOT support the "targetNamespace" attribute + // b) the imports statement would look bad as it always imported the artificial namespace + defs.setTargetNamespace(tcId.getNamespace().getDecoded()); + + // set a unique id to create a valid definitions element + // we do not use UUID to be more human readable and deterministic (for debugging) + String prefix = NamespacesResource.getPrefix(tcId.getNamespace()); + String elId = tcId.getXmlId().getDecoded(); + String id = "winery-defs-for_" + prefix + "-" + elId; + defs.setId(id); + + return defs; + } + + /** + * @throws IOException if content could not be updated in the repository + * @throws IllegalStateException if an JAXBException occurred. This should + * never happen. + */ + public static void persist(Object o, RepositoryFileReference ref, MediaType mediaType) throws IOException { + // We assume that the object is not too large + // Otherwise, http://io-tools.googlecode.com/svn/www/easystream/apidocs/index.html should be used + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Marshaller m; + try { + m = JAXBSupport.createMarshaller(true); + m.marshal(o, out); + } catch (JAXBException e) { + BackendUtils.logger.error("Could not put content to file", e); + throw new IllegalStateException(e); + } + byte[] data = out.toByteArray(); + ByteArrayInputStream in = new ByteArrayInputStream(data); + // this may throw an IOExcpetion. We propagate this exception. + Repository.INSTANCE.putContentToFile(ref, in, mediaType); + } + + /** + * Updates the color if the color is not yet existent + * + * @param name the name of the component. Used as basis for a generated + * color + * @param qname the QName of the color attribute + * @param otherAttributes the plain "XML" attributes. They are used to check + * @param res + */ + public static String getColorAndSetDefaultIfNotExisting(String name, QName qname, Map otherAttributes, TopologyGraphElementEntityTypeResource res) { + String colorStr = otherAttributes.get(qname); + if (colorStr == null) { + colorStr = Util.getColor(name); + otherAttributes.put(qname, colorStr); + BackendUtils.persist(res); + } + return colorStr; + } + + /** + * + * @param tcId The element type id to get the location for + * @param uri uri to use if in XML export mode, null if in CSAR export mode + * @param wrapperElementLocalName the local name of the wrapper element + * @return + */ + public static String getImportLocationForWinerysPropertiesDefinitionXSD(EntityTypeId tcId, URI uri, String wrapperElementLocalName) { + String loc = BackendUtils.getPathInsideRepo(tcId); + loc = loc + "propertiesdefinition/"; + loc = Utils.getURLforPathInsideRepo(loc); + if (uri == null) { + loc = loc + wrapperElementLocalName + ".xsd"; + // for the import later, we need "../" in front + loc = "../" + loc; + } else { + loc = uri + loc + "xsd"; + } + return loc; + } + + /** + * @param ref the file to read from + */ + public static XSModel getXSModel(final RepositoryFileReference ref) { + if (ref == null) { + return null; + } + final InputStream is; + try { + is = Repository.INSTANCE.newInputStream(ref); + } catch (IOException e) { + BackendUtils.logger.debug("Could not create input stream", e); + return null; + } + + // we rely on xerces to parse the XSD + // idea based on http://stackoverflow.com/a/5165177/873282 + XSImplementation impl = new XSImplementationImpl(); + XSLoader schemaLoader = impl.createXSLoader(null); + + // minimal LSInput implementation sufficient for XSLoader in Oracle's JRE7 + LSInput input = new LSInput() { + + @Override + public void setSystemId(String systemId) { + } + + @Override + public void setStringData(String stringData) { + } + + @Override + public void setPublicId(String publicId) { + } + + @Override + public void setEncoding(String encoding) { + } + + @Override + public void setCharacterStream(Reader characterStream) { + } + + @Override + public void setCertifiedText(boolean certifiedText) { + } + + @Override + public void setByteStream(InputStream byteStream) { + } + + @Override + public void setBaseURI(String baseURI) { + } + + @Override + public String getSystemId() { + return null; + } + + @Override + public String getStringData() { + return null; + } + + @Override + public String getPublicId() { + return BackendUtils.getPathInsideRepo(ref); + } + + @Override + public String getEncoding() { + return "UTF-8"; + } + + @Override + public Reader getCharacterStream() { + try { + return new InputStreamReader(is, "UTF-8"); + } catch (UnsupportedEncodingException e) { + System.out.println("exeption"); + throw new IllegalStateException("UTF-8 is unkown", e); + } + } + + @Override + public boolean getCertifiedText() { + return false; + } + + @Override + public InputStream getByteStream() { + return null; + } + + @Override + public String getBaseURI() { + return null; + } + }; + XSModel model = schemaLoader.load(input); + return model; + } + + /** + * Derives Winery's Properties Definition from an existing properties + * definition + * + * @param ci the entity type to try to modify the WPDs + * @param errors the list to add errors to + */ + public static void deriveWPD(TEntityType ci, List errors) { + BackendUtils.logger.trace("deriveWPD"); + PropertiesDefinition propertiesDefinition = ci.getPropertiesDefinition(); + QName element = propertiesDefinition.getElement(); + if (element == null) { + BackendUtils.logger.debug("only works for an element definition, not for types"); + } else { + BackendUtils.logger.debug("Looking for the definition of {" + element.getNamespaceURI() + "}" + element.getLocalPart()); + // fetch the XSD defining the element + XSDImportsResource importsRes = new XSDImportsResource(); + Map mapFromLocalNameToXSD = importsRes.getMapFromLocalNameToXSD(element.getNamespaceURI(), false); + RepositoryFileReference ref = mapFromLocalNameToXSD.get(element.getLocalPart()); + if (ref == null) { + String msg = "XSD not found for " + element.getNamespaceURI() + " / " + element.getLocalPart(); + BackendUtils.logger.debug(msg); + errors.add(msg); + return; + } + + XSModel xsModel = BackendUtils.getXSModel(ref); + XSElementDeclaration elementDeclaration = xsModel.getElementDeclaration(element.getLocalPart(), element.getNamespaceURI()); + if (elementDeclaration == null) { + String msg = "XSD model claimed to contain declaration for {" + element.getNamespaceURI() + "}" + element.getLocalPart() + ", but it did not."; + BackendUtils.logger.debug(msg); + errors.add(msg); + return; + } + + // go through the XSD definition and + XSTypeDefinition typeDefinition = elementDeclaration.getTypeDefinition(); + if (typeDefinition instanceof XSComplexTypeDefinition) { + XSComplexTypeDefinition cTypeDefinition = (XSComplexTypeDefinition) typeDefinition; + XSParticle particle = cTypeDefinition.getParticle(); + if (particle == null) { + BackendUtils.logger.debug("XSD does not follow the requirements put by winery: Complex type does not contain particles"); + } else { + XSTerm term = particle.getTerm(); + if (term instanceof XSModelGroup) { + XSModelGroup modelGroup = (XSModelGroup) term; + if (modelGroup.getCompositor() == XSModelGroup.COMPOSITOR_SEQUENCE) { + XSObjectList particles = modelGroup.getParticles(); + int len = particles.getLength(); + boolean everyThingIsASimpleType = true; + PropertyDefinitionKVList list = new PropertyDefinitionKVList(); + if (len != 0) { + for (int i = 0; i < len; i++) { + XSParticle innerParticle = (XSParticle) particles.item(i); + XSTerm innerTerm = innerParticle.getTerm(); + if (innerTerm instanceof XSElementDeclaration) { + XSElementDeclaration innerElementDeclaration = (XSElementDeclaration) innerTerm; + String name = innerElementDeclaration.getName(); + XSTypeDefinition innerTypeDefinition = innerElementDeclaration.getTypeDefinition(); + if (innerTypeDefinition instanceof XSSimpleType) { + XSSimpleType xsSimpleType = (XSSimpleType) innerTypeDefinition; + String typeNS = xsSimpleType.getNamespace(); + String typeName = xsSimpleType.getName(); + if (typeNS.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI)) { + PropertyDefinitionKV def = new PropertyDefinitionKV(); + def.setKey(name); + // convention at WPD: use "xsd" as prefix for XML Schema Definition + def.setType("xsd:" + typeName); + list.add(def); + } else { + everyThingIsASimpleType = false; + break; + } + } else { + everyThingIsASimpleType = false; + break; + } + } else { + everyThingIsASimpleType = false; + break; + } + } + } + if (everyThingIsASimpleType) { + // everything went allright, we can add a WPD + WinerysPropertiesDefinition wpd = new WinerysPropertiesDefinition(); + wpd.setIsDerivedFromXSD(Boolean.TRUE); + wpd.setElementName(element.getLocalPart()); + wpd.setNamespace(element.getNamespaceURI()); + wpd.setPropertyDefinitionKVList(list); + ModelUtilities.replaceWinerysPropertiesDefinition(ci, wpd); + BackendUtils.logger.debug("Successfully generated WPD"); + } else { + BackendUtils.logger.debug("XSD does not follow the requirements put by winery: Not all types in the sequence are simple types"); + } + } else { + BackendUtils.logger.debug("XSD does not follow the requirements put by winery: Model group is not a sequence"); + } + } else { + BackendUtils.logger.debug("XSD does not follow the requirements put by winery: Not a model group"); + } + } + } else { + BackendUtils.logger.debug("XSD does not follow the requirements put by winery: No Complex Type Definition"); + } + } + } + + /** + * Returns all components available of the given id type + * + * Similar functionality as {@link + * org.eclipse.winery.repository.backend.IGenericRepository. + * getAllTOSCAComponentIds(Class)}, but it crawls through the repository + * + * This method is required as we do not use a database. + * + * @param idClass class of the Ids to search for + * @return empty set if no ids are available + */ + public SortedSet getAllTOSCAElementIds(Class idClass) { + throw new IllegalStateException("Not yet implemented"); + + /* + Implementation idea: + * switch of instance of idClass + * nodetemplate / relationshiptemplate -> fetch all service templates -> crawl through topology -> add all to res + * req/cap do as above, but inspect nodetemplate + * (other special handlings; check spec where each type can be linked from) + */ + } + + /** + * Converts the given collection of TOSCA Component Ids to a collection of + * QNames by using the getQName() method. + * + * This is required for QNameChooser.tag + */ + public static Collection convertTOSCAComponentIdCollectionToQNameCollection(Collection col) { + Collection res = new ArrayList<>(); + for (TOSCAComponentId id : col) { + res.add(id.getQName()); + } + return res; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/IGenericRepository.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/IGenericRepository.java new file mode 100644 index 0000000..9e7ba66 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/IGenericRepository.java @@ -0,0 +1,189 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.backend; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.attribute.FileTime; +import java.util.Collection; +import java.util.Date; +import java.util.SortedSet; + +import javax.ws.rs.core.MediaType; + +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.ids.GenericId; +import org.eclipse.winery.common.ids.Namespace; +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.common.ids.elements.TOSCAElementId; +import org.eclipse.winery.common.interfaces.IWineryRepositoryCommon; + +/** + * Enables access to the winery repository via Ids defined in package + * {@link org.eclipse.winery.common.ids} + * + * In contrast to {@link org.eclipse.winery.repository.backend.IRepository}, + * this is NOT dependent on a particular storage format for the properties. + * These two classes exist to make the need for reengineering explicit. + * + * This is a first attempt to offer methods via GenericId. It might happen, that + * methods, where GenericIds make sense, are simply added to "IWineryRepository" + * instead of being added here. + * + * The ultimate goal is to get rid of this class and to have + * IWineryRepositoryCommon only. + * + * Currently, this class is used internally only + */ +interface IGenericRepository extends IWineryRepositoryCommon { + + /** + * Flags the given TOSCA element as existing. The resources itself create + * appropriate data files. + * + * Pre-Condition: !exists(id)
+ * Post-Condition: exists(id) + * + * Typically, the given TOSCA element is created if a configuration is asked + * for + * + * @param id + * @return + */ + public boolean flagAsExisting(GenericId id); + + /** + * Checks whether the associated TOSA element exists + * + * @param id the id to check + * @return true iff the TOSCA element belonging to the given ID exists + */ + public boolean exists(GenericId id); + + /** + * Deletes the referenced object from the repository + * + * @param ref + */ + public void forceDelete(RepositoryFileReference ref) throws IOException; + + /** + * @param ref reference to check + * @return true if the file associated with the given reference exists + */ + public boolean exists(RepositoryFileReference ref); + + /** + * Puts the given content to the given file. Replaces existing content. + * + * If the parent of the reference does not exist, it is created. + * + * @param ref the reference to the file. Must not be null. + * @param content the content to put into the file. Must not be null. + * @param mediaType the media type of the file. Must not be null. + * + * @throws IOException if something goes wrong + */ + public void putContentToFile(RepositoryFileReference ref, String content, MediaType mediaType) throws IOException; + + /** + * Puts the given content to the given file. Replaces existing content. + * + * If the parent of the reference does not exist, it is created. + * + * @param ref the reference to the file + * @param content the content to put into the file + * @throws IOException if something goes wrong + */ + public void putContentToFile(RepositoryFileReference ref, InputStream inputStream, MediaType mediaType) throws IOException; + + /** + * Creates an opened inputStream of the contents referenced by ref. The + * stream has to be closed by the caller. + * + * @param ref the reference to the file + * @return an inputstream + * @throws IOException if something goes wrong + */ + public InputStream newInputStream(RepositoryFileReference ref) throws IOException; + + /** + * Returns the size of the file referenced by ref + * + * @param ref a refernce to the file stored in the repository + * @return the size in bytes + * @throws IOException if something goes wrong + */ + long getSize(RepositoryFileReference ref) throws IOException; + + /** + * Returns the last modification time of the entry. + * + * @param ref the reference to the file + * @return the time of the last modification + * @throws IOException if something goes wrong + */ + FileTime getLastModifiedTime(RepositoryFileReference ref) throws IOException; + + /** + * Returns the mimetype belonging to the reference. + * + * @param ref the reference to the file + * @return the mimetype as string + * @throws IOException if something goes wrong + * @throws IllegalStateException if an internal error occurs, which is not + * an IOException + */ + String getMimeType(RepositoryFileReference ref) throws IOException; + + /** + * @return the last change date of the file belonging to the given + * reference. NULL if the associated file does not exist. + */ + Date getLastUpdate(RepositoryFileReference ref); + + /** + * Returns all components available of the given id type + * + * @param idClass class of the Ids to search for + * @return empty set if no ids are available + */ + public SortedSet getAllTOSCAComponentIds(Class idClass); + + /** + * Returns the set of all ids nested in the given reference + * + * The generated Ids are linked as child to the id associated to the given + * reference + * + * Required for getting plans nested in a service template: plans are nested + * below the PlansOfOneServiceTemplateId + * + * @param ref a reference to the TOSCA element to be checked. The path + * belonging to this element is checked. + * @param idClass + * @return the set of Ids nested in the given reference. Empty set if there + * are no or the reference itself does not exist. + */ + public SortedSet getNestedIds(GenericId ref, Class idClass); + + /** + * Returns the set of files nested in the given reference + */ + public SortedSet getContainedFiles(GenericId id); + + /** + * Returns all namespaces used by all known TOSCA components + */ + public Collection getUsedNamespaces(); + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/IRepository.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/IRepository.java new file mode 100644 index 0000000..cb9560b --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/IRepository.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.backend; + +import java.util.Date; + +import org.apache.commons.configuration.Configuration; +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.ids.GenericId; + +/** + * Provides interface to the backend. + * + * Currently a file-based backend is implemented. In the future, a git-based or + * a database-based backend is possible. + * + * The properties are managed by org.apache.commons.configuration. In case a new + * backend is added, the appropriate implementation of + * org.apache.commons.configuration.AbstrctConfiguration has to be chosen. + * + */ +public interface IRepository extends IGenericRepository { + + /** + * Returns the configuration of the specified id + * + * If the associated TOSCA element does not exist, an empty configuration is + * returned. That means, the associated TOSCA element is created (SIDE + * EFFECT) + * + * The returned configuration ensures that autoSave is activated + * + * @param id may be a reference to a TOSCAcomponent or to a nested + * TOSCAelement + * @return a Configuration, where isAutoSave == true + */ + Configuration getConfiguration(GenericId id); + + /** + * Enables resources to define additional properties. Currently used for + * tags. + * + * Currently, more a quick hack. A generic TagsManager should be introduced + * to enable auto completion of tag names + * + * If the associated TOSCA element does not exist, an empty configuration is + * returned. That means, the associated TOSCA element is created (SIDE + * EFFECT) + */ + Configuration getConfiguration(RepositoryFileReference ref); + + /** + * + * @return the last change date of the configuration belonging to the given + * id. NULL if the associated TOSCA element does not exist. + */ + Date getConfigurationLastUpdate(GenericId id); + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/IRepositoryAdministration.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/IRepositoryAdministration.java new file mode 100644 index 0000000..a373bdf --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/IRepositoryAdministration.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.backend; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Interface for low-level repository administration + */ +public interface IRepositoryAdministration { + + /** + * Dumps the content of the repository to the given output stream + * + * @param out stream to use to dump the data to. Currently, a ZIP output + * stream is returned. + * @throws IOException + */ + void doDump(OutputStream out) throws IOException; + + /** + * Removes all data + */ + void doClear(); + + /** + * Imports the content of the given stream into the repsotiry. + * + * @param in the stream to use. Currently, only ZIP input is supported. + */ + void doImport(InputStream in); +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/MockXMLElement.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/MockXMLElement.java new file mode 100644 index 0000000..8887cb2 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/MockXMLElement.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.backend; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Class for testing getAny() + * + * It has to be in src/main as src/test is not compiled during production, but + * the jaxbcontext is initialized in src/test and cannot be updated in src/main + * + * Included in {@link oorg.eclipse.winery.repository.JAXBSupport.initContext()} + */ +@XmlRootElement +public class MockXMLElement { + + @XmlElement + public String mock = "mock"; +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/Repository.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/Repository.java new file mode 100644 index 0000000..f333005 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/Repository.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.backend; + +import org.eclipse.winery.repository.Prefs; + +public class Repository { + + public final static IRepository INSTANCE = Prefs.INSTANCE.getRepository(); +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/ResourceCreationResult.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/ResourceCreationResult.java new file mode 100644 index 0000000..2a75eba --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/ResourceCreationResult.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.backend; + +import java.net.URI; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.eclipse.winery.common.ids.GenericId; + +public class ResourceCreationResult { + + private Status status = null; + private URI uri = null; + private GenericId id = null; + + + public ResourceCreationResult() { + } + + public ResourceCreationResult(Status status) { + this.setStatus(status); + } + + public ResourceCreationResult(Status status, URI uri, GenericId id) { + this.setStatus(status); + this.setId(id); + this.setUri(uri); + } + + public Status getStatus() { + return this.status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public URI getUri() { + return this.uri; + } + + public void setUri(URI uri) { + this.uri = uri; + } + + public GenericId getId() { + return this.id; + } + + public void setId(GenericId id) { + this.id = id; + } + + public boolean isSuccess() { + return this.getStatus() == Status.CREATED; + } + + /** + * The possibly existing URI is used as location in Response.created + * + * @return a Response created based on the contained data + */ + public Response getResponse() { + Response res; + if (this.getUri() == null) { + res = Response.status(this.getStatus()).build(); + } else { + assert (this.getStatus().equals(Status.CREATED)); + res = Response.created(this.getUri()).build(); + } + return res; + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/constants/Filename.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/constants/Filename.java new file mode 100644 index 0000000..23dc1b8 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/constants/Filename.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.backend.constants; + +/** + * TODO: check which of them can be removed + */ +public class Filename { + + public static final String FILENAME_BIG_ICON = "bigIcon.png"; + public static final String FILENAME_SMALL_ICON = "smallIcon.png"; + + public static final String FILENAME_JSON_NODETEMPLATES = "nodetemplates.json"; + public static final String FILENAME_JSON_PARENTCACHE = "parents.json"; + public static final String FILENAME_JSON_PLAN = "Plan.json"; + public static final String FILENAME_JSON_RELATIONSHIPTEMPLATE = "realtionshiptemplates.json"; + public static final String FILENAME_JSON_TOPOLOGYTEMPLATE = "TopologyTemplate.json"; + public static final String FILENAME_JSON_OPERATION_WSDL = "wsdl.json"; + public static final String FILENAME_JSON_OPERATION_REST = "rest.json"; + public static final String FILENAME_JSON_OPERATION_SCRIPT = "script.json"; + public static final String FILENAME_XML_PLAN = "Plan.xml"; + public static final String FILENAME_PROPERTIES_ARTIFACT = "artifact.properties"; + public static final String FILENAME_PROPERTIES_ARTIFACTTEMPLATE = "artifacttemplate.properties"; + public static final String FILENAME_PROPERTIES_ARTIFACTTYPE = "artifacttype.properties"; + public static final String FILENAME_PROPERTIES_FILEEXTENSIONTOARTIFACTTYPE = "fileextension-to-artifacttype.properties"; + public static final String FILENAME_PROPERTIES_IMPORTS = "imports.properties"; + public static final String FILENAME_PROPERTIES_NODETYPE = "NodeType.properties"; + public static final String FILENAME_PROPERTIES_OPERATION = "operation.properties"; + public static final String FILENAME_PROPERTIES_PLANCONTAINER = "plancontainer.properties"; + public static final String FILENAME_PROPERTIES_PLANLANGUAGES = "planlanguages.properties"; + public static final String FILENAME_PROPERTIES_PLANTYPES = "plantypes.properties"; + public static final String FILENAME_PROPERTIES_PROPERTIES = "properties.properties"; + public static final String FILENAME_PROPERTIES_RELATIONSHIPTYPE = "RelationshipType.properties"; + public static final String FILENAME_PROPERTIES_SERVICETEMPLATE = "ServiceTemplate.properties"; + public static final String FILENAME_PROPERTIES_TAGS = "tags.properties"; + public static final String FILENAME_PROPERTIES_VISUALAPPEARANCE = "VisualAppearance.properties"; + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/constants/MediaTypes.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/constants/MediaTypes.java new file mode 100644 index 0000000..46fe103 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/constants/MediaTypes.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.backend.constants; + +import javax.ws.rs.core.MediaType; + +import org.eclipse.winery.common.constants.MimeTypes; + +/** + * see also {@link org.eclipse.winery.common.constants.MimeTypes} + */ +public class MediaTypes { + + public static final MediaType MEDIATYPE_TOSCA_DEFINITIONS = MediaType.valueOf(MimeTypes.MIMETYPE_TOSCA_DEFINITIONS); + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/AutoSaveListener.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/AutoSaveListener.java new file mode 100644 index 0000000..ce330a1 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/AutoSaveListener.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.backend.filebased; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration.event.ConfigurationEvent; +import org.apache.commons.configuration.event.ConfigurationListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * We do not count loads and saves as in + * {@link org.apache.commons.configuration.builder.AutoSaveListener}, because + * ConfigurationListener is not aware of such things + */ +class AutoSaveListener implements ConfigurationListener { + + private static final Logger logger = LoggerFactory.getLogger(AutoSaveListener.class); + + private final Path path; + private final PropertiesConfiguration configuration; + + + /** + * + * @param path the file path to write to + * @param configuration the configuration, where the change events come + * from. This is needed as event.getSource() does + * not work + */ + public AutoSaveListener(Path path, PropertiesConfiguration configuration) { + this.path = path; + this.configuration = configuration; + } + + @Override + public void configurationChanged(ConfigurationEvent event) { + if (!event.isBeforeUpdate()) { + try { + if (!Files.exists(this.path.getParent())) { + Files.createDirectories(this.path.getParent()); + } + } catch (IOException ce) { + AutoSaveListener.logger.error("Could not update properties file", ce); + return; + } + try (OutputStream out = Files.newOutputStream(this.path, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) { + OutputStreamWriter writer = new OutputStreamWriter(out); + this.configuration.save(writer); + } catch (ConfigurationException | IOException ce) { + AutoSaveListener.logger.error("Could not update properties file", ce); + } + } + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/FileUtils.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/FileUtils.java new file mode 100644 index 0000000..b970f96 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/FileUtils.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.backend.filebased; + +import static java.nio.file.FileVisitResult.CONTINUE; + +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FileUtils { + + private static final Logger logger = LoggerFactory.getLogger(FileUtils.class); + + + /** + * Deletes given path. If path a file, it is directly deleted. If it is a + * directory, the directory is recursively deleted. + * + * Does not try to change read-only files to read-write files + * + * Only uses Java7's nio, does not fall back to Java6. + * + * @param path the path to delete + * @throws IOException + */ + public static void forceDelete(Path path) throws IOException { + if (Files.isDirectory(path)) { + try { + Files.walkFileTree(path, new SimpleFileVisitor() { + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + try { + Files.delete(file); + } catch (IOException e) { + FileUtils.logger.debug("Could not delete file", e.getMessage()); + } + return CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + if (exc == null) { + try { + Files.delete(dir); + } catch (IOException e) { + FileUtils.logger.debug("Could not delete dir", e); + } + return CONTINUE; + } else { + FileUtils.logger.debug("Could not delete file", exc); + return CONTINUE; + } + } + }); + } catch (IOException e) { + FileUtils.logger.debug("Could not delete dir", e); + } + } else { + try { + Files.delete(path); + } catch (IOException e) { + FileUtils.logger.debug("Could not delete file", e.getMessage()); + } + } + } + + /** + * Creates the given directory including its parent directories, if they do + * not exist. + * + * @param path + * @throws IOException + */ + public static void createDirectory(Path path) throws IOException { + Path parent = path.getParent(); + if (parent == null) { + throw new IOException("No parent found"); + } + if (!Files.exists(parent)) { + FileUtils.createDirectory(parent); + } + if (!Files.exists(path)) { + Files.createDirectory(path); + } + } + + // public static Response readContentFromFile(RepositoryFileReference ref) { + // try { + // Repository.INSTANCE.readContentFromFile(ref); + // } + // } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/FilebasedRepository.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/FilebasedRepository.java new file mode 100644 index 0000000..6964681 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/FilebasedRepository.java @@ -0,0 +1,596 @@ +/******************************************************************************* + * Copyright (c) 2012-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.backend.filebased; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.nio.charset.Charset; +import java.nio.file.DirectoryStream; +import java.nio.file.FileSystem; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileTime; +import java.nio.file.spi.FileSystemProvider; +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +import javax.ws.rs.core.MediaType; + +import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.lang3.SystemUtils; +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.common.ids.GenericId; +import org.eclipse.winery.common.ids.Namespace; +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId; +import org.eclipse.winery.common.ids.definitions.ArtifactTypeId; +import org.eclipse.winery.common.ids.definitions.CapabilityTypeId; +import org.eclipse.winery.common.ids.definitions.NodeTypeId; +import org.eclipse.winery.common.ids.definitions.NodeTypeImplementationId; +import org.eclipse.winery.common.ids.definitions.PolicyTemplateId; +import org.eclipse.winery.common.ids.definitions.PolicyTypeId; +import org.eclipse.winery.common.ids.definitions.RelationshipTypeId; +import org.eclipse.winery.common.ids.definitions.RelationshipTypeImplementationId; +import org.eclipse.winery.common.ids.definitions.RequirementTypeId; +import org.eclipse.winery.common.ids.definitions.ServiceTemplateId; +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.common.ids.elements.TOSCAElementId; +import org.eclipse.winery.repository.Constants; +import org.eclipse.winery.repository.backend.AbstractRepository; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.IRepository; +import org.eclipse.winery.repository.backend.IRepositoryAdministration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * When it comes to a storage of plain files, we use Java 7's nio internally. + * Therefore, we intend to expose the stream types offered by java.nio.Files: + * BufferedReader/BufferedWriter + */ +public class FilebasedRepository extends AbstractRepository implements IRepository, IRepositoryAdministration { + + private static final Logger logger = LoggerFactory.getLogger(FilebasedRepository.class); + + protected final Path repositoryRoot; + + // convenience variables to have a clean code + private final FileSystem fileSystem; + private final FileSystemProvider provider; + + + private Path makeAbsolute(Path relativePath) { + return this.repositoryRoot.resolve(relativePath); + } + + @Override + public boolean flagAsExisting(GenericId id) { + Path path = this.id2AbsolutePath(id); + try { + FileUtils.createDirectory(path); + } catch (IOException e) { + FilebasedRepository.logger.debug(e.toString()); + return false; + } + return true; + } + + private Path id2AbsolutePath(GenericId id) { + Path relativePath = this.fileSystem.getPath(BackendUtils.getPathInsideRepo(id)); + return this.makeAbsolute(relativePath); + } + + /** + * Converts the given reference to an absolute path of the underlying + * FileSystem + */ + public Path ref2AbsolutePath(RepositoryFileReference ref) { + return this.id2AbsolutePath(ref.getParent()).resolve(ref.getFileName()); + } + + /** + * + * @param repositoryLocation a string pointing to a location on the file + * system. May be null. + */ + public FilebasedRepository(String repositoryLocation) { + this.repositoryRoot = this.determineRepositoryPath(repositoryLocation); + this.fileSystem = this.repositoryRoot.getFileSystem(); + this.provider = this.fileSystem.provider(); + } + + private Path determineRepositoryPath(String repositoryLocation) { + Path repositoryPath; + if (repositoryLocation == null) { + if (SystemUtils.IS_OS_WINDOWS) { + if (new File(Constants.GLOBAL_REPO_PATH_WINDOWS).exists()) { + repositoryLocation = Constants.GLOBAL_REPO_PATH_WINDOWS; + File repo = new File(repositoryLocation); + try { + org.apache.commons.io.FileUtils.forceMkdir(repo); + } catch (IOException e) { + FilebasedRepository.logger.error("Could not create repository directory", e); + } + repositoryPath = repo.toPath(); + } else { + repositoryPath = this.createDefaultRepositoryPath(); + } + } else { + repositoryPath = this.createDefaultRepositoryPath(); + } + } else { + File repo = new File(repositoryLocation); + try { + org.apache.commons.io.FileUtils.forceMkdir(repo); + } catch (IOException e) { + FilebasedRepository.logger.error("Could not create repository directory", e); + } + repositoryPath = repo.toPath(); + } + return repositoryPath; + } + + public static File getDefaultRepositoryFilePath() { + return new File(org.apache.commons.io.FileUtils.getUserDirectory(), Constants.DEFAULT_REPO_NAME); + } + + private Path createDefaultRepositoryPath() { + File repo = null; + boolean operationalFileSystemAccess; + try { + repo = FilebasedRepository.getDefaultRepositoryFilePath(); + operationalFileSystemAccess = true; + } catch (NullPointerException e) { + // it seems, we run at a system, where we do not have any filesystem + // access + operationalFileSystemAccess = false; + } + + // operationalFileSystemAccess = false; + + Path repositoryPath; + if (operationalFileSystemAccess) { + try { + org.apache.commons.io.FileUtils.forceMkdir(repo); + } catch (IOException e) { + FilebasedRepository.logger.error("Could not create directory", e); + } + repositoryPath = repo.toPath(); + } else { + assert (!operationalFileSystemAccess); + // we do not have access to the file system + throw new IllegalStateException("No write access to file system"); + } + + return repositoryPath; + } + + @Override + public void forceDelete(RepositoryFileReference ref) throws IOException { + Path relativePath = this.fileSystem.getPath(BackendUtils.getPathInsideRepo(ref)); + Path fileToDelete = this.makeAbsolute(relativePath); + try { + this.provider.delete(fileToDelete); + // Quick hack for deletion of the mime type information + // Alternative: superclass: protected void deleteMimeTypeInformation(RepositoryFileReference ref) throws IOException + // However, this would again call this method, where we would have to check for the extension, too. + // Therefore, we directly delete the information file + Path mimeTypeFile = fileToDelete.getParent().resolve(ref.getFileName() + Constants.SUFFIX_MIMETYPE); + this.provider.delete(mimeTypeFile); + } catch (IOException e) { + if (!(e instanceof NoSuchFileException)) { + // only if file did exist and something else went wrong: complain :) + // (otherwise, silently ignore the error) + FilebasedRepository.logger.debug("Could not delete file", e); + throw e; + } + } + } + + @Override + public void forceDelete(GenericId id) throws IOException { + try { + FileUtils.forceDelete(this.id2AbsolutePath(id)); + } catch (IOException e) { + FilebasedRepository.logger.debug("Could not delete id", id); + throw e; + } + } + + @Override + public boolean exists(GenericId id) { + Path absolutePath = this.id2AbsolutePath(id); + boolean result = Files.exists(absolutePath); + return result; + } + + /** + * {@inheritDoc} + */ + @Override + public void putContentToFile(RepositoryFileReference ref, String content, MediaType mediaType) throws IOException { + if (mediaType == null) { + // quick hack for storing mime type called this method + assert (ref.getFileName().endsWith(Constants.SUFFIX_MIMETYPE)); + // we do not need to store the mime type of the file containing the mime type information + } else { + this.setMimeType(ref, mediaType); + } + Path path = this.ref2AbsolutePath(ref); + FileUtils.createDirectory(path.getParent()); + Files.write(path, content.getBytes()); + } + + /** + * {@inheritDoc} + */ + @Override + public void putContentToFile(RepositoryFileReference ref, InputStream inputStream, MediaType mediaType) throws IOException { + if (mediaType == null) { + // quick hack for storing mime type called this method + assert (ref.getFileName().endsWith(Constants.SUFFIX_MIMETYPE)); + // we do not need to store the mime type of the file containing the mime type information + } else { + this.setMimeType(ref, mediaType); + } + Path targetPath = this.ref2AbsolutePath(ref); + // ensure that parent directory exists + FileUtils.createDirectory(targetPath.getParent()); + + try { + Files.copy(inputStream, targetPath, StandardCopyOption.REPLACE_EXISTING); + } catch (IllegalStateException e) { + FilebasedRepository.logger.debug("Guessing that stream with length 0 is to be written to a file", e); + // copy throws an "java.lang.IllegalStateException: Stream already closed" if the InputStream contains 0 bytes + // For instance, this case happens if SugarCE-6.4.2.zip.removed is tried to be uploaded + // We work around the Java7 issue and create an empty file + if (Files.exists(targetPath)) { + // semantics of putContentToFile: existing content is replaced without notification + Files.delete(targetPath); + } + Files.createFile(targetPath); + } + } + + @Override + public boolean exists(RepositoryFileReference ref) { + return Files.exists(this.ref2AbsolutePath(ref)); + } + + @Override + public SortedSet getAllTOSCAComponentIds(Class idClass) { + SortedSet res = new TreeSet(); + String rootPathFragment = Util.getRootPathFragment(idClass); + Path dir = this.repositoryRoot.resolve(rootPathFragment); + if (!Files.exists(dir)) { + // return empty list if no ids are available + return res; + } + assert (Files.isDirectory(dir)); + + final OnlyNonHiddenDirectories onhdf = new OnlyNonHiddenDirectories(); + + // list all directories contained in this directory + try (DirectoryStream ds = Files.newDirectoryStream(dir, onhdf)) { + for (Path nsP : ds) { + // the current path is the namespace + Namespace ns = new Namespace(nsP.getFileName().toString(), true); + try (DirectoryStream idDS = Files.newDirectoryStream(nsP, onhdf)) { + for (Path idP : idDS) { + XMLId xmlId = new XMLId(idP.getFileName().toString(), true); + Constructor constructor; + try { + constructor = idClass.getConstructor(Namespace.class, XMLId.class); + } catch (Exception e) { + FilebasedRepository.logger.debug("Internal error at determining id constructor", e); + // abort everything, return invalid result + return res; + } + T id; + try { + id = constructor.newInstance(ns, xmlId); + } catch (InstantiationException + | IllegalAccessException + | IllegalArgumentException + | InvocationTargetException e) { + FilebasedRepository.logger.debug("Internal error at invocation of id constructor", e); + // abort everything, return invalid result + return res; + } + res.add(id); + } + } + } + } catch (IOException e) { + FilebasedRepository.logger.debug("Cannot close ds", e); + } + + return res; + } + + @Override + public SortedSet getContainedFiles(GenericId id) { + Path dir = this.id2AbsolutePath(id); + SortedSet res = new TreeSet(); + if (!Files.exists(dir)) { + return res; + } + assert (Files.isDirectory(dir)); + // list all directories contained in this directory + try (DirectoryStream ds = Files.newDirectoryStream(dir, new OnlyNonHiddenFiles())) { + for (Path p : ds) { + RepositoryFileReference ref = new RepositoryFileReference(id, p.getFileName().toString()); + res.add(ref); + } + } catch (IOException e) { + FilebasedRepository.logger.debug("Cannot close ds", e); + } + return res; + } + + @Override + public Configuration getConfiguration(RepositoryFileReference ref) { + Path path = this.ref2AbsolutePath(ref); + + PropertiesConfiguration configuration = new PropertiesConfiguration(); + if (Files.exists(path)) { + try (Reader r = Files.newBufferedReader(path, Charset.defaultCharset())) { + configuration.load(r); + } catch (ConfigurationException | IOException e) { + FilebasedRepository.logger.error("Could not read config file", e); + throw new IllegalStateException("Could not read config file", e); + } + } + + configuration.addConfigurationListener(new AutoSaveListener(path, configuration)); + + // We do NOT implement reloading as the configuration is only accessed + // in JAX-RS resources, which are created on a per-request basis + + return configuration; + } + + /** + * @return null if an error occurred + */ + @Override + public Date getLastUpdate(RepositoryFileReference ref) { + Path path = this.ref2AbsolutePath(ref); + Date res; + if (Files.exists(path)) { + FileTime lastModifiedTime; + try { + lastModifiedTime = Files.getLastModifiedTime(path); + res = new Date(lastModifiedTime.toMillis()); + } catch (IOException e) { + FilebasedRepository.logger.debug(e.getMessage(), e); + res = null; + } + } else { + // this branch is taken if the resource directory exists, but the + // configuration itself does not exist. + // For instance, this happens if icons are manually put for a node + // type, but no color configuration is made. + res = Constants.LASTMODIFIEDDATE_FOR_404; + } + return res; + } + + @Override + public SortedSet getNestedIds(GenericId ref, Class idClass) { + Path dir = this.id2AbsolutePath(ref); + SortedSet res = new TreeSet(); + if (!Files.exists(dir)) { + // the id has been generated by the exporter without existance test. + // This test is done here. + return res; + } + assert (Files.isDirectory(dir)); + // list all directories contained in this directory + try (DirectoryStream ds = Files.newDirectoryStream(dir, new OnlyNonHiddenDirectories())) { + for (Path p : ds) { + XMLId xmlId = new XMLId(p.getFileName().toString(), true); + @SuppressWarnings("unchecked") + Constructor[] constructors = (Constructor[]) idClass.getConstructors(); + assert (constructors.length == 1); + Constructor constructor = constructors[0]; + assert (constructor.getParameterTypes().length == 2); + T id; + try { + id = constructor.newInstance(ref, xmlId); + } catch (InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { + FilebasedRepository.logger.debug("Internal error at invocation of id constructor", e); + // abort everything, return invalid result + return res; + } + res.add(id); + } + } catch (IOException e) { + FilebasedRepository.logger.debug("Cannot close ds", e); + } + return res; + } + + @Override + // below, toscaComponents is an array, which is used in an iterator + // As Java does not allow generic arrays, we have to suppress the warning when fetching an element out of the list + @SuppressWarnings("unchecked") + public Collection getUsedNamespaces() { + // @formatter:off + @SuppressWarnings("rawtypes") + Class[] toscaComponentIds = { + ArtifactTemplateId.class, + ArtifactTypeId.class, + CapabilityTypeId.class, + NodeTypeId.class, + NodeTypeImplementationId.class, + PolicyTemplateId.class, + PolicyTypeId.class, + RelationshipTypeId.class, + RelationshipTypeImplementationId.class, + RequirementTypeId.class, + ServiceTemplateId.class + }; + // @formatter:on + + // we use a HashSet to avoid reporting duplicate namespaces + Collection res = new HashSet(); + + for (Class id : toscaComponentIds) { + String rootPathFragment = Util.getRootPathFragment(id); + Path dir = this.repositoryRoot.resolve(rootPathFragment); + if (!Files.exists(dir)) { + continue; + } + assert (Files.isDirectory(dir)); + + final OnlyNonHiddenDirectories onhdf = new OnlyNonHiddenDirectories(); + + // list all directories contained in this directory + try (DirectoryStream ds = Files.newDirectoryStream(dir, onhdf)) { + for (Path nsP : ds) { + // the current path is the namespace + Namespace ns = new Namespace(nsP.getFileName().toString(), true); + res.add(ns); + } + } catch (IOException e) { + FilebasedRepository.logger.debug("Cannot close ds", e); + } + } + return res; + } + + @Override + public void doDump(OutputStream out) throws IOException { + final ZipOutputStream zout = new ZipOutputStream(out); + final int cutLength = this.repositoryRoot.toString().length() + 1; + + Files.walkFileTree(this.repositoryRoot, new SimpleFileVisitor() { + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { + if (dir.endsWith(".git")) { + return FileVisitResult.SKIP_SUBTREE; + } else { + return FileVisitResult.CONTINUE; + } + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + String name = file.toString().substring(cutLength); + ZipEntry ze = new ZipEntry(name); + try { + ze.setTime(Files.getLastModifiedTime(file).toMillis()); + ze.setSize(Files.size(file)); + zout.putNextEntry(ze); + Files.copy(file, zout); + zout.closeEntry(); + } catch (IOException e) { + FilebasedRepository.logger.debug(e.getMessage()); + } + return FileVisitResult.CONTINUE; + } + }); + zout.close(); + } + + /** + * Removes all files and dirs except the .git directory + */ + @Override + public void doClear() { + try { + DirectoryStream.Filter noGitDirFilter = new DirectoryStream.Filter() { + + @Override + public boolean accept(Path entry) throws IOException { + return !(entry.getFileName().toString().equals(".git")); + } + }; + + DirectoryStream ds = Files.newDirectoryStream(this.repositoryRoot, noGitDirFilter); + for (Path p : ds) { + FileUtils.forceDelete(p); + } + } catch (IOException e) { + FilebasedRepository.logger.error(e.getMessage()); + e.printStackTrace(); + } + } + + @Override + public void doImport(InputStream in) { + ZipInputStream zis = new ZipInputStream(in); + ZipEntry entry; + try { + while ((entry = zis.getNextEntry()) != null) { + if (!entry.isDirectory()) { + Path path = this.repositoryRoot.resolve(entry.getName()); + FileUtils.createDirectory(path.getParent()); + Files.copy(zis, path); + } + } + } catch (IOException e) { + FilebasedRepository.logger.error(e.getMessage()); + } + } + + /** + * {@inheritDoc} + */ + @Override + public long getSize(RepositoryFileReference ref) throws IOException { + return Files.size(this.ref2AbsolutePath(ref)); + } + + /** + * {@inheritDoc} + */ + @Override + public FileTime getLastModifiedTime(RepositoryFileReference ref) throws IOException { + Path path = this.ref2AbsolutePath(ref); + FileTime res = Files.getLastModifiedTime(path); + return res; + } + + /** + * {@inheritDoc} + */ + @Override + public InputStream newInputStream(RepositoryFileReference ref) throws IOException { + Path path = this.ref2AbsolutePath(ref); + InputStream res = Files.newInputStream(path); + return res; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/GitBasedRepository.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/GitBasedRepository.java new file mode 100644 index 0000000..a3f3fc8 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/GitBasedRepository.java @@ -0,0 +1,190 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.backend.filebased; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.eclipse.jgit.api.AddCommand; +import org.eclipse.jgit.api.CleanCommand; +import org.eclipse.jgit.api.CommitCommand; +import org.eclipse.jgit.api.FetchCommand; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.PushCommand; +import org.eclipse.jgit.api.ResetCommand; +import org.eclipse.jgit.api.ResetCommand.ResetType; +import org.eclipse.jgit.api.errors.CheckoutConflictException; +import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.api.errors.NoHeadException; +import org.eclipse.jgit.api.errors.NoMessageException; +import org.eclipse.jgit.api.errors.UnmergedPathsException; +import org.eclipse.jgit.api.errors.WrongRepositoryStateException; +import org.eclipse.jgit.errors.NoWorkTreeException; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.storage.file.FileRepositoryBuilder; +import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; +import org.eclipse.winery.repository.Prefs; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Used for testing only. + * + * Allows to reset repository to a certain commit id + */ +public class GitBasedRepository extends FilebasedRepository { + + private static final Logger logger = LoggerFactory.getLogger(GitBasedRepository.class); + + private final Repository gitRepo; + private final Git git; + private final CredentialsProvider cp; + + public static final String PREFERENCE_GIT_USERNAME = "git.username"; + public static final String PREFERENCE_GIT_PASSWORD = "git.password"; + + + /** + * @param repositoryLocation the location of the repository + * @throws IOException thrown if repository does not exist + */ + public GitBasedRepository(String repositoryLocation) throws IOException { + super(repositoryLocation); + FileRepositoryBuilder builder = new FileRepositoryBuilder(); + this.gitRepo = builder.setWorkTree(this.repositoryRoot.toFile()).setMustExist(true).build(); + this.git = new Git(this.gitRepo); + + this.cp = this.initializeCredentialsProvider(); + } + + /** + * Reads the properties stored in ".winery" in the repository + */ + private Properties dotWineryProperties() { + Properties p = new Properties(); + File f = new File(this.repositoryRoot.toFile(), ".winery"); + InputStream is; + try { + is = new FileInputStream(f); + } catch (FileNotFoundException e1) { + // .winery does not exist in the file-based repository + return p; + } + if (is != null) { + try { + p.load(is); + } catch (IOException e) { + GitBasedRepository.logger.debug(e.getMessage(), e); + } + } + return p; + } + + /** + * Uses git.username und git.password from .winery and winery.properties + * + * Considering .winery is useful if the same war file is used on a dev + * server and a stable server. The WAR file cannot contain the credentials + * if committing is only allowed on only one of these servers + */ + private CredentialsProvider initializeCredentialsProvider() { + CredentialsProvider cp; + + Properties wp = this.dotWineryProperties(); + + String gitUserName = wp.getProperty(GitBasedRepository.PREFERENCE_GIT_USERNAME); + if (gitUserName == null) { + gitUserName = Prefs.INSTANCE.getProperties().getProperty(GitBasedRepository.PREFERENCE_GIT_USERNAME); + } + + String gitPassword = wp.getProperty(GitBasedRepository.PREFERENCE_GIT_PASSWORD); + if (gitPassword == null) { + gitPassword = Prefs.INSTANCE.getProperties().getProperty(GitBasedRepository.PREFERENCE_GIT_PASSWORD); + } + + if (gitUserName == null) { + cp = null; + } else if (gitPassword == null) { + cp = null; + } else { + cp = new UsernamePasswordCredentialsProvider(gitUserName, gitPassword); + } + return cp; + } + + public void addCommitPush() throws NoHeadException, NoMessageException, UnmergedPathsException, ConcurrentRefUpdateException, WrongRepositoryStateException, GitAPIException { + AddCommand add = this.git.add(); + add.addFilepattern("."); + add.call(); + + CommitCommand commit = this.git.commit(); + commit.setMessage("Commit through Winery"); + commit.call(); + + PushCommand push = this.git.push(); + if (this.cp != null) { + push.setCredentialsProvider(this.cp); + } + push.call(); + } + + private void clean() throws NoWorkTreeException, GitAPIException { + GitBasedRepository.logger.trace("git clean"); + // remove untracked files + CleanCommand clean = this.git.clean(); + clean.setCleanDirectories(true); + clean.call(); + } + + public void cleanAndResetHard() throws NoWorkTreeException, GitAPIException { + // enable updating by resetting the content of the repository + this.clean(); + + // fetch the newest thing from upstream + GitBasedRepository.logger.trace("git fetch"); + FetchCommand fetch = this.git.fetch(); + if (this.cp != null) { + fetch.setCredentialsProvider(this.cp); + } + fetch.call(); + + // after fetching, reset to the latest version + GitBasedRepository.logger.trace("git reset --hard"); + ResetCommand reset = this.git.reset(); + reset.setMode(ResetType.HARD); + reset.call(); + } + + public void setRevisionTo(String ref) throws CheckoutConflictException, GitAPIException { + this.clean(); + + // reset repository to the desired reference + ResetCommand reset = this.git.reset(); + reset.setMode(ResetType.HARD); + reset.setRef(ref); + reset.call(); + } + + /** + * Returns true if authentification information (for instance, to push to + * upstream) is available + */ + public boolean authenticationInfoAvailable() { + return this.cp != null; + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/OnlyNonHiddenDirectories.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/OnlyNonHiddenDirectories.java new file mode 100644 index 0000000..a5acd8e --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/OnlyNonHiddenDirectories.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.backend.filebased; + +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; + +public class OnlyNonHiddenDirectories implements DirectoryStream.Filter { + + @Override + public boolean accept(Path entry) throws IOException { + // we return only non-hidden directories + // E.g., DS_Store of Mac OS X is a hidden directory + return Files.isDirectory(entry) && !Files.isHidden(entry); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/OnlyNonHiddenFiles.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/OnlyNonHiddenFiles.java new file mode 100644 index 0000000..3b788b4 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/backend/filebased/OnlyNonHiddenFiles.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.backend.filebased; + +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.eclipse.winery.repository.Constants; + +/** + * Only non-hidden files. Also excludes file names ending with + * Constants.SUFFIX_MIMETYPE + */ +public class OnlyNonHiddenFiles implements DirectoryStream.Filter { + + @Override + public boolean accept(Path entry) throws IOException { + // we return only non-hidden files + // and we do not return the file "FN.mimetype", which are used to store the mimetype of FN + return !Files.isDirectory(entry) && !Files.isHidden(entry) && (!entry.getFileName().toString().endsWith(Constants.SUFFIX_MIMETYPE)); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/FileMeta.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/FileMeta.java new file mode 100644 index 0000000..bf25ae7 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/FileMeta.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.datatypes; + +import java.io.IOException; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.io.FilenameUtils; +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.repository.Constants; +import org.eclipse.winery.repository.Prefs; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.Repository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * based on + * https://github.com/blueimp/jQuery-File-Upload/wiki/Google-App-Engine-Java + * + * The getters are named according to the requirements of the template in + * jquery-file-upload-full.jsp + */ +@XmlRootElement +public class FileMeta { + + private static final Logger logger = LoggerFactory.getLogger(FileMeta.class); + + String name; + long size; + String url; + String deleteUrl; + String deleteType = "DELETE"; + String thumbnailUrl; + + + public String getName() { + return this.name; + } + + public long getSize() { + return this.size; + } + + public String getUrl() { + return this.url; + } + + public String getDeleteUrl() { + return this.deleteUrl; + } + + public String getDeleteType() { + return this.deleteType; + } + + public String getThumbnailUrl() { + return this.thumbnailUrl; + } + + public FileMeta(String filename, long size, String url, String thumbnailUrl) { + this.name = filename; + this.size = size; + this.url = url; + this.thumbnailUrl = thumbnailUrl; + this.deleteUrl = url; + } + + public FileMeta(RepositoryFileReference ref) { + this.name = ref.getFileName(); + try { + this.size = Repository.INSTANCE.getSize(ref); + } catch (IOException e) { + FileMeta.logger.error(e.getMessage(), e); + this.size = 0; + } + this.url = Utils.getAbsoluteURL(ref); + this.deleteUrl = this.url; + this.thumbnailUrl = Prefs.INSTANCE.getResourcePath() + Constants.PATH_MIMETYPEIMAGES + FilenameUtils.getExtension(this.name) + Constants.SUFFIX_MIMETYPEIMAGES; + } + + /** + * @param ref the reference to get information from + * @param URLprefix the string which should be prepended the actual URL. + * Including the "/" + */ + public FileMeta(RepositoryFileReference ref, String URLprefix) { + this(ref); + this.url = URLprefix + this.url; + } + + /** + * The constructor is used for JAX-B only. Therefore, the warning "unused" + * is suppressed + */ + @SuppressWarnings("unused") + private FileMeta() { + } + +} \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/TypeWithShortName.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/TypeWithShortName.java new file mode 100644 index 0000000..eae201d --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/TypeWithShortName.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.datatypes; + +public class TypeWithShortName implements Comparable { + + private final String type; + // we could have used "URI" as type here but this seems to be unnecessary + // overhead + + // this is a kind of ID + private final String shortName; + + + public TypeWithShortName(String type, String shortName) { + this.type = type; + this.shortName = shortName; + } + + public String getType() { + return this.type; + } + + public String getShortName() { + return this.shortName; + } + + @Override + public boolean equals(Object o) { + if (o instanceof TypeWithShortName) { + return ((TypeWithShortName) o).getType().equals(this.getType()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return this.getType().hashCode(); + } + + @Override + public int compareTo(TypeWithShortName o) { + int c = this.getShortName().compareTo(o.getShortName()); + if (c == 0) { + // not sure if this will ever happen + c = this.getType().compareTo(o.getType()); + } + return c; + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/IdNames.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/IdNames.java new file mode 100644 index 0000000..f06c917 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/IdNames.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.datatypes.ids; + +/** + * This class is the brother of {@link org.eclipse.winery.common.id.IdNames} + * + * It includes all id names used additionally in the local ids + */ +public class IdNames { + + // the files belonging to one artifact template are nested in the sub + // directory "files" + public static final String ARTIFACTTEMPLATEDIRECTORY = "files"; + + public static final String CONSTRAINTTYPES = "constrainttypes"; + public static final String NAMESPACES = "namespaces"; + public static final String PLANLANGUAGES = "planlanguages"; + public static final String PLANTYPES = "plantypes"; + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/AdminId.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/AdminId.java new file mode 100644 index 0000000..3a31b05 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/AdminId.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.datatypes.ids.admin; + +import org.eclipse.winery.common.ids.GenericId; +import org.eclipse.winery.common.ids.XMLId; + +/** + * The Id for the single admin resource holding administrative things such as + * the prefixes of namespaces + */ +public abstract class AdminId extends GenericId { + + protected AdminId(XMLId xmlId) { + super(xmlId); + } + + @Override + public int compareTo(GenericId o) { + if (o instanceof AdminId) { + return this.getXmlId().compareTo(o.getXmlId()); + } else { + throw new IllegalStateException(); + } + } + + @Override + public GenericId getParent() { + return null; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof AdminId) { + return this.getXmlId().equals(((AdminId) obj).getXmlId()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return this.getXmlId().hashCode(); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/ConstraintTypesId.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/ConstraintTypesId.java new file mode 100644 index 0000000..210a2c7 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/ConstraintTypesId.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.datatypes.ids.admin; + +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.repository.datatypes.ids.IdNames; + +public class ConstraintTypesId extends TypesId { + + private final static XMLId xmlId = new XMLId(IdNames.CONSTRAINTTYPES, false); + + + public ConstraintTypesId() { + super(ConstraintTypesId.xmlId); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/NamespacesId.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/NamespacesId.java new file mode 100644 index 0000000..4bdb233 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/NamespacesId.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.datatypes.ids.admin; + +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.repository.datatypes.ids.IdNames; + +public class NamespacesId extends AdminId { + + private final static XMLId xmlId = new XMLId(IdNames.NAMESPACES, false); + + + public NamespacesId() { + super(NamespacesId.xmlId); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/PlanLanguagesId.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/PlanLanguagesId.java new file mode 100644 index 0000000..7ebfb7d --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/PlanLanguagesId.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.datatypes.ids.admin; + +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.repository.datatypes.ids.IdNames; + +public class PlanLanguagesId extends TypesId { + + private final static XMLId xmlId = new XMLId(IdNames.PLANLANGUAGES, false); + + + public PlanLanguagesId() { + super(PlanLanguagesId.xmlId); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/PlanTypesId.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/PlanTypesId.java new file mode 100644 index 0000000..e44cd2b --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/PlanTypesId.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.datatypes.ids.admin; + +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.repository.datatypes.ids.IdNames; + +public class PlanTypesId extends TypesId { + + private final static XMLId xmlId = new XMLId(IdNames.PLANTYPES, false); + + + public PlanTypesId() { + super(PlanTypesId.xmlId); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/TypesId.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/TypesId.java new file mode 100644 index 0000000..db40780 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/admin/TypesId.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.datatypes.ids.admin; + +import org.eclipse.winery.common.ids.XMLId; + +public abstract class TypesId extends AdminId { + + protected TypesId(XMLId xmlId) { + super(xmlId); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/elements/ArtifactTemplateDirectoryId.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/elements/ArtifactTemplateDirectoryId.java new file mode 100644 index 0000000..cce2d53 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/elements/ArtifactTemplateDirectoryId.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.datatypes.ids.elements; + +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId; +import org.eclipse.winery.common.ids.elements.TOSCAElementId; +import org.eclipse.winery.repository.datatypes.ids.IdNames; + +public class ArtifactTemplateDirectoryId extends TOSCAElementId { + + private final static XMLId xmlID = new XMLId(IdNames.ARTIFACTTEMPLATEDIRECTORY, false); + + + public ArtifactTemplateDirectoryId(ArtifactTemplateId parent) { + super(parent, ArtifactTemplateDirectoryId.xmlID); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/elements/SelfServiceMetaDataId.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/elements/SelfServiceMetaDataId.java new file mode 100644 index 0000000..6bd5db8 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/elements/SelfServiceMetaDataId.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.datatypes.ids.elements; + +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.common.ids.definitions.ServiceTemplateId; +import org.eclipse.winery.common.ids.elements.TOSCAElementId; + +public class SelfServiceMetaDataId extends TOSCAElementId { + + public SelfServiceMetaDataId(ServiceTemplateId parent) { + super(parent, new XMLId("SELFSERVICE-Metadata", true)); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/elements/VisualAppearanceId.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/elements/VisualAppearanceId.java new file mode 100644 index 0000000..9b7784f --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/ids/elements/VisualAppearanceId.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.datatypes.ids.elements; + +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.common.ids.definitions.TopologyGraphElementEntityTypeId; +import org.eclipse.winery.common.ids.elements.TOSCAElementId; + +/** + * ID for a pseudo-TOSCA-Element holding the data for the visual appearance + * (e.g., icons for node types) + */ +public class VisualAppearanceId extends TOSCAElementId { + + public VisualAppearanceId(TopologyGraphElementEntityTypeId parent) { + super(parent, new XMLId("appearance", true)); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/select2/Select2DataItem.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/select2/Select2DataItem.java new file mode 100644 index 0000000..1b8fb9a --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/select2/Select2DataItem.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.datatypes.select2; + +/** + * Models a data item for select2. In case optgroups have to be returned, use + * this element in a TreeMap + */ +public class Select2DataItem implements Comparable { + + private final String id; + private final String text; + + + public Select2DataItem(String id, String text) { + this.id = id; + this.text = text; + } + + public String getId() { + return this.id; + } + + public String getText() { + return this.text; + } + + /** + * Sort order is based on text + */ + @Override + public int compareTo(Select2DataItem o) { + return this.getText().compareTo(o.getText()); + } + + /** + * Equality is checked at id level + */ + @Override + public boolean equals(Object o) { + if (!(o instanceof Select2DataItem)) { + return false; + } + return this.getId().equals(((Select2DataItem) o).getId()); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/select2/Select2DataWithOptGroups.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/select2/Select2DataWithOptGroups.java new file mode 100644 index 0000000..50e5ecd --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/select2/Select2DataWithOptGroups.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.datatypes.select2; + +import java.util.HashMap; +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; + +public class Select2DataWithOptGroups { + + Map idx = new HashMap<>(); + + + /** + * Add an item to a group + * + * @param group the group + * @param id the id of the item + * @param text the text of the item {@inheritDoc} + */ + public void add(String group, String id, String text) { + Select2OptGroup optGroup = this.idx.get(group); + if (optGroup == null) { + optGroup = new Select2OptGroup(group); + this.idx.put(group, optGroup); + } + + Select2DataItem item = new Select2DataItem(id, text); + optGroup.addItem(item); + } + + public SortedSet asSortedSet() { + // convert the index to the real result + SortedSet res = new TreeSet<>(); + for (Select2OptGroup optGroup : this.idx.values()) { + res.add(optGroup); + } + + return res; + + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/select2/Select2OptGroup.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/select2/Select2OptGroup.java new file mode 100644 index 0000000..7a7a88b --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/select2/Select2OptGroup.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.datatypes.select2; + +import java.util.SortedSet; +import java.util.TreeSet; + +public class Select2OptGroup implements Comparable { + + private final String text; + private final SortedSet children; + + + public Select2OptGroup(String text) { + this.text = text; + this.children = new TreeSet(); + } + + public String getText() { + return this.text; + } + + /** + * Returns the internal SortedSet for data items. + */ + public SortedSet getChildren() { + return this.children; + } + + public void addItem(Select2DataItem item) { + this.children.add(item); + } + + /** + * Quick hack to test Select2OptGroups for equality. Only the text is + * tested, not the contained children. This might cause issues later, but + * currently not. + */ + @Override + public boolean equals(Object o) { + if (!(o instanceof Select2OptGroup)) { + return false; + } + return this.text.equals(((Select2OptGroup) o).text); + } + + /** + * Quick hack to compare Select2OptGroups. Only the text is compared, not + * the contained children. This might cause issues later, but currently not. + */ + @Override + public int compareTo(Select2OptGroup o) { + return this.getText().compareTo(o.getText()); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/select2/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/select2/package-info.java new file mode 100644 index 0000000..ee1fbaf --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/datatypes/select2/package-info.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ + +/** + * This package collects all datatypes required to generate valid select2 data objects + * {@see http://ivaynberg.github.io/select2/}: Example Hierarchical Data + */ +package org.eclipse.winery.repository.datatypes.select2; \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/CSARExporter.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/CSARExporter.java new file mode 100644 index 0000000..ac27478 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/CSARExporter.java @@ -0,0 +1,299 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Kálmán Képes - initial API and implementation and/or initial documentation + * Oliver Kopp - adapted to new storage model and to TOSCA v1.0 + *******************************************************************************/ +package org.eclipse.winery.repository.export; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.bind.JAXBException; +import javax.xml.stream.XMLStreamException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.ArchiveException; +import org.apache.commons.compress.archivers.ArchiveOutputStream; +import org.apache.commons.compress.archivers.ArchiveStreamFactory; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.io.IOUtils; +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.common.constants.MimeTypes; +import org.eclipse.winery.common.ids.definitions.ServiceTemplateId; +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.model.selfservice.Application; +import org.eclipse.winery.model.selfservice.Application.Options; +import org.eclipse.winery.model.selfservice.ApplicationOption; +import org.eclipse.winery.repository.Constants; +import org.eclipse.winery.repository.Prefs; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.datatypes.ids.admin.NamespacesId; +import org.eclipse.winery.repository.datatypes.ids.elements.SelfServiceMetaDataId; +import org.eclipse.winery.repository.resources.admin.NamespacesResource; +import org.eclipse.winery.repository.resources.servicetemplates.selfserviceportal.SelfServicePortalResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; + +/** + * This class exports a CSAR crawling from the the given GenericId
+ * Currently, only ServiceTemplates are supported
+ * commons-compress is used as an output stream should be provided. An + * alternative implementation is to use Java7's Zip File System Provider + */ +public class CSARExporter { + + public static final String PATH_TO_NAMESPACES_PROPERTIES = "winery/Namespaces.properties"; + + private static final Logger logger = LoggerFactory.getLogger(CSARExporter.class); + + private static final String DEFINITONS_PATH_PREFIX = "Definitions/"; + + + /** + * Returns a unique name for the given definitions to be used as filename + */ + private static String getDefinitionsName(TOSCAComponentId id) { + // the prefix is globally unique and the id locally in a namespace + // therefore a concatenation of both is also unique + String res = NamespacesResource.getPrefix(id.getNamespace()) + "__" + id.getXmlId().getEncoded(); + return res; + } + + public static String getDefinitionsFileName(TOSCAComponentId id) { + return CSARExporter.getDefinitionsName(id) + Constants.SUFFIX_TOSCA_DEFINITIONS; + } + + public static String getDefinitionsPathInsideCSAR(TOSCAComponentId id) { + return CSARExporter.DEFINITONS_PATH_PREFIX + CSARExporter.getDefinitionsFileName(id); + } + + /** + * Writes a complete CSAR containing all necessary things reachable from the + * given service template + * + * @param id the id of the service template to export + * @param out the outputstream to write to + * @throws JAXBException + */ + public void writeCSAR(TOSCAComponentId entryId, OutputStream out) throws ArchiveException, IOException, XMLStreamException, JAXBException { + CSARExporter.logger.trace("Starting CSAR export with {}", entryId.toString()); + + Map refMap = new HashMap(); + Collection definitionNames = new ArrayList<>(); + + final ArchiveOutputStream zos = new ArchiveStreamFactory().createArchiveOutputStream("zip", out); + + TOSCAExportUtil exporter = new TOSCAExportUtil(); + Map conf = new HashMap<>(); + + ExportedState exportedState = new ExportedState(); + + TOSCAComponentId currentId = entryId; + do { + String defName = CSARExporter.getDefinitionsPathInsideCSAR(currentId); + definitionNames.add(defName); + + zos.putArchiveEntry(new ZipArchiveEntry(defName)); + Collection referencedIds; + try { + referencedIds = exporter.exportTOSCA(currentId, zos, refMap, conf); + } catch (IllegalStateException e) { + // thrown if something went wrong inside the repo + out.close(); + // we just rethrow as there currently is no error stream. + throw e; + } + zos.closeArchiveEntry(); + + exportedState.flagAsExported(currentId); + exportedState.flagAsExportRequired(referencedIds); + + currentId = exportedState.pop(); + } while (currentId != null); + + // if we export a ServiceTemplate, data for the self-service portal might exist + if (entryId instanceof ServiceTemplateId) { + this.addSelfServiceMetaData((ServiceTemplateId) entryId, refMap); + } + + // now, refMap contains all files to be added to the CSAR + + // write manifest directly after the definitions to have it more at the beginning of the ZIP rather than having it at the very end + this.addManifest(entryId, definitionNames, refMap, zos); + + // used for generated XSD schemas + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer; + try { + transformer = tFactory.newTransformer(); + } catch (TransformerConfigurationException e1) { + CSARExporter.logger.debug(e1.getMessage(), e1); + throw new IllegalStateException("Could not instantiate transformer", e1); + } + + // write all referenced files + for (RepositoryFileReference ref : refMap.keySet()) { + String archivePath = refMap.get(ref); + CSARExporter.logger.trace("Creating {}", archivePath); + ArchiveEntry archiveEntry = new ZipArchiveEntry(archivePath); + zos.putArchiveEntry(archiveEntry); + if (ref instanceof DummyRepositoryFileReferenceForGeneratedXSD) { + CSARExporter.logger.trace("Special treatment for generated XSDs"); + Document document = ((DummyRepositoryFileReferenceForGeneratedXSD) ref).getDocument(); + DOMSource source = new DOMSource(document); + StreamResult result = new StreamResult(zos); + try { + transformer.transform(source, result); + } catch (TransformerException e) { + CSARExporter.logger.debug("Could not serialize generated xsd", e); + } + } else { + try (InputStream is = Repository.INSTANCE.newInputStream(ref)) { + IOUtils.copy(is, zos); + } catch (Exception e) { + CSARExporter.logger.error("Could not copy file content to ZIP outputstream", e); + } + } + zos.closeArchiveEntry(); + } + + this.addNamespacePrefixes(zos); + + zos.finish(); + zos.close(); + } + + /** + * Writes the configured mapping namespaceprefix -> namespace to the archive + * + * This is kind of a quick hack. TODO: during the import, the prefixes + * should be extracted using JAXB and stored in the NamespacesResource + * + * @throws IOException + */ + private void addNamespacePrefixes(ArchiveOutputStream zos) throws IOException { + Configuration configuration = Repository.INSTANCE.getConfiguration(new NamespacesId()); + if (configuration instanceof PropertiesConfiguration) { + // Quick hack: direct serialization only works for PropertiesConfiguration + PropertiesConfiguration pconf = (PropertiesConfiguration) configuration; + ArchiveEntry archiveEntry = new ZipArchiveEntry(CSARExporter.PATH_TO_NAMESPACES_PROPERTIES); + zos.putArchiveEntry(archiveEntry); + try { + pconf.save(zos); + } catch (ConfigurationException e) { + CSARExporter.logger.debug(e.getMessage(), e); + zos.write("#Could not export properties".getBytes()); + zos.write(("#" + e.getMessage()).getBytes()); + } + zos.closeArchiveEntry(); + } + } + + private void addSelfServiceMetaData(ServiceTemplateId entryId, Map refMap) { + SelfServiceMetaDataId id = new SelfServiceMetaDataId(entryId); + if (Repository.INSTANCE.exists(id)) { + SelfServicePortalResource res = new SelfServicePortalResource(entryId); + + refMap.put(res.data_xml_ref, Constants.DIRNAME_SELF_SERVICE_METADATA + "/" + "data.xml"); + + // The schema says that the images have to exist + // However, at a quick modeling, there might be no images + // Therefore, we check for existence + if (Repository.INSTANCE.exists(res.icon_jpg_ref)) { + refMap.put(res.icon_jpg_ref, Constants.DIRNAME_SELF_SERVICE_METADATA + "/" + "icon.jpg"); + } + if (Repository.INSTANCE.exists(res.image_jpg_ref)) { + refMap.put(res.image_jpg_ref, Constants.DIRNAME_SELF_SERVICE_METADATA + "/" + "image.jpg"); + } + + Application application = res.getApplication(); + Options options = application.getOptions(); + if (options != null) { + for (ApplicationOption option : options.getOption()) { + String url = option.getIconUrl(); + if (Util.isRelativeURI(url)) { + RepositoryFileReference ref = new RepositoryFileReference(id, url); + if (Repository.INSTANCE.exists(ref)) { + refMap.put(ref, Constants.DIRNAME_SELF_SERVICE_METADATA + "/" + url); + } else { + CSARExporter.logger.error("Data corrupt: pointing to non-existent file " + ref); + } + } + + url = option.getPlanInputMessageUrl(); + if (Util.isRelativeURI(url)) { + RepositoryFileReference ref = new RepositoryFileReference(id, url); + if (Repository.INSTANCE.exists(ref)) { + refMap.put(ref, Constants.DIRNAME_SELF_SERVICE_METADATA + "/" + url); + } else { + CSARExporter.logger.error("Data corrupt: pointing to non-existent file " + ref); + } + } + } + } + } + } + + private void addManifest(TOSCAComponentId id, Collection definitionNames, Map refMap, ArchiveOutputStream out) throws IOException { + String entryDefinitionsReference = CSARExporter.getDefinitionsPathInsideCSAR(id); + + out.putArchiveEntry(new ZipArchiveEntry("TOSCA-Metadata/TOSCA.meta")); + PrintWriter pw = new PrintWriter(out); + // Setting Versions + pw.println("TOSCA-Meta-Version: 1.0"); + pw.println("CSAR-Version: 1.0"); + String versionString = "Created-By: Winery " + Prefs.INSTANCE.getVersion(); + pw.println(versionString); + // Winery currently is unaware of tDefinitions, therefore, we use the + // name of the service template + pw.println("Entry-Definitions: " + entryDefinitionsReference); + pw.println(); + + assert (definitionNames.contains(entryDefinitionsReference)); + for (String name : definitionNames) { + pw.println("Name: " + name); + pw.println("Content-Type: " + org.eclipse.winery.common.constants.MimeTypes.MIMETYPE_TOSCA_DEFINITIONS); + pw.println(); + } + + // Setting other files, mainly files belonging to artifacts + for (RepositoryFileReference ref : refMap.keySet()) { + String archivePath = refMap.get(ref); + pw.println("Name: " + archivePath); + String mimeType; + if (ref instanceof DummyRepositoryFileReferenceForGeneratedXSD) { + mimeType = MimeTypes.MIMETYPE_XSD; + } else { + mimeType = Repository.INSTANCE.getMimeType(ref); + } + pw.println("Content-Type: " + mimeType); + pw.println(); + } + pw.flush(); + out.closeArchiveEntry(); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/DummyParentForGeneratedXSDRef.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/DummyParentForGeneratedXSDRef.java new file mode 100644 index 0000000..05c7ce1 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/DummyParentForGeneratedXSDRef.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.export; + +import org.eclipse.winery.common.ids.GenericId; +import org.eclipse.winery.common.ids.XMLId; + +public class DummyParentForGeneratedXSDRef extends GenericId { + + protected DummyParentForGeneratedXSDRef() { + super(new XMLId("dummy", false)); + } + + @Override + public int compareTo(GenericId o) { + throw new IllegalStateException("Should never be called."); + } + + @Override + public GenericId getParent() { + throw new IllegalStateException("Should never be called."); + } + + @Override + public boolean equals(Object obj) { + return (obj instanceof DummyParentForGeneratedXSDRef); + } + + @Override + public int hashCode() { + return 0; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/DummyRepositoryFileReferenceForGeneratedXSD.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/DummyRepositoryFileReferenceForGeneratedXSD.java new file mode 100644 index 0000000..ab8386f --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/DummyRepositoryFileReferenceForGeneratedXSD.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.export; + +import org.eclipse.winery.common.RepositoryFileReference; +import org.w3c.dom.Document; + +/** + * Class used to indicate reference to a generated XSD + */ +public class DummyRepositoryFileReferenceForGeneratedXSD extends RepositoryFileReference { + + private final Document document; + + + /** + * @param document the W3C DOM Document holding the generated XSD + */ + public DummyRepositoryFileReferenceForGeneratedXSD(Document document) { + // we have to create a unique filename in the case two different XSDs are exported + // document.hashCode should be unique enough for us + super(new DummyParentForGeneratedXSDRef(), Integer.toString(document.hashCode())); + this.document = document; + } + + public Document getDocument() { + return this.document; + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/ExportedState.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/ExportedState.java new file mode 100644 index 0000000..609d4d6 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/ExportedState.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.export; + +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.HashSet; +import java.util.Queue; + +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; + +/** + * Holds the state of ids regarding the export
+ * + * Required as we do not know at the entry point (usually a service template), + * which other components are linked
+ * + * Users can call flagAsExportRequired more than once for the same id. If an id + * is already exported, it is not flagged as exported again + */ +public class ExportedState { + + private final Collection exported = new HashSet<>(); + private final Queue exportRequired = new ArrayDeque<>(); + + + /** + * @return the first tosca component id to be exported, null if no more + * elements are in the queue + */ + public TOSCAComponentId pop() { + return this.exportRequired.poll(); + } + + public void flagAsExported(TOSCAComponentId id) { + this.exportRequired.remove(id); + this.exported.add(id); + } + + /** + * Flags the given id as required for export, if not already exported + * + * @param id the id to flag + */ + public void flagAsExportRequired(TOSCAComponentId id) { + if (!this.exported.contains(id)) { + this.exportRequired.add(id); + } + } + + public void flagAsExportRequired(Collection ids) { + for (TOSCAComponentId id : ids) { + if ((!this.exported.contains(id)) && (!this.exportRequired.contains(id))) { + this.exportRequired.add(id); + } + } + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/TOSCAExportUtil.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/TOSCAExportUtil.java new file mode 100644 index 0000000..765b07a --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/export/TOSCAExportUtil.java @@ -0,0 +1,802 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Kálmán Képes - initial API and implementation and/or initial documentation + * Oliver Kopp - adapted to new storage model and to TOSCA v1.0 + *******************************************************************************/ +package org.eclipse.winery.repository.export; + +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.SortedSet; + +import javax.xml.XMLConstants; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.namespace.QName; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.common.constants.QNames; +import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId; +import org.eclipse.winery.common.ids.definitions.ArtifactTypeId; +import org.eclipse.winery.common.ids.definitions.CapabilityTypeId; +import org.eclipse.winery.common.ids.definitions.EntityTypeId; +import org.eclipse.winery.common.ids.definitions.NodeTypeId; +import org.eclipse.winery.common.ids.definitions.NodeTypeImplementationId; +import org.eclipse.winery.common.ids.definitions.PolicyTemplateId; +import org.eclipse.winery.common.ids.definitions.PolicyTypeId; +import org.eclipse.winery.common.ids.definitions.RelationshipTypeId; +import org.eclipse.winery.common.ids.definitions.RelationshipTypeImplementationId; +import org.eclipse.winery.common.ids.definitions.RequirementTypeId; +import org.eclipse.winery.common.ids.definitions.ServiceTemplateId; +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.common.ids.definitions.TopologyGraphElementEntityTypeId; +import org.eclipse.winery.common.ids.definitions.imports.GenericImportId; +import org.eclipse.winery.common.ids.elements.PlanId; +import org.eclipse.winery.common.ids.elements.PlansId; +import org.eclipse.winery.common.propertydefinitionkv.WinerysPropertiesDefinition; +import org.eclipse.winery.model.tosca.Definitions; +import org.eclipse.winery.model.tosca.TBoundaryDefinitions; +import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Policies; +import org.eclipse.winery.model.tosca.TCapability; +import org.eclipse.winery.model.tosca.TCapabilityDefinition; +import org.eclipse.winery.model.tosca.TDeploymentArtifact; +import org.eclipse.winery.model.tosca.TDeploymentArtifacts; +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.model.tosca.TEntityType; +import org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition; +import org.eclipse.winery.model.tosca.TImplementationArtifact; +import org.eclipse.winery.model.tosca.TImplementationArtifacts; +import org.eclipse.winery.model.tosca.TImport; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TNodeTemplate.Capabilities; +import org.eclipse.winery.model.tosca.TNodeTemplate.Requirements; +import org.eclipse.winery.model.tosca.TNodeType; +import org.eclipse.winery.model.tosca.TNodeType.CapabilityDefinitions; +import org.eclipse.winery.model.tosca.TNodeType.RequirementDefinitions; +import org.eclipse.winery.model.tosca.TPolicy; +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.model.tosca.TRelationshipType; +import org.eclipse.winery.model.tosca.TRelationshipType.ValidSource; +import org.eclipse.winery.model.tosca.TRelationshipType.ValidTarget; +import org.eclipse.winery.model.tosca.TRequirement; +import org.eclipse.winery.model.tosca.TRequirementDefinition; +import org.eclipse.winery.repository.JAXBSupport; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.backend.constants.Filename; +import org.eclipse.winery.repository.datatypes.ids.elements.ArtifactTemplateDirectoryId; +import org.eclipse.winery.repository.datatypes.ids.elements.VisualAppearanceId; +import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource; +import org.eclipse.winery.repository.resources.AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal; +import org.eclipse.winery.repository.resources.AbstractComponentsResource; +import org.eclipse.winery.repository.resources.EntityTypeResource; +import org.eclipse.winery.repository.resources.entitytemplates.artifacttemplates.ArtifactTemplateResource; +import org.eclipse.winery.repository.resources.entitytemplates.policytemplates.PolicyTemplateResource; +import org.eclipse.winery.repository.resources.entitytypeimplementations.nodetypeimplementations.NodeTypeImplementationResource; +import org.eclipse.winery.repository.resources.entitytypeimplementations.relationshiptypeimplementations.RelationshipTypeImplementationResource; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource; +import org.eclipse.winery.repository.resources.entitytypes.relationshiptypes.RelationshipTypeResource; +import org.eclipse.winery.repository.resources.entitytypes.requirementtypes.RequirementTypeResource; +import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource; +import org.slf4j.ext.XLogger; +import org.slf4j.ext.XLoggerFactory; +import org.w3c.dom.Document; + +public class TOSCAExportUtil { + + private static final XLogger logger = XLoggerFactory.getXLogger(TOSCAExportUtil.class); + + /* + * these two are GLOBAL VARIABLES leading to the fact that this class has to + * be constructed for each export + */ + + // collects the references to be put in the CSAR and the assigned path in + // the CSAR MANIFEST + // this allows to use other paths in the CSAR than on the local storage + private Map referencesToPathInCSARMap = null; + + /** + * Currently a very simple approach to configure the export + */ + private Map exportConfiguration; + + + public enum ExportProperties { + INCLUDEXYCOORDINATES, REPOSITORY_URI + }; + + + /** + * Writes the complete tosca xml into the given outputstream + * + * @param id the id of the TOSCA component instance to export + * @param out outputstream to write to + * @param addRelatedComponents true: all referenced components + * (artifactTemplates, artifactTypes, ...) are added, false: only + * the XML belonging to the id is exported. If XML types are + * generated by Winery (e.g., the properties XSD for node types), + * these XML types are also exported + * @param exportConfiguration the configuration map for the export. Uses + * @param exportedState exportedState object to modify. ExportProperties + * provides the possible keys + * @return a collection of TOSCAcomponentIds referenced by the given + * component + * @throws JAXBException + */ + public Collection exportTOSCA(TOSCAComponentId id, OutputStream out, Map exportConfiguration) throws IOException, JAXBException { + this.exportConfiguration = exportConfiguration; + this.initializeExport(); + return this.writeDefinitionsElement(id, out); + } + + private void initializeExport() { + this.setDefaultExportConfiguration(); + // quick hack to avoid NPE + if (this.referencesToPathInCSARMap == null) { + this.referencesToPathInCSARMap = new HashMap<>(); + } + } + + /** + * Quick hack to set defaults. Typically, a configuration builder or similar + * is used + */ + private void setDefaultExportConfiguration() { + this.checkConfig(ExportProperties.INCLUDEXYCOORDINATES, Boolean.FALSE); + } + + private void checkConfig(ExportProperties propKey, Boolean bo) { + if (!this.exportConfiguration.containsKey(propKey.toString())) { + this.exportConfiguration.put(propKey.toString(), bo); + } + } + + /** + * Writes the complete TOSCA XML into the given outputstream. + * Additionally, a the artifactMap is filled to enable the CSAR exporter to + * create necessary entries in TOSCA-Meta and to add them to the CSAR itself + * + * @param id the component instance to export + * @param out outputstream to write to + * @param exportConfiguration Configures the exporter + * @param referencesToPathInCSARMap collects the references to export. It is + * updated during the export + * @return a collection of TOSCAcomponentIds referenced by the given + * component + * @throws JAXBException + */ + protected Collection exportTOSCA(TOSCAComponentId id, OutputStream out, Map referencesToPathInCSARMap, Map exportConfiguration) throws IOException, JAXBException { + this.referencesToPathInCSARMap = referencesToPathInCSARMap; + return this.exportTOSCA(id, out, exportConfiguration); + } + + /** + * Called when the entry resource is definitions backed + * + * @throws JAXBException + */ + private void writeDefinitionsElement(Definitions entryDefinitions, OutputStream out) throws JAXBException { + Marshaller m = JAXBSupport.createMarshaller(true); + m.marshal(entryDefinitions, out); + } + + /** + * Writes the Definitions belonging to the given TOSCA component to the + * outputstream + * + * @return a collection of TOSCAcomponentIds referenced by the given + * component + * + * @throws IOException + * @throws JAXBException + * @throws IllegalStateException if tcId does not exist + */ + private Collection writeDefinitionsElement(TOSCAComponentId tcId, OutputStream out) throws IOException, JAXBException { + if (!Repository.INSTANCE.exists(tcId)) { + String error = "Component instance " + tcId.toString() + " does not exist."; + TOSCAExportUtil.logger.error(error); + throw new IllegalStateException(error); + } + + AbstractComponentInstanceResource res = AbstractComponentsResource.getComponentInstaceResource(tcId); + Definitions entryDefinitions = res.getDefinitions(); + + // BEGIN: Definitions modification + // the "imports" collection contains the imports of Definitions, not of other definitions + // the other definitions are stored in entryDefinitions.getImport() + // we modify the internal definitions object directly. It is not written back to the storage. Therefore, we do not need to clone it + + // the imports (pointing to not-definitions (xsd, wsdl, ...)) already have a correct relative URL. (quick hack) + URI uri = (URI) this.exportConfiguration.get(TOSCAExportUtil.ExportProperties.REPOSITORY_URI.toString()); + if (uri != null) { + // we are in the plain-XML mode, the URLs of the imports have to be adjusted + for (TImport i : entryDefinitions.getImport()) { + String loc = i.getLocation(); + assert (loc.startsWith("../")); + loc = loc.substring(3); + loc = uri + loc; + // now the location is an absolute URL + i.setLocation(loc); + } + } + + // files of imports have to be added to the CSAR, too + for (TImport i : entryDefinitions.getImport()) { + String loc = i.getLocation(); + if (Util.isRelativeURI(loc)) { + // locally stored, add to CSAR + GenericImportId iid = new GenericImportId(i); + String fileName = Util.getLastURIPart(loc); + fileName = Util.URLdecode(fileName); + RepositoryFileReference ref = new RepositoryFileReference(iid, fileName); + this.putRefAsReferencedItemInCSAR(ref); + } + } + + // adjust imports: add imports of definitions to it + Collection referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds(tcId); + Collection imports = new ArrayList<>(); + for (TOSCAComponentId id : referencedTOSCAComponentIds) { + this.addToImports(id, imports); + } + entryDefinitions.getImport().addAll(imports); + + if (res.getElement() instanceof TEntityType) { + // we have an entity type with a possible properties definition + EntityTypeResource entityTypeRes = (EntityTypeResource) res; + WinerysPropertiesDefinition wpd = ModelUtilities.getWinerysPropertiesDefinition(entityTypeRes.getEntityType()); + if (wpd != null) { + if (wpd.getIsDerivedFromXSD() == null) { + // Write WPD only to file if it exists and is NOT derived from an XSD (which may happen during import) + + String wrapperElementNamespace = wpd.getNamespace(); + String wrapperElementLocalName = wpd.getElementName(); + + // BEGIN: add import and put into CSAR + + TImport imp = new TImport(); + entryDefinitions.getImport().add(imp); + + // fill known import values + imp.setImportType(XMLConstants.W3C_XML_SCHEMA_NS_URI); + imp.setNamespace(wrapperElementNamespace); + // add "winerysPropertiesDefinition" flag to import tag to support + Map otherAttributes = imp.getOtherAttributes(); + otherAttributes.put(QNames.QNAME_WINERYS_PROPERTIES_DEFINITION_ATTRIBUTE, "true"); + + // Determine location + String loc = BackendUtils.getImportLocationForWinerysPropertiesDefinitionXSD((EntityTypeId) tcId, uri, wrapperElementLocalName); + if (uri == null) { + TOSCAExportUtil.logger.trace("CSAR Export mode. Putting XSD into CSAR"); + // CSAR Export mode + // XSD has to be put into the CSAR + Document document = ModelUtilities.getWinerysPropertiesDefinitionXSDAsDocument(wpd); + + // loc in import is URLencoded, loc on filesystem isn't + String locInCSAR = Util.URLdecode(loc); + // furthermore, the path has to start from the root of the CSAR; currently, it starts from Definitions/ + locInCSAR = locInCSAR.substring(3); + TOSCAExportUtil.logger.trace("Location in CSAR: {}", locInCSAR); + this.referencesToPathInCSARMap.put(new DummyRepositoryFileReferenceForGeneratedXSD(document), locInCSAR); + } + imp.setLocation(loc); + + // END: add import and put into CSAR + + // BEGIN: generate TOSCA conforming PropertiesDefinition + + TEntityType entityType = entityTypeRes.getEntityType(); + PropertiesDefinition propertiesDefinition = new PropertiesDefinition(); + propertiesDefinition.setType(new QName(wrapperElementNamespace, wrapperElementLocalName)); + entityType.setPropertiesDefinition(propertiesDefinition); + + // END: generate TOSCA conforming PropertiesDefinition + } else { + // otherwise WPD exists, but is derived from XSD + // we DO NOT have to remove the winery properties definition from the output to allow "debugging" of the CSAR + } + } + } + + // END: Definitions modification + + this.writeDefinitionsElement(entryDefinitions, out); + + return referencedTOSCAComponentIds; + } + + private Collection getReferencedTOSCAComponentIds(EntityTypeId id) { + return this.getReferencedTOSCAComponentIdOfParentForAnAbstractComponentsWithTypeReferenceResource(id); + } + + /** + * There is now equivalent id class for + * AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal, + * therefore we take the super type and hope that the caller knows what he + * does. + */ + private Collection getReferencedTOSCAComponentIdOfParentForAnAbstractComponentsWithTypeReferenceResource(TOSCAComponentId id) { + AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal res = (AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal) AbstractComponentsResource.getComponentInstaceResource(id); + String derivedFrom = res.getInheritanceManagement().getDerivedFrom(); + if (StringUtils.isEmpty(derivedFrom)) { + return Collections.emptySet(); + } else { + // Instantiate an id with the same class as the current id + TOSCAComponentId parentId; + QName qname = QName.valueOf(derivedFrom); + + Constructor constructor; + try { + constructor = id.getClass().getConstructor(QName.class); + } catch (NoSuchMethodException | SecurityException e1) { + throw new IllegalStateException("Could get constructor to instantiate parent id", e1); + } + try { + parentId = constructor.newInstance(qname); + } catch (InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { + throw new IllegalStateException("Could not instantiate id for parent", e); + } + + Collection result = new ArrayList<>(1); + result.add(parentId); + return result; + } + } + + /** + * This method is intended to be used by exportTOSCA. However, + * org.eclipse.winery.repository.client requires an XML representation of a + * component instances without a surrounding definitions element. + * + * We name this method differently to prevent wrong calling due to + * inheritance + * + * @param definitionsElement the parent XML element + */ + private Collection getReferencedTOSCAComponentIds(TOSCAComponentId id) { + Collection referencedTOSCAComponentIds; + + // first of all, handle the concrete elements + if (id instanceof ServiceTemplateId) { + referencedTOSCAComponentIds = this.prepareForExport((ServiceTemplateId) id); + } else if (id instanceof NodeTypeId) { + referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((NodeTypeId) id); + } else if (id instanceof NodeTypeImplementationId) { + referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((NodeTypeImplementationId) id); + } else if (id instanceof RelationshipTypeId) { + referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((RelationshipTypeId) id); + } else if (id instanceof RelationshipTypeImplementationId) { + referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((RelationshipTypeImplementationId) id); + } else if (id instanceof RequirementTypeId) { + referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((RequirementTypeId) id); + } else if (id instanceof CapabilityTypeId) { + referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((CapabilityTypeId) id); + } else if (id instanceof ArtifactTypeId) { + referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((ArtifactTypeId) id); + } else if (id instanceof ArtifactTemplateId) { + referencedTOSCAComponentIds = this.prepareForExport((ArtifactTemplateId) id); + } else if (id instanceof PolicyTypeId) { + referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((PolicyTypeId) id); + } else if (id instanceof PolicyTemplateId) { + referencedTOSCAComponentIds = this.getReferencedTOSCAComponentIds((PolicyTemplateId) id); + } else if (id instanceof GenericImportId) { + // in case of imports, there are no other ids referenced + referencedTOSCAComponentIds = Collections.emptyList(); + } else { + throw new IllegalStateException("Unhandled id class " + id.getClass()); + } + + // Then, handle the super classes, which support inheritance + // Currently, it is EntityType and EntityTypeImplementation only + // Since the latter does not exist in the TOSCA MetaModel, we just handle EntityType here + if (id instanceof EntityTypeId) { + Collection additionalRefs = this.getReferencedTOSCAComponentIds((EntityTypeId) id); + // the original referenceTOSCAComponentIds could be unmodifiable + // we just create a new one... + referencedTOSCAComponentIds = new ArrayList<>(referencedTOSCAComponentIds); + // ...and add the new reference + referencedTOSCAComponentIds.addAll(additionalRefs); + } + + return referencedTOSCAComponentIds; + } + + /** + * Adds the given id as import to the given imports collection + */ + private void addToImports(TOSCAComponentId id, Collection imports) { + TImport imp = new TImport(); + imp.setImportType(org.eclipse.winery.common.constants.Namespaces.TOSCA_NAMESPACE); + imp.setNamespace(id.getNamespace().getDecoded()); + URI uri = (URI) this.exportConfiguration.get(TOSCAExportUtil.ExportProperties.REPOSITORY_URI.toString()); + if (uri == null) { + // self-contained mode + // all Definitions are contained in "Definitions" directory, therefore, we provide the filename only + // references are resolved relatively from a definitions element (COS01, line 425) + String fn = CSARExporter.getDefinitionsFileName(id); + fn = Util.URLencode(fn); + imp.setLocation(fn); + } else { + String path = Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(id)); + path = path + "?definitions"; + URI absoluteURI = uri.resolve(path); + imp.setLocation(absoluteURI.toString()); + } + imports.add(imp); + + // FIXME: Currently the depended elements (such as the artifact templates linked to a node type implementation) are gathered by the corresponding "addXY" method. + // Reason: the corresponding TDefinitions element is *not* updated if a related element is added/removed. + // That means: The imports are not changed. + // The current issue is that TOSCA allows imports of Definitions only and the repository has the concrete elements as main structure + // Although during save the import can be updated (by fetching the associated resource and get the definitions of it), + // The concrete definitions cannot be determined without + // a) having a complete index of all definitions in the repository + // b) crawling through the *complete* repository + // Possibly the current solution, just lazily adding all dependent elements is the better solution. + } + + private Collection getReferencedTOSCAComponentIds(NodeTypeImplementationId id) { + // We have to use a HashSet to ensure that no duplicate ids are added + // There may be multiple DAs/IAs referencing the same type + Collection ids = new HashSet<>(); + + NodeTypeImplementationResource res = new NodeTypeImplementationResource(id); + + // DAs + TDeploymentArtifacts deploymentArtifacts = res.getNTI().getDeploymentArtifacts(); + if (deploymentArtifacts != null) { + for (TDeploymentArtifact da : deploymentArtifacts.getDeploymentArtifact()) { + QName qname; + if ((qname = da.getArtifactRef()) != null) { + ids.add(new ArtifactTemplateId(qname)); + } + ids.add(new ArtifactTypeId(da.getArtifactType())); + } + } + + // IAs + TImplementationArtifacts implementationArtifacts = res.getNTI().getImplementationArtifacts(); + if (implementationArtifacts != null) { + for (TImplementationArtifact ia : implementationArtifacts.getImplementationArtifact()) { + QName qname; + if ((qname = ia.getArtifactRef()) != null) { + ids.add(new ArtifactTemplateId(qname)); + } + ids.add(new ArtifactTypeId(ia.getArtifactType())); + } + } + + // inheritance + ids.addAll(this.getReferencedTOSCAComponentIdOfParentForAnAbstractComponentsWithTypeReferenceResource(id)); + + return ids; + } + + private Collection getReferencedTOSCAComponentIds(RelationshipTypeImplementationId id) { + // We have to use a HashSet to ensure that no duplicate ids are added + // There may be multiple IAs referencing the same type + Collection ids = new HashSet<>(); + + RelationshipTypeImplementationResource res = new RelationshipTypeImplementationResource(id); + + // IAs + for (TImplementationArtifact ia : res.getRTI().getImplementationArtifacts().getImplementationArtifact()) { + QName qname; + if ((qname = ia.getArtifactRef()) != null) { + ids.add(new ArtifactTemplateId(qname)); + } + ids.add(new ArtifactTypeId(ia.getArtifactType())); + } + + // inheritance + ids.addAll(this.getReferencedTOSCAComponentIdOfParentForAnAbstractComponentsWithTypeReferenceResource(id)); + + return ids; + } + + private Collection getReferencedTOSCAComponentIds(RequirementTypeId id) { + Collection ids = new ArrayList<>(1); + + RequirementTypeResource res = new RequirementTypeResource(id); + QName requiredCapabilityType = res.getRequirementType().getRequiredCapabilityType(); + if (requiredCapabilityType != null) { + CapabilityTypeId capId = new CapabilityTypeId(requiredCapabilityType); + ids.add(capId); + } + return ids; + } + + private Collection getReferencedTOSCAComponentIds(CapabilityTypeId id) { + return Collections.emptyList(); + } + + private Collection getReferencedTOSCAComponentIds(PolicyTypeId id) { + return Collections.emptyList(); + } + + private Collection getReferencedTOSCAComponentIds(PolicyTemplateId id) { + Collection ids = new ArrayList<>(); + PolicyTemplateResource res = new PolicyTemplateResource(id); + ids.add(new PolicyTypeId(res.getType())); + return ids; + } + + /** + * Synchronizes the plan model references and returns the referenced TOSCA + * Component Ids. + */ + private Collection prepareForExport(ServiceTemplateId id) { + // We have to use a HashSet to ensure that no duplicate ids are added + // E.g., there may be multiple relationship templates having the same type + Collection ids = new HashSet<>(); + ServiceTemplateResource res = new ServiceTemplateResource(id); + + // ensure that the plans stored locally are the same ones as stored in the definitions + res.synchronizeReferences(); + + // add all plans as reference in the CSAR + // the data model is consistent with the repository + // we crawl through the repository to as putRefAsReferencedItemInCSAR expects a repository file reference + PlansId plansContainerId = new PlansId(id); + SortedSet nestedPlans = Repository.INSTANCE.getNestedIds(plansContainerId, PlanId.class); + for (PlanId planId : nestedPlans) { + SortedSet containedFiles = Repository.INSTANCE.getContainedFiles(planId); + // even if we currently support only one file in the directory, we just add everything + for (RepositoryFileReference ref : containedFiles) { + this.putRefAsReferencedItemInCSAR(ref); + } + } + + // add included things to export queue + + TBoundaryDefinitions boundaryDefs; + if ((boundaryDefs = res.getServiceTemplate().getBoundaryDefinitions()) != null) { + Policies policies = boundaryDefs.getPolicies(); + if (policies != null) { + for (TPolicy policy : policies.getPolicy()) { + PolicyTypeId policyTypeId = new PolicyTypeId(policy.getPolicyType()); + ids.add(policyTypeId); + } + } + + // reqs and caps don't have to be exported here as they are references to existing reqs/caps (of nested node templates) + } + + if (res.getServiceTemplate().getTopologyTemplate() != null) { + for (TEntityTemplate entityTemplate : res.getServiceTemplate().getTopologyTemplate().getNodeTemplateOrRelationshipTemplate()) { + QName qname = entityTemplate.getType(); + if (entityTemplate instanceof TNodeTemplate) { + ids.add(new NodeTypeId(qname)); + TNodeTemplate n = (TNodeTemplate) entityTemplate; + + // crawl through deployment artifacts + TDeploymentArtifacts deploymentArtifacts = n.getDeploymentArtifacts(); + if (deploymentArtifacts != null) { + List das = deploymentArtifacts.getDeploymentArtifact(); + for (TDeploymentArtifact da : das) { + ids.add(new ArtifactTypeId(da.getArtifactType())); + if ((qname = da.getArtifactRef()) != null) { + ids.add(new ArtifactTemplateId(qname)); + } + } + } + + // crawl through reqs/caps + Requirements requirements = n.getRequirements(); + if (requirements != null) { + for (TRequirement req : requirements.getRequirement()) { + QName type = req.getType(); + RequirementTypeId rtId = new RequirementTypeId(type); + ids.add(rtId); + } + } + Capabilities capabilities = n.getCapabilities(); + if (capabilities != null) { + for (TCapability cap : capabilities.getCapability()) { + QName type = cap.getType(); + CapabilityTypeId ctId = new CapabilityTypeId(type); + ids.add(ctId); + } + } + + // crawl through policies + org.eclipse.winery.model.tosca.TNodeTemplate.Policies policies = n.getPolicies(); + if (policies != null) { + for (TPolicy pol : policies.getPolicy()) { + QName type = pol.getPolicyType(); + PolicyTypeId ctId = new PolicyTypeId(type); + ids.add(ctId); + } + } + } else { + assert (entityTemplate instanceof TRelationshipTemplate); + ids.add(new RelationshipTypeId(qname)); + } + } + } + + return ids; + } + + private Collection getReferencedTOSCAComponentIds(ArtifactTypeId id) { + // no recursive crawling needed + return Collections.emptyList(); + } + + /** + * Determines the referenced TOSCA Component Ids and also updates the + * references in the Artifact Template + * + * @return a collection of referenced TOCSA Component Ids + */ + private Collection prepareForExport(ArtifactTemplateId id) { + Collection ids = new ArrayList<>(); + + ArtifactTemplateResource res = new ArtifactTemplateResource(id); + + // "Export" type + QName type = res.getType(); + if (type == null) { + throw new IllegalStateException("Type is null for " + id.toString()); + } + ids.add(new ArtifactTypeId(type)); + + // Export files + + // This method is called BEFORE the concrete definitions element is written. + // Therefore, we adapt the content of the attached files to the really existing files + res.synchronizeReferences(); + + ArtifactTemplateDirectoryId fileDir = new ArtifactTemplateDirectoryId(id); + SortedSet files = Repository.INSTANCE.getContainedFiles(fileDir); + for (RepositoryFileReference ref : files) { + // Even if writing a TOSCA only (!this.writingCSAR), + // we put the virtual path in the TOSCA + // Reason: Winery is mostly used as a service and local storage + // reference to not make sense + // The old implementation had absolutePath.toUri().toString(); + // there, but this does not work when using a cloud blob store. + + this.putRefAsReferencedItemInCSAR(ref); + } + + return ids; + } + + /** + * Puts the given reference as item in the CSAR + * + * Thereby, it uses the global variable referencesToPathInCSARMap + */ + private void putRefAsReferencedItemInCSAR(RepositoryFileReference ref) { + // Determine path + String path = BackendUtils.getPathInsideRepo(ref); + + // put mapping reference to path into global map + // the path is the same as put in "synchronizeReferences" + this.referencesToPathInCSARMap.put(ref, path); + } + + private Collection getReferencedTOSCAComponentIds(RelationshipTypeId id) { + Collection ids = new ArrayList<>(); + + // add all implementations + Collection allTypeImplementations = BackendUtils.getAllElementsRelatedWithATypeAttribute(RelationshipTypeImplementationId.class, id.getQName()); + for (RelationshipTypeImplementationId ntiId : allTypeImplementations) { + ids.add(ntiId); + } + + RelationshipTypeResource res = new RelationshipTypeResource(id); + TRelationshipType relationshipType = (TRelationshipType) res.getElement(); + + ValidSource validSource = relationshipType.getValidSource(); + if (validSource != null) { + QName typeRef = validSource.getTypeRef(); + // can be a node type or a requirement type + + // similar code as for valid target (difference: req/cap) + NodeTypeId ntId = new NodeTypeId(typeRef); + if (Repository.INSTANCE.exists(ntId)) { + ids.add(ntId); + } else { + RequirementTypeId rtId = new RequirementTypeId(typeRef); + ids.add(rtId); + } + } + + ValidTarget validTarget = relationshipType.getValidTarget(); + if (validTarget != null) { + QName typeRef = validTarget.getTypeRef(); + // can be a node type or a capability type + + // similar code as for valid target (difference: req/cap) + NodeTypeId ntId = new NodeTypeId(typeRef); + if (Repository.INSTANCE.exists(ntId)) { + ids.add(ntId); + } else { + CapabilityTypeId capId = new CapabilityTypeId(typeRef); + ids.add(capId); + } + } + + this.addVisualAppearanceToCSAR(id); + + return ids; + } + + private Collection getReferencedTOSCAComponentIds(NodeTypeId id) { + Collection ids = new ArrayList<>(); + Collection allNodeTypeImplementations = BackendUtils.getAllElementsRelatedWithATypeAttribute(NodeTypeImplementationId.class, id.getQName()); + for (NodeTypeImplementationId ntiId : allNodeTypeImplementations) { + ids.add(ntiId); + } + + NodeTypeResource res = new NodeTypeResource(id); + TNodeType nodeType = (TNodeType) res.getElement(); + + // add all referenced requirement types + RequirementDefinitions reqDefsContainer = nodeType.getRequirementDefinitions(); + if (reqDefsContainer != null) { + List reqDefs = reqDefsContainer.getRequirementDefinition(); + for (TRequirementDefinition reqDef : reqDefs) { + RequirementTypeId reqTypeId = new RequirementTypeId(reqDef.getRequirementType()); + ids.add(reqTypeId); + } + } + + // add all referenced capability types + CapabilityDefinitions capDefsContainer = nodeType.getCapabilityDefinitions(); + if (capDefsContainer != null) { + List capDefs = capDefsContainer.getCapabilityDefinition(); + for (TCapabilityDefinition capDef : capDefs) { + CapabilityTypeId capTypeId = new CapabilityTypeId(capDef.getCapabilityType()); + ids.add(capTypeId); + } + } + + this.addVisualAppearanceToCSAR(id); + + return ids; + } + + private void addVisualAppearanceToCSAR(TopologyGraphElementEntityTypeId id) { + VisualAppearanceId visId = new VisualAppearanceId(id); + if (Repository.INSTANCE.exists(visId)) { + // we do NOT check for the id, but simply check for bigIcon.png (only exists in NodeType) and smallIcon.png (exists in NodeType and RelationshipType) + + RepositoryFileReference ref = new RepositoryFileReference(visId, Filename.FILENAME_BIG_ICON); + if (Repository.INSTANCE.exists(ref)) { + this.referencesToPathInCSARMap.put(ref, BackendUtils.getPathInsideRepo(ref)); + } + + ref = new RepositoryFileReference(visId, Filename.FILENAME_SMALL_ICON); + if (Repository.INSTANCE.exists(ref)) { + this.referencesToPathInCSARMap.put(ref, BackendUtils.getPathInsideRepo(ref)); + } + } + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/importing/CSARImporter.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/importing/CSARImporter.java new file mode 100644 index 0000000..26963a9 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/importing/CSARImporter.java @@ -0,0 +1,1158 @@ +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Kálmán Képes - initial API and implementation and/or initial documentation + * Oliver Kopp - adapted to new storage model and to TOSCA v1.0 + *******************************************************************************/ +package org.eclipse.winery.repository.importing; + +import static java.nio.file.FileVisitResult.CONTINUE; +import static java.nio.file.FileVisitResult.SKIP_SUBTREE; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.PathMatcher; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import javax.ws.rs.core.MediaType; +import javax.xml.XMLConstants; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.io.FilenameUtils; +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.common.constants.MimeTypes; +import org.eclipse.winery.common.constants.Namespaces; +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId; +import org.eclipse.winery.common.ids.definitions.EntityTypeId; +import org.eclipse.winery.common.ids.definitions.NodeTypeId; +import org.eclipse.winery.common.ids.definitions.RelationshipTypeId; +import org.eclipse.winery.common.ids.definitions.ServiceTemplateId; +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.common.ids.definitions.imports.GenericImportId; +import org.eclipse.winery.common.ids.definitions.imports.XSDImportId; +import org.eclipse.winery.common.ids.elements.PlanId; +import org.eclipse.winery.common.ids.elements.PlansId; +import org.eclipse.winery.common.propertydefinitionkv.WinerysPropertiesDefinition; +import org.eclipse.winery.model.csar.toscametafile.TOSCAMetaFile; +import org.eclipse.winery.model.csar.toscametafile.TOSCAMetaFileParser; +import org.eclipse.winery.model.tosca.Definitions; +import org.eclipse.winery.model.tosca.TArtifactReference; +import org.eclipse.winery.model.tosca.TArtifactReference.Exclude; +import org.eclipse.winery.model.tosca.TArtifactReference.Include; +import org.eclipse.winery.model.tosca.TArtifactTemplate; +import org.eclipse.winery.model.tosca.TArtifactTemplate.ArtifactReferences; +import org.eclipse.winery.model.tosca.TDefinitions; +import org.eclipse.winery.model.tosca.TDefinitions.Types; +import org.eclipse.winery.model.tosca.TEntityType; +import org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition; +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.model.tosca.TImport; +import org.eclipse.winery.model.tosca.TNodeType; +import org.eclipse.winery.model.tosca.TPlan; +import org.eclipse.winery.model.tosca.TPlan.PlanModelReference; +import org.eclipse.winery.model.tosca.TPlans; +import org.eclipse.winery.model.tosca.TRelationshipType; +import org.eclipse.winery.model.tosca.TServiceTemplate; +import org.eclipse.winery.repository.Constants; +import org.eclipse.winery.repository.JAXBSupport; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.backend.constants.Filename; +import org.eclipse.winery.repository.backend.filebased.FileUtils; +import org.eclipse.winery.repository.datatypes.ids.elements.ArtifactTemplateDirectoryId; +import org.eclipse.winery.repository.datatypes.ids.elements.SelfServiceMetaDataId; +import org.eclipse.winery.repository.datatypes.ids.elements.VisualAppearanceId; +import org.eclipse.winery.repository.export.CSARExporter; +import org.eclipse.winery.repository.resources.admin.NamespacesResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +/** + * Imports a CSAR into the storage. As the internal storage format does not have + * CSARs as the topmost artifacts, but one TDefinition, the CSAR has to be split + * up into several components. + * + * Existing components are not replaced, but silently skipped + * + * Minor errors are logged and not further propagated / notified. That means, a + * user cannot see minor errors. Major errors are immediately thrown. + * + * One instance for each import + */ +public class CSARImporter { + + private static final Logger logger = LoggerFactory.getLogger(CSARImporter.class); + + // ExecutorService for XSD schema initialization + // Threads set to 1 to avoid testing for parallel processing of the same XSD file + private static final ExecutorService xsdParsingService = Executors.newFixedThreadPool(1); + + private static final ExecutorService entityTypeAdjestmentService = Executors.newFixedThreadPool(10); + + + /** + * Reads the CSAR from the given inputstream + * + * @param in the inputstream to read from + * @param errorList the list of errors during the import. Has to be non-null + * @param overwrite if true: contents of the repo are overwritten + * + * @throws InvalidCSARException if the CSAR is invalid + */ + public void readCSAR(InputStream in, List errors, boolean overwrite, final boolean asyncWPDParsing) throws IOException { + // we have to extract the file to a temporary directory as + // the .definitions file does not necessarily have to be the first entry in the archive + Path csarDir = Files.createTempDirectory("winery"); + + try (ZipInputStream zis = new ZipInputStream(in)) { + ZipEntry entry; + while ((entry = zis.getNextEntry()) != null) { + if (!entry.isDirectory()) { + Path targetPath = csarDir.resolve(entry.getName()); + Files.createDirectories(targetPath.getParent()); + Files.copy(zis, targetPath); + } + } + this.importFromDir(csarDir, errors, overwrite, asyncWPDParsing); + } catch (Exception e) { + CSARImporter.logger.debug("Could not import CSAR", e); + throw e; + } finally { + // cleanup: delete all contents of the temporary directory + FileUtils.forceDelete(csarDir); + } + } + + /** + * Import an extracted CSAR from a directory + * + * @param path the root path of an extracted CSAR file + * @param overwrite if true: contents of the repo are overwritten + * @param asyncWPDParsing true if WPD should be parsed asynchronously to + * speed up the import. Required, because JUnit terminates the + * used ExecutorService + * @throws InvalidCSARException + * @throws IOException + */ + void importFromDir(final Path path, final List errors, final boolean overwrite, final boolean asyncWPDParsing) throws IOException { + Path toscaMetaPath = path.resolve("TOSCA-Metadata/TOSCA.meta"); + if (!Files.exists(toscaMetaPath)) { + errors.add("TOSCA.meta does not exist"); + return; + } + final TOSCAMetaFileParser tmfp = new TOSCAMetaFileParser(); + final TOSCAMetaFile tmf = tmfp.parse(toscaMetaPath); + + // we do NOT do any sanity checks, of TOSAC.meta + // and just start parsing + + if (tmf.getEntryDefinitions() != null) { + // we obey the entry definitions and "just" import that + // imported definitions are added recursively + Path defsPath = path.resolve(tmf.getEntryDefinitions()); + this.importDefinitions(tmf, defsPath, errors, overwrite, asyncWPDParsing); + + this.importSelfServiceMetaData(tmf, path, defsPath, errors); + } else { + // no explicit entry definitions found + // we import all available definitions + // The specification says (cos01, Section 16.1, line 2935) that all definitions are contained in the "Definitions" directory + // The alternative is to go through all entries in the TOSCA Meta File, but there is no guarantee that this list is complete + Path definitionsDir = path.resolve("Definitions"); + if (!Files.exists(definitionsDir)) { + errors.add("No entry definitions defined and Definitions directory does not exist."); + return; + } + final List exceptions = new ArrayList(); + Files.walkFileTree(definitionsDir, new SimpleFileVisitor() { + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { + if (dir.endsWith("Definitions")) { + return FileVisitResult.CONTINUE; + } else { + return FileVisitResult.SKIP_SUBTREE; + } + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + try { + CSARImporter.this.importDefinitions(tmf, file, errors, overwrite, asyncWPDParsing); + } catch (IOException e) { + exceptions.add(e); + return FileVisitResult.TERMINATE; + } + return FileVisitResult.CONTINUE; + } + }); + + if (!exceptions.isEmpty()) { + // something went wrong during parsing + // we rethrow the exception + throw exceptions.get(0); + } + } + + this.importNamespacePrefixes(path); + } + + + private static final Pattern GENERATED_PREFIX_PATTERN = Pattern.compile("^ns\\d+$"); + + + /** + * Import namespace prefixes. This is kind of a quick hack. TODO: during the + * import, the prefixes should be extracted using JAXB and stored in the + * NamespacesResource + * + * @param rootPath the root path of the extracted CSAR + */ + private void importNamespacePrefixes(Path rootPath) { + Path properties = rootPath.resolve(CSARExporter.PATH_TO_NAMESPACES_PROPERTIES); + if (Files.exists(properties)) { + PropertiesConfiguration pconf; + try { + pconf = new PropertiesConfiguration(properties.toFile()); + } catch (ConfigurationException e) { + CSARImporter.logger.debug(e.getMessage(), e); + return; + } + Iterator namespaces = pconf.getKeys(); + while (namespaces.hasNext()) { + boolean addToStorage = false; + String namespace = namespaces.next(); + if (NamespacesResource.INSTANCE.getIsPrefixKnownForNamespace(namespace)) { + String storedPrefix = NamespacesResource.getPrefix(namespace); + // QUICK HACK to check whether the prefix is a generated one + // We assume we know the internal generation routine + Matcher m = CSARImporter.GENERATED_PREFIX_PATTERN.matcher(storedPrefix); + if (m.matches()) { + // the stored prefix is a generated one + // replace it by the one stored in the exported properties + addToStorage = true; + } + } else { + addToStorage = true; + } + if (addToStorage) { + String prefix = pconf.getString(namespace); + NamespacesResource.INSTANCE.addNamespace(namespace, prefix); + } + } + } + } + + /** + * Imports a self-service meta data description (if available) + * + * The first service template in the provided entry definitions is taken + * + * @param tmf + * + * @param errors + */ + private void importSelfServiceMetaData(final TOSCAMetaFile tmf, final Path rootPath, Path entryDefinitions, final List errors) { + final Path selfServiceDir = rootPath.resolve(Constants.DIRNAME_SELF_SERVICE_METADATA); + if (!Files.exists(selfServiceDir)) { + CSARImporter.logger.debug("Self-service Portal directory does not exist in CSAR"); + return; + } + if (!Files.exists(entryDefinitions)) { + CSARImporter.logger.debug("Entry definitions does not exist."); + return; + } + + Unmarshaller um = JAXBSupport.createUnmarshaller(); + TDefinitions defs; + try { + defs = (TDefinitions) um.unmarshal(entryDefinitions.toFile()); + } catch (JAXBException e) { + errors.add("Could not unmarshal definitions " + entryDefinitions.getFileName() + " " + e.getMessage()); + return; + } catch (ClassCastException e) { + errors.add("Definitions " + entryDefinitions.getFileName() + " is not a TDefinitions " + e.getMessage()); + return; + } + + final int cutLength = selfServiceDir.toString().length() + 1; + Iterator iterator = defs.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().iterator(); + boolean found = false; + TExtensibleElements next = null; + while (iterator.hasNext() && !found) { + next = iterator.next(); + if (next instanceof TServiceTemplate) { + found = true; + } + } + + if (found) { + TServiceTemplate serviceTemplate = (TServiceTemplate) next; + String namespace = serviceTemplate.getTargetNamespace(); + if (namespace == null) { + namespace = defs.getTargetNamespace(); + } + ServiceTemplateId stId = new ServiceTemplateId(namespace, serviceTemplate.getId(), false); + final SelfServiceMetaDataId id = new SelfServiceMetaDataId(stId); + + // QUICK HACK: We just import all data without any validation + // Reason: the metadata resource can deal with nearly arbitrary formats of the data, therefore we do not do any checking here + + try { + Files.walkFileTree(selfServiceDir, new SimpleFileVisitor() { + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + String name = file.toString().substring(cutLength); + // check: if name contains "/", this could lead to exceptions + RepositoryFileReference ref = new RepositoryFileReference(id, name); + + if (name.equals("data.xml")) { + // we have to check whether the data.xml contains + // (uri:"http://opentosca.org/self-service", local:"application") + // instead of + // (uri:"http://www.eclipse.org/winery/model/selfservice", local:"Application" + // We quickly replace it via String replacement instead of XSLT + try { + String oldContent = org.apache.commons.io.FileUtils.readFileToString(file.toFile(), "UTF-8"); + String newContent = oldContent.replace("http://opentosca.org/self-service", "http://www.eclipse.org/winery/model/selfservice"); + newContent = newContent.replace(":application", ":Application"); + if (!oldContent.equals(newContent)) { + // we replaced something -> write new content to old file + org.apache.commons.io.FileUtils.writeStringToFile(file.toFile(), newContent, "UTF-8"); + } + } catch (IOException e) { + CSARImporter.logger.debug("Could not replace content in data.xml", e); + } + } + CSARImporter.this.importFile(file, ref, tmf, rootPath, errors); + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + CSARImporter.logger.debug(e.getMessage(), e); + errors.add("Self-service Meta Data: " + e.getMessage()); + } + } + + } + + /** + * Recursively imports the given definitions + * + * @param tmf the TOSCAMetaFile object holding the parsed content of a TOSCA + * meta file. If null, no files must be referenced from the given + * definitions + * @param overwrite true: existing contents are overwritten + * @param asyncWPDParsing + * @param definitions the path to the definitions to import + * + * @throws IOException + */ + public void importDefinitions(TOSCAMetaFile tmf, Path defsPath, final List errors, boolean overwrite, boolean asyncWPDParsing) throws IOException { + if (defsPath == null) { + throw new IllegalStateException("path to definitions must not be null"); + } + if (!Files.exists(defsPath)) { + errors.add(String.format("Definitions %1$s does not exist", defsPath.getFileName())); + return; + } + + Unmarshaller um = JAXBSupport.createUnmarshaller(); + TDefinitions defs; + try { + defs = (TDefinitions) um.unmarshal(defsPath.toFile()); + } catch (JAXBException e) { + Throwable cause = e; + String eMsg = ""; + do { + String msg = cause.getMessage(); + if (msg != null) { + eMsg = eMsg + msg + "; "; + } + cause = cause.getCause(); + } while (cause != null); + errors.add("Could not unmarshal definitions " + defsPath.getFileName() + " " + eMsg); + CSARImporter.logger.debug("Unmarshalling error", e); + return; + } catch (ClassCastException e) { + errors.add("Definitions " + defsPath.getFileName() + " is not a TDefinitions " + e.getMessage()); + return; + } + + List imports = defs.getImport(); + this.importImports(defsPath.getParent(), tmf, imports, errors, overwrite, asyncWPDParsing); + // imports has been modified to contain necessary imports only + + // this method adds new imports to defs which may not be imported using "importImports". + // Therefore, "importTypes" has to be called *after* importImports + this.importTypes(defs, errors); + + String defaultNamespace = defs.getTargetNamespace(); + List componentInstanceList = defs.getServiceTemplateOrNodeTypeOrNodeTypeImplementation(); + for (final TExtensibleElements ci : componentInstanceList) { + // Determine namespace + String namespace = this.getNamespace(ci, defaultNamespace); + // Ensure that element has the namespace + this.setNamespace(ci, namespace); + + // Determine id + String id = ModelUtilities.getId(ci); + + // Determine WineryId + Class widClass = org.eclipse.winery.repository.Utils.getComponentIdClassForTExtensibleElements(ci.getClass()); + final TOSCAComponentId wid = BackendUtils.getTOSCAcomponentId(widClass, namespace, id, false); + + if (Repository.INSTANCE.exists(wid)) { + if (overwrite) { + Repository.INSTANCE.forceDelete(wid); + String msg = String.format("Deleted %1$s %2$s to enable replacement", ci.getClass().getName(), wid.getQName().toString()); + CSARImporter.logger.debug(msg); + } else { + String msg = String.format("Skipped %1$s %2$s, because it already exists", ci.getClass().getName(), wid.getQName().toString()); + CSARImporter.logger.debug(msg); + // this is not displayed in the UI as we currently do not distinguish between pre-existing types and types created during the import. + continue; + } + } + + // Create a fresh definitions object without the other data. + final Definitions newDefs = BackendUtils.createWrapperDefinitions(wid); + + // copy over the inputs determined by this.importImports + newDefs.getImport().addAll(imports); + + // add the current TExtensibleElements as the only content to it + newDefs.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().add(ci); + + if (ci instanceof TArtifactTemplate) { + // convention: Definitions are stored in the "Definitions" directory, therefore going to levels up (Definitions dir -> root dir) resolves to the root dir + // COS01, line 2663 states that the path has to be resolved from the *root* of the CSAR + this.adjustArtifactTemplate(defsPath.getParent().getParent(), tmf, (ArtifactTemplateId) wid, (TArtifactTemplate) ci, errors); + } else if (ci instanceof TNodeType) { + this.adjustNodeType(defsPath.getParent().getParent(), (TNodeType) ci, (NodeTypeId) wid, tmf, errors); + } else if (ci instanceof TRelationshipType) { + this.adjustRelationshipType(defsPath.getParent().getParent(), (TRelationshipType) ci, (RelationshipTypeId) wid, tmf, errors); + } else if (ci instanceof TServiceTemplate) { + this.adjustServiceTemplate(defsPath.getParent().getParent(), tmf, (ServiceTemplateId) wid, (TServiceTemplate) ci, errors); + } + + // node types and relationship types are subclasses of TEntityType + // Therefore, we check the entity type separately here + if (ci instanceof TEntityType) { + if (asyncWPDParsing) { + // Adjusting takes a long time + // Therefore, we first save the type as is and convert to Winery-Property-Definitions in the background + CSARImporter.storeDefinitions(wid, newDefs); + CSARImporter.entityTypeAdjestmentService.submit(new Runnable() { + + @Override + public void run() { + CSARImporter.adjustEntityType((TEntityType) ci, (EntityTypeId) wid, newDefs, errors); + CSARImporter.storeDefinitions(wid, newDefs); + } + }); + } else { + CSARImporter.adjustEntityType((TEntityType) ci, (EntityTypeId) wid, newDefs, errors); + CSARImporter.storeDefinitions(wid, newDefs); + } + } else { + CSARImporter.storeDefinitions(wid, newDefs); + } + } + } + + /** + * Imports the specified types into the repository. The types are converted + * to an import statement + * + * @param errors Container for error messages + */ + private void importTypes(TDefinitions defs, final List errors) { + Types typesContainer = defs.getTypes(); + if (typesContainer != null) { + List types = typesContainer.getAny(); + for (Object type : types) { + if (type instanceof Element) { + Element element = (Element) type; + + // generate id part of ImportId out of definitions' id + // we do not use the name as the name has to be URLencoded again and we have issues with the interplay with org.eclipse.winery.common.ids.definitions.imports.GenericImportId.getId(TImport) then. + String id = defs.getId(); + // try to make the id unique by hashing the "content" of the definition + id = id + "-" + Integer.toHexString(element.hashCode()); + + // set importId + TOSCAComponentId importId; + String ns; + if (element.getNamespaceURI().equals(XMLConstants.W3C_XML_SCHEMA_NS_URI)) { + ns = element.getAttribute("targetNamespace"); + importId = new XSDImportId(ns, id, false); + } else { + // Quick hack for non-XML-Schema-definitions + ns = "unknown"; + importId = new GenericImportId(ns, id, false, element.getNamespaceURI()); + } + + // Following code is adapted from importOtherImports + + TDefinitions wrapperDefs = BackendUtils.createWrapperDefinitions(importId); + TImport imp = new TImport(); + String fileName = id + ".xsd"; + imp.setLocation(fileName); + imp.setImportType(XMLConstants.W3C_XML_SCHEMA_NS_URI); + imp.setNamespace(ns); + wrapperDefs.getImport().add(imp); + CSARImporter.storeDefinitions(importId, wrapperDefs); + + // put the file itself to the repo + // ref is required to generate fileRef + RepositoryFileReference ref = BackendUtils.getRefOfDefinitions(importId); + RepositoryFileReference fileRef = new RepositoryFileReference(ref.getParent(), fileName); + // convert element to document + // QUICK HACK. Alternative: Add new method Repository.INSTANCE.getOutputStream and transform DOM node to OuptputStream + String content = Util.getXMLAsString(element); + try { + Repository.INSTANCE.putContentToFile(fileRef, content, MediaType.APPLICATION_XML_TYPE); + } catch (IOException e) { + CSARImporter.logger.debug("Could not put XML Schema definition to file " + fileRef.toString(), e); + errors.add("Could not put XML Schema definition to file " + fileRef.toString()); + } + + // add import to definitions + + // adapt path - similar to importOtherImport + String newLoc = "../" + Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(fileRef)); + imp.setLocation(newLoc); + defs.getImport().add(imp); + } else { + // This is a known type. Otherwise JAX-B would render it as Element + errors.add("There is a Type of class " + type.getClass().toString() + " which is unknown to Winery. The type element is imported as is"); + } + } + } + } + + /** + * All EntityTypes may contain properties definition. In case a winery + * properties definition is found, the TOSCA conforming properties + * definition is removed + * + * @param ci the entity type + * @param wid the Winery id of the entitytype + * @param newDefs the definitions, the entiy type is contained in. The + * imports might be adjusted here + * @param errors + */ + private static void adjustEntityType(TEntityType ci, EntityTypeId wid, Definitions newDefs, final List errors) { + PropertiesDefinition propertiesDefinition = ci.getPropertiesDefinition(); + if (propertiesDefinition != null) { + WinerysPropertiesDefinition winerysPropertiesDefinition = ModelUtilities.getWinerysPropertiesDefinition(ci); + boolean deriveWPD; + if (winerysPropertiesDefinition == null) { + deriveWPD = true; + } else { + if (winerysPropertiesDefinition.getIsDerivedFromXSD() == null) { + // if the winery's properties are defined by Winery itself, + // remove the TOSCA conforming properties definition as a Winery properties definition exists (and which takes precedence) + ci.setPropertiesDefinition(null); + + // no derivation from properties required as the properties are generated by Winery + deriveWPD = false; + + // we have to remove the import, too + // Determine the location + String elementName = winerysPropertiesDefinition.getElementName(); + String loc = BackendUtils.getImportLocationForWinerysPropertiesDefinitionXSD(wid, null, elementName); + // remove the import matching that location + List imports = newDefs.getImport(); + boolean found = false; + if (imports != null) { + Iterator iterator = imports.iterator(); + TImport imp; + while (iterator.hasNext()) { + imp = iterator.next(); + // TODO: add check for QNames.QNAME_WINERYS_PROPERTIES_DEFINITION_ATTRIBUTE instead of import location. The current routine, however, works, too. + if (imp.getLocation().equals(loc)) { + found = true; + break; + } + } + if (found) { + // imp with Winery's k/v location found + iterator.remove(); + // the XSD has been imported in importOtherImport + // it was too difficult to do the location check there, therefore we just remove the XSD from the repository here + XSDImportId importId = new XSDImportId(winerysPropertiesDefinition.getNamespace(), elementName, false); + try { + Repository.INSTANCE.forceDelete(importId); + } catch (IOException e) { + CSARImporter.logger.debug("Could not delete Winery's generated XSD definition", e); + errors.add("Could not delete Winery's generated XSD definition"); + } + } else { + // K/V properties definition was incomplete + } + } + } else { + // winery's properties are derived from an XSD + // The export does NOT add an imports statement: only the wpd exists + // We remove that as + ModelUtilities.removeWinerysPropertiesDefinition(ci); + // derive the WPDs again from the properties definition + deriveWPD = true; + } + } + if (deriveWPD) { + BackendUtils.deriveWPD(ci, errors); + } + } + } + + /** + * In case plans are provided, the plans are imported into Winery's storage + * + * @param rootPath the root path of the extracted csar + * @param tmf the TOSCAMetaFile object used to determine the mime type of + * the plan + * @param wid Winery's internal id of the service template + * @param st the the service template to be imported {@inheritDoc} + * + * @throws InvalidCSARException + */ + private void adjustServiceTemplate(Path rootPath, TOSCAMetaFile tmf, ServiceTemplateId wid, TServiceTemplate st, final List errors) { + TPlans plans = st.getPlans(); + if (plans != null) { + for (TPlan plan : plans.getPlan()) { + PlanModelReference refContainer = plan.getPlanModelReference(); + if (refContainer != null) { + String ref = refContainer.getReference(); + if (ref != null) { + // URLs are stored encoded -> undo the encoding + ref = Util.URLdecode(ref); + URI refURI; + try { + refURI = new URI(ref); + } catch (URISyntaxException e) { + errors.add(String.format("Invalid URI %1$s", ref)); + continue; + } + if (refURI.isAbsolute()) { + // Points to somewhere external + // This is a linked plan + // We have to do nothing + continue; + } + Path path = rootPath.resolve(ref); + if (!Files.exists(path)) { + // possibly, the reference is relative to the Definitions subfolder + // COS01 does not make any explicit statement how to resolve the reference here + path = rootPath.resolve("Definitions").resolve(ref); + if (!Files.exists(path)) { + errors.add(String.format("Plan reference %1$s not found", ref)); + // we quickly remove the reference to reflect the not-found in the data + refContainer.setReference(null); + continue; + } + } + PlansId plansId = new PlansId(wid); + PlanId pid = new PlanId(plansId, new XMLId(plan.getId(), false)); + if (Files.isDirectory(path)) { + errors.add(String.format("Reference %1$s is a directory and Winery currently does not support importing directories", ref)); + continue; + } + RepositoryFileReference fref = new RepositoryFileReference(pid, path.getFileName().toString()); + this.importFile(path, fref, tmf, rootPath, errors); + + // file is imported + // Adjust the reference + refContainer.setReference("../" + Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(fref))); + } + } + } + } + } + + /** + * Adds a color to the given relationship type + */ + private void adjustRelationshipType(Path rootPath, TRelationshipType ci, RelationshipTypeId wid, TOSCAMetaFile tmf, final List errors) { + VisualAppearanceId visId = new VisualAppearanceId(wid); + this.importIcons(rootPath, visId, tmf, errors); + } + + private void adjustNodeType(Path rootPath, TNodeType ci, NodeTypeId wid, TOSCAMetaFile tmf, final List errors) { + VisualAppearanceId visId = new VisualAppearanceId(wid); + this.importIcons(rootPath, visId, tmf, errors); + } + + private void importIcons(Path rootPath, VisualAppearanceId visId, TOSCAMetaFile tmf, final List errors) { + String pathInsideRepo = BackendUtils.getPathInsideRepo(visId); + Path visPath = rootPath.resolve(pathInsideRepo); + this.importIcon(visId, visPath, Filename.FILENAME_BIG_ICON, tmf, rootPath, errors); + } + + private void importIcon(VisualAppearanceId visId, Path visPath, String fileName, TOSCAMetaFile tmf, Path rootPath, final List errors) { + Path file = visPath.resolve(fileName); + if (Files.exists(file)) { + RepositoryFileReference ref = new RepositoryFileReference(visId, fileName); + this.importFile(file, ref, tmf, rootPath, errors); + } + } + + /** + * Adjusts the given artifact template to conform with the repository format + * + * We import the files given at the artifact references + * + * @throws InvalidCSARException + * @throws IOException + */ + private void adjustArtifactTemplate(Path rootPath, TOSCAMetaFile tmf, ArtifactTemplateId atid, TArtifactTemplate ci, final List errors) throws IOException { + ArtifactReferences refs = ci.getArtifactReferences(); + if (refs == null) { + // no references stored - break + return; + } + List refList = refs.getArtifactReference(); + Iterator iterator = refList.iterator(); + while (iterator.hasNext()) { + TArtifactReference ref = iterator.next(); + String reference = ref.getReference(); + // URLs are stored encoded -> undo the encoding + reference = Util.URLdecode(reference); + + URI refURI; + try { + refURI = new URI(reference); + } catch (URISyntaxException e) { + errors.add(String.format("Invalid URI %1$s", ref)); + continue; + } + if (refURI.isAbsolute()) { + // Points to somewhere external + // We have to do nothing + continue; + } + + // we remove the current element as it will be handled during the export + iterator.remove(); + + Path path = rootPath.resolve(reference); + if (!Files.exists(path)) { + errors.add(String.format("Reference %1$s not found", reference)); + return; + } + Set allFiles; + if (Files.isRegularFile(path)) { + allFiles = new HashSet(); + allFiles.add(path); + } else { + assert (Files.isDirectory(path)); + Path localRoot = rootPath.resolve(path); + List includeOrExclude = ref.getIncludeOrExclude(); + + if (includeOrExclude.get(0) instanceof TArtifactReference.Exclude) { + // Implicit semantics of an exclude listed first: + // include all files and then exclude the files matched by the pattern + allFiles = this.getAllFiles(localRoot); + } else { + // semantics if include lited as first: + // same as listed at other places + allFiles = new HashSet<>(); + } + + for (Object object : includeOrExclude) { + if (object instanceof TArtifactReference.Include) { + this.handleInclude((TArtifactReference.Include) object, localRoot, allFiles); + } else { + assert (object instanceof TArtifactReference.Exclude); + this.handleExclude((TArtifactReference.Exclude) object, localRoot, allFiles); + } + } + } + this.importAllFiles(allFiles, atid, tmf, rootPath, errors); + } + + if (refList.isEmpty()) { + // everything is imported and is a file stored locally + // we don't need the references stored locally: they are generated on the fly when exporting + ci.setArtifactReferences(null); + } + } + + /** + * Imports a file from the filesystem to the repository + * + * @param p the file to read from + * @param fref the "file" to put the content to + * @param tmf the TOSCAMetaFile object used to determine the mimetype. Must + * not be null. + * @param rootPath used to relativize p to determine the mime type + * @throws InvalidCSARException + */ + private void importFile(Path p, RepositoryFileReference fref, TOSCAMetaFile tmf, Path rootPath, final List errors) { + if (tmf == null) { + throw new IllegalStateException("tmf must not be null"); + } + try (InputStream is = Files.newInputStream(p); + BufferedInputStream bis = new BufferedInputStream(is)) { + String mediaType = tmf.getMimeType(p.relativize(rootPath).toString()); + if (mediaType == null) { + // Manually find out mime type + try { + mediaType = Utils.getMimeType(bis, p.getFileName().toString()); + } catch (IOException e) { + errors.add(String.format("No MimeType given for %1$s (%2$s)", p.getFileName(), e.getMessage())); + return; + } + if (mediaType == null) { + errors.add(String.format("No MimeType given for %1$s", p.getFileName())); + return; + } + } + try { + Repository.INSTANCE.putContentToFile(fref, bis, MediaType.valueOf(mediaType)); + } catch (IllegalArgumentException | IOException e) { + throw new IllegalStateException(e); + } + } catch (IOException e1) { + throw new IllegalStateException("Could not work on generated temporary files", e1); + } + } + + private void importAllFiles(Collection allFiles, ArtifactTemplateId atid, TOSCAMetaFile tmf, Path rootPath, final List errors) { + // import all files to repository + ArtifactTemplateDirectoryId fileDir = new ArtifactTemplateDirectoryId(atid); + for (Path p : allFiles) { + if (!Files.exists(p)) { + errors.add(String.format("File %1$s does not exist", p.toString())); + return; + } + RepositoryFileReference fref = new RepositoryFileReference(fileDir, p.getFileName().toString()); + this.importFile(p, fref, tmf, rootPath, errors); + } + + } + + /** + * Modifies given allFiles object to exclude all files given by the excl + * pattern + * + * Semantics: Remove all files from the set, which match the given pattern + */ + private void handleExclude(Exclude excl, Path localRoot, Set allFiles) { + PathMatcher pathMatcher = localRoot.getFileSystem().getPathMatcher("glob:" + excl.getPattern()); + Iterator it = allFiles.iterator(); + while (it.hasNext()) { + Path curPath = it.next(); + if (pathMatcher.matches(curPath)) { + it.remove(); + } + } + } + + /** + * Modifies given allFiles object to include all files given by the incl + * pattern + * + * Semantics: Add all files from localRoot to allFiles matching the pattern + */ + private void handleInclude(final Include incl, final Path localRoot, final Set allFiles) { + final PathMatcher pathMatcher = localRoot.getFileSystem().getPathMatcher("glob:" + incl.getPattern()); + try { + Files.walkFileTree(localRoot, new SimpleFileVisitor() { + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Path relFile = localRoot.relativize(file); + if (pathMatcher.matches(relFile)) { + allFiles.add(file); + } + return CONTINUE; + } + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + if (pathMatcher.matches(dir)) { + Set filesToAdd = CSARImporter.this.getAllFiles(dir); + allFiles.addAll(filesToAdd); + return SKIP_SUBTREE; + } else { + return CONTINUE; + } + } + }); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + /** + * Lists all files contained in the given path + */ + private Set getAllFiles(Path startPath) { + final Set res = new HashSet<>(); + try { + Files.walkFileTree(startPath, new SimpleFileVisitor() { + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + res.add(file); + return CONTINUE; + } + }); + } catch (IOException e) { + throw new IllegalStateException(e); + } + return res; + } + + /** + * Sets the namespace on the CI if CI offers the method "setTargetNamespace" + * + * @param ci the component instance to set the namespace + * @param namespace the namespace to set + */ + private void setNamespace(TExtensibleElements ci, String namespace) { + Method method; + try { + method = ci.getClass().getMethod("setTargetNamespace", String.class); + method.invoke(ci, namespace); + } catch (NoSuchMethodException ne) { + // this is OK, because we do not check, whether the method really exists + // Special case for TArtifactTemplate not offering setTargetNamespace + // just ignore it + } catch (Exception e) { + throw new IllegalStateException("Could not set target namespace", e); + } + } + + /** + * @param ci the component instance to get the namespace from + * @param defaultNamespace the namespace to use if the TExtensibleElements + * has no targetNamespace + */ + private String getNamespace(TExtensibleElements ci, String defaultNamespace) { + Method method; + Object res; + try { + method = ci.getClass().getMethod("getTargetNamespace"); + res = method.invoke(ci); + } catch (Exception e) { + // we are at TArtifactTemplate, which does not offer getTargetNamespace + res = null; + } + String ns = (String) res; + if (ns == null) { + ns = defaultNamespace; + } + return ns; + } + + /** + * @param basePath the base path where to resolve files from. This is the + * directory of the Definitions + * @param imports the list of imports to import. SIDE EFFECT: this list is + * modified. After this method has run, the list contains the + * imports to be put into the wrapper element + */ + private void importImports(Path basePath, TOSCAMetaFile tmf, List imports, final List errors, boolean overwrite, final boolean asyncWPDParsing) throws IOException { + for (Iterator iterator = imports.iterator(); iterator.hasNext();) { + TImport imp = iterator.next(); + String importType = imp.getImportType(); + String namespace = imp.getNamespace(); + String loc = imp.getLocation(); + + if (namespace == null) { + errors.add("not namespace-qualified imports are not supported."); + continue; + } + + if (loc == null) { + errors.add("Empty location imports are not supported."); + } else { + if (importType.equals(Namespaces.TOSCA_NAMESPACE)) { + if (!Util.isRelativeURI(loc)) { + errors.add("Absolute URIs for definitions import not supported."); + continue; + } + + // URIs are encoded + loc = Util.URLdecode(loc); + + Path defsPath = basePath.resolve(loc); + // fallback for older CSARs, where the location is given from the root + if (!Files.exists(defsPath)) { + defsPath = basePath.getParent().resolve(loc); + // the real existence check is done in importDefinitions + } + this.importDefinitions(tmf, defsPath, errors, overwrite, asyncWPDParsing); + // imports of definitions don't have to be kept as these are managed by Winery + iterator.remove(); + } else { + this.importOtherImport(basePath, imp, errors, importType, overwrite); + } + } + } + } + + /** + * SIDE EFFECT: modifies the location of imp to point to the correct + * relative location (when read from the exported CSAR) + * + * @param rootPath the absolute path where to resolve files from + */ + private void importOtherImport(Path rootPath, TImport imp, final List errors, String type, boolean overwrite) { + assert (!type.equals(Namespaces.TOSCA_NAMESPACE)); + String loc = imp.getLocation(); + + if (!Util.isRelativeURI(loc)) { + // This is just an information message + errors.add("Absolute URIs are not resolved by Winery (" + loc + ")"); + return; + } + + // location URLs are encoded: http://www.w3.org/TR/2001/WD-charmod-20010126/#sec-URIs, RFC http://www.ietf.org/rfc/rfc2396.txt + loc = Util.URLdecode(loc); + Path path; + try { + path = rootPath.resolve(loc); + } catch (Exception e) { + // java.nio.file.InvalidPathException could be thrown which is a RuntimeException + errors.add(e.getMessage()); + return; + } + if (!Files.exists(path)) { + // fallback for older CSARs, where the location is given from the root + path = rootPath.getParent().resolve(loc); + if (!Files.exists(path)) { + errors.add(String.format("File %1$s does not exist", loc)); + return; + } + } + String namespace = imp.getNamespace(); + String fileName = path.getFileName().toString(); + String id = fileName; + id = FilenameUtils.removeExtension(id); + // Convention: id of import is filename without extension + + GenericImportId rid; + if (type.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI)) { + rid = new XSDImportId(namespace, id, false); + } else { + rid = new GenericImportId(namespace, id, false, type); + } + + boolean importDataExistsInRepo = Repository.INSTANCE.exists(rid); + + if (!importDataExistsInRepo) { + // We have to + // a) create a .definitions file + // b) put the file itself in the repo + + // Create the definitions file + TDefinitions defs = BackendUtils.createWrapperDefinitions(rid); + defs.getImport().add(imp); + // QUICK HACK: We change the imp object's location here and below again + // This is "OK" as "storeDefinitions" serializes the current state and not the future state of the imp object + // change the location to point to the file in the folder of the .definitions file + imp.setLocation(fileName); + + // put the definitions file to the repository + CSARImporter.storeDefinitions(rid, defs); + } + + // put the file itself to the repo + // ref is required to generate fileRef + RepositoryFileReference ref = BackendUtils.getRefOfDefinitions(rid); + RepositoryFileReference fileRef = new RepositoryFileReference(ref.getParent(), fileName); + + // location is relative to Definitions/ + // even if the import already exists, we have to adapt the path + // URIs are encoded + String newLoc = "../" + Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(fileRef)); + imp.setLocation(newLoc); + + if (!importDataExistsInRepo || overwrite) { + // finally write the file to the storage + try (InputStream is = Files.newInputStream(path); + BufferedInputStream bis = new BufferedInputStream(is)) { + MediaType mediaType; + if (type.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI)) { + mediaType = MediaType.valueOf(MimeTypes.MIMETYPE_XSD); + } else { + String mimeType = Utils.getMimeType(bis, path.getFileName().toString()); + mediaType = MediaType.valueOf(mimeType); + } + Repository.INSTANCE.putContentToFile(fileRef, bis, mediaType); + } catch (IllegalArgumentException | IOException e) { + throw new IllegalStateException(e); + } + + // we have to update the cache in case of a new XSD to speedup usage of winery + if (rid instanceof XSDImportId) { + // We do the initialization asynchronously + // We do not check whether the XSD has already been checked + // We cannot just checck whether an XSD already has been handled since the XSD could change over time + // Synchronization at org.eclipse.winery.repository.resources.imports.xsdimports.XSDImportResource.getAllDefinedLocalNames(short) also isn't feasible as the backend doesn't support locks + CSARImporter.xsdParsingService.submit(new Runnable() { + + @Override + public void run() { + CSARImporter.logger.debug("Updating XSD import cache data"); + // We call the queries without storing the result: + // We use the SIDEEFFECT that a cache is created + Utils.getAllXSDElementDefinitionsForTypeAheadSelection(); + Utils.getAllXSDTypeDefinitionsForTypeAheadSelection(); + CSARImporter.logger.debug("Updated XSD import cache data"); + } + }); + } + } + } + + private static void storeDefinitions(TOSCAComponentId id, TDefinitions defs) { + RepositoryFileReference ref = BackendUtils.getRefOfDefinitions(id); + String s = Utils.getXMLAsString(defs, true); + try { + Repository.INSTANCE.putContentToFile(ref, s, MediaType.valueOf(MimeTypes.MIMETYPE_TOSCA_DEFINITIONS)); + } catch (IllegalArgumentException | IOException e) { + throw new IllegalStateException(e); + } + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/json/TTopologyTemplateSerializer.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/json/TTopologyTemplateSerializer.java new file mode 100644 index 0000000..72d2220 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/json/TTopologyTemplateSerializer.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.json; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.model.tosca.TTopologyTemplate; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +public class TTopologyTemplateSerializer extends JsonSerializer { + + /** + * Does NOT wrap the result into an object. Assumes that the current + * position at jgen is in an object + * + * @param value the list of entity templates to serialize + */ + public void serialize(List value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + List relationshipTemplates = new ArrayList(); + + jgen.writeFieldName("nodeTemplates"); + jgen.writeStartObject(); + for (TEntityTemplate template : value) { + if (template instanceof TNodeTemplate) { + // write out as : + jgen.writeFieldName(template.getId()); + provider.defaultSerializeValue(template, jgen); + + } else { + assert (template instanceof TRelationshipTemplate); + relationshipTemplates.add((TRelationshipTemplate) template); + } + } + jgen.writeEndObject(); + + jgen.writeFieldName("relationshipTemplates"); + jgen.writeStartObject(); + for (TRelationshipTemplate template : relationshipTemplates) { + // write out as : + jgen.writeFieldName(template.getId()); + provider.defaultSerializeValue(template, jgen); + } + jgen.writeEndObject(); + } + + @Override + public void serialize(TTopologyTemplate topologyTemplate, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeStartObject(); + + // write out the other fields unmodified + jgen.writeFieldName("documentation"); + provider.defaultSerializeValue(topologyTemplate.getDocumentation(), jgen); + jgen.writeFieldName("any"); + provider.defaultSerializeValue(topologyTemplate.getAny(), jgen); + jgen.writeFieldName("otherAttributes"); + provider.defaultSerializeValue(topologyTemplate.getOtherAttributes(), jgen); + + // finally, write the topology template + this.serialize(topologyTemplate.getNodeTemplateOrRelationshipTemplate(), jgen, provider); + + jgen.writeEndObject(); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/json/TopologyTemplateModule.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/json/TopologyTemplateModule.java new file mode 100644 index 0000000..e5d9950 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/json/TopologyTemplateModule.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.json; + +import org.eclipse.winery.model.tosca.TTopologyTemplate; + +import com.fasterxml.jackson.databind.module.SimpleModule; + +@SuppressWarnings("serial") +public class TopologyTemplateModule extends SimpleModule { + + public TopologyTemplateModule() { + this.addSerializer(TTopologyTemplate.class, new TTopologyTemplateSerializer()); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/API/APIResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/API/APIResource.java new file mode 100644 index 0000000..9393b7e --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/API/APIResource.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * Copyright (c) 2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.API; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.xml.namespace.QName; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.common.ids.definitions.ServiceTemplateId; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.datatypes.select2.Select2DataWithOptGroups; +import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource; + +public class APIResource { + + @GET + @Path("getallartifacttemplatesofcontaineddeploymentartifacts") + @Produces(MediaType.APPLICATION_JSON) + public Response getAllArtifactTemplatesOfContainedDeploymentArtifacts(@QueryParam("servicetemplate") String serviceTemplateQNameString, @QueryParam("nodetemplateid") String nodeTemplateId) { + if (StringUtils.isEmpty(serviceTemplateQNameString)) { + return Response.status(Status.BAD_REQUEST).entity("servicetemplate has be given as query parameter").build(); + } + + QName serviceTemplateQName = QName.valueOf(serviceTemplateQNameString); + + ServiceTemplateId serviceTemplateId = new ServiceTemplateId(serviceTemplateQName); + if (!Repository.INSTANCE.exists(serviceTemplateId)) { + return Response.status(Status.BAD_REQUEST).entity("service template does not exist").build(); + } + ServiceTemplateResource serviceTemplateResource = new ServiceTemplateResource(serviceTemplateId); + + Collection artifactTemplates = new ArrayList<>(); + List allNestedNodeTemplates = BackendUtils.getAllNestedNodeTemplates(serviceTemplateResource.getServiceTemplate()); + for (TNodeTemplate nodeTemplate : allNestedNodeTemplates) { + if (StringUtils.isEmpty(nodeTemplateId) || nodeTemplate.getId().equals(nodeTemplateId)) { + Collection ats = BackendUtils.getArtifactTemplatesOfReferencedDeploymentArtifacts(nodeTemplate); + artifactTemplates.addAll(ats); + } + } + + // convert QName list to select2 data + Select2DataWithOptGroups res = new Select2DataWithOptGroups(); + for (QName qName : artifactTemplates) { + res.add(qName.getNamespaceURI(), qName.toString(), qName.getLocalPart()); + } + return Response.ok().entity(res.asSortedSet()).build(); + } + + /** + * Implementation similar to + * getAllArtifactTemplatesOfContainedDeploymentArtifacts. Only difference is + * "getArtifactTemplatesOfReferencedImplementationArtifacts" instead of + * "getArtifactTemplatesOfReferencedDeploymentArtifacts". + */ + @GET + @Path("getallartifacttemplatesofcontainedimplementationartifacts") + @Produces(MediaType.APPLICATION_JSON) + public Response getAllArtifactTemplatesOfContainedImplementationArtifacts(@QueryParam("servicetemplate") String serviceTemplateQNameString, @QueryParam("nodetemplateid") String nodeTemplateId) { + if (StringUtils.isEmpty(serviceTemplateQNameString)) { + return Response.status(Status.BAD_REQUEST).entity("servicetemplate has be given as query parameter").build(); + } + QName serviceTemplateQName = QName.valueOf(serviceTemplateQNameString); + + ServiceTemplateId serviceTemplateId = new ServiceTemplateId(serviceTemplateQName); + if (!Repository.INSTANCE.exists(serviceTemplateId)) { + return Response.status(Status.BAD_REQUEST).entity("service template does not exist").build(); + } + ServiceTemplateResource serviceTemplateResource = new ServiceTemplateResource(serviceTemplateId); + + Collection artifactTemplates = new ArrayList<>(); + List allNestedNodeTemplates = BackendUtils.getAllNestedNodeTemplates(serviceTemplateResource.getServiceTemplate()); + for (TNodeTemplate nodeTemplate : allNestedNodeTemplates) { + if (StringUtils.isEmpty(nodeTemplateId) || nodeTemplate.getId().equals(nodeTemplateId)) { + Collection ats = BackendUtils.getArtifactTemplatesOfReferencedImplementationArtifacts(nodeTemplate); + artifactTemplates.addAll(ats); + } + } + + // convert QName list to select2 data + Select2DataWithOptGroups res = new Select2DataWithOptGroups(); + for (QName qName : artifactTemplates) { + res.add(qName.getNamespaceURI(), qName.toString(), qName.getLocalPart()); + } + return Response.ok().entity(res.asSortedSet()).build(); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/API/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/API/package-info.java new file mode 100644 index 0000000..6eda321 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/API/package-info.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ + +/** + * This package contains all packages providing extended access to the stored models + * + * The idea is that the resources provide information stored in the respective definition file. + * With this API, the stored data is interpreted more abstractly. As a long-term goal, things + * such as inherticance should be supported here + */ +package org.eclipse.winery.repository.resources.API; \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceResource.java new file mode 100644 index 0000000..d4cc201 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceResource.java @@ -0,0 +1,516 @@ +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.StreamingOutput; +import javax.ws.rs.core.UriInfo; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; + +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.TOSCADocumentBuilderFactory; +import org.eclipse.winery.common.constants.MimeTypes; +import org.eclipse.winery.common.ids.Namespace; +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.model.tosca.Definitions; +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.model.tosca.TImport; +import org.eclipse.winery.repository.JAXBSupport; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.backend.constants.MediaTypes; +import org.eclipse.winery.repository.export.TOSCAExportUtil; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources.documentation.DocumentationsResource; +import org.eclipse.winery.repository.resources.imports.genericimports.GenericImportResource; +import org.eclipse.winery.repository.resources.tags.TagsResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import com.sun.jersey.api.view.Viewable; + +/** + * Resource for a component ( + *
    + *
  • ServiceTemplates,
  • + *
  • EntityTypes,
  • + *
  • EntityTypeImplementations,
  • + *
  • EntityTemplates
  • + *
+ * ). A component is directly nested in a TDefinitions element. See also + * {@link org.eclipse.winery.common.ids.definitions.TOSCAComponentId} + * + * Bundles all operations required for all components. e.g., namespace+XMLid, + * object comparison, import, export, tags + * + * Uses a TDefinitions document as storage. + * + * Additional setters and getters are added if it comes to Winery's extensions + * such as the color of a relationship type + */ +public abstract class AbstractComponentInstanceResource implements Comparable, IPersistable { + + private static final Logger logger = LoggerFactory.getLogger(AbstractComponentInstanceResource.class); + + protected final TOSCAComponentId id; + + private final RepositoryFileReference ref; + + // the object representing the data of this resource + private Definitions definitions = null; + + // shortcut for this.definitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0); + protected TExtensibleElements element = null; + + + /** + * Instantiates the resource. Assumes that the resource should exist + * (assured by the caller) + * + * The caller should not create the resource by other ways. E.g., + * by instantiating this resource and then adding data. + */ + public AbstractComponentInstanceResource(TOSCAComponentId id) { + this.id = id; + + // the resource itself exists + assert (Repository.INSTANCE.exists(id)); + + // the data file might not exist + this.ref = BackendUtils.getRefOfDefinitions(id); + if (Repository.INSTANCE.exists(this.ref)) { + this.load(); + } else { + this.createNew(); + } + } + + /** + * Convenience method for getId().getNamespace() + */ + public final Namespace getNamespace() { + return this.id.getNamespace(); + } + + /** + * Convenience method for getId().getXmlId() + */ + public final XMLId getXmlId() { + return this.id.getXmlId(); + } + + /** + * Convenience method for getId().getQName(); + * + * @return the QName associated with this resource + */ + public final QName getQName() { + return this.getId().getQName(); + } + + /** + * Returns the id associated with this resource + */ + public final TOSCAComponentId getId() { + return this.id; + } + + /** + * called from AbstractComponentResource + */ + @DELETE + public final Response onDelete() { + Response res = BackendUtils.delete(this.id); + return res; + } + + @Override + public final int compareTo(AbstractComponentInstanceResource o) { + return this.id.compareTo(o.id); + } + + @Override + public final boolean equals(Object o) { + if (o instanceof String) { + throw new IllegalStateException(); + } else if (o instanceof AbstractComponentInstanceResource) { + if (o.getClass().equals(this.getClass())) { + // only compare if the two objects are from the same class + return ((AbstractComponentInstanceResource) o).getId().equals(this.getId()); + } else { + throw new IllegalStateException(); + } + } else { + throw new IllegalStateException(); + } + } + + @Override + public final int hashCode() { + return this.getId().hashCode(); + } + + @GET + @Path("id") + public String getTOSCAId() { + return this.id.getXmlId().getDecoded(); + } + + @PUT + @Path("id") + public Response putId(@FormParam("id") String id) { + // this renames the entity type resource + // TODO: implement rename functionality + return Response.serverError().entity("not yet implemented").build(); + } + + /** + * Main page + */ + // @Produces(MediaType.TEXT_HTML) // not true because of ?csar leads to send + // a csar. We nevertheless have to annotate that to be able to get a JSON + // representation required for the file upload (in {@link + // ArtifactTemplateResource}) + // + // we cannot issue a request expecting content-type application/zip as it is + // not possible to offer the result in a "save-as"-dialog: + // http://stackoverflow.com/questions/7464665/ajax-response-content-disposition-attachment + @GET + @Produces(MediaType.TEXT_HTML) + public final Response getHTML(@QueryParam(value = "definitions") String definitions, @QueryParam(value = "csar") String csar, @Context UriInfo uriInfo) { + if (!Repository.INSTANCE.exists(this.id)) { + return Response.status(Status.NOT_FOUND).build(); + } + if (definitions != null) { + return Utils.getDefinitionsOfSelectedResource(this, uriInfo.getBaseUri()); + } else if (csar != null) { + return this.getCSAR(); + } else { + String type = Utils.getTypeForInstance(this.getClass()); + String viewableName = "/jsp/" + Utils.getIntermediateLocationStringForType(type, "/") + "/" + type.toLowerCase() + ".jsp"; + Viewable viewable = new Viewable(viewableName, this); + + return Response.ok().entity(viewable).build(); + + // we can't do the following as the GET request from the browser + // cannot set the accept header properly + // "vary: accept" header has to be set as we may also return a THOR + // on the same URL + // return Response.ok().header(HttpHeaders.VARY, + // HttpHeaders.ACCEPT).entity(viewable).build(); + } + } + + @GET + @Produces(MimeTypes.MIMETYPE_ZIP) + public final Response getCSAR() { + if (!Repository.INSTANCE.exists(this.id)) { + return Response.status(Status.NOT_FOUND).build(); + } + return Utils.getCSARofSelectedResource(this); + } + + /** + * Returns the definitions of this resource. Includes required imports of + * other definitions + * + * @param csar used because plan generator's GET request lands here + */ + @GET + @Produces({MimeTypes.MIMETYPE_TOSCA_DEFINITIONS, MediaType.APPLICATION_XML, MediaType.TEXT_XML}) + public Response getDefinitionsAsResponse(@QueryParam(value = "csar") String csar) { + if (!Repository.INSTANCE.exists(this.id)) { + return Response.status(Status.NOT_FOUND).build(); + } + + if (csar != null) { + return Utils.getCSARofSelectedResource(this); + } + + StreamingOutput so = new StreamingOutput() { + + @Override + public void write(OutputStream output) throws IOException, WebApplicationException { + TOSCAExportUtil exporter = new TOSCAExportUtil(); + // we include everything related + Map conf = new HashMap<>(); + try { + exporter.exportTOSCA(AbstractComponentInstanceResource.this.id, output, conf); + } catch (JAXBException e) { + throw new WebApplicationException(e); + } + } + }; + return Response.ok().type(MediaType.TEXT_XML).entity(so).build(); + } + + /** + * @throws IllegalStateException if an IOException occurred. We opted not to + * propagate the IOException directly as this exception occurs + * seldom and is a not an exception to be treated by all callers + * in the prototype. + */ + private void load() { + try { + InputStream is = Repository.INSTANCE.newInputStream(this.ref); + Unmarshaller u = JAXBSupport.createUnmarshaller(); + this.definitions = (Definitions) u.unmarshal(is); + } catch (Exception e) { + AbstractComponentInstanceResource.logger.error("Could not read content from file " + this.ref, e); + throw new IllegalStateException(e); + } + try { + this.element = this.definitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0); + } catch (IndexOutOfBoundsException e) { + if (this instanceof GenericImportResource) { + // everything allright: + // ImportResource is a quick hack using 99% of the functionality offered here + // As only 1% has to be "quick hacked", we do that instead of a clean design + // Clean design: Introduce a class between this and AbstractComponentInstanceResource, where this class and ImportResource inhertis from + // A clean design introducing a super class AbstractDefinitionsBackedResource does not work, as we currently also support PropertiesBackedResources and such a super class would required multi-inheritance + } else { + throw new IllegalStateException("Wrong storage format: No ServiceTemplateOrNodeTypeOrNodeTypeImplementation found."); + } + } + } + + @Override + public void persist() throws IOException { + BackendUtils.persist(this.definitions, this.ref, MediaTypes.MEDIATYPE_TOSCA_DEFINITIONS); + } + + /** + * Creates a new instance of the object represented by this resource + */ + private void createNew() { + this.definitions = BackendUtils.createWrapperDefinitions(this.getId()); + + // create empty element + this.element = this.createNewElement(); + + // add the element to the definitions + this.definitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().add(this.element); + + // copy ns + id + this.copyIdToFields(); + + // ensure that the definitions is persisted. Ensures that export works. + BackendUtils.persist(this); + } + + /** + * Creates an empty instance of an Element. + * + * The implementors do nothave to copy the ns and the id to the + * appropriate fields. + * + * we have two implementation possibilities: + *
    + *
  • a) each subclass implements this method and returns the appropriate + * object
  • + *
  • b) we use java reflection to invoke the right constructor as done in + * the resources
  • + *
+ * We opted for a) to increase readability of the code + */ + protected abstract TExtensibleElements createNewElement(); + + /** + * Copies the current id of the resource to the appropriate fields in the + * element. + * + * For instance, the id is put in the "name" field for EntityTypes + * + * We opted for a separate method from createNewElement to enable renaming + * of the object + */ + protected abstract void copyIdToFields(); + + /** + * Returns the Element belonging to this resource. As Java does not allow + * overriding returned classes, we expect the caller to either cast right or + * to use "getXY" defined by each subclass, where XY is the concrete type + * + * Shortcut for + * getDefinitions().getServiceTemplateOrNodeTypeOrNodeTypeImplementation + * ().get(0); + * + * @return TCapabilityType|... + */ + public TExtensibleElements getElement() { + return this.element; + } + + /** + * @return the reference to the internal list of imports. Can be changed if + * some imports are required or should be removed + * @throws IllegalStateException if definitions was not loaded or not + * initialized + */ + protected List getImport() { + if (this.definitions == null) { + throw new IllegalStateException("Trying to access uninitalized definitions object"); + } + return this.definitions.getImport(); + } + + /** + * Returns an XML representation of the definitions + * + * We return the complete definitions to allow the user changes to it, such + * as adding imports, etc. + */ + public String getDefinitionsAsXMLString() { + StringWriter w = new StringWriter(); + Marshaller m = JAXBSupport.createMarshaller(true); + try { + m.marshal(this.definitions, w); + } catch (JAXBException e) { + AbstractComponentInstanceResource.logger.error("Could not marshal definitions", e); + throw new IllegalStateException(e); + } + String res = w.toString(); + return res; + } + + /** + * @return the reference to the internal Definitions object + */ + public Definitions getDefinitions() { + return this.definitions; + } + + @PUT + @Consumes({MimeTypes.MIMETYPE_TOSCA_DEFINITIONS, MediaType.APPLICATION_XML, MediaType.TEXT_XML}) + public Response updateDefinitions(InputStream requestBodyStream) { + Unmarshaller u; + Definitions defs; + Document doc; + final StringBuilder sb = new StringBuilder(); + try { + DocumentBuilder db = TOSCADocumentBuilderFactory.INSTANCE.getTOSCADocumentBuilder(); + db.setErrorHandler(new ErrorHandler() { + + @Override + public void warning(SAXParseException exception) throws SAXException { + // we don't care + } + + @Override + public void fatalError(SAXParseException exception) throws SAXException { + sb.append("Fatal Error: "); + sb.append(exception.getMessage()); + sb.append("\n"); + } + + @Override + public void error(SAXParseException exception) throws SAXException { + sb.append("Fatal Error: "); + sb.append(exception.getMessage()); + sb.append("\n"); + } + }); + doc = db.parse(requestBodyStream); + if (sb.length() > 0) { + // some error happened + // doc is not null, because the parser parses even if it is not XSD conforming + return Response.status(Status.BAD_REQUEST).entity(sb.toString()).build(); + } + } catch (SAXException | IOException e) { + AbstractComponentInstanceResource.logger.debug("Could not parse XML", e); + return Utils.getResponseForException(e); + } + try { + u = JAXBSupport.createUnmarshaller(); + defs = (Definitions) u.unmarshal(doc); + } catch (JAXBException e) { + AbstractComponentInstanceResource.logger.debug("Could not unmarshal from request body stream", e); + return Utils.getResponseForException(e); + } + + // initial validity check + + // we allow changing the target namespace and the id + // This allows for inserting arbitrary definitions XML + // if (!this.definitions.getTargetNamespace().equals(this.id.getNamespace().getDecoded())) { + // return Response.status(Status.BAD_REQUEST).entity("Changing of the namespace is not supported").build(); + // } + // this.definitions.setTargetNamespace(this.id.getNamespace().getDecoded()); + + // TODO: check the provided definitions for validity + + TExtensibleElements tExtensibleElements = defs.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0); + if (!tExtensibleElements.getClass().equals(this.createNewElement().getClass())) { + return Response.status(Status.BAD_REQUEST).entity("First type in Definitions is not matching the type modeled by this resource").build(); + } + + this.definitions = defs; + + // replace existing element by retrieved data + this.element = this.definitions.getServiceTemplateOrNodeTypeOrNodeTypeImplementation().get(0); + + // ensure that ids did not change + // TODO: future work: raise error if user changed id or namespace + this.copyIdToFields(); + + return BackendUtils.persist(this); + } + + @GET + @Path("xml/") + @Produces(MediaType.TEXT_HTML) + public Response getXML() { + Viewable viewable = new Viewable("/jsp/xmlSource.jsp", this); + return Response.ok().entity(viewable).build(); + } + + @Path("documentation/") + public DocumentationsResource getDocumentationsResource() { + return new DocumentationsResource(this, this.getElement().getDocumentation()); + } + + @Path("tags/") + public final TagsResource getTags() { + return new TagsResource(this.id); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.java new file mode 100644 index 0000000..7bc7c73 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.java @@ -0,0 +1,200 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import java.lang.reflect.Method; + +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.xml.namespace.QName; + +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.model.tosca.TBoolean; +import org.eclipse.winery.model.tosca.TEntityType.DerivedFrom; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Models a component instance with name, derived from, abstract, and final
+ * Tags are provided by AbstractComponentInstanceResource + * + * This class mirrors + * AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinalConfigurationBacked + * . We did not include interfaces as the getters are currently only called at + * the jsp + */ +public abstract class AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal extends AbstractComponentInstanceResource { + + private static final Logger logger = LoggerFactory.getLogger(AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.class); + + + protected AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal(TOSCAComponentId id) { + super(id); + } + + /** + * @return The associated name of this resource. CSDPR01 foresees a NCName + * name and no ID for an entity type. Therefore, we use the ID as + * unique identification and convert it to a name when a read + * request is put. + */ + @GET + @Path("name") + public String getName() { + return ModelUtilities.getName(this.getElement()); + } + + @PUT + @Path("name") + public Response putName(String name) { + ModelUtilities.setName(this.getElement(), name); + return BackendUtils.persist(this); + } + + @GET + @Path("derivedFrom") + public String getDerivedFrom() { + // TOSCA does not introduce a type like WithNameDerivedFromAbstractFinal + // We could enumerate all possible implementing classes + // Or use java reflection, what we're doing now. + Method method; + // We have three different "DerivedFrom", for NodeTypeImplementation and RelationshipTypeImplementation, we have to assign to a different "DerivedFrom" + // This has to be done in the derived resources + DerivedFrom derivedFrom; + try { + method = this.getElement().getClass().getMethod("getDerivedFrom"); + derivedFrom = (DerivedFrom) method.invoke(this.getElement()); + } catch (ClassCastException e) { + AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.logger.error("Seems that *Implementation is now Definitions backed, but not yet fully implented", e); + throw new IllegalStateException(e); + } catch (Exception e) { + AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.logger.error("Could not get derivedFrom", e); + throw new IllegalStateException(e); + } + if (derivedFrom == null) { + return null; + } + QName typeRef = derivedFrom.getTypeRef(); + if (typeRef == null) { + return null; + } else { + return typeRef.toString(); + } + } + + @PUT + @Path("derivedFrom") + public Response putDerivedFrom(String type) { + QName qname = QName.valueOf(type); + + // see getDerivedFrom for verbose comments + Method method; + DerivedFrom derivedFrom = new DerivedFrom(); + derivedFrom.setTypeRef(qname); + try { + method = this.getElement().getClass().getMethod("setDerivedFrom", DerivedFrom.class); + method.invoke(this.getElement(), derivedFrom); + } catch (ClassCastException e) { + AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.logger.error("Seems that *Implementation is now Definitions backed, but not yet fully implemented", e); + return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e).build(); + } catch (Exception e) { + AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.logger.error("Could not set derivedFrom", e); + return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e).build(); + } + + return BackendUtils.persist(this); + } + + /** + * @param methodName the method to call: getAbstract|getFinal + * @return {@inheritDoc} + */ + private String getTBoolean(String methodName) { + // see getDerivedFrom for verbose comments + Method method; + TBoolean tBoolean; + try { + method = this.getElement().getClass().getMethod(methodName); + tBoolean = (TBoolean) method.invoke(this.getElement()); + } catch (Exception e) { + AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.logger.error("Could not get boolean " + methodName, e); + throw new IllegalStateException(e); + } + if (tBoolean == null) { + return null; + } else { + return tBoolean.value(); + } + } + + /** + * @param methodName the method to call: setAbstract|setFinal + * @return {@inheritDoc} + */ + private Response putTBoolean(String tBooleanStr, String methodName) { + // see getDerivedFrom for verbose comments + + Method method; + TBoolean tBoolean = TBoolean.fromValue(tBooleanStr); + try { + method = this.getElement().getClass().getMethod(methodName, TBoolean.class); + method.invoke(this.getElement(), tBoolean); + } catch (Exception e) { + AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal.logger.error("Could not set tBoolean " + methodName, e); + return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e).build(); + } + + return BackendUtils.persist(this); + } + + /** + * Method name is not "getAbstract" as ${it.abstract} does not work as + * "abstract" is not allowed at that place + */ + @GET + @Path("abstract") + public String getIsAbstract() { + return this.getTBoolean("getAbstract"); + } + + @PUT + @Path("abstract") + public Response putIsAbstract(String isAbstract) { + return this.putTBoolean(isAbstract, "setAbstract"); + } + + @GET + @Path("final") + public String getIsFinal() { + return this.getTBoolean("getFinal"); + } + + @PUT + @Path("final") + public Response putIsFinal(String isFinal) { + return this.putTBoolean(isFinal, "setFinal"); + } + + /** + * @return resource managing abstract, final, derivedFrom + */ + @Path("inheritance/") + public InheritanceResource getInheritanceManagement() { + return new InheritanceResource(this); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceWithReferencesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceWithReferencesResource.java new file mode 100644 index 0000000..3b63b0f --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentInstanceWithReferencesResource.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import javax.ws.rs.core.Response; + +import org.eclipse.winery.model.tosca.Definitions; +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; + +public abstract class AbstractComponentInstanceWithReferencesResource extends AbstractComponentInstanceResource { + + public AbstractComponentInstanceWithReferencesResource(TOSCAComponentId id) { + super(id); + } + + /** + * Ensures that the presented XML is in line with the stored files + */ + @Override + public Response getXML() { + this.synchronizeReferences(); + return super.getXML(); + } + + @Override + public String getDefinitionsAsXMLString() { + this.synchronizeReferences(); + return super.getDefinitionsAsXMLString(); + } + + @Override + public Definitions getDefinitions() { + this.synchronizeReferences(); + return super.getDefinitions(); + } + + /** + * Synchronizes the artifact references with the files stored in the + * repository + */ + public abstract void synchronizeReferences(); + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentsResource.java new file mode 100644 index 0000000..5702376 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentsResource.java @@ -0,0 +1,279 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import java.io.StringWriter; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.SortedSet; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.xml.namespace.QName; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId; +import org.eclipse.winery.common.ids.definitions.PolicyTemplateId; +import org.eclipse.winery.common.ids.definitions.ServiceTemplateId; +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.backend.ResourceCreationResult; +import org.eclipse.winery.repository.resources.entitytemplates.artifacttemplates.ArtifactTemplatesResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; +import com.sun.jersey.api.NotFoundException; +import com.sun.jersey.api.view.Viewable; + +/** + * Resource handling of a set of components. Each component has to provide a + * class to handle the set. This is required to provide the correct instances of + * TOSCAcomponentIds. + * + * TODO: Add generics here! + * {@link Utils.getComponentIdClassForComponentContainer} is then obsolete + */ +public abstract class AbstractComponentsResource { + + protected static final Logger logger = LoggerFactory.getLogger(AbstractComponentsResource.class); + + + @GET + @Produces(MediaType.TEXT_HTML) + public Response getHTML() { + return Response.ok().entity(new Viewable("/jsp/genericcomponentpage.jsp", new GenericComponentPageData(this.getClass()))).build(); + } + + /** + * Creates a new component instance in the given namespace + * + * @param namespace plain namespace + * @param id plain id + */ + protected ResourceCreationResult onPost(String namespace, String name) { + ResourceCreationResult res; + if (StringUtils.isEmpty(namespace) || StringUtils.isEmpty(name)) { + res = new ResourceCreationResult(Status.BAD_REQUEST); + } else { + String id = Utils.createXMLidAsString(name); + TOSCAComponentId tcId; + try { + tcId = this.getTOSCAcomponentId(namespace, id, false); + res = this.createComponentInstance(tcId); + // in case the resource additionally supports a name attribute, we set the original name + if (res.getStatus().equals(Status.CREATED)) { + if ((tcId instanceof ServiceTemplateId) || (tcId instanceof ArtifactTemplateId) || (tcId instanceof PolicyTemplateId)) { + // these three types have an additional name (instead of a pure id) + // we store the name + IHasName resource = (IHasName) AbstractComponentsResource.getComponentInstaceResource(tcId); + resource.setName(name); + } + } + } catch (Exception e) { + AbstractComponentsResource.logger.debug("Could not create id instance", e); + res = new ResourceCreationResult(Status.INTERNAL_SERVER_ERROR); + } + } + return res; + } + + /** + * Creates a new component instance in the given namespace + * + * @param namespace plain namespace + * @param id plain id + * @param ignored this parameter is ignored, but necessary for + * {@link ArtifactTemplatesResource} to be able to accept the + * artifact type at a post + */ + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + @Produces(MediaType.TEXT_PLAIN) + public Response onPost(@FormParam("namespace") String namespace, @FormParam("name") String name, String ignored) { + ResourceCreationResult res = this.onPost(namespace, name); + return res.getResponse(); + } + + /** + * Creates a TOSCAcomponentId for the given namespace / id combination + * + * Uses reflection to create a new instance + */ + protected TOSCAComponentId getTOSCAcomponentId(String namespace, String id, boolean URLencoded) throws Exception { + Class idClass = Utils.getComponentIdClassForComponentContainer(this.getClass()); + return BackendUtils.getTOSCAcomponentId(idClass, namespace, id, URLencoded); + } + + /** + * Creates a new instance of the current component + * + * @return
    + *
  • Status.CREATED (201) if the resource has been created,
  • + *
  • Status.CONFLICT if the resource already exists,
  • + *
  • Status.INTERNAL_SERVER_ERROR (500) if something went wrong
  • + *
+ */ + protected ResourceCreationResult createComponentInstance(TOSCAComponentId tcId) { + return BackendUtils.create(tcId); + } + + @SuppressWarnings("unchecked") + private static Class getComponentInstanceResourceClassForType(String type) { + // Guess the package + String pkg = "org.eclipse.winery.repository.resources."; + + pkg += Utils.getIntermediateLocationStringForType(type, "."); + + // naming convention: Instance is named after container, but without the + // plural s + String className = pkg + "." + type + "Resource"; + try { + return (Class) Class.forName(className); + } catch (ClassNotFoundException e) { + throw new IllegalStateException("Could not find id class for component instance", e); + } + } + + /** + * + * @param namespace encoded namespace + * @param id encoded id + * @return an instance of the requested resource + */ + @Path("{namespace}/{id}/") + public R getComponentInstaceResource(@PathParam("namespace") String namespace, @PathParam("id") String id) { + return this.getComponentInstaceResource(namespace, id, true); + } + + /** + * @param encoded specifies whether namespace and id are encoded + * @return an instance of the requested resource + */ + @SuppressWarnings("unchecked") + public R getComponentInstaceResource(String namespace, String id, boolean encoded) { + TOSCAComponentId tcId; + try { + tcId = this.getTOSCAcomponentId(namespace, id, encoded); + } catch (Exception e) { + throw new IllegalStateException("Could not create id instance", e); + } + return (R) AbstractComponentsResource.getComponentInstaceResource(tcId); + } + + /** + * @return an instance of the requested resource + */ + public AbstractComponentInstanceResource getComponentInstaceResource(QName qname) { + return this.getComponentInstaceResource(qname.getNamespaceURI(), qname.getLocalPart(), false); + } + + /** + * @return an instance of the requested resource + * @throws NotFoundException if resource doesn't exist. + */ + public static AbstractComponentInstanceResource getComponentInstaceResource(TOSCAComponentId tcId) { + String type = Util.getTypeForComponentId(tcId.getClass()); + if (!Repository.INSTANCE.exists(tcId)) { + AbstractComponentsResource.logger.debug("TOSCA component id " + tcId.toString() + " not found"); + throw new NotFoundException("TOSCA component id " + tcId.toString() + " not found"); + } + Class newResource = AbstractComponentsResource.getComponentInstanceResourceClassForType(type); + Constructor[] constructors = newResource.getConstructors(); + assert (constructors.length == 1); + AbstractComponentInstanceResource newInstance; + try { + newInstance = (AbstractComponentInstanceResource) constructors[0].newInstance(tcId); + } catch (InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { + AbstractComponentsResource.logger.error("Could not instantiate sub resource " + tcId); + throw new IllegalStateException("Could not instantiate sub resource", e); + } + return newInstance; + } + + /** + * Returns resources for all known component instances + * + * Required by topologytemplateedit.jsp + */ + public Collection getAll() { + Class idClass = Utils.getComponentIdClassForComponentContainer(this.getClass()); + SortedSet allTOSCAcomponentIds = Repository.INSTANCE.getAllTOSCAComponentIds(idClass); + ArrayList res = new ArrayList(allTOSCAcomponentIds.size()); + for (TOSCAComponentId id : allTOSCAcomponentIds) { + AbstractComponentInstanceResource r = AbstractComponentsResource.getComponentInstaceResource(id); + res.add(r); + } + return res; + } + + /** + * Used by org.eclipse.winery.repository.repository.client and by the + * artifactcreationdialog.tag. Especially the "name" field is used there at + * the UI + * + * @return A list of all ids of all instances of this component type. If the + * "name" attribute is required, that name is used as id
+ * Format: + * [({"namespace": "", "id": ""},)* ]. A + * name field is added if the model allows an additional name attribute + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + public String getListOfAllIds() { + Class idClass = Utils.getComponentIdClassForComponentContainer(this.getClass()); + boolean supportsNameAttribute = Util.instanceSupportsNameAttribute(idClass); + SortedSet allTOSCAcomponentIds = Repository.INSTANCE.getAllTOSCAComponentIds(idClass); + JsonFactory jsonFactory = new JsonFactory(); + StringWriter sw = new StringWriter(); + + try { + JsonGenerator jg = jsonFactory.createGenerator(sw); + // We produce org.eclipse.winery.repository.client.WineryRepositoryClient.NamespaceAndId by hand here + // Refactoring could move this class to common and fill it here + jg.writeStartArray(); + for (TOSCAComponentId id : allTOSCAcomponentIds) { + jg.writeStartObject(); + jg.writeStringField("namespace", id.getNamespace().getDecoded()); + jg.writeStringField("id", id.getXmlId().getDecoded()); + if (supportsNameAttribute) { + AbstractComponentInstanceResource componentInstaceResource = AbstractComponentsResource.getComponentInstaceResource(id); + String name = ((IHasName) componentInstaceResource).getName(); + jg.writeStringField("name", name); + } + jg.writeEndObject(); + } + jg.writeEndArray(); + jg.close(); + } catch (Exception e) { + AbstractComponentsResource.logger.error(e.getMessage(), e); + return "[]"; + } + return sw.toString(); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentsWithTypeReferenceResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentsWithTypeReferenceResource.java new file mode 100644 index 0000000..33bc1d4 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/AbstractComponentsWithTypeReferenceResource.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.repository.backend.ResourceCreationResult; +import org.restdoc.annotations.RestDocParam; + +/** + * This class does NOT inherit from TEntityTemplatesResource + * as these templates are directly nested in a TDefinitionsElement + */ +public abstract class AbstractComponentsWithTypeReferenceResource extends AbstractComponentsResource { + + /** + * Creates the resource and sets the specified type + * + * In contrast to the other component instances in this package, we + * additionally need the parameter "type" to set the type of the artifact + * template. + * + * @param namespace Namespace of the template + * @param name name attribute of the template + * @param type: QName of the type, format: {namespace}localname is retrieved + * from namespace manager + * + * @return URI of the created Resource, null if resource already exists, + * URI_internalServerError if an internal server error occurred + */ + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + @Produces(MediaType.TEXT_PLAIN) + @Override + public Response onPost(@RestDocParam(description = "Namespace of the component") @FormParam("namespace") String namespace, @RestDocParam(description = "name attribute of the component") @FormParam("name") String name, @RestDocParam(description = "QName of the type, format: {namespace}localname") @FormParam("type") String type) { + // only check for type parameter as namespace and name are checked in super.onPost + if (StringUtils.isEmpty(type)) { + return Response.status(Status.BAD_REQUEST).build(); + } + ResourceCreationResult creationResult = super.onPost(namespace, name); + if (!creationResult.isSuccess()) { + return creationResult.getResponse(); + } + if (creationResult.getStatus().equals(Status.CREATED)) { + IHasTypeReference resource = (IHasTypeReference) AbstractComponentsResource.getComponentInstaceResource((TOSCAComponentId) creationResult.getId()); + resource.setType(type); + // we assume that setType succeeded and just return the result of the + // creation of the artifact template resource + // Thus, we do NOT change res + } + return creationResult.getResponse(); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/ConstraintResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/ConstraintResource.java new file mode 100644 index 0000000..b9eb345 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/ConstraintResource.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.eclipse.winery.model.tosca.TConstraint; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdResource; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource; + +public class ConstraintResource extends EntityWithoutIdResource { + + /** + * + * @param constraint the current constraint value + * @param list the list this constraint belongs to + * @param res the node type resource this constraint belongs to. Required + * for saving + */ + public ConstraintResource(TConstraint constraint, int idx, List list, NodeTypeResource res) { + super(constraint, idx, list, res); + } + + /** + * Required for collectionResource + * + * @throws ClassCastException of !(res instanceof NodeTypeResource) + */ + public ConstraintResource(TConstraint constraint, int idx, List list, AbstractComponentInstanceResource res) { + this(constraint, idx, list, (NodeTypeResource) res); + } + + private TConstraint getConstraint() { + return this.o; + } + + @GET + @Path("type") + @Produces(MediaType.TEXT_PLAIN) + public String getConstraintType() { + return this.getConstraint().getConstraintType(); + } + + @PUT + @Path("type") + @Consumes(MediaType.TEXT_PLAIN) + public Response putConstraintType(String constraintType) { + this.getConstraint().setConstraintType(constraintType); + return BackendUtils.persist(this.res); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/ConstraintsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/ConstraintsResource.java new file mode 100644 index 0000000..8aea92f --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/ConstraintsResource.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import java.util.List; + +import org.eclipse.winery.model.tosca.TConstraint; +import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdCollectionResource; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jersey.api.view.Viewable; + +public class ConstraintsResource extends EntityWithoutIdCollectionResource { + + private static final Logger logger = LoggerFactory.getLogger(ConstraintsResource.class); + + + public ConstraintsResource(List constraints, NodeTypeResource res) { + super(ConstraintResource.class, TConstraint.class, constraints, res); + } + + @Override + public Viewable getHTML() { + // TODO Auto-generated method stub + throw new IllegalStateException("Not yet implemented."); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/EntityTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/EntityTypeResource.java new file mode 100644 index 0000000..1b70d56 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/EntityTypeResource.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import java.util.Collection; +import java.util.SortedSet; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.model.tosca.TEntityType; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.datatypes.select2.Select2DataWithOptGroups; +import org.eclipse.winery.repository.datatypes.select2.Select2OptGroup; +import org.eclipse.winery.repository.resources.entitytypes.properties.PropertiesDefinitionResource; + +public abstract class EntityTypeResource extends AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal { + + protected EntityTypeResource(TOSCAComponentId id) { + super(id); + } + + @Override + protected void copyIdToFields() { + TEntityType entityType = this.getEntityType(); + entityType.setTargetNamespace(this.getId().getNamespace().getDecoded()); + entityType.setName(this.getId().getXmlId().getDecoded()); + } + + /** + * Convenience method to avoid casting. Required by + * PropertiesDefinitionResource's jsp + */ + public TEntityType getEntityType() { + return (TEntityType) this.element; + } + + /** + * Models PropertiesDefinition + */ + @Path("propertiesdefinition/") + public PropertiesDefinitionResource getPropertiesDefinitionResource() { + return new PropertiesDefinitionResource(this); + } + + /** + * Used by children to implement getListOfAllInstances() + */ + protected SortedSet getListOfAllInstances(Class clazz) { + Select2DataWithOptGroups data = new Select2DataWithOptGroups(); + + Collection instanceIds = BackendUtils.getAllElementsRelatedWithATypeAttribute(clazz, this.id.getQName()); + + for (TOSCAComponentId instanceId : instanceIds) { + String groupText = instanceId.getNamespace().getDecoded(); + String text = BackendUtils.getName(instanceId); + data.add(groupText, instanceId.getQName().toString(), text); + } + + return data.asSortedSet(); + } + + /** + * Returns an array suitable for processing in a {@code select2} field See + * {@link http://ivaynberg.github.io/select2} + * + * Each element: {id: "{ns}localname", text: "name/id"} + */ + @Path("instances/") + @GET + @Produces(MediaType.APPLICATION_JSON) + public SortedSet getListOfAllInstances() { + Response res = Response.status(Status.INTERNAL_SERVER_ERROR).entity("not yet implemented").build(); + throw new WebApplicationException(res); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/GenericComponentPageData.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/GenericComponentPageData.java new file mode 100644 index 0000000..a2a8533 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/GenericComponentPageData.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import java.util.Collection; +import java.util.Collections; +import java.util.SortedSet; + +import org.eclipse.winery.common.ids.definitions.ArtifactTypeId; +import org.eclipse.winery.common.ids.definitions.NodeTypeId; +import org.eclipse.winery.common.ids.definitions.PolicyTypeId; +import org.eclipse.winery.common.ids.definitions.RelationshipTypeId; +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.resources.entitytemplates.artifacttemplates.ArtifactTemplatesResource; +import org.eclipse.winery.repository.resources.entitytemplates.policytemplates.PolicyTemplatesResource; +import org.eclipse.winery.repository.resources.entitytypeimplementations.nodetypeimplementations.NodeTypeImplementationsResource; +import org.eclipse.winery.repository.resources.entitytypeimplementations.relationshiptypeimplementations.RelationshipTypeImplementationsResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class GenericComponentPageData { + + private static final Logger logger = LoggerFactory.getLogger(GenericComponentPageData.class); + + private final SortedSet componentInstanceIds; + + private final Class resourceClass; + + + public GenericComponentPageData(Class resourceClass) { + this.resourceClass = resourceClass; + Class cIdClass = Utils.getComponentIdClassForComponentContainer(resourceClass); + this.componentInstanceIds = Repository.INSTANCE.getAllTOSCAComponentIds(cIdClass); + } + + /** + * Outputs the data for GenericComponentPage (Name / Id / Namespace) needed + * for the genericcomponentpage.jsp + */ + public SortedSet getComponentInstanceIds() { + return this.componentInstanceIds; + } + + public String getType() { + return Utils.getTypeForComponentContainer(this.resourceClass); + } + + public String getCSSclass() { + // The resources do NOT know their CSS class + // Layout is far away from a resource + // Instead of a huge if/else-cascade, we derive the CSS name from the + // class name + String type = this.getType(); + // convention: first letter in small letters + String res = type.substring(0, 1).toLowerCase() + type.substring(1); + // this generated "xSDImport" as CSS class for XSDImport + return res; + } + + public String getLabel() { + String type = this.getType(); + // E.g., convert ArtifactTemplate to Artifact Template + String res = type.replaceAll("(\\p{Lower})(\\p{Upper})", "$1 $2"); + return res; + } + + /** + * Required for genericcomponentpage.jsp -> addComponentInstance.jsp + * + * May only be used if the component supports the type (e.g., artifact + * templates) + * + * @return the list of all known types + */ + public Collection getTypeSelectorData() { + Class typeIdClass; + if (this.resourceClass.equals(ArtifactTemplatesResource.class)) { + typeIdClass = ArtifactTypeId.class; + } else if (this.resourceClass.equals(NodeTypeImplementationsResource.class)) { + typeIdClass = NodeTypeId.class; + } else if (this.resourceClass.equals(RelationshipTypeImplementationsResource.class)) { + typeIdClass = RelationshipTypeId.class; + } else if (this.resourceClass.equals(PolicyTemplatesResource.class)) { + typeIdClass = PolicyTypeId.class; + } else { + return Collections.emptyList(); + } + SortedSet allTOSCAcomponentIds = Repository.INSTANCE.getAllTOSCAComponentIds(typeIdClass); + return allTOSCAcomponentIds; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/GenericVisualAppearanceResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/GenericVisualAppearanceResource.java new file mode 100644 index 0000000..51bbcf1 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/GenericVisualAppearanceResource.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import java.io.InputStream; +import java.net.URI; +import java.util.Map; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.xml.namespace.QName; + +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.ids.elements.TOSCAElementId; +import org.eclipse.winery.repository.Prefs; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.constants.Filename; +import org.eclipse.winery.repository.datatypes.ids.elements.VisualAppearanceId; +import org.eclipse.winery.repository.resources.entitytypes.TopologyGraphElementEntityTypeResource; + +//import com.fasterxml.jackson.annotation.JsonIgnore; // currently not required +import com.sun.jersey.multipart.FormDataBodyPart; +import com.sun.jersey.multipart.FormDataParam; + +/** + * Contains methods for both visual appearance for + *
    + *
  • node types
  • + *
  • relationship types
  • + *
+ */ +public abstract class GenericVisualAppearanceResource { + + protected final Map otherAttributes; + protected final TopologyGraphElementEntityTypeResource res; + protected final TOSCAElementId id; + + + @DELETE + public Response onDelete() { + return BackendUtils.delete(this.id); + } + + /** + * Used for GUI when accessing the resource as data E.g., for topology + * template + */ + //@JsonIgnore + public URI getAbsoluteURL() { + String URI = Prefs.INSTANCE.getResourcePath(); + URI = URI + "/" + Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(this.id)); + return Utils.createURI(URI); + } + + //@JsonIgnore + public TOSCAElementId getId() { + return this.id; + } + + /** + * @param res + * @param otherAttributes the other attributes of the node/relationship type + * @param id the id of this subresource required for storing the images + */ + public GenericVisualAppearanceResource(TopologyGraphElementEntityTypeResource res, Map otherAttributes, VisualAppearanceId id) { + this.id = id; + this.res = res; + this.otherAttributes = otherAttributes; + } + + /** + * Determines repository reference to file in repo + */ + protected RepositoryFileReference getRepoFileRef(String name) { + return new RepositoryFileReference(this.id, name); + } + + protected Response getImage(String name, String modified) { + RepositoryFileReference target = this.getRepoFileRef(name); + return BackendUtils.returnRepoPath(target, modified); + } + + /** + * Arbitrary images are supported. There currently is no check for valid + * image media types + */ + protected Response putImage(String name, InputStream uploadedInputStream, MediaType mediaType) { + RepositoryFileReference target = this.getRepoFileRef(name); + return BackendUtils.putContentToFile(target, uploadedInputStream, mediaType); + } + + @GET + @Path("16x16") + public Response get16x16Image(@HeaderParam("If-Modified-Since") String modified) { + // Even if the extension is "png", it might contain a jpg, too + // We keep the file extension as the windows explorer can display previews even if the content is not a png + return this.getImage(Filename.FILENAME_SMALL_ICON, modified); + } + + @PUT + @Path("16x16") + @Consumes(MediaType.MULTIPART_FORM_DATA) + public Response post16x16Image(@FormDataParam("file") InputStream uploadedInputStream, @FormDataParam("file") FormDataBodyPart body) { + return this.putImage(Filename.FILENAME_SMALL_ICON, uploadedInputStream, body.getMediaType()); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/IHasName.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/IHasName.java new file mode 100644 index 0000000..08a3696 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/IHasName.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.restdoc.annotations.RestDoc; + +/** + * Ensures that the AbstractComponentInstance has a getName method + */ +public interface IHasName { + + @GET + @Path("name") + // @formatter:off + @RestDoc(methodDescription = "Returns the name of the element. " + + "Defaults to the ID of the element. " + + "Some other ComponentInstances either carry a name or an ID. ") + // @formatter:on + @Produces(MediaType.TEXT_PLAIN) + public String getName(); + + @PUT + @Path("name") + public Response setName(@FormParam("value") String name); + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/IHasTypeReference.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/IHasTypeReference.java new file mode 100644 index 0000000..cb42158 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/IHasTypeReference.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import javax.ws.rs.core.Response; +import javax.xml.namespace.QName; + +public interface IHasTypeReference { + + /** + * @return the QName of the type with full namespace, never null (according + * to spec) + */ + public QName getType(); + + /** + * Sets the type and directly persists the resource + */ + public Response setType(QName type); + + /** + * Calls setType(QName) with QName.valueOf(typeStr) + * + * Directly persists the resource + * + * @param typeStr a textual representation of a QName + */ + public Response setType(String typeStr); + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTemplateResourceOrNodeTypeImplementationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTemplateResourceOrNodeTypeImplementationResource.java new file mode 100644 index 0000000..c8438ef --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTemplateResourceOrNodeTypeImplementationResource.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +/** + * Implementors can have DAs attached + */ +public interface INodeTemplateResourceOrNodeTypeImplementationResource extends INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource { + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource.java new file mode 100644 index 0000000..7bd178e --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import org.eclipse.winery.common.ids.Namespace; + +/** + * Implementors can have IAs or DAs attached + */ +public interface INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource { + + Namespace getNamespace(); + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTypeImplementationResourceOrRelationshipTypeImplementationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTypeImplementationResourceOrRelationshipTypeImplementationResource.java new file mode 100644 index 0000000..892a7cb --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/INodeTypeImplementationResourceOrRelationshipTypeImplementationResource.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +/** + * Implementors can have IAs attached + */ +public interface INodeTypeImplementationResourceOrRelationshipTypeImplementationResource extends INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource { + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/InheritanceResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/InheritanceResource.java new file mode 100644 index 0000000..7cc878a --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/InheritanceResource.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.ws.rs.GET; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.repository.backend.Repository; + +import com.sun.jersey.api.view.Viewable; + +/** + * Class for managing inheritance properties: abstract, final, derivedFromn + * + * The linking in the resources tree is different than the others. Here, there + * is no additional Id generated. + * + * We separated the code here to have the collection of valid super types in a + * separate class. We think, this is less confusing than including this + * functionality in + * AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinalDefinitionsBacked + */ +public class InheritanceResource { + + private AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal managedResource; + + + public InheritanceResource(AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal res) { + this.managedResource = res; + } + + @GET + @Produces(MediaType.TEXT_HTML) + public Viewable getHTML() { + return new Viewable("/jsp/inheritance.jsp", this); + } + + public String getIsAbstract() { + return this.managedResource.getIsAbstract(); + } + + public String getIsFinal() { + return this.managedResource.getIsAbstract(); + } + + public String getDerivedFrom() { + return this.managedResource.getDerivedFrom(); + } + + /** JSP Data **/ + + public SortedSet getPossibleSuperTypes() { + // sorted by Name, not by namespace + SortedSet allTOSCAcomponentIds = Repository.INSTANCE.getAllTOSCAComponentIds(this.managedResource.getId().getClass()); + SortedSet res = new TreeSet<>(allTOSCAcomponentIds); + res.remove(this.managedResource.getId()); + // FEATURE: Possibly exclude all subtypes to avoid circles. However, this could be disappointing for users who know what they are doing + return res; + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/MainResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/MainResource.java new file mode 100644 index 0000000..87b5275 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/MainResource.java @@ -0,0 +1,189 @@ +/******************************************************************************* + * Copyright (c) 2012-2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.commons.io.FileUtils; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.importing.CSARImporter; +import org.eclipse.winery.repository.resources.API.APIResource; +import org.eclipse.winery.repository.resources.admin.AdminTopResource; +import org.eclipse.winery.repository.resources.entitytemplates.artifacttemplates.ArtifactTemplatesResource; +import org.eclipse.winery.repository.resources.entitytemplates.policytemplates.PolicyTemplatesResource; +import org.eclipse.winery.repository.resources.entitytypeimplementations.nodetypeimplementations.NodeTypeImplementationsResource; +import org.eclipse.winery.repository.resources.entitytypeimplementations.relationshiptypeimplementations.RelationshipTypeImplementationsResource; +import org.eclipse.winery.repository.resources.entitytypes.artifacttypes.ArtifactTypesResource; +import org.eclipse.winery.repository.resources.entitytypes.capabilitytypes.CapabilityTypesResource; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypesResource; +import org.eclipse.winery.repository.resources.entitytypes.policytypes.PolicyTypesResource; +import org.eclipse.winery.repository.resources.entitytypes.relationshiptypes.RelationshipTypesResource; +import org.eclipse.winery.repository.resources.entitytypes.requirementtypes.RequirementTypesResource; +import org.eclipse.winery.repository.resources.imports.ImportsResource; +import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplatesResource; +import org.restdoc.annotations.RestDoc; +import org.restdoc.annotations.RestDocParam; +import org.restdoc.annotations.RestDocReturnCode; + +import com.sun.jersey.api.view.Viewable; +import com.sun.jersey.core.header.FormDataContentDisposition; +import com.sun.jersey.multipart.FormDataParam; + +/** + * All paths listed here have to be listed in Jersey's filter configuration + */ +@Path("/") +public class MainResource { + + @Path("API/") + public APIResource api() { + return new APIResource(); + } + + @Path("artifacttemplates/") + public ArtifactTemplatesResource artifacttemplates() { + return new ArtifactTemplatesResource(); + } + + @Path("artifacttypes/") + public ArtifactTypesResource artifactypes() { + return new ArtifactTypesResource(); + } + + @Path("admin/") + public AdminTopResource admin() { + return new AdminTopResource(); + } + + @Path("capabilitytypes/") + public CapabilityTypesResource capabilitytypes() { + return new CapabilityTypesResource(); + } + + @Path("imports/") + public ImportsResource imports() { + return new ImportsResource(); + } + + @Path("nodetypes/") + public NodeTypesResource nodetypes() { + return new NodeTypesResource(); + } + + @Path("nodetypeimplementations/") + public NodeTypeImplementationsResource nodetypeimplementations() { + return new NodeTypeImplementationsResource(); + } + + @Path("other/") + @GET + @Produces(MediaType.TEXT_HTML) + public Viewable getOtherElements() { + return new Viewable("/jsp/otherElements.jsp"); + } + + @Path("policytemplates/") + public PolicyTemplatesResource policytemplates() { + return new PolicyTemplatesResource(); + } + + @Path("policytypes/") + public PolicyTypesResource policytypes() { + return new PolicyTypesResource(); + } + + @Path("relationshiptypes/") + public RelationshipTypesResource relationshiptypes() { + return new RelationshipTypesResource(); + } + + @Path("requirementtypes/") + public RequirementTypesResource requirementtypes() { + return new RequirementTypesResource(); + } + + @Path("relationshiptypeimplementations/") + public RelationshipTypeImplementationsResource relationshiptypeimplementations() { + return new RelationshipTypeImplementationsResource(); + } + + @Path("servicetemplates/") + public ServiceTemplatesResource servicetemplates() { + return new ServiceTemplatesResource(); + } + + /** + * Returns the main page of winery. + */ + @GET + @Produces(MediaType.TEXT_HTML) + public Response onGet() { + return Response.temporaryRedirect(Utils.createURI("servicetemplates/")).build(); + } + + @POST + @Consumes(MediaType.MULTIPART_FORM_DATA) + @RestDoc(methodDescription = "Imports the given CSAR (sent by simplesinglefileupload.jsp)") + @RestDocReturnCode(code = "200", description = "If the CSAR could be partially imported, the points where it failed are returned in the body") + // @formatter:off + public Response importCSAR( + @FormDataParam("file") InputStream uploadedInputStream, @FormDataParam("file") FormDataContentDisposition fileDetail, + @FormDataParam("overwrite") @RestDocParam(description = "true: content of CSAR overwrites existing content. false (default): existing content is kept") Boolean overwrite) { + // @formatter:on + CSARImporter importer = new CSARImporter(); + List errors = new ArrayList(); + boolean ow; + ow = (overwrite != null) && overwrite; + try { + importer.readCSAR(uploadedInputStream, errors, ow, true); + } catch (Exception e) { + return Response.serverError().entity("Could not import CSAR").entity(e.getMessage()).build(); + } + if (errors.isEmpty()) { + return Response.noContent().build(); + } else { + // In case there are errors, we send them as "bad request" + return Response.status(Status.BAD_REQUEST).entity(errors).build(); + } + } + + @POST + @Consumes(MediaType.APPLICATION_XML) + @Produces(MediaType.APPLICATION_JSON) + public Response importDefinitions(InputStream is) throws IOException { + File toscaFile; + toscaFile = File.createTempFile("TOSCA", ".tosca"); + FileUtils.copyInputStreamToFile(is, toscaFile); + CSARImporter importer = new CSARImporter(); + List errors = new ArrayList<>(); + importer.importDefinitions(null, toscaFile.toPath(), errors, false, true); + if (errors.isEmpty()) { + return Response.noContent().build(); + } else { + return Response.status(Status.BAD_REQUEST).entity(errors).build(); + } + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/SubMenuData.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/SubMenuData.java new file mode 100644 index 0000000..3f79c87 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/SubMenuData.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +/** + * Data used to render a submenu item + */ +public class SubMenuData { + + private final String href; + private final String text; + + public static final SubMenuData SUBMENU_DOCUMENTATION = new SubMenuData("#documentation", "Documentation"); + public static final SubMenuData SUBMENU_XML = new SubMenuData("#xml", "XML"); + + + public SubMenuData(String href, String text) { + this.href = href; + this.text = text; + } + + public String getHref() { + return this.href; + } + + public String getText() { + return this.text; + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/IPersistable.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/IPersistable.java new file mode 100644 index 0000000..85f565c --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/IPersistable.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources._support; + +import java.io.IOException; + +public interface IPersistable { + + /** + * @throws IOException if content could not be updated in the repository + * @throws IllegalStateException if an JAXBException occurred. This should + * never happen. + */ + public void persist() throws IOException; +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/CollectionsHelper.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/CollectionsHelper.java new file mode 100644 index 0000000..f150855 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/CollectionsHelper.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources._support.collections; + +import javax.ws.rs.core.Response; + +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources._support.IPersistable; + +public class CollectionsHelper { + + private CollectionsHelper() { + } + + /** + * + * @param + * @param resource the resource to be persisted + * @param idDetermination the object to use to determine the id of the + * entity + * @param entity the entity that was persisted. Used to determine the id + * @return the new id id of the resource + */ + public static Response persist(IPersistable resource, IIdDetermination idDetermination, X entity) { + Response res = BackendUtils.persist(resource); + if (res.getStatus() == 204) { + String id = idDetermination.getId(entity); + res = Response.ok(id).build(); + } + return res; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityCollectionResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityCollectionResource.java new file mode 100644 index 0000000..64d0fbe --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityCollectionResource.java @@ -0,0 +1,206 @@ +/******************************************************************************* + * Copyright (c) 2012-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources._support.collections; + +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.eclipse.winery.common.Util; +import org.eclipse.winery.repository.datatypes.select2.Select2DataItem; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.restdoc.annotations.RestDoc; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jersey.api.NotFoundException; +import com.sun.jersey.api.view.Viewable; + +/** + * Class managing a list of entities. It is intended to manage subresources, + * which are stored in a list. Either all entities have a unique key given by + * the TOSCA specification (subclass EntityWithIdCollectionResource) or a unique + * key is generated (subclass EntityWithoutIdCollectionResource) + * + * @param the resource modeling the entity + * @param the entity type of single items in the list + */ +public abstract class EntityCollectionResource, EntityT> implements IIdDetermination { + + private static final Logger logger = LoggerFactory.getLogger(EntityCollectionResource.class); + + protected final List list; + + protected final IPersistable res; + + protected final Class entityTClazz; + + protected final Class entityResourceTClazz; + + + /** + * @param clazz the class of EntityT. Required as it is not possible to call + * new EntityT (see http://stackoverflow.com/a/1090488/873282) + * @param list the list of entities contained in this resource. Has to be + * typed as not all TOSCA elements in the specification + * inherit from TExtensibleElements + * @param res the main resource the list is belonging to. Required for + * persistence. + */ + public EntityCollectionResource(Class entityResourceTClazz, Class entityTClazz, List list, IPersistable res) { + this.entityResourceTClazz = entityResourceTClazz; + this.entityTClazz = entityTClazz; + this.list = list; + this.res = res; + } + + /** + * Returns a list of ids of all entities nested here + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + public Object getListOfAllEntityIds(@QueryParam("select2") String select2) { + if (select2 == null) { + return this.getListOfAllEntityIdsAsList(); + } else { + // return data ready for consumption by select2 + List res = new ArrayList(this.list.size()); + for (EntityT o : this.list) { + String id = this.getId(o); + Select2DataItem di = new Select2DataItem(id, id); + res.add(di); + } + return res; + } + } + + public List getListOfAllEntityIdsAsList() { + List res = new ArrayList(this.list.size()); + for (EntityT o : this.list) { + // We assume that different Object serializations *always* have different hashCodes + res.add(this.getId(o)); + } + return res; + } + + /** + * Required by reqandcapdefs.jsp + */ + public List getAllEntityResources() { + List listOfAllSubResources = this.getListOfAllEntityIdsAsList(); + List res = new ArrayList(listOfAllSubResources.size()); + for (String id : listOfAllSubResources) { + res.add(this.getEntityResourceFromDecodedId(id)); + } + return res; + } + + public EntityResourceT getEntityResourceFromDecodedId(String id) { + EntityT entity = null; + int idx = -1; + for (EntityT c : this.list) { + idx++; + String cId = this.getId(c); + if (cId.equals(id)) { + entity = c; + break; + } + } + if (entity == null) { + throw new NotFoundException(); + } else { + return this.getEntityResourceInstance(entity, idx); + } + } + + @Path("{id}/") + public EntityResourceT getEntityResource(@PathParam("id") String id) { + if (id == null) { + throw new IllegalArgumentException("id has to be given"); + } + id = Util.URLdecode(id); + return this.getEntityResourceFromDecodedId(id); + } + + /** + * @param entity the entity to create a resource for + * @param idx the index in the list + * @return the resource managing the given entity + */ + protected abstract EntityResourceT getEntityResourceInstance(EntityT entity, int idx); + + @GET + @Produces(MediaType.TEXT_HTML) + @RestDoc(methodDescription = "@return the HTML fragment (DIV-container) to be embedded in the 'Interface' part of nodetype.js ") + public Response getHTMLAsResponse() { + Viewable viewable = this.getHTML(); + return Response.ok().header(HttpHeaders.VARY, HttpHeaders.ACCEPT).entity(viewable).build(); + } + + /** + * called by getHTMLAsResponse + */ + public abstract Viewable getHTML(); + + /** + * Adds a new entity + * + * In case the element already exists, we return "CONFLICT" + */ + @POST + @Consumes({MediaType.TEXT_XML, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + public Response addNewElement(EntityT entity) { + if (entity == null) { + return Response.status(Status.BAD_REQUEST).entity("a valid XML/JSON element has to be posted").build(); + } + if (this.alreadyContains(entity)) { + // we do not replace the element, but replace it + return Response.status(Status.CONFLICT).build(); + } + this.list.add(entity); + return CollectionsHelper.persist(this.res, this, entity); + } + + @Override + public abstract String getId(EntityT entity); + + /** + * Checks for containment of e in the list. equals is not used + * as most EntityT do not offer a valid implementation + * + * @return true if list already contains e. + */ + public boolean alreadyContains(EntityT e) { + String id = this.getId(e); + for (EntityT el : this.list) { + if (this.getId(el).equals(id)) { + // break loop + // we found an equal list item + return true; + } + } + // all items checked: nothing equal contained + return false; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityResource.java new file mode 100644 index 0000000..361fcfb --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/EntityResource.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources._support.collections; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources._support.IPersistable; + +/** + * Class to hold a single entity residing in a list of entities + * + * @param the entity type contained in the list + */ +public abstract class EntityResource { + + // This is non-final as a "PUT" may update the object + // it might be unnecessary to update this object as the resource is created at each request + // We update the reference nevertheless to be safe if the resource is used in another context + protected EntityT o; + + protected final int idx; + + protected final List list; + + protected final IPersistable res; + + protected IIdDetermination idDetermination; + + + /** + * + * @param idDetermination the object offering determination of an id of + * EntityT. May be null. If null, then setIdDetermination(obj) + * has to be called to enable this class functioning properly + * @param o the object this resource is representing + * @param idx the index of the object in the list + * @param list the list, where the object is stored in + * @param res the resource the object/list belongs to + */ + public EntityResource(IIdDetermination idDetermination, EntityT o, int idx, List list, IPersistable res) { + this.idDetermination = idDetermination; + this.o = o; + this.idx = idx; + this.list = list; + this.res = res; + } + + /** + * Quick hack for AbstractReqOrCapDefResource which is itself an + * IIdDetermination + */ + protected final void setIdDetermination(IIdDetermination idDetermination) { + this.idDetermination = idDetermination; + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response getJSON() { + assert (this.o != null); + return Response.ok().entity(this.o).build(); + } + + @GET + @Produces(MediaType.TEXT_XML) + @SuppressWarnings("unchecked") + public Response getXML() { + assert (this.o != null); + // Utils.getXML has to be used as Jersey can only serialize XMLRootElements + return Utils.getXML((Class) this.o.getClass(), this.o); + } + + /** + * Replaces the whole entity by the given entity + * + * As we use the hash code as index, the index changes when the resource is + * updated. This is not in line with REST. The alternative implementation is + * to use the index in the list as resource identification. That changes at + * each modification of the list itself (if elements are deleted / inserted + * before the current entry). When using the hash value, users may + * concurrently edit items and the list may also be updated + * + * @return the new id. + */ + @PUT + @Consumes(MediaType.TEXT_XML) + @Produces(MediaType.TEXT_PLAIN) + public Response setValue(EntityT o) { + this.list.set(this.idx, o); + this.o = o; + return CollectionsHelper.persist(this.res, this.idDetermination, o); + } + + @DELETE + public Response onDelete() { + try { + this.list.remove(this.idx); + } catch (IndexOutOfBoundsException e) { + return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not delete entity, even if it should exist").build(); + } + return BackendUtils.persist(this.res); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/IIdDetermination.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/IIdDetermination.java new file mode 100644 index 0000000..e479e70 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/IIdDetermination.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources._support.collections; + +public interface IIdDetermination { + + /** + * @return the id of the given entity + */ + public String getId(EntityT e); +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withid/EntityWithIdCollectionResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withid/EntityWithIdCollectionResource.java new file mode 100644 index 0000000..f428752 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withid/EntityWithIdCollectionResource.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources._support.collections.withid; + +import java.lang.reflect.Constructor; +import java.util.List; + +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.EntityCollectionResource; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class EntityWithIdCollectionResource, EntityT> extends EntityCollectionResource { + + private static final Logger logger = LoggerFactory.getLogger(EntityWithIdCollectionResource.class); + + + /** + * {@inheritDoc} + */ + public EntityWithIdCollectionResource(Class entityResourceTClazz, Class entityTClazz, List list, IPersistable res) { + super(entityResourceTClazz, entityTClazz, list, res); + } + + /** + * Each CollectionResource has to implement the id getting by itself as + * TOSCA XSD does not provide a general purpose id fetching mechanism + */ + @Override + public abstract String getId(EntityT entity); + + @Override + protected EntityResourceT getEntityResourceInstance(EntityT entity, int idx) { + Constructor constructor; + try { + constructor = this.entityResourceTClazz.getConstructor(IIdDetermination.class, this.entityTClazz, int.class, List.class, this.res.getClass()); + } catch (Exception e) { + try { + constructor = this.entityResourceTClazz.getConstructor(IIdDetermination.class, this.entityTClazz, int.class, List.class, IPersistable.class); + } catch (Exception e2) { + EntityWithIdCollectionResource.logger.debug("Could not get constructor", e); + EntityWithIdCollectionResource.logger.debug("res.getClass() was {}", this.res.getClass()); + throw new IllegalStateException(e2); + } + } + EntityResourceT newInstance; + try { + newInstance = constructor.newInstance(this, entity, idx, this.list, this.res); + } catch (Exception e) { + EntityWithIdCollectionResource.logger.debug("Could not instantiate class", e); + throw new IllegalStateException(e); + } + return newInstance; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withid/EntityWithIdResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withid/EntityWithIdResource.java new file mode 100644 index 0000000..1ac6775 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withid/EntityWithIdResource.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources._support.collections.withid; + +import java.util.List; + +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.EntityResource; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; + +public class EntityWithIdResource extends EntityResource { + + /** + * {@inheritDoc} + */ + public EntityWithIdResource(IIdDetermination idDetermination, EntityT o, int idx, List list, IPersistable res) { + super(idDetermination, o, idx, list, res); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/EntityWithoutIdCollectionResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/EntityWithoutIdCollectionResource.java new file mode 100644 index 0000000..8255f5d --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/EntityWithoutIdCollectionResource.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources._support.collections.withoutid; + +import java.lang.reflect.Constructor; +import java.util.List; + +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +import org.eclipse.winery.common.Util; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.EntityCollectionResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jersey.api.NotFoundException; + +/** + * Class managing a list of entities. It is intended to manage subresources, + * where the TOSCA specification did not specify a unique key. Currently, the + * hashCode of the XML String representation is used. If other representation + * should be used, the method {@code getEntityResource} has to be overriden. + * + * @param the resource modeling the entity + * @param the entity type of single items in the list + */ +public abstract class EntityWithoutIdCollectionResource, EntityT> extends EntityCollectionResource { + + private static final Logger logger = LoggerFactory.getLogger(EntityWithoutIdCollectionResource.class); + + + /** + * {@inheritDoc} + */ + public EntityWithoutIdCollectionResource(Class entityResourceTClazz, Class entityTClazz, List list, IPersistable res) { + super(entityResourceTClazz, entityTClazz, list, res); + } + + /** + * Method searching the list for an id with the hashcode instead of + * getId(EntityT) + */ + @Override + @Path("{id}/") + public EntityResourceT getEntityResource(@PathParam("id") String id) { + id = Util.URLdecode(id); + int idInt; + try { + idInt = Integer.parseInt(id); + } catch (java.lang.NumberFormatException e) { + throw new NotFoundException(id + " is not a valid id"); + } + EntityT entity = null; + int idx = -1; + for (EntityT c : this.list) { + idx++; + // speed optimization - instead of using getId() we directly use the hash code + int hash = Utils.getXMLAsString(c).hashCode(); + if (hash == idInt) { + entity = c; + break; + } + } + if (entity == null) { + throw new NotFoundException(); + } else { + return this.getEntityResourceInstance(entity, idx); + } + } + + @Override + public String getId(EntityT entity) { + return IdDeterminationWithHashCode.INSTANCE.getId(entity); + } + + /** + * {@inheritDoc} + */ + @Override + protected EntityResourceT getEntityResourceInstance(EntityT entity, int idx) { + Constructor constructor; + try { + constructor = this.entityResourceTClazz.getConstructor(this.entityTClazz, int.class, List.class, AbstractComponentInstanceResource.class); + } catch (Exception e) { + try { + constructor = this.entityResourceTClazz.getConstructor(this.entityTClazz, int.class, List.class, IPersistable.class); + } catch (NoSuchMethodException | SecurityException e1) { + EntityWithoutIdCollectionResource.logger.debug("Could not get constructor", e); + throw new IllegalStateException(e); + } + } + EntityResourceT newInstance; + try { + newInstance = constructor.newInstance(entity, idx, this.list, this.res); + } catch (Exception e) { + EntityWithoutIdCollectionResource.logger.debug("Could not instantiate class", e); + throw new IllegalStateException(e); + } + return newInstance; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/EntityWithoutIdResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/EntityWithoutIdResource.java new file mode 100644 index 0000000..0cf2766 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/EntityWithoutIdResource.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources._support.collections.withoutid; + +import java.util.List; + +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.EntityResource; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; + +/** + * {@inheritDoc} + */ +public abstract class EntityWithoutIdResource extends EntityResource { + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public EntityWithoutIdResource(EntityT o, int idx, List list, IPersistable res) { + super((IIdDetermination) IdDeterminationWithHashCode.INSTANCE, o, idx, list, res); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/IdDeterminationWithHashCode.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/IdDeterminationWithHashCode.java new file mode 100644 index 0000000..6b4e247 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/IdDeterminationWithHashCode.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources._support.collections.withoutid; + +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; + +public class IdDeterminationWithHashCode implements IIdDetermination { + + public static final IdDeterminationWithHashCode INSTANCE = new IdDeterminationWithHashCode(); + + + @Override + public String getId(Object entity) { + // We assume that different Object serializations *always* have different hashCodes + int hash = Utils.getXMLAsString(entity).hashCode(); + return Integer.toString(hash); + } + + /** + * Static wrapper method for functions.tld + */ + public static String getIdStatically(Object entity) { + return IdDeterminationWithHashCode.INSTANCE.getId(entity); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/package-info.java new file mode 100644 index 0000000..c62b344 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/_support/collections/withoutid/package-info.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +/** + * This package contains abstract resources implementing common functionality to + * support collections of entities, where the data model does not provide a + * unique id + */ +package org.eclipse.winery.repository.resources._support.collections.withoutid; \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/AbstractAdminResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/AbstractAdminResource.java new file mode 100644 index 0000000..cd4e20e --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/AbstractAdminResource.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.admin; + +import javax.ws.rs.DELETE; +import javax.ws.rs.core.Response; + +import org.apache.commons.configuration.Configuration; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.datatypes.ids.admin.AdminId; + +/** + * Instance of one admin resource + * + * Offers a configuration object to store data + */ +public abstract class AbstractAdminResource { + + protected final AdminId id; + protected Configuration configuration; + + + /** + * @param id the id of the element rendered by this resource + */ + public AbstractAdminResource(AdminId id) { + this.id = id; + this.configuration = Repository.INSTANCE.getConfiguration(id); + } + + @DELETE + public Response onDelete() { + return BackendUtils.delete(this.id); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/AdminTopResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/AdminTopResource.java new file mode 100644 index 0000000..7e4a662 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/AdminTopResource.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.admin; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.eclipse.winery.repository.resources.admin.types.ConstraintTypesManager; +import org.eclipse.winery.repository.resources.admin.types.PlanLanguagesManager; +import org.eclipse.winery.repository.resources.admin.types.PlanTypesManager; + +import com.sun.jersey.api.view.Viewable; + +public class AdminTopResource { + + @GET + @Produces(MediaType.TEXT_HTML) + public Viewable getHTML() { + return new Viewable("/jsp/admin/adminindex.jsp", this); + } + + @Path("namespaces/") + public NamespacesResource getNamespacesResource() { + return NamespacesResource.INSTANCE; + } + + @Path("repository/") + public RepositoryAdminResource getRepositoryAdminResource() { + return new RepositoryAdminResource(); + } + + @Path("planlanguages/") + public PlanLanguagesManager getPlanLanguagesResource() { + return PlanLanguagesManager.INSTANCE; + } + + @Path("plantypes/") + public PlanTypesManager getPlanTypesResource() { + return PlanTypesManager.INSTANCE; + } + + @Path("constrainttypes/") + public ConstraintTypesManager getConstraintTypesManager() { + return ConstraintTypesManager.INSTANCE; + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/NamespacesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/NamespacesResource.java new file mode 100644 index 0000000..f8fb9f1 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/NamespacesResource.java @@ -0,0 +1,253 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.admin; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.TreeSet; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.common.ids.Namespace; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.datatypes.ids.admin.NamespacesId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.sun.jersey.api.view.Viewable; + +/** + * Manages prefixes for the namespaces + */ +public class NamespacesResource extends AbstractAdminResource { + + private static final Logger logger = LoggerFactory.getLogger(NamespacesResource.class); + + public final static NamespacesResource INSTANCE = new NamespacesResource(); + + private Integer nsCount = 0; + + + private NamespacesResource() { + super(new NamespacesId()); + + // globally set prefixes + // if that behavior is not desired, the code has to be moved to "generatePrefix" which checks for existence, ... + this.configuration.setProperty("http://www.w3.org/2001/XMLSchema", "xsd"); + this.configuration.setProperty("http://www.w3.org/XML/1998/namespace", "xmlns"); + this.configuration.setProperty(org.eclipse.winery.common.constants.Namespaces.TOSCA_NAMESPACE, "tosca"); + this.configuration.setProperty(org.eclipse.winery.common.constants.Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "winery"); + } + + private Collection getAllPrefixes() { + Iterator keys = this.configuration.getKeys(); + HashSet res = new HashSet(); + while (keys.hasNext()) { + String key = keys.next(); + String prefix = this.configuration.getString(key); + res.add(prefix); + } + return res; + } + + @GET + @Produces(MediaType.TEXT_HTML) + public Response getHTML() { + Viewable viewable = new Viewable("/jsp/admin/namespaces.jsp", this); + return Response.ok().entity(viewable).build(); + } + + /** + * Sets / overwrites prefix/namespace mapping + * + * In case the prefix is already bound to another namespace, BAD_REQUEST is + * returned. + */ + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public Response addNamespace(@FormParam("namespace") String namespace, @FormParam("nsPrefix") String prefix) { + if (StringUtils.isEmpty(namespace)) { + return Response.status(Status.BAD_REQUEST).entity("namespace must be given.").build(); + } + if (StringUtils.isEmpty(prefix)) { + return Response.status(Status.BAD_REQUEST).entity("prefix must be given.").build(); + } + namespace = Util.URLdecode(namespace); + prefix = Util.URLdecode(prefix); + Collection allPrefixes = this.getAllPrefixes(); + if (allPrefixes.contains(prefix)) { + if (NamespacesResource.getPrefix(namespace).equals(prefix)) { + return Response.notModified().build(); + } else { + // the requested prefix is already bound to a different namespace + return Response.status(Status.BAD_REQUEST).entity("prefix already bound to a different namespace.").build(); + } + } + this.configuration.setProperty(namespace, prefix); + return Response.noContent().build(); + } + + /** + * Deletes given namespace from the repository + * + * @param URI to delete. The namespace is URLencoded. + * @return + */ + @DELETE + @Path("{namespace}") + public Response onDelete(@PathParam("namespace") String URI) { + Response res; + URI = Util.URLdecode(URI); + if (this.configuration.containsKey(URI)) { + this.configuration.clearProperty(URI); + res = Response.noContent().build(); + } else { + res = Response.status(Status.NOT_FOUND).build(); + } + return res; + } + + /** + * SIDEFFECT: URI is added to list of known namespaces if it did not exist + * before + */ + public static String getPrefix(Namespace namespace) { + String ns = namespace.getDecoded(); + return NamespacesResource.getPrefix(ns); + } + + @Path("{namespace}") + @GET + @Produces(MediaType.TEXT_PLAIN) + public String getPrefixForEncodedNamespace(@PathParam("namespace") String URI) { + URI = Util.URLdecode(URI); + return NamespacesResource.getPrefix(URI); + } + + /** + * SIDEFFECT: URI is added to list of known namespaces if it did not exist + * before + */ + public static String getPrefix(String namespace) { + if (namespace == null) { + throw new IllegalArgumentException("Namespace must not be null"); + } + String prefix = NamespacesResource.INSTANCE.configuration.getString(namespace); + if (prefix == null) { + prefix = NamespacesResource.generatePrefix(namespace); + NamespacesResource.INSTANCE.configuration.setProperty(namespace, prefix); + } + return prefix; + } + + private static String generatePrefix(String namespace) { + String prefix = null; + Collection allPrefixes = NamespacesResource.INSTANCE.getAllPrefixes(); + + // TODO: generate prefix using URI (and not "arbitrary" prefix) + do { + prefix = String.format("ns%d", NamespacesResource.INSTANCE.nsCount); + NamespacesResource.INSTANCE.nsCount++; + } while (allPrefixes.contains(prefix)); + return prefix; + } + + /** + * Returns the list of all namespaces registered with his manager. It could + * be incomplete, if entries have been added manually to the repository + * + * @return all namespaces registered with this manager. + */ + private HashSet getRegisteredNamespaces() { + HashSet res = new HashSet(); + Iterator keys = this.configuration.getKeys(); + while (keys.hasNext()) { + String key = keys.next(); + Namespace ns = new Namespace(key, false); + res.add(ns); + } + return res; + } + + /** + * Returns the list of all namespaces registered with his manager and used + * at component instances. + */ + public static Collection getNamespaces() { + HashSet res = NamespacesResource.INSTANCE.getRegisteredNamespaces(); + res.addAll(Repository.INSTANCE.getUsedNamespaces()); + return res; + } + + /** + * This method is required because static methods cannot be accessed by EL + * + * @return see getNamespaces() + */ + public Collection getNamespacesForJSP() { + return NamespacesResource.getNamespaces(); + } + + /** + * Returns the list of all namespaces registered with his manager and used + * at component instances. + * + * @return a JSON list containing the non-encoded URIs of each known + * namespace + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + public String getNamespacesAsJSONlist() { + Collection namespaces = NamespacesResource.getNamespaces(); + + // We now have all namespaces + // We need to convert from Namespace to String + + TreeSet stringNamespaces = new TreeSet(); + for (Namespace ns : namespaces) { + stringNamespaces.add(ns.getDecoded()); + } + + String res; + try { + res = Utils.mapper.writeValueAsString(stringNamespaces); + } catch (JsonProcessingException e) { + NamespacesResource.logger.error(e.getMessage(), e); + res = "[]"; + } + return res; + } + + /** + * Checks whether a prefix is registered for a namespace + * + * Used at CSARImporter + */ + public boolean getIsPrefixKnownForNamespace(String namespace) { + return this.configuration.containsKey(namespace); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/RepositoryAdminResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/RepositoryAdminResource.java new file mode 100644 index 0000000..408704d --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/RepositoryAdminResource.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.admin; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; + +import org.eclipse.winery.repository.Prefs; +import org.eclipse.winery.repository.backend.IRepositoryAdministration; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.backend.filebased.GitBasedRepository; +import org.restdoc.annotations.RestDoc; +import org.restdoc.annotations.RestDocParam; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jersey.api.view.Viewable; +import com.sun.jersey.core.header.FormDataContentDisposition; +import com.sun.jersey.multipart.FormDataParam; + +public class RepositoryAdminResource { + + private static final Logger logger = LoggerFactory.getLogger(RepositoryAdminResource.class); + + + // @formatter:off + @GET + @Produces(MediaType.TEXT_HTML) // we cannot add MimeTypes.MIMETYPE_ZIP as dumpRepository also produces that mimetype + @RestDoc(methodDescription = "Returns the repository admin page and implements administration utility") + public Response onGet( + @QueryParam(value = "dump") @RestDocParam(description = "If given, a dump of the repository is sent") String dump, + @QueryParam(value = "reset") @RestDocParam(description = "Resets the repository to the last “official” known state") String reset, + @QueryParam(value = "commit") @RestDocParam(description = "Commits the current state to the repository and pushes it upstream") String commit + ) { + // @formatter:on + if (dump != null) { + return this.dumpRepository(); + } else if (reset != null) { + try { + ((GitBasedRepository) Prefs.INSTANCE.getRepository()).cleanAndResetHard(); + } catch (Exception e) { + Response res; + res = Response.serverError().entity(e.getMessage()).build(); + return res; + } + return Response.noContent().build(); + } else if (commit != null) { + try { + ((GitBasedRepository) Prefs.INSTANCE.getRepository()).addCommitPush(); + } catch (Exception e) { + Response res; + res = Response.serverError().entity(e.getMessage()).build(); + return res; + } + return Response.noContent().build(); + } else { + Viewable viewable = new Viewable("/jsp/admin/repository.jsp", this); + return Response.ok().entity(viewable).build(); + } + } + + /** + * Imports the given ZIP + */ + @POST + @Consumes(MediaType.MULTIPART_FORM_DATA) + public Response importRepositoryDump(@FormDataParam("file") InputStream uploadedInputStream, @FormDataParam("file") FormDataContentDisposition fileDetail) { + ((IRepositoryAdministration) Repository.INSTANCE).doImport(uploadedInputStream); + return Response.noContent().build(); + } + + @DELETE + public void deleteRepositoryData() { + ((IRepositoryAdministration) Repository.INSTANCE).doClear(); + } + + @GET + @Produces(org.eclipse.winery.common.constants.MimeTypes.MIMETYPE_ZIP) + public Response dumpRepository() { + StreamingOutput so = new StreamingOutput() { + + @Override + public void write(OutputStream output) throws IOException, WebApplicationException { + ((IRepositoryAdministration) Repository.INSTANCE).doDump(output); + } + }; + StringBuilder sb = new StringBuilder(); + sb.append("attachment;filename=\"repository.zip\""); + return Response.ok().header("Content-Disposition", sb.toString()).type(org.eclipse.winery.common.constants.MimeTypes.MIMETYPE_ZIP).entity(so).build(); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/AbstractTypesManager.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/AbstractTypesManager.java new file mode 100644 index 0000000..bf3c024 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/AbstractTypesManager.java @@ -0,0 +1,204 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.admin.types; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.SortedSet; +import java.util.TreeSet; + +import javax.ws.rs.DELETE; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriInfo; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.repository.datatypes.TypeWithShortName; +import org.eclipse.winery.repository.datatypes.ids.admin.TypesId; +import org.eclipse.winery.repository.datatypes.select2.Select2DataItem; +import org.eclipse.winery.repository.resources.admin.AbstractAdminResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jersey.api.view.Viewable; + +/** + * Handles longname/shortname by using properties + * + * FIXME: This class does NOT support dynamic reloading of the underlying + * Configuration instance + * + */ +public abstract class AbstractTypesManager extends AbstractAdminResource { + + @Context + private UriInfo uriInfo; + + protected static final Logger logger = LoggerFactory.getLogger(AbstractTypesManager.class); + + // hashes from a long type string to the type object holding complete type data + private final HashMap hashTypeStringToType; + + + public AbstractTypesManager(TypesId id) { + super(id); + // now, this.configuration is filled with stored data + + // copy over information from configuration to internal data structure + this.hashTypeStringToType = new HashMap(); + Iterator keys = this.configuration.getKeys(); + while (keys.hasNext()) { + String key = keys.next(); + String value = this.configuration.getString(key); + TypeWithShortName typeInfo = new TypeWithShortName(key, value); + this.hashTypeStringToType.put(key, typeInfo); + } + } + + protected void addData(String longName, String shortName) { + TypeWithShortName t = new TypeWithShortName(longName, shortName); + this.addData(t); + } + + /** + * Adds data to the internal data structure WITHOUT persisting it + * + * More or less a quick hack to enable adding default types without + * persisting them in the storage + * + * @param t the type to add + */ + private void addData(TypeWithShortName t) { + this.hashTypeStringToType.put(t.getType(), t); + } + + public synchronized void addTypeWithShortName(TypeWithShortName type) { + this.addData(type); + this.configuration.setProperty(type.getType(), type.getShortName()); + } + + /** + * Removes a type. Will not remove a type added by "addData" + */ + @DELETE + @Path("{type}") + public Response removeTypeWithResponse(@PathParam("type") String type) { + type = Util.URLdecode(type); + if (this.configuration.containsKey(type)) { + this.hashTypeStringToType.remove(type); + this.configuration.clearProperty(type); + return Response.noContent().build(); + } else if (this.hashTypeStringToType.containsKey(type)) { + // predefined types may not be deleted + // this branch is hit at types added via addData (e.g., predefined plantypes) + return Response.status(Status.FORBIDDEN).build(); + } else { + return Response.status(Status.NOT_FOUND).build(); + } + } + + /** + * Returns a sorted list of all available types + */ + public Collection getTypes() { + Collection res = new TreeSet(this.hashTypeStringToType.values()); + return res; + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + public Object getTypesAsJSONArrayList(@QueryParam("select2") String select2) { + if (select2 == null) { + return this.getTypes(); + } else { + // select2 mode + SortedSet res = new TreeSet<>(); + for (TypeWithShortName t : this.getTypes()) { + Select2DataItem item = new Select2DataItem(t.getType(), t.getShortName()); + res.add(item); + } + return res; + } + } + + /** + * SIDEEFFECT: If there currently isn't any short type name, it is + * created + */ + public TypeWithShortName getTypeWithShortName(String typeString) { + TypeWithShortName t = this.hashTypeStringToType.get(typeString); + if (t == null) { + String shortName = this.getShortName(typeString); + t = new TypeWithShortName(typeString, shortName); + this.addTypeWithShortName(t); + } + return t; + } + + /** + * SIDEEFFECT: If there currently isn't any short type name, it is + * created + */ + public String getShortName(String typeString) { + TypeWithShortName type = this.hashTypeStringToType.get(typeString); + String res; + if (type == null) { + // happens if artifact type is not registered in artifacttypes.list + // (DATAFILENAME) + res = typeString; + } else { + res = type.getShortName(); + } + return res; + } + + @GET + @Produces(MediaType.TEXT_HTML) + public Viewable getHTML(@Context UriInfo uriInfo) { + this.uriInfo = uriInfo; + return new Viewable("/jsp/admin/types/types.jsp", this); + } + + @POST + public Response updateTypeMapping(@FormParam("shortname") String shortName, @FormParam("type") String type) { + if (StringUtils.isEmpty(shortName)) { + return Response.status(Status.BAD_REQUEST).entity("shortName has to be given").build(); + } + if (StringUtils.isEmpty(type)) { + return Response.status(Status.BAD_REQUEST).entity("type has to be given").build(); + } + shortName = Util.URLdecode(shortName); + type = Util.URLdecode(type); + TypeWithShortName tws = new TypeWithShortName(type, shortName); + this.addTypeWithShortName(tws); + return Response.noContent().build(); + } + + /** + * Required by types.jsp + */ + public String getURL() { + return this.uriInfo.getAbsolutePath().toString(); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/ConstraintTypesManager.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/ConstraintTypesManager.java new file mode 100644 index 0000000..d8a9c0e --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/ConstraintTypesManager.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.admin.types; + +import org.eclipse.winery.repository.datatypes.ids.admin.ConstraintTypesId; + +public class ConstraintTypesManager extends AbstractTypesManager { + + public final static ConstraintTypesManager INSTANCE = new ConstraintTypesManager(); + + + private ConstraintTypesManager() { + super(new ConstraintTypesId()); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/PlanLanguagesManager.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/PlanLanguagesManager.java new file mode 100644 index 0000000..e5b35b9 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/PlanLanguagesManager.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.admin.types; + +import org.eclipse.winery.repository.datatypes.ids.admin.PlanLanguagesId; + +public class PlanLanguagesManager extends AbstractTypesManager { + + public final static PlanLanguagesManager INSTANCE = new PlanLanguagesManager(); + + + private PlanLanguagesManager() { + super(new PlanLanguagesId()); + // add data without rendering in the plan languages file + this.addData(org.eclipse.winery.common.constants.Namespaces.URI_BPEL20_EXECUTABLE, "BPEL 2.0 (executable)"); + this.addData(org.eclipse.winery.common.constants.Namespaces.URI_BPMN20_MODEL, "BPMN 2.0"); + this.addData(org.eclipse.winery.common.constants.Namespaces.URI_BPMN4TOSCA_20, "BPMN4TOSCA 2.0"); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/PlanTypesManager.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/PlanTypesManager.java new file mode 100644 index 0000000..de6e7ba --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/types/PlanTypesManager.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.admin.types; + +import org.eclipse.winery.repository.datatypes.ids.admin.PlanTypesId; + +public class PlanTypesManager extends AbstractTypesManager { + + public final static PlanTypesManager INSTANCE = new PlanTypesManager(); + + + private PlanTypesManager() { + super(new PlanTypesId()); + // add data without rendering in the plan types file + this.addData(org.eclipse.winery.repository.Constants.TOSCA_PLANTYPE_BUILD_PLAN, "Build Plan"); + this.addData(org.eclipse.winery.repository.Constants.TOSCA_PLANTYPE_TERMINATION_PLAN, "Termination Plan"); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/DeploymentArtifactResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/DeploymentArtifactResource.java new file mode 100644 index 0000000..ec7a86b --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/DeploymentArtifactResource.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.artifacts; + +import java.util.List; + +import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId; +import org.eclipse.winery.common.ids.definitions.ArtifactTypeId; +import org.eclipse.winery.model.tosca.TDeploymentArtifact; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; + +public class DeploymentArtifactResource extends GenericArtifactResource { + + private final TDeploymentArtifact a; + + + /** + * Converts the given artifactId to an DeploymentArtifact. + * + * SIDE EFFECT Adds it to the DeploymentArtifacts list if it does + * not yet exist. + */ + private static TDeploymentArtifact getDeploymentArtifact(String artifactId, List deploymentArtifacts) { + for (TDeploymentArtifact ia : deploymentArtifacts) { + if (ia.getName().equals(artifactId)) { + return ia; + } + } + // DA does not exist in list + TDeploymentArtifact ia = new TDeploymentArtifact(); + ia.setName(artifactId); + deploymentArtifacts.add(ia); + return ia; + } + + public DeploymentArtifactResource(String artifactId, List deploymentArtifacts, IPersistable res) { + this(DeploymentArtifactResource.getDeploymentArtifact(artifactId, deploymentArtifacts), deploymentArtifacts, res); + } + + public DeploymentArtifactResource(IIdDetermination idDetermination, TDeploymentArtifact o, int idx, List list, IPersistable res) { + super(idDetermination, o, idx, list, res); + this.a = o; + } + + public DeploymentArtifactResource(TDeploymentArtifact deploymentArtifact, List deploymentArtifacts, IPersistable res) { + this(new IIdDetermination() { + + @Override + public String getId(TDeploymentArtifact e) { + return e.getName(); + } + }, deploymentArtifact, deploymentArtifacts.indexOf(deploymentArtifact), deploymentArtifacts, res); + } + + public TDeploymentArtifact getDeploymentArtifact() { + return this.a; + } + + @Override + public void setArtifactType(ArtifactTypeId artifactTypeId) { + this.getDeploymentArtifact().setArtifactType(artifactTypeId.getQName()); + BackendUtils.persist(this.res); + } + + @Override + public void setArtifactTemplate(ArtifactTemplateId artifactTemplateId) { + this.getDeploymentArtifact().setArtifactRef(artifactTemplateId.getQName()); + BackendUtils.persist(this.res); + } + + @Override + public TDeploymentArtifact getA() { + return this.a; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/DeploymentArtifactsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/DeploymentArtifactsResource.java new file mode 100644 index 0000000..dcb5ca7 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/DeploymentArtifactsResource.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.artifacts; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.eclipse.winery.model.tosca.TDeploymentArtifact; +import org.eclipse.winery.model.tosca.TDeploymentArtifacts; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.repository.resources.INodeTemplateResourceOrNodeTypeImplementationResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DeploymentArtifactsResource extends GenericArtifactsResource { + + private static final Logger logger = LoggerFactory.getLogger(DeploymentArtifactsResource.class); + + private List deploymentArtifacts; + + + public DeploymentArtifactsResource(List deploymentArtifact, INodeTemplateResourceOrNodeTypeImplementationResource res) { + super(DeploymentArtifactResource.class, TDeploymentArtifact.class, deploymentArtifact, res); + this.deploymentArtifacts = deploymentArtifact; + } + + /** + * Determines the list of DAs belonging to the given node template. + * + * If no DAs are existing, an empty list is created in the model for the + * node template + */ + private static List getDeploymentArtifacts(TNodeTemplate nodeTemplate) { + TDeploymentArtifacts deploymentArtifacts = nodeTemplate.getDeploymentArtifacts(); + final List res; + if (deploymentArtifacts == null) { + deploymentArtifacts = new TDeploymentArtifacts(); + nodeTemplate.setDeploymentArtifacts(deploymentArtifacts); + } + res = deploymentArtifacts.getDeploymentArtifact(); + return res; + } + + public DeploymentArtifactsResource(TNodeTemplate nodeTemplate, INodeTemplateResourceOrNodeTypeImplementationResource res) { + this(DeploymentArtifactsResource.getDeploymentArtifacts(nodeTemplate), res); + } + + @Override + public Collection getAllArtifactResources() { + Collection res = new ArrayList(this.deploymentArtifacts.size()); + for (TDeploymentArtifact da : this.deploymentArtifacts) { + DeploymentArtifactResource r = new DeploymentArtifactResource(da, this.deploymentArtifacts, this.res); + res.add(r); + } + return res; + } + + @Override + public String getId(TDeploymentArtifact entity) { + return entity.getName(); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactResource.java new file mode 100644 index 0000000..9295082 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactResource.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.artifacts; + +import java.util.List; + +import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId; +import org.eclipse.winery.common.ids.definitions.ArtifactTypeId; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource; + +/** + * Currently no common things for deployment artifacts and implementation + * artifacts as the data model also has no common ancestor (besides + * TExensibleElement) + */ +public abstract class GenericArtifactResource extends EntityWithIdResource { + + public GenericArtifactResource(IIdDetermination idDetermination, ArtifactT o, int idx, List list, IPersistable res) { + super(idDetermination, o, idx, list, res); + } + + public abstract void setArtifactType(ArtifactTypeId artifactTypeId); + + public abstract void setArtifactTemplate(ArtifactTemplateId artifactTemplateId); + + /** + * required by artifacts.jsp + */ + public abstract ArtifactT getA(); + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactsResource.java new file mode 100644 index 0000000..0cef56e --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactsResource.java @@ -0,0 +1,572 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.artifacts; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.SortedSet; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriInfo; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.common.ids.Namespace; +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId; +import org.eclipse.winery.common.ids.definitions.ArtifactTypeId; +import org.eclipse.winery.common.ids.definitions.NodeTypeId; +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.generators.ia.Generator; +import org.eclipse.winery.model.tosca.TDeploymentArtifact; +import org.eclipse.winery.model.tosca.TEntityTemplate.Properties; +import org.eclipse.winery.model.tosca.TImplementationArtifacts.ImplementationArtifact; +import org.eclipse.winery.model.tosca.TInterface; +import org.eclipse.winery.model.tosca.TNodeType; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.backend.ResourceCreationResult; +import org.eclipse.winery.repository.backend.filebased.FileUtils; +import org.eclipse.winery.repository.datatypes.ids.elements.ArtifactTemplateDirectoryId; +import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource; +import org.eclipse.winery.repository.resources.AbstractComponentsResource; +import org.eclipse.winery.repository.resources.IHasTypeReference; +import org.eclipse.winery.repository.resources.INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource; +import org.eclipse.winery.repository.resources.entitytemplates.PropertiesResource; +import org.eclipse.winery.repository.resources.entitytemplates.artifacttemplates.ArtifactTemplateResource; +import org.eclipse.winery.repository.resources.entitytypeimplementations.EntityTypeImplementationResource; +import org.eclipse.winery.repository.resources.entitytypeimplementations.nodetypeimplementations.NodeTypeImplementationResource; +import org.eclipse.winery.repository.resources.entitytypeimplementations.relationshiptypeimplementations.RelationshipTypeImplementationResource; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource; +import org.eclipse.winery.repository.resources.servicetemplates.topologytemplates.NodeTemplateResource; +import org.restdoc.annotations.RestDoc; +import org.restdoc.annotations.RestDocParam; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Text; +import org.xml.sax.InputSource; + +import com.sun.jersey.api.view.Viewable; + +/** + * Resource handling both deployment and implementation artifacts + * + */ +public abstract class GenericArtifactsResource, ArtifactT> extends EntityWithIdCollectionResource { + + private static final Logger logger = LoggerFactory.getLogger(GenericArtifactsResource.class); + + protected final INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource resWithNamespace; + + + public GenericArtifactsResource(Class entityResourceTClazz, Class entityTClazz, List list, INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource res) { + super(entityResourceTClazz, entityTClazz, list, GenericArtifactsResource.getAbstractComponentInstanceResource(res)); + this.resWithNamespace = res; + } + + // @formatter:off + + /** + * @return TImplementationArtifact | TDeploymentArtifact (XML) | URL of generated IA zip (in case of autoGenerateIA) + */ + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + @Produces(MediaType.TEXT_XML) + @RestDoc(methodDescription = "Creates a new implementation/deployment artifact. " + + "If an implementation artifact with the same name already exists, it is overridden.") + @SuppressWarnings("unchecked") + public Response onPost( + @FormParam("artifactName") + @RestDocParam(description = "This is the name of the implementation/deployment artifact. " + + "Is alsoused as prefix of the name of the corresponding artifact template if no specific template is provided. " + + "In contrast to CS01, we require a artifactName also for the implementationArtifact to be able to properly referencing it.") + String artifactNameStr, + + @FormParam("artifactTemplate") + @RestDocParam(description = "QName of the artifact Template - used by Winery Backend instead of artifactTemplateName + artifactTemplateNS") + String artifactTemplate, + + @FormParam("artifactTemplateName") + @RestDocParam(description = "if provided and autoCreateArtifactTemplate, a template of this id localname and artifactTemplateNS generated. " + + "Winery always sends this string if auto creation is desired.") + String artifactTemplateName, + + @FormParam("artifactTemplateNS") + String artifactTemplateNS, + + @FormParam("autoCreateArtifactTemplate") + @RestDocParam(description = "if empty, no, or false, no artifact template is created. " + + "An artifact type has to be given in that case. " + + "Furthermore, an artifact template name + artifact template namespace has to be provided. " + + "Otherwise, the artifactNameStr is used as name for the artifact and a new artifact template is created having {@code Template} as name") + String autoCreateArtifactTemplate, + + @FormParam("artifactType") + @RestDocParam(description = "QName of the type, format: {namespace}localname. " + + "Optional if artifactTemplateName + artifactTempalteNS is provided") + String artifactTypeStr, + + @FormParam("artifactSpecificContent") + @RestDocParam(description = "XML snippet that should be put inside the artifact XML in the TOSCA serialization. " + + "This feature will be removed soon. " + + "TODO: This only works if there is a single child element expected and not several elements. " + + "Future versions of the Winery will support arbitrary content there.") + String artifactSpecificContent, + + @FormParam("interfaceName") + String interfaceNameStr, + + @FormParam("operationName") + String operationNameStr, + + @FormParam("autoGenerateIA") + @RestDocParam(description = "If not empty, the IA generator will be called") + String autoGenerateIA, + + @FormParam("javapackage") + @RestDocParam(description = "The Java package to use for IA generation") + String javapackage, + + @Context UriInfo uriInfo + ){ + // we assume that the parent ComponentInstance container exists + + // @formatter:on + + if (StringUtils.isEmpty(artifactNameStr)) { + return Response.status(Status.BAD_REQUEST).entity("Empty artifactName").build(); + } + if (StringUtils.isEmpty(artifactTypeStr)) { + if (StringUtils.isEmpty(artifactTemplateName) || StringUtils.isEmpty(artifactTemplateNS)) { + if (StringUtils.isEmpty(artifactTemplate)) { + return Response.status(Status.BAD_REQUEST).entity("No artifact type given and no template given. Cannot guess artifact type").build(); + } + } + } + + if (!StringUtils.isEmpty(autoGenerateIA)) { + if (StringUtils.isEmpty(javapackage)) { + return Response.status(Status.BAD_REQUEST).entity("no java package name supplied for IA auto generation.").build(); + } + if (StringUtils.isEmpty(interfaceNameStr)) { + return Response.status(Status.BAD_REQUEST).entity("no interface name supplied for IA auto generation.").build(); + } + } + + // convert second calling form to first calling form + if (!StringUtils.isEmpty(artifactTemplate)) { + QName qname = QName.valueOf(artifactTemplate); + artifactTemplateName = qname.getLocalPart(); + artifactTemplateNS = qname.getNamespaceURI(); + } + + Document doc = null; + + // check artifact specific content for validity + // if invalid, abort and do not create anything + if (!StringUtils.isEmpty(artifactSpecificContent)) { + try { + DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + InputSource is = new InputSource(); + StringReader sr = new StringReader(artifactSpecificContent); + is.setCharacterStream(sr); + doc = db.parse(is); + } catch (Exception e) { + // FIXME: currently we allow a single element only. However, the content should be internally wrapped by an (arbitrary) XML element as the content will be nested in the artifact element, too + GenericArtifactsResource.logger.debug("Invalid content", e); + return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); + } + } + + // determine artifactTemplate and artifactType + + ArtifactTypeId artifactTypeId; + ArtifactTemplateId artifactTemplateId = null; + ArtifactTemplateResource artifactTemplateResource = null; + + boolean doAutoCreateArtifactTemplate = !(StringUtils.isEmpty(autoCreateArtifactTemplate) || autoCreateArtifactTemplate.equalsIgnoreCase("no") || autoCreateArtifactTemplate.equalsIgnoreCase("false")); + if (!doAutoCreateArtifactTemplate) { + // no auto creation + if (!StringUtils.isEmpty(artifactTemplateName) && !StringUtils.isEmpty(artifactTemplateNS)) { + QName artifactTemplateQName = new QName(artifactTemplateNS, artifactTemplateName); + artifactTemplateId = BackendUtils.getTOSCAcomponentId(ArtifactTemplateId.class, artifactTemplateQName); + } + if (StringUtils.isEmpty(artifactTypeStr)) { + // derive the type from the artifact template + if (artifactTemplateId == null) { + return Response.status(Status.NOT_ACCEPTABLE).entity("No artifactTemplate and no artifactType provided. Deriving the artifactType is not possible.").build(); + } + artifactTemplateResource = new ArtifactTemplateResource(artifactTemplateId); + artifactTypeId = BackendUtils.getTOSCAcomponentId(ArtifactTypeId.class, artifactTemplateResource.getType()); + } else { + // artifactTypeStr is directly given, use that + artifactTypeId = BackendUtils.getTOSCAcomponentId(ArtifactTypeId.class, artifactTypeStr); + } + } else { + // do the artifact template auto creation magic + + if (StringUtils.isEmpty(artifactTypeStr)) { + return Response.status(Status.BAD_REQUEST).entity("Artifact template auto creation requested, but no artifact type supplied.").build(); + } + + // we assume that the type points to a valid artifact type + artifactTypeId = BackendUtils.getTOSCAcomponentId(ArtifactTypeId.class, artifactTypeStr); + + if (StringUtils.isEmpty(artifactTemplateName) || StringUtils.isEmpty(artifactTemplateNS)) { + // no explicit name provided + // we use the artifactNameStr as prefix for the + // artifact template name + + // we create a new artifact template in the namespace of the parent + // element + Namespace namespace = this.resWithNamespace.getNamespace(); + + artifactTemplateId = new ArtifactTemplateId(namespace, new XMLId(artifactNameStr + "artifactTemplate", false)); + } else { + QName artifactTemplateQName = new QName(artifactTemplateNS, artifactTemplateName); + artifactTemplateId = new ArtifactTemplateId(artifactTemplateQName); + } + ResourceCreationResult creationResult = BackendUtils.create(artifactTemplateId); + if (!creationResult.isSuccess()) { + // something went wrong. skip + return creationResult.getResponse(); + } + + // associate the type to the created artifact template + artifactTemplateResource = new ArtifactTemplateResource(artifactTemplateId); + // set the type. The resource is automatically persisted inside + artifactTemplateResource.setType(artifactTypeStr); + } + + // variable artifactTypeId is set + // variable artifactTemplateId is not null if artifactTemplate has been generated + + // we have to generate the DA/IA resource now + // Doing it here instead of doing it at the subclasses is dirty on the + // one hand, but quicker to implement on the other hand + + // Create the artifact itself + + ArtifactT resultingArtifact; + + if (this instanceof ImplementationArtifactsResource) { + ImplementationArtifact a = new ImplementationArtifact(); + // Winery internal id is the name of the artifact: + // store the name + a.setName(artifactNameStr); + a.setInterfaceName(interfaceNameStr); + a.setOperationName(operationNameStr); + assert (artifactTypeId != null); + a.setArtifactType(artifactTypeId.getQName()); + if (artifactTemplateId != null) { + a.setArtifactRef(artifactTemplateId.getQName()); + } + if (doc != null) { + // the content has been checked for validity at the beginning of the method. + // If this point in the code is reached, the XML has been parsed into doc + // just copy over the dom node. Hopefully, that works... + a.getAny().add(doc.getDocumentElement()); + } + + this.list.add((ArtifactT) a); + resultingArtifact = (ArtifactT) a; + } else { + // for comments see other branch + + TDeploymentArtifact a = new TDeploymentArtifact(); + a.setName(artifactNameStr); + assert (artifactTypeId != null); + a.setArtifactType(artifactTypeId.getQName()); + if (artifactTemplateId != null) { + a.setArtifactRef(artifactTemplateId.getQName()); + } + if (doc != null) { + a.getAny().add(doc.getDocumentElement()); + } + + this.list.add((ArtifactT) a); + resultingArtifact = (ArtifactT) a; + } + + Response persistResponse = BackendUtils.persist(super.res); + // TODO: check for error and in case one found return that + + if (StringUtils.isEmpty(autoGenerateIA)) { + // no IA generation + // we include an XML for the data table + + String implOrDeplArtifactXML = Utils.getXMLAsString(resultingArtifact); + + return Response.created(Utils.createURI(Util.URLencode(artifactNameStr))).entity(implOrDeplArtifactXML).build(); + } else { + // after everything was created, we fire up the artifact generation + return this.generateImplementationArtifact(interfaceNameStr, javapackage, uriInfo, artifactTemplateId, artifactTemplateResource); + } + } + + /** + * Generates a unique and valid name to be used for the generated maven + * project name, java project name, class name, port type name. + */ + private String generateName(NodeTypeId nodeTypeId, String interfaceName) { + String name = Util.namespaceToJavaPackage(nodeTypeId.getNamespace().getDecoded()); + name += Util.FORBIDDEN_CHARACTER_REPLACEMENT; + + // Winery already ensures that this is a valid NCName + // getName() returns the id of the nodeType: A nodeType carries the "id" attribute only (and no name attribute) + name += nodeTypeId.getXmlId().getDecoded(); + + // Two separators to distinguish node type and interface part + name += Util.FORBIDDEN_CHARACTER_REPLACEMENT; + name += Util.FORBIDDEN_CHARACTER_REPLACEMENT; + name += Util.namespaceToJavaPackage(interfaceName); + + // In addition we must replace '.', because Java class names must not + // contain dots, but for Winery they are fine. + return name.replace(".", Util.FORBIDDEN_CHARACTER_REPLACEMENT); + } + + /** + * Generates the implementation artifact using the implementation artifact + * generator. Also sets the proeprties according to the requirements of + * OpenTOSCA. + * + * @param interfaceNameStr + * @param javapackage + * @param uriInfo + * @param artifactTemplateId + * @param artifactTemplateResource the resource associated with the + * artifactTempalteId. If null, the object is created in this + * method + * + * @return {@inheritDoc} + */ + private Response generateImplementationArtifact(String interfaceNameStr, String javapackage, UriInfo uriInfo, ArtifactTemplateId artifactTemplateId, ArtifactTemplateResource artifactTemplateResource) { + TInterface iface; + + assert (this instanceof ImplementationArtifactsResource); + IHasTypeReference typeRes = (EntityTypeImplementationResource) this.res; + QName type = typeRes.getType(); + TOSCAComponentId typeId; + TNodeType nodeType = null; + if (typeRes instanceof NodeTypeImplementationResource) { + // TODO: refactor: This is more a model/repo utilities thing than something which should happen here... + + typeId = new NodeTypeId(type); + NodeTypeResource ntRes = (NodeTypeResource) AbstractComponentsResource.getComponentInstaceResource(typeId); + + // required for IA Generation + nodeType = ntRes.getNodeType(); + + List interfaces = nodeType.getInterfaces().getInterface(); + Iterator it = interfaces.iterator(); + do { + iface = it.next(); + if (iface.getName().equals(interfaceNameStr)) { + break; + } + } while (it.hasNext()); + // iface now contains the right interface + } else { + assert (typeRes instanceof RelationshipTypeImplementationResource); + return Response.serverError().entity("IA creation for relation ship type implementations not yet possible").build(); + } + + Path workingDir; + try { + workingDir = Files.createTempDirectory("winery"); + } catch (IOException e2) { + GenericArtifactsResource.logger.debug("Could not create temporary directory", e2); + return Response.serverError().entity("Could not create temporary directory").build(); + } + + URI artifactTemplateFilesUri = uriInfo.getBaseUri().resolve(Utils.getAbsoluteURL(artifactTemplateId)).resolve("files/"); + URL artifactTemplateFilesUrl; + try { + artifactTemplateFilesUrl = artifactTemplateFilesUri.toURL(); + } catch (MalformedURLException e2) { + GenericArtifactsResource.logger.debug("Could not convert URI to URL", e2); + return Response.serverError().entity("Could not convert URI to URL").build(); + } + + String name = this.generateName((NodeTypeId) typeId, interfaceNameStr); + Generator gen = new Generator(iface, javapackage, artifactTemplateFilesUrl, name, workingDir.toFile()); + File zipFile = gen.generateProject(); + if (zipFile == null) { + return Response.serverError().entity("IA generator failed").build(); + } + + // store it + // TODO: refactor: this is more a RepositoryUtils thing than a special thing here; see also importFile at CSARImporter + + ArtifactTemplateDirectoryId fileDir = new ArtifactTemplateDirectoryId(artifactTemplateId); + RepositoryFileReference fref = new RepositoryFileReference(fileDir, zipFile.getName().toString()); + try (InputStream is = Files.newInputStream(zipFile.toPath()); + BufferedInputStream bis = new BufferedInputStream(is)) { + String mediaType = Utils.getMimeType(bis, zipFile.getName()); + // TODO: do the catch thing as in CSARImporter + + Repository.INSTANCE.putContentToFile(fref, bis, MediaType.valueOf(mediaType)); + } catch (IOException e1) { + throw new IllegalStateException("Could not import generated files", e1); + } + + // cleanup dir + try { + FileUtils.forceDelete(workingDir); + } catch (IOException e) { + GenericArtifactsResource.logger.debug("Could not delete working directory", e); + } + + // store the properties in the artifact template + if (artifactTemplateResource == null) { + artifactTemplateResource = (ArtifactTemplateResource) AbstractComponentsResource.getComponentInstaceResource(artifactTemplateId); + } + this.storeProperties(artifactTemplateResource, typeId, name); + + URI url = uriInfo.getBaseUri().resolve(Utils.getAbsoluteURL(fref)); + return Response.created(url).build(); + } + + + private final String NS_OPENTOSCA_WAR_TYPE = "http://www.uni-stuttgart.de/opentosca"; + + + private void storeProperties(ArtifactTemplateResource artifactTemplateResource, TOSCAComponentId typeId, String name) { + // We generate the properties by hand instead of using JAX-B as using JAX-B causes issues at org.eclipse.winery.common.ModelUtilities.getPropertiesKV(TEntityTemplate): + // getAny() does not always return "w3c.dom.element" anymore + + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder; + try { + builder = dbf.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + GenericArtifactsResource.logger.error(e.getMessage(), e); + return; + } + Document doc = builder.newDocument(); + Element root = doc.createElementNS(this.NS_OPENTOSCA_WAR_TYPE, "WSProperties"); + doc.appendChild(root); + + Element element = doc.createElementNS(this.NS_OPENTOSCA_WAR_TYPE, "ServiceEndpoint"); + Text text = doc.createTextNode("/services/" + name + "Port"); + element.appendChild(text); + root.appendChild(element); + + element = doc.createElementNS(this.NS_OPENTOSCA_WAR_TYPE, "PortType"); + text = doc.createTextNode("{" + typeId.getNamespace().getDecoded() + "}" + name); + element.appendChild(text); + root.appendChild(element); + + element = doc.createElementNS(this.NS_OPENTOSCA_WAR_TYPE, "InvocationType"); + text = doc.createTextNode("SOAP/HTTP"); + element.appendChild(text); + root.appendChild(element); + + Properties properties = new Properties(); + properties.setAny(root); + PropertiesResource propertiesResource = artifactTemplateResource.getPropertiesResource(); + propertiesResource.setProperties(properties); + } + + @Override + public Viewable getHTML() { + return new Viewable("/jsp/artifacts/artifacts.jsp", this); + } + + /** + * Required for artifacts.jsp + * + * @return list of known artifact types. + */ + public List getAllArtifactTypes() { + SortedSet allArtifactTypes = Repository.INSTANCE.getAllTOSCAComponentIds(ArtifactTypeId.class); + List res = new ArrayList(allArtifactTypes.size()); + for (ArtifactTypeId id : allArtifactTypes) { + res.add(id.getQName()); + } + return res; + } + + /** + * Required for artifacts.jsp + * + * @return list of all contained artifacts. + */ + public abstract Collection getAllArtifactResources(); + + /** + * Required by artifact.jsp to decide whether to display + * "Deployment Artifact" or "Implementation Artifact" + */ + public boolean getIsDeploymentArtifacts() { + boolean res = (this instanceof DeploymentArtifactsResource); + return res; + } + + /** + * required by artifacts.jsp + */ + public String getNamespace() { + return this.resWithNamespace.getNamespace().getDecoded(); + } + + /** + * For saving resources, an AbstractComponentInstanceResource is required. + * DAs may be attached to a node template, which is not an + * AbstractComponentInstanceResource, but its grandparent resource + * ServiceTemplate is + * + * @param res the resource to determine the the + * AbstractComponentInstanceResource for + * @return the AbstractComponentInstanceResource where the given res is + * contained in + */ + public static AbstractComponentInstanceResource getAbstractComponentInstanceResource(INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource res) { + final AbstractComponentInstanceResource r; + if (res instanceof NodeTemplateResource) { + r = ((NodeTemplateResource) res).getServiceTemplateResource(); + } else { + // quick hack: the resource has to be an abstract component instance + r = (AbstractComponentInstanceResource) res; + } + return r; + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/ImplementationArtifactResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/ImplementationArtifactResource.java new file mode 100644 index 0000000..bc5580c --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/ImplementationArtifactResource.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.artifacts; + +import java.util.List; + +import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId; +import org.eclipse.winery.common.ids.definitions.ArtifactTypeId; +import org.eclipse.winery.model.tosca.TImplementationArtifacts.ImplementationArtifact; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; + +public class ImplementationArtifactResource extends GenericArtifactResource { + + private ImplementationArtifact a; + + + /** + * Converts the given artifactId to an ImplementArtifact. + * + * SIDE EFFECT Adds it to the implementationArtifacts list if it + * does not yet exist. + */ + private static ImplementationArtifact getImplementationArtifact(String artifactId, List implementationArtifacts) { + if (artifactId == null) { + throw new IllegalArgumentException("artifactId must not be null"); + } + if (implementationArtifacts == null) { + throw new IllegalArgumentException("implementationArtifacts must not be null"); + } + for (ImplementationArtifact ia : implementationArtifacts) { + // ia.getName() might be null as TOSCA COS01 does not forsee a name on the implementation artifact + // Therefore, we begin the test with "artifactId" + if (artifactId.equals(ia.getName())) { + return ia; + } + } + // IA does not exist in list + ImplementationArtifact ia = new ImplementationArtifact(); + ia.setName(artifactId); + implementationArtifacts.add(ia); + return ia; + } + + public ImplementationArtifactResource(String artifactId, List implementationArtifacts, IPersistable res) { + this(ImplementationArtifactResource.getImplementationArtifact(artifactId, implementationArtifacts), implementationArtifacts, res); + } + + public ImplementationArtifactResource(IIdDetermination idDetermination, ImplementationArtifact o, int idx, List list, IPersistable res) { + super(idDetermination, o, idx, list, res); + this.a = o; + } + + public ImplementationArtifactResource(ImplementationArtifact a, List implementationArtifacts, IPersistable res) { + this(new IIdDetermination() { + + @Override + public String getId(ImplementationArtifact e) { + return e.getName(); + } + }, a, implementationArtifacts.indexOf(a), implementationArtifacts, res); + } + + public ImplementationArtifact getImplementationArtifact() { + return this.a; + } + + @Override + public void setArtifactType(ArtifactTypeId artifactTypeId) { + this.getImplementationArtifact().setArtifactType(artifactTypeId.getQName()); + BackendUtils.persist(this.res); + } + + @Override + public void setArtifactTemplate(ArtifactTemplateId artifactTemplateId) { + this.getImplementationArtifact().setArtifactRef(artifactTemplateId.getQName()); + BackendUtils.persist(this.res); + } + + @Override + public ImplementationArtifact getA() { + return this.a; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/ImplementationArtifactsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/ImplementationArtifactsResource.java new file mode 100644 index 0000000..e1d7aa6 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/ImplementationArtifactsResource.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.artifacts; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.eclipse.winery.model.tosca.TImplementationArtifacts.ImplementationArtifact; +import org.eclipse.winery.repository.resources.INodeTypeImplementationResourceOrRelationshipTypeImplementationResource; +import org.eclipse.winery.repository.resources.entitytypeimplementations.nodetypeimplementations.NodeTypeImplementationResource; +import org.eclipse.winery.repository.resources.entitytypeimplementations.relationshiptypeimplementations.RelationshipTypeImplementationResource; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypesResource; +import org.eclipse.winery.repository.resources.entitytypes.relationshiptypes.RelationshipTypeResource; +import org.eclipse.winery.repository.resources.entitytypes.relationshiptypes.RelationshipTypesResource; +import org.eclipse.winery.repository.resources.interfaces.InterfaceResource; + +/** + * ImplementationArtifact instead of TImplementationArtifact has to be used + * because of difference in the XSD at tImplementationArtifacts vs. + * tDeploymentArtifacts + */ +public class ImplementationArtifactsResource extends GenericArtifactsResource { + + private List implementationArtifacts; + + + public ImplementationArtifactsResource(List implementationArtifact, INodeTypeImplementationResourceOrRelationshipTypeImplementationResource res) { + super(ImplementationArtifactResource.class, ImplementationArtifact.class, implementationArtifact, res); + this.implementationArtifacts = implementationArtifact; + } + + /** + * @return a cast to TNodeTypeImplementationResource of the parent of this + * resource. + */ + protected NodeTypeImplementationResource getNTI() { + return (NodeTypeImplementationResource) this.res; + } + + /** + * @return a cast to TNodeTypeImplementationResource of the parent of this + * resource. + */ + protected RelationshipTypeImplementationResource getRTI() { + return (RelationshipTypeImplementationResource) this.res; + } + + @Override + public Collection getAllArtifactResources() { + Collection res = new ArrayList(this.implementationArtifacts.size()); + for (ImplementationArtifact da : this.implementationArtifacts) { + ImplementationArtifactResource r = new ImplementationArtifactResource(da, this.implementationArtifacts, this.res); + res.add(r); + } + return res; + } + + /** required by artifacts.jsp **/ + public List getInterfacesOfAssociatedType() { + boolean isNodeTypeImplementation = this.res instanceof NodeTypeImplementationResource; + QName type; + List interfaces = new ArrayList(); + if (isNodeTypeImplementation) { + type = this.getNTI().getType(); + NodeTypeResource typeResource = (NodeTypeResource) new NodeTypesResource().getComponentInstaceResource(type); + interfaces.addAll(typeResource.getInterfaces().getAllEntityResources()); + } else { + type = this.getRTI().getType(); + RelationshipTypeResource typeResource = (RelationshipTypeResource) new RelationshipTypesResource().getComponentInstaceResource(type); + interfaces.addAll(typeResource.getSourceInterfaces().getAllEntityResources()); + interfaces.addAll(typeResource.getTargetInterfaces().getAllEntityResources()); + } + return interfaces; + } + + @Override + public String getId(ImplementationArtifact entity) { + return entity.getName(); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/documentation/DocumentationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/documentation/DocumentationResource.java new file mode 100644 index 0000000..6783948 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/documentation/DocumentationResource.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.documentation; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.PUT; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.eclipse.winery.model.tosca.TDocumentation; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.CollectionsHelper; +import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdResource; + +public class DocumentationResource extends EntityWithoutIdResource { + + public DocumentationResource(TDocumentation o, int idx, List list, IPersistable res) { + super(o, idx, list, res); + } + + @PUT + @Consumes(MediaType.TEXT_HTML) + @Produces(MediaType.TEXT_PLAIN) + public Response setValue(String documentation) { + this.o.getContent().clear(); + this.o.getContent().add(documentation); + this.list.set(this.idx, this.o); + return CollectionsHelper.persist(this.res, this.idDetermination, this.o); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/documentation/DocumentationsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/documentation/DocumentationsResource.java new file mode 100644 index 0000000..1466a57 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/documentation/DocumentationsResource.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.documentation; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.eclipse.winery.model.tosca.TDocumentation; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.CollectionsHelper; +import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdCollectionResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jersey.api.view.Viewable; + +public class DocumentationsResource extends EntityWithoutIdCollectionResource { + + private static final Logger logger = LoggerFactory.getLogger(DocumentationResource.class); + + + public DocumentationsResource(IPersistable res, List documentations) { + super(DocumentationResource.class, TDocumentation.class, documentations, res); + } + + @Override + public Viewable getHTML() { + return new Viewable("/jsp/documentation.jsp", this.list); + } + + /** + * Adds a new documentation + */ + @POST + @Consumes(MediaType.TEXT_HTML) + public Response addNewElement(String documentation) { + if (documentation == null) { + return Response.status(Status.BAD_REQUEST).entity("No content provided").build(); + } + TDocumentation doc = new TDocumentation(); + doc.getContent().add(documentation); + // TODO: check for duplicates as in instance states + this.list.add(doc); + return CollectionsHelper.persist(this.res, this, doc); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/IEntityTemplateResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/IEntityTemplateResource.java new file mode 100644 index 0000000..e5025b1 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/IEntityTemplateResource.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytemplates; + +import javax.ws.rs.DELETE; +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; + +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource; +import org.eclipse.winery.repository.resources.IHasTypeReference; + +/** + * Interface ensuring that no methods are forgotten when implementing an + * {@link AbstractComponentInstanceResource}, which is also a template + */ +public interface IEntityTemplateResource extends IHasTypeReference { + + @Path("properties/") + public PropertiesResource getPropertiesResource(); + + @DELETE + public Response onDelete(); + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/PropertiesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/PropertiesResource.java new file mode 100644 index 0000000..4341095 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/PropertiesResource.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytemplates; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource; + +import com.sun.jersey.api.view.Viewable; + +public class PropertiesResource { + + private AbstractComponentInstanceResource res; + private TEntityTemplate template; + + + /** + * @param template the template to store the definitions at + * @param res the resource to save after modifications + */ + public PropertiesResource(TEntityTemplate template, AbstractComponentInstanceResource res) { + this.template = template; + this.res = res; + } + + /** + * Currently, properties can only be updated as a whole XML fragment + * + * Getting/setting a fragment of properties is not possible yet + */ + @PUT + @Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON}) + public Response setProperties(TEntityTemplate.Properties properties) { + this.getTemplate().setProperties(properties); + return BackendUtils.persist(this.res); + } + + @GET + @Produces(MediaType.TEXT_HTML) + public Viewable getHTML() { + return new Viewable("/jsp/entitytemplates/properties.jsp", this); + } + + /** data for the JSP **/ + + public TEntityTemplate getTemplate() { + return this.template; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/TEntityTemplateResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/TEntityTemplateResource.java new file mode 100644 index 0000000..ee9064b --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/TEntityTemplateResource.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2012-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytemplates; + +import java.util.List; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; +import javax.xml.namespace.QName; + +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource; +import org.eclipse.winery.repository.resources.IHasTypeReference; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource; + +public class TEntityTemplateResource extends EntityWithIdResource implements IEntityTemplateResource, IHasTypeReference { + + /** + * This constructor is used for both entity templates nested in an component + * instance as well as for entity templates being component instances + * itself. + * + * As Java does not support multi-inheritance, we implemented a quick hack + * to re-use this class as inner implementation at templates extending + * AbstractComponentInstanceResourceDefinitionsBacked + */ + public TEntityTemplateResource(IIdDetermination idDetermination, E o, int idx, List list, IPersistable res) { + super(idDetermination, o, idx, list, res); + } + + // public String getId() { + // return this.template.getId(); + // } + // + // public void setId(String id) { + // // TODO: There is no check for uniqueness of the given id + // this.template.setId(id); + // } + + /** + * {@inheritDoc} + */ + @Override + public QName getType() { + return this.o.getType(); + } + + @Path("type") + @GET + public String getTypeAsQNameString() { + return this.getType().toString(); + } + + /** + * {@inheritDoc} + */ + @Override + public Response setType(QName type) { + this.o.setType(type); + return BackendUtils.persist(this.res); + } + + /** + * {@inheritDoc} + */ + @Override + public Response setType(String typeStr) { + return this.setType(QName.valueOf(typeStr)); + } + + /** + * {@inheritDoc} + */ + @Override + public PropertiesResource getPropertiesResource() { + return new PropertiesResource(this.o, (AbstractComponentInstanceResource) this.res); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/TEntityTemplatesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/TEntityTemplatesResource.java new file mode 100644 index 0000000..256e376 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/TEntityTemplatesResource.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2012-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytemplates; + +import java.util.List; + +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource; + +/** + * This resource models the list of TEntityTemplates + */ +public abstract class TEntityTemplatesResource, T extends TEntityTemplate> extends EntityWithIdCollectionResource { + + public TEntityTemplatesResource(Class entityResourceTClazz, Class entityTClazz, List list, IPersistable res) { + super(entityResourceTClazz, entityTClazz, list, res); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/ArtifactTemplateResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/ArtifactTemplateResource.java new file mode 100644 index 0000000..f3ed0e9 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/ArtifactTemplateResource.java @@ -0,0 +1,308 @@ +/******************************************************************************* + * Copyright (c) 2012-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytemplates.artifacttemplates; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.SortedSet; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.xml.namespace.QName; + +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId; +import org.eclipse.winery.common.ids.definitions.ArtifactTypeId; +import org.eclipse.winery.common.ids.definitions.NodeTypeImplementationId; +import org.eclipse.winery.common.ids.definitions.RelationshipTypeImplementationId; +import org.eclipse.winery.common.ids.definitions.ServiceTemplateId; +import org.eclipse.winery.model.tosca.TArtifactReference; +import org.eclipse.winery.model.tosca.TArtifactTemplate; +import org.eclipse.winery.model.tosca.TArtifactTemplate.ArtifactReferences; +import org.eclipse.winery.model.tosca.TDeploymentArtifact; +import org.eclipse.winery.model.tosca.TDeploymentArtifacts; +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.model.tosca.TImplementationArtifact; +import org.eclipse.winery.model.tosca.TImplementationArtifacts; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TTopologyTemplate; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.datatypes.ids.elements.ArtifactTemplateDirectoryId; +import org.eclipse.winery.repository.resources.AbstractComponentInstanceWithReferencesResource; +import org.eclipse.winery.repository.resources.AbstractComponentsResource; +import org.eclipse.winery.repository.resources.IHasName; +import org.eclipse.winery.repository.resources.entitytemplates.IEntityTemplateResource; +import org.eclipse.winery.repository.resources.entitytemplates.PropertiesResource; +import org.eclipse.winery.repository.resources.entitytemplates.TEntityTemplateResource; +import org.eclipse.winery.repository.resources.entitytypeimplementations.nodetypeimplementations.NodeTypeImplementationResource; +import org.eclipse.winery.repository.resources.entitytypeimplementations.relationshiptypeimplementations.RelationshipTypeImplementationResource; +import org.eclipse.winery.repository.resources.entitytypes.artifacttypes.ArtifactTypeResource; +import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource; + +/** + * Models an Artifact Template with its artifact references + * + * The associated files (through tArtifactReference) are stored directly within + * this resource. The element is generated during export + * only + * + * This class inherits from AbstractComponentInstanceResourceDefinitionsBacked + * and not from TEntityTemplateResource, because + * ArtifactTemplates are directly available under TDefinitions and we need the + * generic resource handling + */ + +public class ArtifactTemplateResource extends AbstractComponentInstanceWithReferencesResource implements IEntityTemplateResource, IHasName { + + private final TEntityTemplateResource entityTemplateResource; + + + public ArtifactTemplateResource(ArtifactTemplateId id) { + super(id); + // we provide the minimum requirements for the resource + this.entityTemplateResource = new TEntityTemplateResource(null, this.getTArtifactTemplate(), 0, null, this); + } + + /** + * @return null if no artifact type resource is defined + */ + public ArtifactTypeResource getAritfactTypeResource() { + ArtifactTypeId atId = new ArtifactTypeId(this.getTArtifactTemplate().getType()); + return new ArtifactTypeResource(atId); + } + + private TArtifactTemplate getTArtifactTemplate() { + return (TArtifactTemplate) this.element; + } + + @Override + public String getName() { + String name = this.getTArtifactTemplate().getName(); + if (name == null) { + return this.getTArtifactTemplate().getId(); + } else { + return name; + } + } + + @Override + public Response setName(String name) { + this.getTArtifactTemplate().setName(name); + return BackendUtils.persist(this); + } + + @Override + protected TExtensibleElements createNewElement() { + return new TArtifactTemplate(); + } + + @Override + protected void copyIdToFields() { + this.getTArtifactTemplate().setId(this.getId().getXmlId().getDecoded()); + // Namespace cannot be set as the namespace is contained in TDefinitions only + } + + /** + * {@inheritDoc} + */ + @Override + public void synchronizeReferences() { + TArtifactTemplate template = this.getTArtifactTemplate(); + + ArtifactTemplateDirectoryId fileDir = new ArtifactTemplateDirectoryId((ArtifactTemplateId) this.id); + SortedSet files = Repository.INSTANCE.getContainedFiles(fileDir); + if (files.isEmpty()) { + // clear artifact references + template.setArtifactReferences(null); + } else { + ArtifactReferences artifactReferences = new ArtifactReferences(); + template.setArtifactReferences(artifactReferences); + List artRefList = artifactReferences.getArtifactReference(); + for (RepositoryFileReference ref : files) { + // determine path + // path relative from the root of the CSAR is ok (COS01, line 2663) + String path = Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(ref)); + + // put path into data structure + // we do not use Inlude/Exclude as we directly reference a concrete file + TArtifactReference artRef = new TArtifactReference(); + artRef.setReference(path); + artRefList.add(artRef); + } + } + } + + @Path("files/") + public FilesResource getFilesResource() { + ArtifactTemplateDirectoryId fileDir = new ArtifactTemplateDirectoryId((ArtifactTemplateId) this.id); + return new FilesResource(fileDir); + } + + /*********************************************************************** + * "inheritance" from TEntityTemplateResource * + * + * Offering all methods of TEntityTemplateResource and + * forwarding it to our private instance of it + */ + + @Override + public QName getType() { + return this.entityTemplateResource.getType(); + } + + @Override + public Response setType(QName type) { + this.entityTemplateResource.setType(type); + return BackendUtils.persist(this); + } + + @Override + public Response setType(String typeStr) { + this.entityTemplateResource.setType(typeStr); + return BackendUtils.persist(this); + } + + @Override + public PropertiesResource getPropertiesResource() { + return new PropertiesResource(this.getTArtifactTemplate(), this); + } + + int getReferenceCount() { + // We do not use a database, therefore, we have to go through all possibilities pointing to the artifact template + // DAs and IAs point to an artifact template + // DAs are contained in Node Type Implementations and Node Templates + // IAs are contained in Node Type Implementations and Relationship Type Implementations + + int count = 0; + + Collection allDAs = new HashSet<>(); + Collection allIAs = new HashSet<>(); + + // handle Node Type Implementation, which contains DAs and IAs + SortedSet nodeTypeImplementations = Repository.INSTANCE.getAllTOSCAComponentIds(NodeTypeImplementationId.class); + for (NodeTypeImplementationId ntiId : nodeTypeImplementations) { + NodeTypeImplementationResource ntiRes = (NodeTypeImplementationResource) AbstractComponentsResource.getComponentInstaceResource(ntiId); + TDeploymentArtifacts deploymentArtifacts = ntiRes.getNTI().getDeploymentArtifacts(); + if (deploymentArtifacts != null) { + allDAs.addAll(deploymentArtifacts.getDeploymentArtifact()); + } + TImplementationArtifacts implementationArtifacts = ntiRes.getNTI().getImplementationArtifacts(); + if (implementationArtifacts != null) { + allIAs.addAll(implementationArtifacts.getImplementationArtifact()); + } + } + + // check all Relationshiptype Implementations for IAs + SortedSet relationshipTypeImplementations = Repository.INSTANCE.getAllTOSCAComponentIds(RelationshipTypeImplementationId.class); + for (RelationshipTypeImplementationId rtiId : relationshipTypeImplementations) { + RelationshipTypeImplementationResource rtiRes = (RelationshipTypeImplementationResource) AbstractComponentsResource.getComponentInstaceResource(rtiId); + TImplementationArtifacts implementationArtifacts = rtiRes.getRTI().getImplementationArtifacts(); + if (implementationArtifacts != null) { + allIAs.addAll(implementationArtifacts.getImplementationArtifact()); + } + } + + // check all node templates for DAs + SortedSet serviceTemplates = Repository.INSTANCE.getAllTOSCAComponentIds(ServiceTemplateId.class); + for (ServiceTemplateId sid : serviceTemplates) { + ServiceTemplateResource serviceTemplateRes = (ServiceTemplateResource) AbstractComponentsResource.getComponentInstaceResource(sid); + TTopologyTemplate topologyTemplate = serviceTemplateRes.getServiceTemplate().getTopologyTemplate(); + if (topologyTemplate != null) { + List nodeTemplateOrRelationshipTemplate = topologyTemplate.getNodeTemplateOrRelationshipTemplate(); + for (TEntityTemplate template : nodeTemplateOrRelationshipTemplate) { + if (template instanceof TNodeTemplate) { + TNodeTemplate nodeTemplate = (TNodeTemplate) template; + TDeploymentArtifacts deploymentArtifacts = nodeTemplate.getDeploymentArtifacts(); + if (deploymentArtifacts != null) { + allDAs.addAll(deploymentArtifacts.getDeploymentArtifact()); + } + } + } + } + } + + // now we have all DAs and IAs + + QName ourQName = this.getQName(); + + // check DAs for artifact templates + for (TDeploymentArtifact da : allDAs) { + QName artifactRef = da.getArtifactRef(); + if (ourQName.equals(artifactRef)) { + count++; + } + } + + // check IAs for artifact templates + for (TImplementationArtifact ia : allIAs) { + QName artifactRef = ia.getArtifactRef(); + if (ourQName.equals(artifactRef)) { + count++; + } + } + + return count; + } + + /** + * Query parameter {@code type}:
+ * Returns the type of the artifact template + * + * Query parameter {@code referenceCount}:
+ * Determines the number of elements known by the repository which point to + * this resource. This method probably can be moved up the type hierarchy. + * Currently, it is only required here by the topology modeler. + * + * @return the type of the artifact template OR the number of references + * pointing to this resource + */ + @GET + @Produces(MediaType.TEXT_PLAIN) + public Response getRefereneCount(@QueryParam("referenceCount") String referenceCount, @QueryParam("type") String type) { + if (referenceCount != null) { + String res = Integer.toString(this.getReferenceCount()); + return Response.ok().entity(res).build(); + } else if (type != null) { + String res = this.getType().toString(); + return Response.ok().entity(res).build(); + } else { + // we enforce the query parameter to be extensible to other queries + return Response.status(Status.BAD_REQUEST).entity("You have to pass the query parameter referenceCount or type").build(); + } + + } + + /* not yet implemented */ + /* + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response getReferenes(@QueryParam("references") String references) { + if (references== null) { + // we enforce the query parameter to be extensible to other queries + return Response.status(Status.BAD_REQUEST).entity("You have to pass the query parameter references").build(); + } + + String res = Integer.toString(this.getReferenceCount()); + return Response.ok().entity(res).build(); + } + */ + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/ArtifactTemplatesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/ArtifactTemplatesResource.java new file mode 100644 index 0000000..e02a668 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/ArtifactTemplatesResource.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytemplates.artifacttemplates; + +import org.eclipse.winery.repository.resources.AbstractComponentsWithTypeReferenceResource; + +/** + * This class does NOT inherit from TEntityTemplatesResource + * as these templates are directly nested in a TDefinitionsElement + */ +public class ArtifactTemplatesResource extends AbstractComponentsWithTypeReferenceResource { +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/FilesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/FilesResource.java new file mode 100644 index 0000000..0a910fe --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/FilesResource.java @@ -0,0 +1,163 @@ +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytemplates.artifacttemplates; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.SortedSet; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriInfo; + +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.repository.Constants; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.datatypes.FileMeta; +import org.eclipse.winery.repository.datatypes.ids.elements.ArtifactTemplateDirectoryId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jersey.api.view.Viewable; +import com.sun.jersey.core.header.FormDataContentDisposition; +import com.sun.jersey.multipart.FormDataBodyPart; +import com.sun.jersey.multipart.FormDataParam; + +public class FilesResource { + + private static final Logger logger = LoggerFactory.getLogger(FilesResource.class); + private final ArtifactTemplateDirectoryId fileDir; + + + public FilesResource(ArtifactTemplateDirectoryId fileDir) { + this.fileDir = fileDir; + } + + private String getData4jqueryFileUpload(List metas) { + String data4jqueryFileUpload = Utils.Object2JSON(metas); + data4jqueryFileUpload = "{\"files\":" + data4jqueryFileUpload + "}"; + return data4jqueryFileUpload; + } + + /** + * Handles the upload of a single file. Adds the given file to the + * current artifact template. + * + * If the file already exists, is it overridden + * + * @return JSON with data required by JQuery-File-Upload (see + * https://github.com/blueimp/jQuery-File-Upload/wiki/Setup) + */ + @POST + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.MULTIPART_FORM_DATA) + public Response onPost(@FormDataParam("files[]") InputStream uploadedInputStream, @FormDataParam("files[]") FormDataContentDisposition fileDetail, @FormDataParam("files[]") FormDataBodyPart body, @Context UriInfo uriInfo) { + // existence check not required as instantiation of the resource ensures that the object only exists if the resource exists + FilesResource.logger.debug("Beginning with file upload"); + + String fileName = fileDetail.getFileName(); + if (StringUtils.isEmpty(fileName)) { + return Response.status(Status.BAD_REQUEST).build(); + } + RepositoryFileReference ref = this.fileName2fileRef(fileName, false); + + // TODO: instead of fixing the media type, we could overwrite the browser's mediatype by using some user configuration + BufferedInputStream bis = new BufferedInputStream(uploadedInputStream); + MediaType mediaType = Utils.getFixedMimeType(bis, fileName, body.getMediaType()); + + Response response = BackendUtils.putContentToFile(ref, bis, mediaType); + if (response.getStatus() == Status.INTERNAL_SERVER_ERROR.getStatusCode()) { + return response; + } + + // create FileMeta object + String URL = Utils.getAbsoluteURL(this.fileDir) + Util.URLencode(fileName); + String thumbnailURL = uriInfo.getBaseUriBuilder().path(Constants.PATH_MIMETYPEIMAGES).path(FilenameUtils.getExtension(fileName) + Constants.SUFFIX_MIMETYPEIMAGES).build().toString(); + long size; + try { + size = Repository.INSTANCE.getSize(ref); + } catch (IOException e) { + FilesResource.logger.error(e.getMessage(), e); + return Response.serverError().entity(e.getMessage()).build(); + } + FileMeta fileMeta = new FileMeta(fileName, size, URL, thumbnailURL); + + List metas = new ArrayList(); + metas.add(fileMeta); + return Response.created(Utils.createURI(URL)).entity(this.getData4jqueryFileUpload(metas)).build(); + } + + /** + * Returns a list of file meta object + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + public String getJSON() { + return this.getData4jqueryFileUpload(this.getAllFileMetas()); + } + + private List getAllFileMetas() { + List res = new ArrayList(); + SortedSet fileRefs = Repository.INSTANCE.getContainedFiles(this.fileDir); + for (RepositoryFileReference ref : fileRefs) { + res.add(new FileMeta(ref)); + } + return res; + } + + private RepositoryFileReference fileName2fileRef(String fileName, boolean encoded) { + if (encoded) { + fileName = Util.URLdecode(fileName); + } + RepositoryFileReference ref = new RepositoryFileReference(this.fileDir, fileName); + return ref; + } + + @GET + @Produces(MediaType.TEXT_HTML) + public Viewable getHTML() { + return new Viewable("/jsp/entitytemplates/artifacttemplates/files.jsp"); + } + + @GET + @Path("/{fileName}") + public Response getFile(@PathParam("fileName") String fileName, @HeaderParam("If-Modified-Since") String modified) { + RepositoryFileReference ref = this.fileName2fileRef(fileName, true); + return BackendUtils.returnRepoPath(ref, modified); + } + + @DELETE + @Path("/{fileName}") + public Response deleteFile(@PathParam("fileName") String fileName) { + RepositoryFileReference ref = this.fileName2fileRef(fileName, true); + return BackendUtils.delete(ref); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/package-info.java new file mode 100644 index 0000000..4375378 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/package-info.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +/** + * The sub packages of this package contains all resources, which are derived + * from tEntityTemplate + * + * EntityTemplates get their namespaces from the surrounding + * Definitions-element.
+ * Nevertheless, they are stored using the same filesystem structure as + * EntityTypes + * + * {@link org.eclipse.winery.repository.resources.servicetemplates.topologytemplates.RelationshipTemplateResource} + * and + * {@link org.eclipse.winery.repository.resources.servicetemplates.topologytemplates.NodeTemplateResource} + * are stored in the topology package + */ +package org.eclipse.winery.repository.resources.entitytemplates; + diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/policytemplates/PolicyTemplateResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/policytemplates/PolicyTemplateResource.java new file mode 100644 index 0000000..e69a282 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/policytemplates/PolicyTemplateResource.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytemplates.policytemplates; + +import javax.ws.rs.core.Response; +import javax.xml.namespace.QName; + +import org.eclipse.winery.common.ids.definitions.PolicyTemplateId; +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.model.tosca.TPolicyTemplate; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource; +import org.eclipse.winery.repository.resources.IHasName; +import org.eclipse.winery.repository.resources.entitytemplates.IEntityTemplateResource; +import org.eclipse.winery.repository.resources.entitytemplates.PropertiesResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class PolicyTemplateResource extends AbstractComponentInstanceResource implements IEntityTemplateResource, IHasName { + + private static final Logger logger = LoggerFactory.getLogger(PolicyTemplateResource.class); + + + /** + * Constructor has to be public because of test cases + */ + public PolicyTemplateResource(PolicyTemplateId id) { + super(id); + } + + /** + * Convenience method to avoid casting at the caller's side. + */ + public TPolicyTemplate getPolicyTemplate() { + return (TPolicyTemplate) this.getElement(); + } + + @Override + protected TExtensibleElements createNewElement() { + return new TPolicyTemplate(); + } + + @Override + public QName getType() { + return this.getPolicyTemplate().getType(); + } + + @Override + public Response setType(QName type) { + this.getPolicyTemplate().setType(type); + return BackendUtils.persist(this); + } + + @Override + public Response setType(String typeStr) { + this.getPolicyTemplate().setType(QName.valueOf(typeStr)); + return BackendUtils.persist(this); + } + + @Override + public PropertiesResource getPropertiesResource() { + return new PropertiesResource(this.getPolicyTemplate(), this); + } + + @Override + protected void copyIdToFields() { + this.getPolicyTemplate().setId(this.getId().getXmlId().getDecoded()); + } + + @Override + public String getName() { + String name = this.getPolicyTemplate().getName(); + if (name == null) { + return this.getPolicyTemplate().getId(); + } else { + return name; + } + } + + @Override + public Response setName(String name) { + this.getPolicyTemplate().setName(name); + return BackendUtils.persist(this); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/policytemplates/PolicyTemplatesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/policytemplates/PolicyTemplatesResource.java new file mode 100644 index 0000000..685ab66 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytemplates/policytemplates/PolicyTemplatesResource.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytemplates.policytemplates; + +import org.eclipse.winery.repository.resources.AbstractComponentsWithTypeReferenceResource; + +/** + * Manages all policy types in all available namespaces
+ * The actual implementation is done in the + * AbstractComponentsWithTypeReferenceResource + */ +public class PolicyTemplatesResource extends AbstractComponentsWithTypeReferenceResource { + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/EntityTypeImplementationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/EntityTypeImplementationResource.java new file mode 100644 index 0000000..8b48e74 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/EntityTypeImplementationResource.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypeimplementations; + +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.repository.resources.AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal; +import org.eclipse.winery.repository.resources.IHasTypeReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class EntityTypeImplementationResource extends AbstractComponentInstanceResourceWithNameDerivedFromAbstractFinal implements IHasTypeReference { + + private static final Logger logger = LoggerFactory.getLogger(EntityTypeImplementationResource.class); + + + protected EntityTypeImplementationResource(TOSCAComponentId id) { + super(id); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/nodetypeimplementations/NodeTypeImplementationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/nodetypeimplementations/NodeTypeImplementationResource.java new file mode 100644 index 0000000..95b95d2 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/nodetypeimplementations/NodeTypeImplementationResource.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypeimplementations.nodetypeimplementations; + +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; +import javax.xml.namespace.QName; + +import org.eclipse.winery.common.ids.definitions.NodeTypeImplementationId; +import org.eclipse.winery.model.tosca.TDeploymentArtifacts; +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.model.tosca.TImplementationArtifacts; +import org.eclipse.winery.model.tosca.TNodeTypeImplementation; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources.INodeTemplateResourceOrNodeTypeImplementationResource; +import org.eclipse.winery.repository.resources.INodeTypeImplementationResourceOrRelationshipTypeImplementationResource; +import org.eclipse.winery.repository.resources.artifacts.DeploymentArtifactsResource; +import org.eclipse.winery.repository.resources.artifacts.ImplementationArtifactsResource; +import org.eclipse.winery.repository.resources.entitytypeimplementations.EntityTypeImplementationResource; + +public class NodeTypeImplementationResource extends EntityTypeImplementationResource implements INodeTemplateResourceOrNodeTypeImplementationResource, INodeTypeImplementationResourceOrRelationshipTypeImplementationResource { + + public NodeTypeImplementationResource(NodeTypeImplementationId id) { + super(id); + } + + /** + * public because of exporter + */ + public TNodeTypeImplementation getNTI() { + return (TNodeTypeImplementation) this.getElement(); + } + + /** + * Even if both node type implementations and relationship type + * implementations have implementation artifacts, there is no common + * supertype. To avoid endless casts, we just implement the method here + * + * @return + */ + @Path("implementationartifacts/") + public ImplementationArtifactsResource getImplementationArtifacts() { + TImplementationArtifacts implementationArtifacts; + implementationArtifacts = this.getNTI().getImplementationArtifacts(); + if (implementationArtifacts == null) { + implementationArtifacts = new TImplementationArtifacts(); + this.getNTI().setImplementationArtifacts(implementationArtifacts); + } + return new ImplementationArtifactsResource(implementationArtifacts.getImplementationArtifact(), this); + } + + /** + * Only NodeTypes have deployment artifacts, not RelationshipType. + * Therefore, this method is declared in + * {@link NodeTypeImplementationResource} and not in + * {@link EntityTypeImplementationResource} + */ + @Path("deploymentartifacts/") + public DeploymentArtifactsResource getDeploymentArtifacts() { + TDeploymentArtifacts deploymentArtifacts; + deploymentArtifacts = this.getNTI().getDeploymentArtifacts(); + if (deploymentArtifacts == null) { + deploymentArtifacts = new TDeploymentArtifacts(); + this.getNTI().setDeploymentArtifacts(deploymentArtifacts); + } + return new DeploymentArtifactsResource(deploymentArtifacts.getDeploymentArtifact(), this); + } + + @Override + protected TExtensibleElements createNewElement() { + return new TNodeTypeImplementation(); + } + + @Override + protected void copyIdToFields() { + this.getNTI().setTargetNamespace(this.getId().getNamespace().getDecoded()); + this.getNTI().setName(this.getId().getXmlId().getDecoded()); + } + + @Override + public QName getType() { + return this.getNTI().getNodeType(); + } + + @Override + public Response setType(QName type) { + this.getNTI().setNodeType(type); + return BackendUtils.persist(this); + } + + @Override + public Response setType(String typeStr) { + QName type = QName.valueOf(typeStr); + return this.setType(type); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/nodetypeimplementations/NodeTypeImplementationsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/nodetypeimplementations/NodeTypeImplementationsResource.java new file mode 100644 index 0000000..b9c0836 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/nodetypeimplementations/NodeTypeImplementationsResource.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypeimplementations.nodetypeimplementations; + +import org.eclipse.winery.repository.resources.AbstractComponentsWithTypeReferenceResource; + +public class NodeTypeImplementationsResource extends AbstractComponentsWithTypeReferenceResource { + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/package-info.java new file mode 100644 index 0000000..af1c346 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/package-info.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +/** + * The sub packages of this package contains all resources, which are + * implementations of a type.
+ * The specification does NOT introduce tEntityTypeImplementation, but we + * implement as if that had been happened. + */ +package org.eclipse.winery.repository.resources.entitytypeimplementations; + diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/relationshiptypeimplementations/RelationshipTypeImplementationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/relationshiptypeimplementations/RelationshipTypeImplementationResource.java new file mode 100644 index 0000000..521758a --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/relationshiptypeimplementations/RelationshipTypeImplementationResource.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypeimplementations.relationshiptypeimplementations; + +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; +import javax.xml.namespace.QName; + +import org.eclipse.winery.common.ids.definitions.RelationshipTypeImplementationId; +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.model.tosca.TImplementationArtifacts; +import org.eclipse.winery.model.tosca.TRelationshipTypeImplementation; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources.INodeTypeImplementationResourceOrRelationshipTypeImplementationResource; +import org.eclipse.winery.repository.resources.artifacts.ImplementationArtifactsResource; +import org.eclipse.winery.repository.resources.entitytypeimplementations.EntityTypeImplementationResource; + +public class RelationshipTypeImplementationResource extends EntityTypeImplementationResource implements INodeTypeImplementationResourceOrRelationshipTypeImplementationResource { + + public RelationshipTypeImplementationResource(RelationshipTypeImplementationId id) { + super(id); + } + + public TRelationshipTypeImplementation getRTI() { + return (TRelationshipTypeImplementation) this.getElement(); + } + + /** + * Even if both node type implementations and relationship type + * implementations have implementation artifacts, there is no common + * supertype. To avoid endless casts, we just implement the method here + */ + @Path("implementationartifacts/") + public ImplementationArtifactsResource getImplementationArtifacts() { + TImplementationArtifacts implementationArtifacts; + implementationArtifacts = this.getRTI().getImplementationArtifacts(); + if (implementationArtifacts == null) { + implementationArtifacts = new TImplementationArtifacts(); + this.getRTI().setImplementationArtifacts(implementationArtifacts); + } + return new ImplementationArtifactsResource(implementationArtifacts.getImplementationArtifact(), this); + } + + @Override + protected TExtensibleElements createNewElement() { + return new TRelationshipTypeImplementation(); + } + + @Override + protected void copyIdToFields() { + this.getRTI().setTargetNamespace(this.getId().getNamespace().getDecoded()); + this.getRTI().setName(this.getId().getXmlId().getDecoded()); + } + + @Override + public QName getType() { + return this.getRTI().getRelationshipType(); + } + + @Override + public Response setType(QName type) { + this.getRTI().setRelationshipType(type); + return BackendUtils.persist(this); + } + + @Override + public Response setType(String typeStr) { + QName qname = QName.valueOf(typeStr); + return this.setType(qname); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/relationshiptypeimplementations/RelationshipTypeImplementationsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/relationshiptypeimplementations/RelationshipTypeImplementationsResource.java new file mode 100644 index 0000000..f503a6f --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypeimplementations/relationshiptypeimplementations/RelationshipTypeImplementationsResource.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypeimplementations.relationshiptypeimplementations; + +import org.eclipse.winery.repository.resources.AbstractComponentsWithTypeReferenceResource; + +public class RelationshipTypeImplementationsResource extends AbstractComponentsWithTypeReferenceResource { + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/ImplementationsOfOneType.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/ImplementationsOfOneType.java new file mode 100644 index 0000000..5f4d06e --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/ImplementationsOfOneType.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes; + +import java.util.Collection; + +import javax.ws.rs.GET; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.eclipse.winery.common.ids.Namespace; +import org.eclipse.winery.common.ids.definitions.TopologyGraphElementEntityTypeId; +import org.eclipse.winery.repository.resources.admin.NamespacesResource; + +import com.sun.jersey.api.view.Viewable; + +/** + * specifies the methods required by implementations.jsp + */ +public abstract class ImplementationsOfOneType { + + private final TopologyGraphElementEntityTypeId typeId; + + + public ImplementationsOfOneType(TopologyGraphElementEntityTypeId typeId) { + this.typeId = typeId; + } + + public TopologyGraphElementEntityTypeId getTypeId() { + return this.typeId; + } + + @GET + @Produces(MediaType.TEXT_HTML) + public Response getHTML() { + Viewable viewable = new Viewable("/jsp/entitytypes/implementations.jsp", this); + return Response.ok().entity(viewable).build(); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + public abstract Response getJSON(); + + public Collection getNamespaceAutocompletionList() { + return NamespacesResource.getNamespaces(); + } + + /** + * @return a list of type implementations implementing the associated node + * type + */ + public abstract String getImplementationsTableData(); + + /** + * The string used as URL part + */ + public abstract String getType(); + + /** + * The string displayed to the user + */ + public abstract String getTypeStr(); + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/InstanceStatesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/InstanceStatesResource.java new file mode 100644 index 0000000..4eaea1c --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/InstanceStatesResource.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.model.tosca.TTopologyElementInstanceStates; +import org.eclipse.winery.model.tosca.TTopologyElementInstanceStates.InstanceState; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.repository.backend.BackendUtils; + +import com.sun.jersey.api.view.Viewable; + +/** + * Resource for instance states
+ * Used by relationship types and node types + */ +public class InstanceStatesResource { + + private TopologyGraphElementEntityTypeResource typeResource; + private TTopologyElementInstanceStates instanceStates; + + + /** + * + * @param instanceStates the instanceStates to manage + * @param typeResource the type resource, where the instance states are + * managed. This reference is required to fire "persist()" in + * case of updates + */ + public InstanceStatesResource(TTopologyElementInstanceStates instanceStates, TopologyGraphElementEntityTypeResource typeResource) { + this.instanceStates = instanceStates; + this.typeResource = typeResource; + } + + @GET + @Produces(MediaType.TEXT_HTML) + public Viewable getHTML() { + return new Viewable("/jsp/entitytypes/instancestates.jsp", this); + } + + public List getInstanceStates() { + List instanceStates = this.instanceStates.getInstanceState(); + ArrayList states = new ArrayList(instanceStates.size()); + for (InstanceState instanceState : instanceStates) { + states.add(instanceState.getState()); + } + return states; + } + + @DELETE + @Path("{instanceState}") + public Response deleteInstanceState(@PathParam("instanceState") String instanceStateToRemove) { + if (StringUtils.isEmpty(instanceStateToRemove)) { + return Response.status(Status.BAD_REQUEST).entity("null instance to remove").build(); + } + instanceStateToRemove = Util.URLdecode(instanceStateToRemove); + + // InstanceState does not override "equals()", therefore we have to manually remove it + + List instanceStates = this.instanceStates.getInstanceState(); + Iterator iterator = instanceStates.iterator(); + boolean found = false; + while (iterator.hasNext() && !found) { + if (iterator.next().getState().equals(instanceStateToRemove)) { + found = true; + } + } + + if (!found) { + return Response.status(Status.NOT_FOUND).build(); + } + + iterator.remove(); + + return BackendUtils.persist(this.typeResource); + } + + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public Response addInstanceState(@FormParam("state") String state) { + if (StringUtils.isEmpty(state)) { + return Response.notAcceptable(null).build(); + } + + // InstanceState does not override "equals()", therefore we have to manually check for existance + + List instanceStates = this.instanceStates.getInstanceState(); + Iterator iterator = instanceStates.iterator(); + boolean found = false; + while (iterator.hasNext() && !found) { + if (iterator.next().getState().equals(state)) { + found = true; + } + } + + if (found) { + // no error, just return + return Response.noContent().build(); + } + + InstanceState instanceState = new InstanceState(); + instanceState.setState(state); + instanceStates.add(instanceState); + + return BackendUtils.persist(this.typeResource); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/TopologyGraphElementEntityTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/TopologyGraphElementEntityTypeResource.java new file mode 100644 index 0000000..6cebfe8 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/TopologyGraphElementEntityTypeResource.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes; + +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.repository.resources.EntityTypeResource; + +public abstract class TopologyGraphElementEntityTypeResource extends EntityTypeResource { + + protected TopologyGraphElementEntityTypeResource(TOSCAComponentId id) { + super(id); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/artifacttypes/ArtifactTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/artifacttypes/ArtifactTypeResource.java new file mode 100644 index 0000000..232d4f9 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/artifacttypes/ArtifactTypeResource.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.artifacttypes; + +import java.util.SortedSet; + +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; +import javax.xml.namespace.QName; + +import org.eclipse.winery.common.constants.Namespaces; +import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId; +import org.eclipse.winery.common.ids.definitions.ArtifactTypeId; +import org.eclipse.winery.model.tosca.TArtifactType; +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.datatypes.select2.Select2OptGroup; +import org.eclipse.winery.repository.resources.EntityTypeResource; + +public class ArtifactTypeResource extends EntityTypeResource { + + public ArtifactTypeResource(ArtifactTypeId id) { + super(id); + } + + + private final QName qnameFileExtension = new QName(Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "fileExtension"); + + + /** + * @return the file extension associated with this artifact type. May be + * null + */ + @GET + @Path("/fileextension") + public String getAssociatedFileExtension() { + return this.getDefinitions().getOtherAttributes().get(this.qnameFileExtension); + } + + @PUT + @Path("/fileextension") + public Response setAssociatedFileExtension(String fileExtension) { + this.getDefinitions().getOtherAttributes().put(this.qnameFileExtension, fileExtension); + return BackendUtils.persist(this); + } + + @Override + protected TExtensibleElements createNewElement() { + return new TArtifactType(); + } + + @Override + public SortedSet getListOfAllInstances() { + return this.getListOfAllInstances(ArtifactTemplateId.class); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/artifacttypes/ArtifactTypesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/artifacttypes/ArtifactTypesResource.java new file mode 100644 index 0000000..b52aa31 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/artifacttypes/ArtifactTypesResource.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.artifacttypes; + +import java.util.SortedSet; + +import javax.ws.rs.GET; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.eclipse.winery.common.ids.definitions.ArtifactTypeId; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.resources.AbstractComponentsResource; + +public class ArtifactTypesResource extends AbstractComponentsResource { + + // This cannot be used as the INSTANCE is per startup of the whole + // application + // We could do some checking for the number of ArtifactTypeResources or + // timestamp, + // + // private final HashMap fileExtensionMapping + // = new ArtifactTypesResource().getFileExtensionMapping(); + + /** + * @return a mapping from file extension to artifact type resources + */ + // public HashMap getFileExtensionMapping() { + // HashMap res = new HashMap(); + // for (ArtifactTypeResource at : this.getArtifactTypeResources()) { + // if (at.getAssociatedFileExtension() != null) { + // res.put(at.getAssociatedFileExtension(), at); + // } + // } + // return res; + // } + + @GET + // should be "QName", but that MIME type is not available. XLink is too + // complicated for our setup + @Produces(MediaType.TEXT_PLAIN) + public Response getArtifactTypeQNameForExtension(@QueryParam("extension") String extension) { + if (extension == null) { + return Response.status(Status.NOT_ACCEPTABLE).build(); + } + ArtifactTypeResource artifactType = this.getArtifactTypeForExtension(extension); + Response res; + if (artifactType == null) { + res = Response.status(Status.NOT_FOUND).build(); + } else { + res = Response.ok().entity(artifactType.getId().getQName().toString()).build(); + } + return res; + } + + /** + * Returns the first matching ArtifactTypeResource for the given file + * extension. Returns null if no such ArtifactType can be found + * + * The case of the extension is ignored. + * + * This is more a DAO method + */ + public ArtifactTypeResource getArtifactTypeForExtension(String extension) { + SortedSet allArtifactTypeIds = Repository.INSTANCE.getAllTOSCAComponentIds(ArtifactTypeId.class); + ArtifactTypeResource res = null; + for (ArtifactTypeId id : allArtifactTypeIds) { + ArtifactTypeResource r = new ArtifactTypeResource(id); + if (extension.equalsIgnoreCase(r.getAssociatedFileExtension())) { + res = r; + break; + } + } + return res; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/CapabilityTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/CapabilityTypeResource.java new file mode 100644 index 0000000..924efd4 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/CapabilityTypeResource.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.capabilitytypes; + +import org.eclipse.winery.model.tosca.TCapabilityType; +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.common.ids.definitions.CapabilityTypeId; +import org.eclipse.winery.repository.resources.EntityTypeResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class CapabilityTypeResource extends EntityTypeResource { + + private static final Logger logger = LoggerFactory.getLogger(CapabilityTypeResource.class); + + + /** + * Constructor has to be public because of test cases + */ + public CapabilityTypeResource(CapabilityTypeId id) { + super(id); + } + + /** + * Convenience method to avoid casting at the caller's side. + * + * @return the CapabilityType object this resource is representing + */ + public TCapabilityType getCapabilityType() { + return (TCapabilityType) this.getElement(); + } + + @Override + protected TExtensibleElements createNewElement() { + return new TCapabilityType(); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/CapabilityTypesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/CapabilityTypesResource.java new file mode 100644 index 0000000..a34aac2 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/CapabilityTypesResource.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.capabilitytypes; + +import org.eclipse.winery.repository.resources.AbstractComponentsResource; + +/** + * Manages all capability types in all available namespaces
+ * The actual implementation is done in the AbstractComponentsResource + */ +public class CapabilityTypesResource extends AbstractComponentsResource { + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/ImplementationsOfOneNodeTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/ImplementationsOfOneNodeTypeResource.java new file mode 100644 index 0000000..63d483d --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/ImplementationsOfOneNodeTypeResource.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.nodetypes; + +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Collection; + +import javax.ws.rs.core.Response; +import javax.xml.namespace.QName; + +import org.eclipse.winery.common.ids.definitions.NodeTypeId; +import org.eclipse.winery.common.ids.definitions.NodeTypeImplementationId; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources.entitytypes.ImplementationsOfOneType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; + +public class ImplementationsOfOneNodeTypeResource extends ImplementationsOfOneType { + + private static final Logger logger = LoggerFactory.getLogger(ImplementationsOfOneNodeTypeResource.class); + + + /** + * The constructor is different from the usual constructors as this resource + * does NOT store own data, but retrieves its data solely from the + * associated node type + * + * @param nodeTypeId the node type id, where this list of implementations + * belongs to + */ + public ImplementationsOfOneNodeTypeResource(NodeTypeId nodeTypeId) { + super(nodeTypeId); + } + + /** + * required by implementations.jsp + * + * @return for each node type implementation implementing the associated + * node type + */ + @Override + public String getImplementationsTableData() { + String res; + JsonFactory jsonFactory = new JsonFactory(); + StringWriter tableDataSW = new StringWriter(); + try { + JsonGenerator jGenerator = jsonFactory.createGenerator(tableDataSW); + jGenerator.writeStartArray(); + + Collection allNodeTypeImplementations = BackendUtils.getAllElementsRelatedWithATypeAttribute(NodeTypeImplementationId.class, this.getTypeId().getQName()); + for (NodeTypeImplementationId ntiID : allNodeTypeImplementations) { + jGenerator.writeStartArray(); + jGenerator.writeString(ntiID.getNamespace().getDecoded()); + jGenerator.writeString(ntiID.getXmlId().getDecoded()); + jGenerator.writeEndArray(); + } + jGenerator.writeEndArray(); + jGenerator.close(); + tableDataSW.close(); + res = tableDataSW.toString(); + } catch (Exception e) { + ImplementationsOfOneNodeTypeResource.logger.error(e.getMessage(), e); + res = "[]"; + } + return res; + } + + @Override + public String getType() { + return "nodetype"; + } + + @Override + public String getTypeStr() { + return "Node Type"; + } + + @Override + public Response getJSON() { + Collection allImplementations = BackendUtils.getAllElementsRelatedWithATypeAttribute(NodeTypeImplementationId.class, this.getTypeId().getQName()); + ArrayList res = new ArrayList(allImplementations.size()); + for (NodeTypeImplementationId id : allImplementations) { + res.add(id.getQName()); + } + return Response.ok().entity(res).build(); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/NodeTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/NodeTypeResource.java new file mode 100644 index 0000000..6c573a5 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/NodeTypeResource.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.nodetypes; + +import javax.ws.rs.Path; + +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.model.tosca.TNodeType; +import org.eclipse.winery.model.tosca.TNodeType.CapabilityDefinitions; +import org.eclipse.winery.model.tosca.TNodeType.Interfaces; +import org.eclipse.winery.model.tosca.TNodeType.RequirementDefinitions; +import org.eclipse.winery.model.tosca.TTopologyElementInstanceStates; +import org.eclipse.winery.common.ids.definitions.NodeTypeId; +import org.eclipse.winery.repository.resources.entitytypes.InstanceStatesResource; +import org.eclipse.winery.repository.resources.entitytypes.TopologyGraphElementEntityTypeResource; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.reqandcapdefs.CapabilityDefinitionsResource; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.reqandcapdefs.RequirementDefinitionsResource; +import org.eclipse.winery.repository.resources.interfaces.InterfacesResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NodeTypeResource extends TopologyGraphElementEntityTypeResource { + + private static final Logger logger = LoggerFactory.getLogger(NodeTypeResource.class); + + + public NodeTypeResource(NodeTypeId id) { + super(id); + } + + /** + * Convenience method to avoid casting at the caller's side. + */ + public TNodeType getNodeType() { + return (TNodeType) this.getElement(); + } + + /** sub-resources **/ + + @Path("implementations/") + public ImplementationsOfOneNodeTypeResource getImplementations() { + return new ImplementationsOfOneNodeTypeResource((NodeTypeId) this.id); + } + + @Path("instancestates/") + public InstanceStatesResource getInstanceStatesResource() { + TTopologyElementInstanceStates instanceStates = this.getNodeType().getInstanceStates(); + if (instanceStates == null) { + // if an explicit (empty) list does not exist, create it + instanceStates = new TTopologyElementInstanceStates(); + this.getNodeType().setInstanceStates(instanceStates); + } + return new InstanceStatesResource(instanceStates, this); + } + + @Path("interfaces/") + public InterfacesResource getInterfaces() { + Interfaces interfaces = this.getNodeType().getInterfaces(); + if (interfaces == null) { + interfaces = new Interfaces(); + this.getNodeType().setInterfaces(interfaces); + } + return new InterfacesResource(null, interfaces.getInterface(), this); + } + + @Path("requirementdefinitions/") + public RequirementDefinitionsResource getRequirementDefinitions() { + RequirementDefinitions definitions = this.getNodeType().getRequirementDefinitions(); + if (definitions == null) { + definitions = new RequirementDefinitions(); + this.getNodeType().setRequirementDefinitions(definitions); + } + return new RequirementDefinitionsResource(this, definitions.getRequirementDefinition()); + } + + @Path("capabilitydefinitions/") + public CapabilityDefinitionsResource getCapabilityDefinitions() { + CapabilityDefinitions definitions = this.getNodeType().getCapabilityDefinitions(); + if (definitions == null) { + definitions = new CapabilityDefinitions(); + this.getNodeType().setCapabilityDefinitions(definitions); + } + return new CapabilityDefinitionsResource(this, definitions.getCapabilityDefinition()); + } + + @Path("visualappearance/") + public VisualAppearanceResource getVisualAppearanceResource() { + return new VisualAppearanceResource(this, this.getElement().getOtherAttributes(), (NodeTypeId) this.id); + } + + @Override + protected TExtensibleElements createNewElement() { + return new TNodeType(); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/NodeTypesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/NodeTypesResource.java new file mode 100644 index 0000000..798e5a5 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/NodeTypesResource.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.nodetypes; + +import org.eclipse.winery.repository.resources.AbstractComponentsResource; + +/** + * Manages all nodetypes in all available namespaces
+ * The actual implementation is done in the AbstractComponentsResource + */ +public class NodeTypesResource extends AbstractComponentsResource { + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/VisualAppearanceResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/VisualAppearanceResource.java new file mode 100644 index 0000000..d897efe --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/VisualAppearanceResource.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.nodetypes; + +import java.io.InputStream; +import java.util.Map; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.xml.namespace.QName; + +import org.eclipse.winery.common.constants.QNames; +import org.eclipse.winery.common.ids.definitions.NodeTypeId; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.constants.Filename; +import org.eclipse.winery.repository.datatypes.ids.elements.VisualAppearanceId; +import org.eclipse.winery.repository.resources.GenericVisualAppearanceResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jersey.api.view.Viewable; +import com.sun.jersey.multipart.FormDataBodyPart; +import com.sun.jersey.multipart.FormDataParam; + +public class VisualAppearanceResource extends GenericVisualAppearanceResource { + + private static final Logger logger = LoggerFactory.getLogger(VisualAppearanceResource.class); + + + public VisualAppearanceResource(NodeTypeResource res, Map map, NodeTypeId parentId) { + super(res, map, new VisualAppearanceId(parentId)); + } + + @GET + @Produces(MediaType.TEXT_HTML) + public Response getHTML() { + Viewable viewable = new Viewable("/jsp/entitytypes/nodetypes/visualappearance.jsp", this); + return Response.ok().entity(viewable).build(); + } + + @GET + @Path("50x50") + public Response get50x50Image(@HeaderParam("If-Modified-Since") String modified) { + return this.getImage(Filename.FILENAME_BIG_ICON, modified); + } + + @PUT + @Path("50x50") + @Consumes(MediaType.MULTIPART_FORM_DATA) + public Response post50x50Image(@FormDataParam("file") InputStream uploadedInputStream, @FormDataParam("file") FormDataBodyPart body) { + return this.putImage(Filename.FILENAME_BIG_ICON, uploadedInputStream, body.getMediaType()); + } + + @GET + @Path("bordercolor") + public String getBorderColor() { + return BackendUtils.getColorAndSetDefaultIfNotExisting(this.getId().getParent().getXmlId().getDecoded(), QNames.QNAME_BORDER_COLOR, this.otherAttributes, this.res); + } + + @PUT + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + @Path("bordercolor") + public Response putBorderColor(@FormParam("color") String color) { + this.otherAttributes.put(QNames.QNAME_BORDER_COLOR, color); + return BackendUtils.persist(this.res); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/AbstractReqOrCapDefResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/AbstractReqOrCapDefResource.java new file mode 100644 index 0000000..b7eea92 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/AbstractReqOrCapDefResource.java @@ -0,0 +1,177 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.nodetypes.reqandcapdefs; + +import java.lang.reflect.Method; +import java.util.List; + +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.xml.namespace.QName; + +import org.eclipse.winery.model.tosca.TCapabilityDefinition; +import org.eclipse.winery.model.tosca.TConstraint; +import org.eclipse.winery.model.tosca.TRequirementDefinition; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources.ConstraintsResource; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Bundles common properties of TRequirementDefinition and TCapabilityDefinition + * + * We agreed in the project not to modify org.eclipse.winery.model.tosca. + * Therefore, this resource models the common properties of a + * TRequirementDefinition and a TCapabilityDefinition + */ +public abstract class AbstractReqOrCapDefResource extends EntityWithIdResource implements IIdDetermination { + + private static final Logger logger = LoggerFactory.getLogger(AbstractReqOrCapDefResource.class); + + protected NodeTypeResource parent; + + // the capability or the requirement + private Object reqOrCapDef; + + private List constraints; + + + /** + * @param constraints additional parameter (in comparison to the constructor + * of EntityWithIdResource) as we require that sublist for the + * constrinats sub resource + */ + public AbstractReqOrCapDefResource(IIdDetermination idDetermination, ReqOrCapDef reqOrCapDef, int idx, List list, NodeTypeResource res, List constraints) { + super(idDetermination, reqOrCapDef, idx, list, res); + assert ((reqOrCapDef instanceof TRequirementDefinition) || (reqOrCapDef instanceof TCapabilityDefinition)); + this.parent = res; + this.reqOrCapDef = reqOrCapDef; + this.constraints = constraints; + } + + @GET + @Path("name") + public String getName() { + return (String) this.invokeGetter("getName"); + } + + static String getName(Object reqOrCapDef) { + return (String) AbstractReqOrCapDefResource.invokeGetter(reqOrCapDef, "getName"); + } + + @GET + @Path("lowerbound") + public int getLowerBound() { + return (int) this.invokeGetter("getLowerBound"); + } + + @GET + @Path("upperbound") + public String getUpperBound() { + return (String) this.invokeGetter("getUpperBound"); + } + + @PUT + @Path("name") + public Response setName(@FormParam(value = "name") String name) { + // TODO: type check - see also min/max Instance of a node template + this.invokeSetter("setName", name); + return BackendUtils.persist(this.parent); + } + + @PUT + @Path("lowerbound") + public Response setLowerBound(@FormParam(value = "lowerbound") String value) { + // TODO: type check + this.invokeSetter("setLowerBound", value); + return BackendUtils.persist(this.parent); + } + + @PUT + @Path("upperbound") + public Response setUpperBound(@FormParam(value = "upperbound") String value) { + // TODO: type check + this.invokeSetter("setUpperBound", value); + return BackendUtils.persist(this.parent); + } + + @Path("constraints/") + public ConstraintsResource getConstraintsResource() { + return new ConstraintsResource(this.constraints, this.parent); + } + + private static Object invokeGetter(Object reqOrCapDef, String getterName) { + Method method; + Object res; + try { + method = reqOrCapDef.getClass().getMethod(getterName); + res = method.invoke(reqOrCapDef); + } catch (Exception e) { + AbstractReqOrCapDefResource.logger.error("Could not invoke getter {}", getterName, e); + throw new IllegalStateException(e); + } + return res; + } + + private Object invokeGetter(String getterName) { + return AbstractReqOrCapDefResource.invokeGetter(this.reqOrCapDef, getterName); + } + + /** + * Quick hack method for RequirementOrCapabilityDefinitionsResource + */ + static void invokeSetter(Object reqOrCapDef, String setterName, Object value) { + Method method; + try { + method = reqOrCapDef.getClass().getMethod(setterName, value.getClass()); + method.invoke(reqOrCapDef, value); + } catch (Exception e) { + AbstractReqOrCapDefResource.logger.error("Could not invoke setter {}", setterName, e); + throw new IllegalStateException(e); + } + } + + private void invokeSetter(String setterName, Object value) { + AbstractReqOrCapDefResource.invokeSetter(this.reqOrCapDef, setterName, value); + } + + @GET + @Path("type") + @Produces(MediaType.TEXT_PLAIN) + public String getTypeAsString() { + return this.getType().toString(); + } + + /** + * required by the JSP. + * + * Therefore, we have two getters for the type: QName for the JSP and String + * for REST clients + */ + public abstract QName getType(); + + /** + * Required by reqandcapdefs.jsp + */ + public Object getDef() { + return this.reqOrCapDef; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/CapabilityDefinitionResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/CapabilityDefinitionResource.java new file mode 100644 index 0000000..0fd3bd3 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/CapabilityDefinitionResource.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.nodetypes.reqandcapdefs; + +import java.util.List; + +import javax.ws.rs.FormParam; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; +import javax.xml.namespace.QName; + +import org.eclipse.winery.model.tosca.TCapabilityDefinition; +import org.eclipse.winery.model.tosca.TCapabilityDefinition.Constraints; +import org.eclipse.winery.model.tosca.TConstraint; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource; + +/** + * Implementation similar to RequirementDefinitionResource, but with + * TCapabilityDefinition instead of TRequirementDefinition + */ +public final class CapabilityDefinitionResource extends AbstractReqOrCapDefResource { + + private TCapabilityDefinition capDef; + + + /** + * Constructor has to follow the pattern of EnetityTResource as the + * constructor is invoked by reflection in EntityWithIdcollectionResource + * + * @param res the resource this req def is nested in. Has to be of Type + * "NodeTypeResource". Due to the implementation of + * org.eclipse.winery .repository.resources._support.collections. + * withid.EntityWithIdCollectionResource + * .getEntityResourceInstance(EntityT, int), we have to use + * "AbstractComponentInstanceResource" as type + */ + public CapabilityDefinitionResource(IIdDetermination idDetermination, TCapabilityDefinition capDef, int idx, List list, AbstractComponentInstanceResource res) { + super(idDetermination, capDef, idx, list, (NodeTypeResource) res, CapabilityDefinitionResource.getConstraints(capDef)); + this.capDef = capDef; + } + + /** + * Quick hack to avoid internal server error + */ + public CapabilityDefinitionResource(IIdDetermination idDetermination, TCapabilityDefinition capDef, int idx, List list, IPersistable res) { + this(idDetermination, capDef, idx, list, (AbstractComponentInstanceResource) res); + } + + /** + * Fetch the list of constraints from the given definition. If the list does + * not exist, the list is created an stored in the given capDef + */ + public static List getConstraints(TCapabilityDefinition capDef) { + Constraints constraints = capDef.getConstraints(); + if (constraints == null) { + constraints = new Constraints(); + capDef.setConstraints(constraints); + } + return constraints.getConstraint(); + } + + public QName getType() { + return this.capDef.getCapabilityType(); + } + + @PUT + @Path("type") + public Response setType(@FormParam(value = "type") String value) { + QName qname = QName.valueOf(value); + this.capDef.setCapabilityType(qname); + return BackendUtils.persist(this.parent); + } + + @Override + public String getId(TCapabilityDefinition e) { + return e.getName(); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/CapabilityDefinitionsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/CapabilityDefinitionsResource.java new file mode 100644 index 0000000..d93edb4 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/CapabilityDefinitionsResource.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.nodetypes.reqandcapdefs; + +import java.util.Collection; +import java.util.List; +import java.util.SortedSet; + +import javax.xml.namespace.QName; + +import org.eclipse.winery.common.ids.definitions.CapabilityTypeId; +import org.eclipse.winery.model.tosca.TCapabilityDefinition; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jersey.api.view.Viewable; + +public class CapabilityDefinitionsResource extends RequirementOrCapabilityDefinitionsResource { + + private static final Logger logger = LoggerFactory.getLogger(CapabilityDefinitionsResource.class); + + + public CapabilityDefinitionsResource(NodeTypeResource res, List defs) { + super(CapabilityDefinitionResource.class, TCapabilityDefinition.class, defs, res); + } + + @Override + public Viewable getHTML() { + return new Viewable("/jsp/entitytypes/nodetypes/reqandcapdefs/capdefs.jsp", this); + } + + @Override + public Collection getAllTypes() { + SortedSet allTOSCAComponentIds = Repository.INSTANCE.getAllTOSCAComponentIds(CapabilityTypeId.class); + return BackendUtils.convertTOSCAComponentIdCollectionToQNameCollection(allTOSCAComponentIds); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementDefinitionResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementDefinitionResource.java new file mode 100644 index 0000000..aeee000 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementDefinitionResource.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.nodetypes.reqandcapdefs; + +import java.util.List; + +import javax.ws.rs.FormParam; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; +import javax.xml.namespace.QName; + +import org.eclipse.winery.model.tosca.TConstraint; +import org.eclipse.winery.model.tosca.TRequirementDefinition; +import org.eclipse.winery.model.tosca.TRequirementDefinition.Constraints; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource; + +public final class RequirementDefinitionResource extends AbstractReqOrCapDefResource { + + private TRequirementDefinition reqDef; + + + /** + * Constructor has to follow the pattern of EnetityTResource as the + * constructor is invoked by reflection in EntityWithIdcollectionResource + * + * @param res the resource this req def is nested in. Has to be of Type + * "NodeTypeResource". Due to the implementation of + * org.eclipse.winery .repository.resources._support.collections. + * withid.EntityWithIdCollectionResource + * .getEntityResourceInstance(EntityT, int), we have to use + * "AbstractComponentInstanceResource" as type + */ + public RequirementDefinitionResource(IIdDetermination idDetermination, TRequirementDefinition reqDef, int idx, List list, AbstractComponentInstanceResource res) { + super(idDetermination, reqDef, idx, list, (NodeTypeResource) res, RequirementDefinitionResource.getConstraints(reqDef)); + this.reqDef = reqDef; + } + + /** + * Quick fix to avoid internal server error when opening + * RequirementDefinitions Tab + */ + public RequirementDefinitionResource(IIdDetermination idDetermination, TRequirementDefinition reqDef, int idx, List list, IPersistable res) { + this(idDetermination, reqDef, idx, list, (AbstractComponentInstanceResource) res); + } + + /** + * Fetch the list of constraints from the given definition. If the list does + * not exist, the list is created an stored in the given def + */ + public static List getConstraints(TRequirementDefinition def) { + Constraints constraints = def.getConstraints(); + if (constraints == null) { + constraints = new Constraints(); + def.setConstraints(constraints); + } + return constraints.getConstraint(); + } + + public QName getType() { + return this.reqDef.getRequirementType(); + } + + @PUT + @Path("type") + public Response setType(@FormParam(value = "type") String value) { + QName qname = QName.valueOf(value); + this.reqDef.setRequirementType(qname); + return BackendUtils.persist(this.parent); + } + + @Override + public String getId(TRequirementDefinition e) { + return e.getName(); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementDefinitionsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementDefinitionsResource.java new file mode 100644 index 0000000..62db596 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementDefinitionsResource.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.nodetypes.reqandcapdefs; + +import java.util.Collection; +import java.util.List; +import java.util.SortedSet; + +import javax.xml.namespace.QName; + +import org.eclipse.winery.common.ids.definitions.RequirementTypeId; +import org.eclipse.winery.model.tosca.TRequirementDefinition; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource; + +import com.sun.jersey.api.view.Viewable; + +public class RequirementDefinitionsResource extends RequirementOrCapabilityDefinitionsResource { + + public RequirementDefinitionsResource(NodeTypeResource res, List defs) { + super(RequirementDefinitionResource.class, TRequirementDefinition.class, defs, res); + } + + @Override + public Viewable getHTML() { + return new Viewable("/jsp/entitytypes/nodetypes/reqandcapdefs/reqdefs.jsp", this); + } + + @Override + public Collection getAllTypes() { + SortedSet allTOSCAComponentIds = Repository.INSTANCE.getAllTOSCAComponentIds(RequirementTypeId.class); + return BackendUtils.convertTOSCAComponentIdCollectionToQNameCollection(allTOSCAComponentIds); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementOrCapabilityDefinitionsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementOrCapabilityDefinitionsResource.java new file mode 100644 index 0000000..0c6936e --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/RequirementOrCapabilityDefinitionsResource.java @@ -0,0 +1,131 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.nodetypes.reqandcapdefs; + +import java.util.Collection; +import java.util.List; + +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.xml.namespace.QName; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.model.tosca.TCapabilityDefinition; +import org.eclipse.winery.model.tosca.TRequirementDefinition; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource; +import org.eclipse.winery.repository.resources.entitytypes.nodetypes.NodeTypeResource; + +import com.sun.jersey.api.view.Viewable; + +/** + * This superclass has only a few methods as we cannot easily abstract from the + * subclasses: We would need Java reflection to invoke "getName" (to get the + * subresource). The hope is that this copy'n'paste programming will not + * introduce bugs when changing childs + * + * We try to abstract from the problems by using generics and reflections + * + * @param TRequirementDefinition or TCapabilityDefinition + * @param the resource managing ReqDefOrCapDef + */ +public abstract class RequirementOrCapabilityDefinitionsResource, ReqDefOrCapDef> extends EntityWithIdCollectionResource { + + protected final NodeTypeResource res; + + + public RequirementOrCapabilityDefinitionsResource(Class entityResourceTClazz, Class entityTClazz, List list, NodeTypeResource res) { + super(entityResourceTClazz, entityTClazz, list, res); + this.res = res; + } + + @Override + public abstract Viewable getHTML(); + + /** + * @return collection of all available types + */ + public abstract Collection getAllTypes(); + + @POST + // As there is no supertype of TCapabilityType and TRequirementType containing the common attributes, we have to rely on unchecked casts + @SuppressWarnings("unchecked") + public Response onPost(@FormParam("name") String name, @FormParam("type") String type, @FormParam("lowerbound") String lowerBound, @FormParam("upperbound") String upperbound) { + if (StringUtils.isEmpty(name)) { + return Response.status(Status.BAD_REQUEST).entity("Name has to be provided").build(); + } + if (StringUtils.isEmpty(type)) { + return Response.status(Status.BAD_REQUEST).entity("Type has to be provided").build(); + } + + int lbound = 1; + if (!StringUtils.isEmpty(lowerBound)) { + try { + lbound = Integer.parseInt(lowerBound); + } catch (NumberFormatException e) { + return Response.status(Status.BAD_REQUEST).entity("Bad format of lowerbound: " + e.getMessage()).build(); + } + } + + String ubound = "1"; + if (!StringUtils.isEmpty(upperbound)) { + ubound = upperbound; + } + + // we also support replacement of existing requirements + // therefore, we loop through the existing requirements + int idx = -1; + boolean found = false; + for (ReqDefOrCapDef d : this.list) { + idx++; + if (this.getId(d).equals(name)) { + found = true; + break; + } + } + + QName typeQName = QName.valueOf(type); + // Create object and put type in it + ReqDefOrCapDef def; + if (this instanceof CapabilityDefinitionsResource) { + def = (ReqDefOrCapDef) new TCapabilityDefinition(); + ((TCapabilityDefinition) def).setCapabilityType(typeQName); + } else { + assert (this instanceof RequirementDefinitionsResource); + def = (ReqDefOrCapDef) new TRequirementDefinition(); + ((TRequirementDefinition) def).setRequirementType(typeQName); + } + + // copy all other data into object + AbstractReqOrCapDefResource.invokeSetter(def, "setName", name); + AbstractReqOrCapDefResource.invokeSetter(def, "setLowerBound", lbound); + AbstractReqOrCapDefResource.invokeSetter(def, "setUpperBound", ubound); + + if (found) { + // replace element + this.list.set(idx, def); + } else { + // add new element + this.list.add(def); + } + + Response r = BackendUtils.persist(this.res); + return r; + } + + @Override + public String getId(ReqDefOrCapDef reqDefOrCapDef) { + return AbstractReqOrCapDefResource.getName(reqDefOrCapDef); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/package-info.java new file mode 100644 index 0000000..6fbbc5a --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/package-info.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +/** + * The sub packages of this package contains all resources, which are derived + * from tEntityType + */ +package org.eclipse.winery.repository.resources.entitytypes; + diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/AppliesToResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/AppliesToResource.java new file mode 100644 index 0000000..0e4b560 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/AppliesToResource.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.policytypes; + +import javax.ws.rs.GET; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.eclipse.winery.model.tosca.TPolicyType; + +import com.sun.jersey.api.view.Viewable; + +public class AppliesToResource { + + private PolicyTypeResource policyTypeResource; + + + public AppliesToResource(PolicyTypeResource policyTypeResource) { + this.policyTypeResource = policyTypeResource; + } + + @GET + @Produces(MediaType.TEXT_HTML) + public Viewable getHTML() { + return new Viewable("/jsp/entitytypes/policytypes/appliesto.jsp", this); + } + + public TPolicyType getPolicyType() { + return this.policyTypeResource.getPolicyType(); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/LanguageResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/LanguageResource.java new file mode 100644 index 0000000..036cc73 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/LanguageResource.java @@ -0,0 +1,28 @@ +package org.eclipse.winery.repository.resources.entitytypes.policytypes; + +import javax.ws.rs.GET; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import com.sun.jersey.api.view.Viewable; + +public class LanguageResource { + + private PolicyTypeResource policyTypeResource; + + + public LanguageResource(PolicyTypeResource policyTypeResource) { + this.policyTypeResource = policyTypeResource; + } + + @GET + @Produces(MediaType.TEXT_HTML) + public Viewable getHTML() { + return new Viewable("/jsp/entitytypes/policytypes/language.jsp", this); + } + + public String getLanguage() { + return this.policyTypeResource.getPolicyType().getPolicyLanguage(); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/PolicyTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/PolicyTypeResource.java new file mode 100644 index 0000000..62c728a --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/PolicyTypeResource.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.policytypes; + +import java.util.SortedSet; + +import javax.ws.rs.Path; + +import org.eclipse.winery.common.ids.definitions.PolicyTemplateId; +import org.eclipse.winery.common.ids.definitions.PolicyTypeId; +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.model.tosca.TPolicyType; +import org.eclipse.winery.repository.datatypes.select2.Select2OptGroup; +import org.eclipse.winery.repository.resources.EntityTypeResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class PolicyTypeResource extends EntityTypeResource { + + private static final Logger logger = LoggerFactory.getLogger(PolicyTypeResource.class); + + + /** + * Constructor has to be public because of test cases + */ + public PolicyTypeResource(PolicyTypeId id) { + super(id); + } + + /** + * Convenience method to avoid casting at the caller's side. + */ + public TPolicyType getPolicyType() { + return (TPolicyType) this.getElement(); + } + + @Override + protected TExtensibleElements createNewElement() { + return new TPolicyType(); + } + + @Path("appliesto/") + public AppliesToResource getAppliesTo() { + return new AppliesToResource(this); + } + + @Path("language/") + public LanguageResource getLanguage() { + return new LanguageResource(this); + } + + @Override + public SortedSet getListOfAllInstances() { + return this.getListOfAllInstances(PolicyTemplateId.class); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/PolicyTypesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/PolicyTypesResource.java new file mode 100644 index 0000000..17d4db0 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/policytypes/PolicyTypesResource.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.policytypes; + +import org.eclipse.winery.repository.resources.AbstractComponentsResource; + +/** + * Manages all policy types in all available namespaces
+ * The actual implementation is done in the AbstractComponentsResource + */ +public class PolicyTypesResource extends AbstractComponentsResource { + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/JSPData.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/JSPData.java new file mode 100644 index 0000000..a5338ed --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/JSPData.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.properties; + +import java.util.List; + +import org.eclipse.winery.common.propertydefinitionkv.PropertyDefinitionKV; +import org.eclipse.winery.common.propertydefinitionkv.WinerysPropertiesDefinition; +import org.eclipse.winery.model.tosca.TEntityType; + +/** + * Collects data used by the JSP + */ +public class JSPData { + + // FIXME: this is a quick hack and provides a fixed list of available + // property types only. This list has to be made dynamically updatable (and offer plugins to edit) + // currently only http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/#built-in-datatypes are supported + private static final String[] availablePropertyTypes = {"xsd:string", "xsd:boolean", "xsd:decimal", "xsd:float", "xsd:anyURI", "xsd:QName"}; + + private final PropertiesDefinitionResource propertiesDefinitionResource; + private final WinerysPropertiesDefinition wpd; + + + public JSPData(PropertiesDefinitionResource propertiesDefinitionResource, WinerysPropertiesDefinition wpd) { + this.propertiesDefinitionResource = propertiesDefinitionResource; + this.wpd = wpd; + } + + public List getPropertyDefinitionKVList() { + // as this method is used by the JSP, we have to initialize the list and not provide a fake list + // in other words: we are in the mode, where the user has chosen the winery property handling + assert (this.getIsWineryKeyValueProperties()); + if (this.wpd.getPropertyDefinitionKVList() == null) { + return java.util.Collections.emptyList(); + } else { + return this.wpd.getPropertyDefinitionKVList(); + } + } + + public Boolean getIsWineryKeyValueProperties() { + return (this.wpd != null); + // the jsp renders list data only if the list is existing + // we could (somehow) also always keep the old list, but we opted for keeping the choice between the four options also in the XML (and not storing stale data) + // in the case, the WPD is derived from XSD, the list is rendered nevertheless + } + + public boolean getIsWineryKeyValuePropertiesDerivedFromXSD() { + return ((this.wpd != null) && (this.wpd.getIsDerivedFromXSD() != null)); + } + + public String[] getAvailablePropertyTypes() { + return JSPData.availablePropertyTypes; + } + + public TEntityType getEntityType() { + return this.propertiesDefinitionResource.getEntityType(); + } + + public String getElementName() { + if (this.wpd == null) { + return null; + } else { + return this.wpd.getElementName(); + } + } + + public String getNamespace() { + if (this.wpd == null) { + return null; + } else { + return this.wpd.getNamespace(); + } + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/PropertiesDefinitionResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/PropertiesDefinitionResource.java new file mode 100644 index 0000000..6a63791 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/PropertiesDefinitionResource.java @@ -0,0 +1,161 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.properties; + +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.xml.namespace.QName; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.common.constants.MimeTypes; +import org.eclipse.winery.common.propertydefinitionkv.WinerysPropertiesDefinition; +import org.eclipse.winery.model.tosca.TEntityType; +import org.eclipse.winery.model.tosca.TEntityType.PropertiesDefinition; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources.EntityTypeResource; +import org.eclipse.winery.repository.resources.entitytypes.properties.winery.WinerysPropertiesDefinitionResource; +import org.restdoc.annotations.RestDoc; +import org.restdoc.annotations.RestDocParam; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jersey.api.view.Viewable; + +/** + * Models + *
    + *
  1. TOSCA conforming properties definition (XML element / XML schema / none)
  2. + *
  3. Winery's KV properties (in the subresource "winery")
  4. + *
+ * + * This class does not have "KV" in its name, because it models + * {@link TEntityType.PropertiesDefinition} + */ +public class PropertiesDefinitionResource { + + private static final Logger logger = LoggerFactory.getLogger(PropertiesDefinitionResource.class); + + // We hold a copy of super.res as we work on the type EntityTypeResource instead of AbstractComponentInstanceResource + private final EntityTypeResource parentRes; + + // we assume that this class is created at each request + // therefore, we can have "wpd" final + private final WinerysPropertiesDefinition wpd; + + + public PropertiesDefinitionResource(EntityTypeResource res) { + this.parentRes = res; + this.wpd = ModelUtilities.getWinerysPropertiesDefinition(res.getEntityType()); + } + + @GET + @Produces(MediaType.TEXT_HTML) + public Viewable getHTML() { + return new Viewable("/jsp/entitytypes/properties/propertiesDefinition.jsp", new JSPData(this, this.wpd)); + } + + public TEntityType getEntityType() { + return this.parentRes.getEntityType(); + } + + @Path("winery/") + public WinerysPropertiesDefinitionResource getWinerysPropertiesDefinitionResource() { + // this.wpd is null if there is no winery definition exisitin. The subresource handles that case, too + return new WinerysPropertiesDefinitionResource(this.parentRes, this.wpd); + } + + @DELETE + public Response clearPropertiesDefinition() { + this.getEntityType().setPropertiesDefinition(null); + ModelUtilities.removeWinerysPropertiesDefinition(this.getEntityType()); + return BackendUtils.persist(this.parentRes); + } + + public boolean getIsWineryKeyValueProperties() { + return (this.wpd != null); + } + + @GET + @Produces(MimeTypes.MIMETYPE_XSD) + public Response getXSD() { + if (this.getIsWineryKeyValueProperties()) { + return Response.ok().entity(ModelUtilities.getWinerysPropertiesDefinitionXSDAsDocument(this.wpd)).build(); + } else { + // not yet implemented + // We would have to check the imports in the repo for the defined property + // This also has to be similarly done at the export to determine the right imports + return Response.status(Status.NOT_FOUND).build(); + } + } + + @GET + @RestDoc(methodDescription = "We provide the XSD at . and at ./xsd/ to enable simple quering in the browser without the hazzle of setting the correct mime type.") + @Path("xsd/") + @Produces(MimeTypes.MIMETYPE_XSD) + public Response getXSDAtSubResource() { + return this.getXSD(); + } + + // @formatter:off + @POST + @RestDoc(methodDescription="Updates/creates a property based on XSD element or XML schema.") + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + @Produces(MediaType.TEXT_PLAIN) + public Response onPost( + @FormParam("name") @RestDocParam(description="Either xsdelement or xsdtype. 'name' comes from x-editable, which uses that as field name") String name, + @FormParam("value") @RestDocParam(description="The qname") String value) { + // @formatter:on + if (StringUtils.isEmpty(name)) { + return Response.status(Status.BAD_REQUEST).entity("You have to provide a key/type or a name/value pair").build(); + } + if (StringUtils.isEmpty(value)) { + return Response.status(Status.BAD_REQUEST).entity("If a name is provided, a value has also to be provided").build(); + } + + // first of all, remove Winery's Properties definition (if it exists) + ModelUtilities.removeWinerysPropertiesDefinition(this.getEntityType()); + + QName qname = QName.valueOf(value); + + // replace old properties definition by new one + PropertiesDefinition def = new PropertiesDefinition(); + if (name.equals("xsdtype")) { + def.setType(qname); + } else if (name.equals("xsdelement")) { + def.setElement(qname); + } else { + return Response.status(Status.BAD_REQUEST).entity("Invalid name. Choose xsdelement or xsdtype").build(); + } + this.getEntityType().setPropertiesDefinition(def); + List errors = new ArrayList<>(); + BackendUtils.deriveWPD(this.getEntityType(), errors); + // currently the errors are just logged + for (String error : errors) { + PropertiesDefinitionResource.logger.debug(error); + } + return BackendUtils.persist(this.parentRes); + + } + +} \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/PropertyDefinitionKVListResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/PropertyDefinitionKVListResource.java new file mode 100644 index 0000000..f967042 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/PropertyDefinitionKVListResource.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.properties.winery; + +import org.eclipse.winery.common.propertydefinitionkv.PropertyDefinitionKV; +import org.eclipse.winery.common.propertydefinitionkv.PropertyDefinitionKVList; +import org.eclipse.winery.repository.resources.EntityTypeResource; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource; + +import com.sun.jersey.api.view.Viewable; + +/** + * Supports Winery's k/v properties introducing sub resources + * "PropertyDefinition", which defines one property + */ +public class PropertyDefinitionKVListResource extends EntityWithIdCollectionResource { + + public PropertyDefinitionKVListResource(EntityTypeResource res, PropertyDefinitionKVList list) { + super(PropertyDefinitionKVResource.class, PropertyDefinitionKV.class, list, res); + } + + @Override + public String getId(PropertyDefinitionKV entity) { + return entity.getKey(); + } + + @Override + public Viewable getHTML() { + throw new IllegalStateException("Not yet implemented."); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/PropertyDefinitionKVResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/PropertyDefinitionKVResource.java new file mode 100644 index 0000000..00a8d24 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/PropertyDefinitionKVResource.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.properties.winery; + +import java.util.List; + +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; + +import org.eclipse.winery.common.propertydefinitionkv.PropertyDefinitionKV; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource; +import org.restdoc.annotations.RestDoc; + +/** + * Models a definition of one property + * + * This is NOT in line with CSPRD01, which forces one element of one type + */ +public class PropertyDefinitionKVResource extends EntityWithIdResource { + + public PropertyDefinitionKVResource(IIdDetermination idDetermination, PropertyDefinitionKV o, int idx, List list, AbstractComponentInstanceResource res) { + super(idDetermination, o, idx, list, res); + } + + public PropertyDefinitionKVResource(IIdDetermination idDetermination, PropertyDefinitionKV o, int idx, List list, IPersistable res) { + super(idDetermination, o, idx, list, res); + } + + @GET + @RestDoc(methodDescription = "@return type is the 'id' of the type ('shortType'), not the full type name") + @Path("type") + public String getType() { + return this.o.getType(); + } + + @PUT + @RestDoc(methodDescription = "@return type is the 'id' of the type ('shortType'), not the full type name") + @Path("type") + public Response setType(@FormParam("type") String type) { + this.o.setType(type); + return BackendUtils.persist(this.res); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/WinerysPropertiesDefinitionResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/WinerysPropertiesDefinitionResource.java new file mode 100644 index 0000000..0d219e3 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/properties/winery/WinerysPropertiesDefinitionResource.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.properties.winery; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.eclipse.winery.model.tosca.TEntityType; +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.common.propertydefinitionkv.PropertyDefinitionKVList; +import org.eclipse.winery.common.propertydefinitionkv.WinerysPropertiesDefinition; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources.EntityTypeResource; +import org.restdoc.annotations.RestDoc; + +import com.sun.jersey.api.NotFoundException; + +public class WinerysPropertiesDefinitionResource { + + private final EntityTypeResource res; + private final WinerysPropertiesDefinition wpd; + + + /** + * @param res the resource where winery's k/v properties are defined + * @param wpd winery's properties definition object, MAY be null + */ + public WinerysPropertiesDefinitionResource(EntityTypeResource res, WinerysPropertiesDefinition wpd) { + this.res = res; + this.wpd = wpd; + } + + @POST + @RestDoc(methodDescription = "switches the mode to winery properties instead of element/type properties") + public Response onPost() { + TEntityType et = this.res.getEntityType(); + + // clear current properties definition + et.setPropertiesDefinition(null); + + // create empty winery properties definition and persist it + WinerysPropertiesDefinition wpd = new WinerysPropertiesDefinition(); + ModelUtilities.replaceWinerysPropertiesDefinition(et, wpd); + return BackendUtils.persist(this.res); + } + + @Path("namespace") + @GET + @Produces(MediaType.TEXT_PLAIN) + public String getNamespace() { + if (this.wpd == null) { + throw new NotFoundException(); + } + return this.wpd.getNamespace(); + } + + @Path("namespace") + @PUT + @Consumes(MediaType.TEXT_PLAIN) + public Response setNamespace(String namespace) { + if (this.wpd == null) { + throw new NotFoundException(); + } + this.wpd.setNamespace(namespace); + return BackendUtils.persist(this.res); + } + + @Path("elementname") + @GET + @Produces(MediaType.TEXT_PLAIN) + public String getElementName() { + if (this.wpd == null) { + throw new NotFoundException(); + } + return this.wpd.getElementName(); + } + + @Path("elementname") + @PUT + @Consumes(MediaType.TEXT_PLAIN) + public Response setLocalname(String elementName) { + if (this.wpd == null) { + throw new NotFoundException(); + } + this.wpd.setElementName(elementName); + return BackendUtils.persist(this.res); + } + + @Path("elementname") + @PUT + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public Response setLocalnameViaWebUI(@FormParam(value = "name") String elementName) { + if (this.wpd == null) { + throw new NotFoundException(); + } + this.wpd.setElementName(elementName); + return BackendUtils.persist(this.res); + } + + /** + * Here, also the addition of k/v properties is handled. + */ + @Path("list/") + public PropertyDefinitionKVListResource getListResource() { + if (this.wpd == null) { + throw new NotFoundException(); + } + PropertyDefinitionKVList list = this.wpd.getPropertyDefinitionKVList(); + if (list == null) { + list = new PropertyDefinitionKVList(); + this.wpd.setPropertyDefinitionKVList(list); + } + return new PropertyDefinitionKVListResource(this.res, list); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/ImplementationsOfOneRelationshipTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/ImplementationsOfOneRelationshipTypeResource.java new file mode 100644 index 0000000..c7cf2d6 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/ImplementationsOfOneRelationshipTypeResource.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.relationshiptypes; + +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Collection; + +import javax.ws.rs.core.Response; +import javax.xml.namespace.QName; + +import org.eclipse.winery.common.ids.definitions.RelationshipTypeId; +import org.eclipse.winery.common.ids.definitions.RelationshipTypeImplementationId; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources.entitytypes.ImplementationsOfOneType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; + +public class ImplementationsOfOneRelationshipTypeResource extends ImplementationsOfOneType { + + public ImplementationsOfOneRelationshipTypeResource(RelationshipTypeId typeId) { + super(typeId); + } + + + private static final Logger logger = LoggerFactory.getLogger(ImplementationsOfOneRelationshipTypeResource.class); + + + /** + * required by implementations.jsp + * + * Method similar top the one of ImplementationsOfOneNodeTypeResource + * + * @return for each node type implementation implementing the associated + * node type + */ + @Override + public String getImplementationsTableData() { + String res; + JsonFactory jsonFactory = new JsonFactory(); + StringWriter tableDataSW = new StringWriter(); + try { + JsonGenerator jGenerator = jsonFactory.createGenerator(tableDataSW); + jGenerator.writeStartArray(); + + Collection allNTIids = BackendUtils.getAllElementsRelatedWithATypeAttribute(RelationshipTypeImplementationId.class, this.getTypeId().getQName()); + for (RelationshipTypeImplementationId ntiID : allNTIids) { + jGenerator.writeStartArray(); + jGenerator.writeString(ntiID.getNamespace().getDecoded()); + jGenerator.writeString(ntiID.getXmlId().getDecoded()); + jGenerator.writeEndArray(); + } + jGenerator.writeEndArray(); + jGenerator.close(); + tableDataSW.close(); + res = tableDataSW.toString(); + } catch (Exception e) { + ImplementationsOfOneRelationshipTypeResource.logger.error(e.getMessage(), e); + res = "[]"; + } + return res; + } + + @Override + public String getType() { + return "relationshiptype"; + } + + @Override + public String getTypeStr() { + return "Relationship Type"; + } + + @Override + public Response getJSON() { + Collection allImplementations = BackendUtils.getAllElementsRelatedWithATypeAttribute(RelationshipTypeImplementationId.class, this.getTypeId().getQName()); + ArrayList res = new ArrayList(allImplementations.size()); + for (RelationshipTypeImplementationId id : allImplementations) { + res.add(id.getQName()); + } + return Response.ok().entity(res).build(); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/RelationshipTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/RelationshipTypeResource.java new file mode 100644 index 0000000..c874bd5 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/RelationshipTypeResource.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.relationshiptypes; + +import java.util.Collection; +import java.util.SortedSet; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.xml.namespace.QName; + +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.model.tosca.TRelationshipType; +import org.eclipse.winery.model.tosca.TRelationshipType.SourceInterfaces; +import org.eclipse.winery.model.tosca.TRelationshipType.TargetInterfaces; +import org.eclipse.winery.model.tosca.TRelationshipType.ValidSource; +import org.eclipse.winery.model.tosca.TRelationshipType.ValidTarget; +import org.eclipse.winery.model.tosca.TTopologyElementInstanceStates; +import org.eclipse.winery.common.ids.definitions.NodeTypeId; +import org.eclipse.winery.common.ids.definitions.RelationshipTypeId; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.resources.entitytypes.InstanceStatesResource; +import org.eclipse.winery.repository.resources.entitytypes.TopologyGraphElementEntityTypeResource; +import org.eclipse.winery.repository.resources.interfaces.InterfacesResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jersey.api.view.Viewable; + +public class RelationshipTypeResource extends TopologyGraphElementEntityTypeResource { + + private static final Logger logger = LoggerFactory.getLogger(RelationshipTypeResource.class); + + + public RelationshipTypeResource(RelationshipTypeId id) { + super(id); + } + + @Path("implementations/") + public ImplementationsOfOneRelationshipTypeResource getImplementations() { + return new ImplementationsOfOneRelationshipTypeResource((RelationshipTypeId) this.id); + } + + @Path("visualappearance/") + public VisualAppearanceResource getVisualAppearanceResource() { + return new VisualAppearanceResource(this, this.getElement().getOtherAttributes(), (RelationshipTypeId) this.id); + } + + @Path("instancestates/") + public InstanceStatesResource getInstanceStatesResource() { + TTopologyElementInstanceStates instanceStates = this.getRelationshipType().getInstanceStates(); + if (instanceStates == null) { + // if an explicit (empty) list does not exist, create it + instanceStates = new TTopologyElementInstanceStates(); + this.getRelationshipType().setInstanceStates(instanceStates); + } + return new InstanceStatesResource(this.getRelationshipType().getInstanceStates(), this); + } + + @Path("sourceinterfaces/") + public InterfacesResource getSourceInterfaces() { + SourceInterfaces interfaces = this.getRelationshipType().getSourceInterfaces(); + if (interfaces == null) { + interfaces = new SourceInterfaces(); + this.getRelationshipType().setSourceInterfaces(interfaces); + } + return new InterfacesResource("source", interfaces.getInterface(), this); + } + + @Path("targetinterfaces/") + public InterfacesResource getTargetInterfaces() { + TargetInterfaces interfaces = this.getRelationshipType().getTargetInterfaces(); + if (interfaces == null) { + interfaces = new TargetInterfaces(); + this.getRelationshipType().setTargetInterfaces(interfaces); + } + return new InterfacesResource("target", interfaces.getInterface(), this); + } + + @Path("validendings/") + @GET + @Produces(MediaType.TEXT_HTML) + public Response getHTML() { + Viewable viewable = new Viewable("/jsp/entitytypes/relationshiptypes/validendings.jsp", this); + return Response.ok().entity(viewable).build(); + } + + @Path("validsource") + @GET + public String getValidSource() { + ValidSource validSource; + if (((validSource = this.getRelationshipType().getValidSource()) == null) || (validSource.getTypeRef() == null)) { + return null; + } + return this.getRelationshipType().getValidSource().getTypeRef().toString(); + } + + @Path("validsource") + @PUT + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public Response setValidSource(String typeRef) { + ValidSource vs = new ValidSource(); + QName qname = QName.valueOf(typeRef); + vs.setTypeRef(qname); + this.getRelationshipType().setValidSource(vs); + return BackendUtils.persist(this); + } + + @Path("validtarget") + @GET + public String getValidTarget() { + ValidTarget validTarget; + if (((validTarget = this.getRelationshipType().getValidTarget()) == null) || (validTarget.getTypeRef() == null)) { + return null; + } + return this.getRelationshipType().getValidTarget().getTypeRef().toString(); + } + + @Path("validtarget") + @PUT + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public Response setValidTarget(String typeRef) { + ValidTarget vt = new ValidTarget(); + QName qname = QName.valueOf(typeRef); + vt.setTypeRef(qname); + this.getRelationshipType().setValidTarget(vt); + return BackendUtils.persist(this); + } + + /** + * Required for validendings.jsp + */ + public Collection getPossibleValidEndings() { + SortedSet allNodeTypeIds = Repository.INSTANCE.getAllTOSCAComponentIds(NodeTypeId.class); + return allNodeTypeIds; + } + + /** + * Convenience method to avoid casting at the caller's side. + */ + public TRelationshipType getRelationshipType() { + return (TRelationshipType) this.getElement(); + } + + @Override + protected TExtensibleElements createNewElement() { + return new TRelationshipType(); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/RelationshipTypesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/RelationshipTypesResource.java new file mode 100644 index 0000000..1c73ab0 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/RelationshipTypesResource.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.relationshiptypes; + +import org.eclipse.winery.repository.resources.AbstractComponentsResource; + +public class RelationshipTypesResource extends AbstractComponentsResource { +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/VisualAppearanceResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/VisualAppearanceResource.java new file mode 100644 index 0000000..c17c19b --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/relationshiptypes/VisualAppearanceResource.java @@ -0,0 +1,291 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + * Jerome Tagliaferri - support for setting the color + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.relationshiptypes; + +import java.io.StringWriter; +import java.util.Map; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.xml.namespace.QName; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.common.constants.Defaults; +import org.eclipse.winery.common.constants.Namespaces; +import org.eclipse.winery.common.constants.QNames; +import org.eclipse.winery.common.ids.definitions.RelationshipTypeId; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.datatypes.ids.elements.VisualAppearanceId; +import org.eclipse.winery.repository.resources.GenericVisualAppearanceResource; +import org.restdoc.annotations.RestDoc; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; +import com.sun.jersey.api.view.Viewable; + +public class VisualAppearanceResource extends GenericVisualAppearanceResource { + + private static final Logger logger = LoggerFactory.getLogger(VisualAppearanceResource.class); + + private static final QName QNAME_ARROWHEAD_SOURCE = new QName(Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "sourceArrowHead"); + private static final QName QNAME_ARROWHEAD_TARGET = new QName(Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "targetArrowHead"); + private static final QName QNAME_DASH = new QName(Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "dash"); + private static final QName QNAME_LINEWIDTH = new QName(Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "linewidth"); + private static final QName QNAME_HOVER_COLOR = new QName(Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "hovercolor"); + + + public VisualAppearanceResource(RelationshipTypeResource res, Map map, RelationshipTypeId parentId) { + super(res, map, new VisualAppearanceId(parentId)); + } + + @GET + @Produces(MediaType.TEXT_HTML) + public Response getHTML() { + Viewable viewable = new Viewable("/jsp/entitytypes/relationshiptypes/visualappearance.jsp", this); + return Response.ok().entity(viewable).build(); + } + + @GET + @RestDoc(methodDescription = "@return JSON object to be used at jsPlumb.registerConnectionType('NAME', )") + @Produces(MediaType.APPLICATION_JSON) + public Response getConnectionTypeForJsPlumbData() { + JsonFactory jsonFactory = new JsonFactory(); + StringWriter sw = new StringWriter(); + try { + JsonGenerator jg = jsonFactory.createGenerator(sw); + jg.writeStartObject(); + + jg.writeFieldName("connector"); + jg.writeString("Flowchart"); + + jg.writeFieldName("paintStyle"); + jg.writeStartObject(); + jg.writeFieldName("lineWidth"); + jg.writeNumber(this.getLineWidth()); + jg.writeFieldName("strokeStyle"); + jg.writeObject(this.getColor()); + String dash = this.getDash(); + if (!StringUtils.isEmpty(dash)) { + String dashStyle = null; + switch (dash) { + case "dotted": + dashStyle = "1 5"; + break; + case "dotted2": + dashStyle = "3 4"; + break; + case "plain": + // default works + // otherwise, "1 0" can be used + break; + } + if (dashStyle != null) { + jg.writeStringField("dashstyle", dashStyle); + } + } + jg.writeEndObject(); + + jg.writeFieldName("hoverPaintStyle"); + jg.writeStartObject(); + jg.writeFieldName("strokeStyle"); + jg.writeObject(this.getHoverColor()); + jg.writeEndObject(); + + // BEGIN: Overlays + + jg.writeFieldName("overlays"); + jg.writeStartArray(); + + // source arrow head + String head = this.getSourceArrowHead(); + if (!head.equals("none")) { + jg.writeStartArray(); + jg.writeString(head); + + jg.writeStartObject(); + + jg.writeFieldName("location"); + jg.writeNumber(0); + + // arrow should point towards the node and not away from it + jg.writeFieldName("direction"); + jg.writeNumber(-1); + + jg.writeFieldName("width"); + jg.writeNumber(20); + + jg.writeFieldName("length"); + jg.writeNumber(12); + + jg.writeEndObject(); + jg.writeEndArray(); + } + + // target arrow head + head = this.getTargetArrowHead(); + if (!head.equals("none")) { + jg.writeStartArray(); + jg.writeString(head); + jg.writeStartObject(); + jg.writeFieldName("location"); + jg.writeNumber(1); + jg.writeFieldName("width"); + jg.writeNumber(20); + jg.writeFieldName("length"); + jg.writeNumber(12); + jg.writeEndObject(); + jg.writeEndArray(); + } + + // Type in brackets on the arrow + jg.writeStartArray(); + jg.writeString("Label"); + jg.writeStartObject(); + jg.writeStringField("id", "label"); + jg.writeStringField("label", "(" + ((RelationshipTypeResource) this.res).getName() + ")"); + jg.writeStringField("cssClass", "relationshipTypeLabel"); + jg.writeFieldName("location"); + jg.writeNumber(0.5); + jg.writeEndObject(); + jg.writeEndArray(); + + jg.writeEndArray(); + + // END: Overlays + + jg.writeEndObject(); + + jg.close(); + } catch (Exception e) { + VisualAppearanceResource.logger.error(e.getMessage(), e); + return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e).build(); + } + String res = sw.toString(); + return Response.ok(res).build(); + } + + private String getOtherAttributeWithDefault(QName qname, String def) { + String res = this.otherAttributes.get(qname); + if (StringUtils.isEmpty(res)) { + return def; + } else { + return res; + } + } + + /* * * source arrow head * * */ + + public String getSourceArrowHead() { + return this.getOtherAttributeWithDefault(VisualAppearanceResource.QNAME_ARROWHEAD_SOURCE, Defaults.DEFAULT_RT_ARROWHEAD_SOURCE); + } + + @PUT + @Consumes(MediaType.TEXT_PLAIN) + @Path("sourcearrowhead") + public Response onPutSourceHead(String config) { + if (StringUtils.isEmpty(config)) { + return Response.status(Status.BAD_REQUEST).entity("config must not be empty").build(); + } + this.otherAttributes.put(VisualAppearanceResource.QNAME_ARROWHEAD_SOURCE, config); + return BackendUtils.persist(this.res); + } + + /* * * target arrow head * * */ + + public String getTargetArrowHead() { + return this.getOtherAttributeWithDefault(VisualAppearanceResource.QNAME_ARROWHEAD_TARGET, Defaults.DEFAULT_RT_ARROWHEAD_TARGET); + } + + @PUT + @Consumes(MediaType.TEXT_PLAIN) + @Path("targetarrowhead") + public Response onPutTargetHead(String config) { + if (StringUtils.isEmpty(config)) { + return Response.status(Status.BAD_REQUEST).entity("config must not be empty").build(); + } + this.otherAttributes.put(VisualAppearanceResource.QNAME_ARROWHEAD_TARGET, config); + return BackendUtils.persist(this.res); + } + + /* * * + * + * stroke dash array / represents the line + * + * Attention: if a linewidth != 1 is chosen, the dash has to be multiplied somehow by the line width + * See: http://jsplumbtoolkit.com/doc/paint-styles: + * "The dashstyle attribute is specified as an array of strokes and spaces, where each value is some multiple of the width of the Connector" + * + * * * */ + + public String getDash() { + return this.getOtherAttributeWithDefault(VisualAppearanceResource.QNAME_DASH, Defaults.DEFAULT_RT_DASH); + } + + @PUT + @Consumes(MediaType.TEXT_PLAIN) + @Path("dash") + public Response onPutDash(String config) { + if (StringUtils.isEmpty(config)) { + return Response.status(Status.BAD_REQUEST).entity("config must not be empty").build(); + } + this.otherAttributes.put(VisualAppearanceResource.QNAME_DASH, config); + return BackendUtils.persist(this.res); + } + + /* * * stroke/line width * * */ + + public String getLineWidth() { + return this.getOtherAttributeWithDefault(VisualAppearanceResource.QNAME_LINEWIDTH, Defaults.DEFAULT_RT_LINEWIDTH); + } + + /* * * color * * */ + + /** + * read by topologytemplateeditor.jsp via ${it.color} + */ + public String getColor() { + return BackendUtils.getColorAndSetDefaultIfNotExisting(this.getId().getParent().getXmlId().getDecoded(), QNames.QNAME_COLOR, this.otherAttributes, this.res); + } + + @PUT + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + @Path("color") + public Response onPutColor(@FormParam("color") String color) { + this.otherAttributes.put(QNames.QNAME_COLOR, color); + return BackendUtils.persist(this.res); + } + + /** + * read by topologytemplateeditor.jsp via ${it.hoverColor} + */ + public String getHoverColor() { + return this.getOtherAttributeWithDefault(VisualAppearanceResource.QNAME_HOVER_COLOR, Defaults.DEFAULT_RT_HOVER_COLOR); + } + + @PUT + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + @Path("hovercolor") + public Response onPutHoverColor(@FormParam("color") String color) { + this.otherAttributes.put(VisualAppearanceResource.QNAME_HOVER_COLOR, color); + return BackendUtils.persist(this.res); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequiredCapabilityTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequiredCapabilityTypeResource.java new file mode 100644 index 0000000..c076835 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequiredCapabilityTypeResource.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.requirementtypes; + +import java.util.Collection; +import java.util.SortedSet; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.xml.namespace.QName; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.common.ids.definitions.CapabilityTypeId; +import org.eclipse.winery.model.tosca.TRequirementType; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; + +import com.sun.jersey.api.NotFoundException; +import com.sun.jersey.api.view.Viewable; + +public class RequiredCapabilityTypeResource { + + private RequirementTypeResource requirementTypeResource; + + + public RequiredCapabilityTypeResource(RequirementTypeResource requirementTypeResource) { + this.requirementTypeResource = requirementTypeResource; + } + + @GET + @Produces(MediaType.TEXT_HTML) + public Viewable getHTML() { + return new Viewable("/jsp/entitytypes/requirementtypes/requiredcapabilitytype.jsp", this); + } + + public TRequirementType getRequirementType() { + return this.requirementTypeResource.getRequirementType(); + } + + @PUT + @Consumes(MediaType.TEXT_PLAIN) + public Response putRequiredCapabilityType(String type) { + if (StringUtils.isEmpty(type)) { + return Response.status(Status.BAD_REQUEST).entity("type must not be empty").build(); + } + QName qname = QName.valueOf(type); + CapabilityTypeId id = new CapabilityTypeId(qname); + if (Repository.INSTANCE.exists(id)) { + // everything allright. Store new reference + this.getRequirementType().setRequiredCapabilityType(qname); + return BackendUtils.persist(this.requirementTypeResource); + } else { + throw new NotFoundException("Given QName could not be resolved to an existing capability type"); + } + } + + @DELETE + public Response deleteRequiredCapabilityType() { + this.getRequirementType().setRequiredCapabilityType(null); + return BackendUtils.persist(this.requirementTypeResource); + } + + /** required for jsp **/ + public Collection getAllCapabilityTypes() { + SortedSet allTOSCAComponentIds = Repository.INSTANCE.getAllTOSCAComponentIds(CapabilityTypeId.class); + return BackendUtils.convertTOSCAComponentIdCollectionToQNameCollection(allTOSCAComponentIds); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequirementTypeResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequirementTypeResource.java new file mode 100644 index 0000000..0f143fb --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequirementTypeResource.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.requirementtypes; + +import javax.ws.rs.Path; + +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.model.tosca.TRequirementType; +import org.eclipse.winery.common.ids.definitions.RequirementTypeId; +import org.eclipse.winery.repository.resources.EntityTypeResource; + +public class RequirementTypeResource extends EntityTypeResource { + + public RequirementTypeResource(RequirementTypeId id) { + super(id); + } + + /** + * Convenience method to avoid casting at the caller's side. + */ + public TRequirementType getRequirementType() { + return (TRequirementType) this.getElement(); + } + + @Override + protected TExtensibleElements createNewElement() { + return new TRequirementType(); + } + + @Path("requiredcapabilitytype/") + public RequiredCapabilityTypeResource getRequiredCapabilityTypeResource() { + return new RequiredCapabilityTypeResource(this); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequirementTypesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequirementTypesResource.java new file mode 100644 index 0000000..955e4fb --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/entitytypes/requirementtypes/RequirementTypesResource.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.requirementtypes; + +import org.eclipse.winery.repository.resources.AbstractComponentsResource; + +/** + * Manages all capability types in all available namespaces
+ * The actual implementation is done in the AbstractComponentsResource + */ +public class RequirementTypesResource extends AbstractComponentsResource { + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/ImportsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/ImportsResource.java new file mode 100644 index 0000000..82ff02e --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/ImportsResource.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.imports; + +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +import org.eclipse.winery.common.Util; +import org.eclipse.winery.repository.resources.AbstractComponentsResource; +import org.eclipse.winery.repository.resources.imports.genericimports.GenericImportsResource; +import org.eclipse.winery.repository.resources.imports.xsdimports.XSDImportsResource; + +/** + * The specification does not nest the sequence of import elements in an imports + * container. We introduce such a container to be consistent with the other + * resource naming + */ +public class ImportsResource { + + @Path("{id}/") + public AbstractComponentsResource getXSDsResource(@PathParam("id") String id) { + // once: decoding for browser locations + id = Util.URLdecode(id); + // once again: real URI + id = Util.URLdecode(id); + if (id.equals("http://www.w3.org/2001/XMLSchema")) { + // Models http://www.w3.org/2001/XMLSchema. We do not use xsd instead of the + // encoded namespace, because this induces special cases at many places + return new XSDImportsResource(); + } else { + return new GenericImportsResource(id); + } + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/genericimports/GenericImportResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/genericimports/GenericImportResource.java new file mode 100644 index 0000000..ddcb462 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/genericimports/GenericImportResource.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.imports.genericimports; + +import java.util.SortedSet; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.common.ids.definitions.imports.GenericImportId; +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.model.tosca.TImport; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.resources.AbstractComponentInstanceResource; + +public class GenericImportResource extends AbstractComponentInstanceResource { + + // The import belonging to this resource + protected final TImport theImport; + + + public GenericImportResource(GenericImportId id) { + super(id); + + boolean needsPersistence = false; + + if (this.getDefinitions().getServiceTemplateOrNodeTypeOrNodeTypeImplementation().isEmpty()) { + // super class loaded an existing definitions + + // we have to manually assign our import right + this.theImport = this.getDefinitions().getImport().get(0); + + // element is not assigned as there are no service templates/... + // we assign the value to be sure that no NPEs occur + this.element = this.theImport; + } else { + // super class created a new import + + // store it locally + this.theImport = (TImport) this.element; + + // undo the side effect of adding it at the wrong place at TDefinitions + this.getDefinitions().getServiceTemplateOrNodeTypeOrNodeTypeImplementation().clear(); + + // add import at the right place + this.getDefinitions().getImport().add(this.theImport); + + // Super class has persisted the definitions + // We have to persist the new variant + needsPersistence = true; + } + + if (this.theImport.getLocation() == null) { + // invalid import -- try to synchronize with storage + + SortedSet containedFiles = Repository.INSTANCE.getContainedFiles(id); + // there is also a .definitions contained + // we are only interested in the non-.definitions + for (RepositoryFileReference ref : containedFiles) { + if (!ref.getFileName().endsWith(".definitions")) { + // associated file found + // set the filename of the import to the found xsd + // TODO: no more validity checks are done currently. In the case of XSD: targetNamespace matches, not more than one xsd + this.theImport.setLocation(ref.getFileName()); + needsPersistence = true; + break; + } + } + } + + if (needsPersistence) { + BackendUtils.persist(this); + } + } + + @Override + protected TExtensibleElements createNewElement() { + throw new IllegalStateException("This should not never happen."); + } + + @Override + protected void copyIdToFields() { + // this.theImport cannot be used as this method is called by the super constructor + ((TImport) this.element).setNamespace(this.id.getNamespace().getDecoded()); + } + + @GET + @Path("{filename}") + public Response getFile(@PathParam("filename") String fileName) { + fileName = Util.URLdecode(fileName); + String location; + if ((location = this.getLocation()) == null) { + return Response.status(Status.NOT_FOUND).build(); + } + if (!location.equals(fileName)) { + return Response.status(Status.NOT_FOUND).build(); + } + RepositoryFileReference ref = new RepositoryFileReference(this.id, location); + return BackendUtils.returnRepoPath(ref, null); + + } + + public String getLocation() { + return this.theImport.getLocation(); + } + + /** + * @return a name suitable for componentnaming.jspf + */ + public String getName() { + if (this.getLocation() == null) { + return this.id.getXmlId().getDecoded(); + } else { + return this.getLocation(); + } + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/genericimports/GenericImportsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/genericimports/GenericImportsResource.java new file mode 100644 index 0000000..9117175 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/genericimports/GenericImportsResource.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.imports.genericimports; + +import org.eclipse.winery.common.ids.definitions.imports.GenericImportId; +import org.eclipse.winery.repository.resources.AbstractComponentsResource; + +/** + * Manages a certain kind of imports without special treatments + */ +public class GenericImportsResource extends AbstractComponentsResource { + + private String type; + + + /** + * @param id the (decoded) id, e.g., http://schemas.xmlsoap.org/wsdl/ + */ + public GenericImportsResource(String id) { + this.type = id; + } + + @Override + public GenericImportResource getComponentInstaceResource(String namespace, String id, boolean encoded) { + GenericImportId iId = new GenericImportId(namespace, id, encoded, this.type); + return new GenericImportResource(iId); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/xsdimports/XSDImportResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/xsdimports/XSDImportResource.java new file mode 100644 index 0000000..49ea468 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/xsdimports/XSDImportResource.java @@ -0,0 +1,174 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.imports.xsdimports; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import javax.ws.rs.GET; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.xml.XMLConstants; + +import org.apache.xerces.xs.XSConstants; +import org.apache.xerces.xs.XSModel; +import org.apache.xerces.xs.XSNamedMap; +import org.apache.xerces.xs.XSObject; +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.ids.definitions.imports.XSDImportId; +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.model.tosca.TImport; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.resources.imports.genericimports.GenericImportResource; +import org.restdoc.annotations.RestDoc; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonProcessingException; + +/** + * Even if we are not a component instance, we use that infrastructure to manage + * imports. Some hacks will be necessary. However, these are less effort than + * doing a clean design + */ +public class XSDImportResource extends GenericImportResource { + + private static final Logger logger = LoggerFactory.getLogger(XSDImportResource.class); + + + public XSDImportResource(XSDImportId id) { + super(id); + } + + @Override + protected TExtensibleElements createNewElement() { + TImport imp = new TImport(); + imp.setImportType(XMLConstants.W3C_XML_SCHEMA_NS_URI); + return imp; + } + + /** + * public required by XSDImportsResource + * + * @return null if XSD file does not exist + */ + public RepositoryFileReference getXSDFileReference() { + String loc = this.getLocation(); + if (loc == null) { + return null; + } + final RepositoryFileReference ref = new RepositoryFileReference(this.id, loc); + return ref; + } + + /** + * @return null if no file is associated + */ + private XSModel getXSModel() { + final RepositoryFileReference ref = this.getXSDFileReference(); + return BackendUtils.getXSModel(ref); + } + + // we need "unchecked", because of the parsing of the cache + @SuppressWarnings("unchecked") + public Collection getAllDefinedLocalNames(short type) { + RepositoryFileReference ref = this.getXSDFileReference(); + if (ref == null) { + return Collections.emptySet(); + } + Date lastUpdate = Repository.INSTANCE.getLastUpdate(ref); + + String cacheFileName = "definedLocalNames " + Integer.toString(type) + ".cache"; + RepositoryFileReference cacheRef = new RepositoryFileReference(this.id, cacheFileName); + boolean cacheNeedsUpdate = true; + if (Repository.INSTANCE.exists(cacheRef)) { + Date lastUpdateCache = Repository.INSTANCE.getLastUpdate(cacheRef); + if (lastUpdate.compareTo(lastUpdateCache) <= 0) { + cacheNeedsUpdate = false; + } + } + + List result; + if (cacheNeedsUpdate) { + + XSModel model = this.getXSModel(); + if (model == null) { + return Collections.emptySet(); + } + XSNamedMap components = model.getComponents(type); + //@SuppressWarnings("unchecked") + int len = components.getLength(); + result = new ArrayList(len); + for (int i = 0; i < len; i++) { + XSObject item = components.item(i); + // if queried for TYPE_DEFINITION, then XSD base types (such as IDREF) are also returned + // We want to return only types defined in the namespace of this resource + if (item.getNamespace().equals(this.id.getNamespace().getDecoded())) { + result.add(item.getName()); + } + } + + String cacheContent = null; + try { + cacheContent = Utils.mapper.writeValueAsString(result); + } catch (JsonProcessingException e) { + XSDImportResource.logger.error("Could not generate cache content", e); + } + try { + Repository.INSTANCE.putContentToFile(cacheRef, cacheContent, MediaType.APPLICATION_JSON_TYPE); + } catch (IOException e) { + XSDImportResource.logger.error("Could not update cache", e); + } + } else { + // read content from cache + // cache should contain most recent information + try (InputStream is = Repository.INSTANCE.newInputStream(cacheRef)) { + result = Utils.mapper.readValue(is, java.util.List.class); + } catch (IOException e) { + XSDImportResource.logger.error("Could not read from cache", e); + result = Collections.emptyList(); + } + } + return result; + } + + public Collection getAllDefinedElementsLocalNames() { + return this.getAllDefinedLocalNames(XSConstants.ELEMENT_DECLARATION); + } + + public Collection getAllDefinedTypesLocalNames() { + return this.getAllDefinedLocalNames(XSConstants.TYPE_DEFINITION); + } + + @GET + @RestDoc(methodDescription = "May be used by the modeler to generate an XML editor based on the XML schema") + // we cannot use "MimeTypes.MIMETYPE_XSD" here as the latter is "text/xml" and org.eclipse.winery.repository.resources.AbstractComponentInstanceResource.getDefinitionsAsResponse() also produces text/xml + @Produces("text/xsd") + public Response getXSD() { + String location; + if ((location = this.getLocation()) == null) { + return Response.status(Status.NOT_FOUND).build(); + } + RepositoryFileReference ref = new RepositoryFileReference(this.id, location); + return BackendUtils.returnRepoPath(ref, null); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/xsdimports/XSDImportsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/xsdimports/XSDImportsResource.java new file mode 100644 index 0000000..61af3bd --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/imports/xsdimports/XSDImportsResource.java @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.imports.xsdimports; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.ids.Namespace; +import org.eclipse.winery.common.ids.definitions.imports.XSDImportId; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.resources.AbstractComponentsResource; +import org.restdoc.annotations.RestDoc; + +import com.fasterxml.jackson.core.JsonProcessingException; + +/** + * Manages all imports of type XML Schema Definition
+ * The actual implementation is done in the AbstractComponentsResource + * + * FIXME: This class should be generalized to handle ImportId + */ +public class XSDImportsResource extends AbstractComponentsResource { + + @Path("{namespace}/") + @GET + @RestDoc(methodDescription = "Returns all available local names of defined elements in this namespace") + @Produces(MediaType.APPLICATION_JSON) + public String getAllElementLocalNames(@PathParam("namespace") String nsString, @QueryParam(value = "elements") String returnElements, @QueryParam(value = "types") String returnTypes) { + // returnElements is not read as either types or elements may be read + Set allNCNames = this.getAllElementLocalNamesAsSet(nsString, returnTypes != null); + try { + return Utils.mapper.writeValueAsString(allNCNames); + } catch (JsonProcessingException e) { + throw new IllegalStateException(e); + } + } + + /** + * @param nsString the namesapce as String + * @param returnTypes true: return ElementTypes, false: return Elements + */ + private Set getAllElementLocalNamesAsSet(final String nsString, final boolean getTypes) { + Set importsOfNS = this.getImportsOfNS(nsString); + + // TreeSet enables ordering + Set allNCNames = new TreeSet(); + + for (XSDImportId imp : importsOfNS) { + XSDImportResource res = new XSDImportResource(imp); + Collection col; + if (getTypes) { + col = res.getAllDefinedTypesLocalNames(); + } else { + col = res.getAllDefinedElementsLocalNames(); + } + allNCNames.addAll(col); + } + return allNCNames; + } + + /** + * Finds out all imports belonging to the given namespace + * + * @param nsString the namespace to query + */ + private Set getImportsOfNS(final String nsString) { + // FIXME: Currently not supported by the repository, therefore, we filter by hand + Set allImports = Repository.INSTANCE.getAllTOSCAComponentIds(XSDImportId.class); + Namespace ns = new Namespace(nsString, true); + Set importsOfNs = new HashSet(); + for (XSDImportId imp : allImports) { + if (imp.getNamespace().equals(ns)) { + importsOfNs.add(imp); + } + } + return importsOfNs; + } + + /** + * Returns a mapping from localnames to XSD files, containing the defined + * local names for the given namespace + */ + public Map getMapFromLocalNameToXSD(final String nsString, final boolean getTypes) { + Set importsOfNS = this.getImportsOfNS(nsString); + Map result = new HashMap<>(); + for (XSDImportId imp : importsOfNS) { + XSDImportResource res = new XSDImportResource(imp); + Collection col; + if (getTypes) { + col = res.getAllDefinedTypesLocalNames(); + } else { + col = res.getAllDefinedElementsLocalNames(); + } + RepositoryFileReference ref = res.getXSDFileReference(); + for (String localName : col) { + result.put(localName, ref); + } + } + return result; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/InterfaceResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/InterfaceResource.java new file mode 100644 index 0000000..b7b7c15 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/InterfaceResource.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.interfaces; + +import java.util.List; + +import javax.ws.rs.Path; + +import org.eclipse.winery.model.tosca.TInterface; +import org.eclipse.winery.model.tosca.TOperation; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource; + +public class InterfaceResource extends EntityWithIdResource { + + private final TInterface iface; + + + public InterfaceResource(IIdDetermination idDetermination, TInterface o, int idx, List list, IPersistable res) { + super(idDetermination, o, idx, list, res); + this.iface = o; + } + + /** + * required by artifacts.jsp + */ + public String getName() { + return this.iface.getName(); + } + + @Path("operations/") + public OperationsResource getOperationsResouce() { + List list = this.o.getOperation(); + return new OperationsResource(list, this.res); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/InterfacesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/InterfacesResource.java new file mode 100644 index 0000000..4acfbd9 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/InterfacesResource.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.interfaces; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.model.tosca.TInterface; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource; +import org.eclipse.winery.repository.resources.entitytypes.TopologyGraphElementEntityTypeResource; +import org.eclipse.winery.repository.resources.entitytypes.relationshiptypes.RelationshipTypeResource; +import org.restdoc.annotations.RestDoc; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jersey.api.view.Viewable; + +public class InterfacesResource extends EntityWithIdCollectionResource { + + private static final Logger logger = LoggerFactory.getLogger(InterfacesResource.class); + + private TopologyGraphElementEntityTypeResource typeResource; + + private String urlPrefix; + + + public InterfacesResource(IPersistable res, List list) { + super(InterfaceResource.class, TInterface.class, list, res); + } + + /** + * @param urlPrefix prefix to be prepended to the URL. + * "source"|"target"|null. E.g., "source" for "sourceinterfaces" + */ + public InterfacesResource(String urlPrefix, List list, IPersistable typeResource) { + super(InterfaceResource.class, TInterface.class, list, typeResource); + this.urlPrefix = urlPrefix; + this.typeResource = (TopologyGraphElementEntityTypeResource) typeResource; + } + + @Override + public Viewable getHTML() { + return new Viewable("/jsp/interfaces/interfaces.jsp", this); + } + + /** + * Implementation base:
+ * {@link org.eclipse.winery.repository.resources.AbstractComponentResource. + * onPost(String)} + * + * @return entity: id of the stored interface + */ + @POST + @RestDoc(methodDescription = "Creates a new interface. Returns conflict if interface already exists") + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + @Produces(MediaType.TEXT_PLAIN) + public Response onPost(@FormParam("interfaceName") String interfaceName) { + if (StringUtils.isEmpty(interfaceName)) { + return Response.status(Status.BAD_REQUEST).entity("null interfaceName").build(); + } + + TInterface iface = new TInterface(); + iface.setName(interfaceName); + + // check for duplicates + // return "conflict" if interface already exists + if (this.alreadyContains(iface)) { + return Response.status(Status.CONFLICT).build(); + } + + this.list.add(iface); + return BackendUtils.persist(this.res); + } + + /** + * Required by interfaces.jsp + */ + public String getUrlPrefix() { + return this.urlPrefix; + } + + @Override + public String getId(TInterface entity) { + return entity.getName(); + } + + /** + * @return the namespace of the node/relationship type + */ + public String getNamespace() { + return this.typeResource.getId().getNamespace().getDecoded(); + } + + /** + * @return the name of the node/relationship type + */ + public String getName() { + return this.typeResource.getName(); + } + + public String getRelationshipTypeOrNodeTypeURLFragment() { + if (this.typeResource instanceof RelationshipTypeResource) { + return "relationshiptype"; + } else { + return "nodetype"; + } + } + + public String getRelationshipTypeOrNodeType() { + if (this.typeResource instanceof RelationshipTypeResource) { + return "Relationship Type"; + } else { + return "Node Type"; + } + } + + public String getTypeQName() { + String res = this.typeResource.getId().getQName().toString(); + return res; + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/OperationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/OperationResource.java new file mode 100644 index 0000000..7657e99 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/OperationResource.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.interfaces; + +import java.util.List; + +import javax.ws.rs.Path; + +import org.eclipse.winery.model.tosca.TInterface; +import org.eclipse.winery.model.tosca.TOperation; +import org.eclipse.winery.model.tosca.TOperation.InputParameters; +import org.eclipse.winery.model.tosca.TOperation.OutputParameters; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OperationResource extends EntityWithIdResource { + + private static final Logger logger = LoggerFactory.getLogger(OperationResource.class); + + + public OperationResource(IIdDetermination idDetermination, TOperation o, int idx, List list, IPersistable res) { + super(idDetermination, o, idx, list, res); + } + + /** + * @return TOperation object for the corresponding object of operationName + * in the operation list contained in the given interface. null if + * interface could not be found in list + */ + public static TOperation getTOperation(String operationName, TInterface iface) { + List operationList = iface.getOperation(); + for (TOperation op : operationList) { + if (op.getName().equals(operationName)) { + return op; + } + } + return null; + } + + @Path("inputparameters/") + public ParametersResource getInputparameters() { + InputParameters inputParameters = this.o.getInputParameters(); + if (inputParameters == null) { + inputParameters = new InputParameters(); + this.o.setInputParameters(inputParameters); + } + return new ParametersResource(inputParameters.getInputParameter(), this.res); + } + + @Path("outputparameters/") + public ParametersResource getOutputparameters() { + OutputParameters outputParameters = this.o.getOutputParameters(); + if (outputParameters == null) { + outputParameters = new OutputParameters(); + this.o.setOutputParameters(outputParameters); + } + return new ParametersResource(outputParameters.getOutputParameter(), this.res); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/OperationsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/OperationsResource.java new file mode 100644 index 0000000..3e214e4 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/OperationsResource.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.interfaces; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.model.tosca.TOperation; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource; +import org.restdoc.annotations.RestDocParam; + +import com.sun.jersey.api.view.Viewable; + +public class OperationsResource extends EntityWithIdCollectionResource { + + public OperationsResource(List list, IPersistable res) { + super(OperationResource.class, TOperation.class, list, res); + } + + @Override + public String getId(TOperation entity) { + return entity.getName(); + } + + @Override + public Viewable getHTML() { + throw new IllegalStateException("Not yet implemented."); + } + + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + @Produces(MediaType.TEXT_PLAIN) + public Response createOperation(@FormParam("name") @RestDocParam(description = "used as name and id") String operationName) { + if (StringUtils.isEmpty(operationName)) { + return Response.status(Status.BAD_REQUEST).entity("operationName not provided").build(); + } + + operationName = Util.URLdecode(operationName); + + // TODO: check for duplicates as in instance states + + TOperation operation = new TOperation(); + operation.setName(operationName); + this.list.add(operation); + + return BackendUtils.persist(this.res); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/ParameterResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/ParameterResource.java new file mode 100644 index 0000000..46662fd --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/ParameterResource.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.interfaces; + +import java.util.List; + +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; + +import org.eclipse.winery.model.tosca.TBoolean; +import org.eclipse.winery.model.tosca.TParameter; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource; + +public class ParameterResource extends EntityWithIdResource { + + public ParameterResource(IIdDetermination idDetermination, TParameter o, int idx, List list, IPersistable res) { + super(idDetermination, o, idx, list, res); + } + + @GET + @Path("type") + public String getType() { + return this.o.getType(); + } + + @PUT + @Path("type") + public Response putType(@FormParam(value = "type") String type) { + this.o.setType(type); + return BackendUtils.persist(this.res); + } + + @GET + @Path("required") + public String getRequired() { + return this.o.getRequired().toString(); + } + + @PUT + @Path("required") + public Response putRequired(@FormParam(value = "required") String required) { + TBoolean tb = TBoolean.valueOf(required); + this.o.setRequired(tb); + return BackendUtils.persist(this.res); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/ParametersResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/ParametersResource.java new file mode 100644 index 0000000..c3afcbc --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/interfaces/ParametersResource.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.interfaces; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.model.tosca.TBoolean; +import org.eclipse.winery.model.tosca.TParameter; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource; +import org.restdoc.annotations.RestDocParam; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jersey.api.view.Viewable; + +public class ParametersResource extends EntityWithIdCollectionResource { + + private static final Logger logger = LoggerFactory.getLogger(ParametersResource.class); + + + public ParametersResource(List parameters, IPersistable typeResource) { + super(ParameterResource.class, TParameter.class, parameters, typeResource); + } + + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + @Produces(MediaType.TEXT_PLAIN) + // @formatter:off + public Response createParamter( + @FormParam("name") String name, + @FormParam("type") String type, + @FormParam("required") @RestDocParam(description="type tYesNo, not Boolean. For convenience, on/off is also supported. In case this parameter is not provided, 'off' is assumed. This is in contrast to the specification, but it eases implementing the UI") String required) { + // @formatter:on + if (StringUtils.isEmpty(name)) { + return Response.status(Status.BAD_REQUEST).entity("name must not be null").build(); + } + if (StringUtils.isEmpty(type)) { + return Response.status(Status.BAD_REQUEST).entity("type must not be null").build(); + } + + TParameter param = new TParameter(); + param.setName(name); + param.setType(type); + TBoolean tb; + if (required == null) { + // The specification states that the default value is "yes" + // We assume "no", because Chrome does not send the checkbox data if a checkbox is not checked + tb = TBoolean.NO; + } else { + if (required.equalsIgnoreCase("on")) { + tb = TBoolean.YES; + } else if (required.equalsIgnoreCase("off")) { + tb = TBoolean.NO; + } else { + try { + tb = TBoolean.valueOf(required); + } catch (java.lang.IllegalArgumentException e) { + return Response.status(Status.BAD_REQUEST).entity("Wrong format of required").build(); + } + } + } + param.setRequired(tb); + + this.list.add(param); + + return BackendUtils.persist(this.res); + } + + @Override + public String getId(TParameter entity) { + return entity.getName(); + } + + @Override + public Viewable getHTML() { + throw new IllegalStateException("Not yet implemented."); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/package-info.java new file mode 100644 index 0000000..ea94a21 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/package-info.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +/** + * This package contains the REST resources + * + * Mostly, they produces Viewables, where a JSP and the current resource is + * passed As the JSP itself handles plain Java objects and not Responses, the + * resources have also methods returning POJOs. This might be ugly design, but + * was quick to implement. + * + * The package structure is mirrored in src/main/webapp/jsp to ease finding the + * JSPs belonging to a resource. + * + * The resources are not in line with the resource model of the TOSCA + * container. Especially, we do not employ HATEOAS here. + */ +package org.eclipse.winery.repository.resources; + diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/ServiceTemplateResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/ServiceTemplateResource.java new file mode 100644 index 0000000..6a249df --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/ServiceTemplateResource.java @@ -0,0 +1,263 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.SortedSet; + +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.xml.namespace.QName; + +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.common.ids.definitions.ServiceTemplateId; +import org.eclipse.winery.common.ids.elements.PlanId; +import org.eclipse.winery.common.ids.elements.PlansId; +import org.eclipse.winery.model.tosca.TBoundaryDefinitions; +import org.eclipse.winery.model.tosca.TExtensibleElements; +import org.eclipse.winery.model.tosca.TPlan; +import org.eclipse.winery.model.tosca.TPlan.PlanModelReference; +import org.eclipse.winery.model.tosca.TPlans; +import org.eclipse.winery.model.tosca.TServiceTemplate; +import org.eclipse.winery.model.tosca.TTopologyTemplate; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.resources.AbstractComponentInstanceWithReferencesResource; +import org.eclipse.winery.repository.resources.IHasName; +import org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.BoundaryDefinitionsResource; +import org.eclipse.winery.repository.resources.servicetemplates.plans.PlansResource; +import org.eclipse.winery.repository.resources.servicetemplates.selfserviceportal.SelfServicePortalResource; +import org.eclipse.winery.repository.resources.servicetemplates.topologytemplates.TopologyTemplateResource; +import org.restdoc.annotations.RestDoc; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ServiceTemplateResource extends AbstractComponentInstanceWithReferencesResource implements IHasName { + + private static final Logger logger = LoggerFactory.getLogger(ServiceTemplateResource.class); + + + public ServiceTemplateResource(ServiceTemplateId id) { + super(id); + } + + /** sub-resources **/ + + @Path("topologytemplate/") + public TopologyTemplateResource getTopologyTemplateResource() { + if (this.getServiceTemplate().getTopologyTemplate() == null) { + // the main service template resource exists + // default topology template: empty template + // This eases the JSPs etc. and is valid as a non-existant topology template is equal to an empty one + this.getServiceTemplate().setTopologyTemplate(new TTopologyTemplate()); + } + return new TopologyTemplateResource(this); + } + + @Path("plans/") + public PlansResource getPlansResource() { + TPlans plans = this.getServiceTemplate().getPlans(); + if (plans == null) { + plans = new TPlans(); + this.getServiceTemplate().setPlans(plans); + } + return new PlansResource(plans.getPlan(), this); + } + + @Path("selfserviceportal/") + public SelfServicePortalResource getSelfServicePortalResource() { + return new SelfServicePortalResource(this); + } + + @Path("boundarydefinitions/") + public BoundaryDefinitionsResource getBoundaryDefinitionsResource() { + TBoundaryDefinitions boundaryDefinitions = this.getServiceTemplate().getBoundaryDefinitions(); + if (boundaryDefinitions == null) { + boundaryDefinitions = new TBoundaryDefinitions(); + this.getServiceTemplate().setBoundaryDefinitions(boundaryDefinitions); + } + return new BoundaryDefinitionsResource(this, boundaryDefinitions); + } + + @Override + public String getName() { + String name = this.getServiceTemplate().getName(); + if (name == null) { + // place default + name = this.getId().getXmlId().getDecoded(); + } + return name; + } + + @Override + public Response setName(String name) { + this.getServiceTemplate().setName(name); + return BackendUtils.persist(this); + } + + // @formatter:off + @GET + @RestDoc(methodDescription="Returns the associated node type, which can be substituted by this service template.
" + + "@return a QName of the form {namespace}localName is returned.") + @Path("substitutableNodeType") + @Produces(MediaType.TEXT_PLAIN) + // @formatter:on + public Response getSubstitutableNodeTypeAsResponse() { + QName qname = this.getServiceTemplate().getSubstitutableNodeType(); + if (qname == null) { + return Response.status(Status.NOT_FOUND).build(); + } else { + return Response.ok(qname.toString()).build(); + } + } + + /** + * + * @return null if there is no substitutable node type + */ + public QName getSubstitutableNodeType() { + return this.getServiceTemplate().getSubstitutableNodeType(); + } + + @DELETE + @RestDoc(methodDescription = "Removes the association to substitutable node type") + @Path("substitutableNodeType") + public Response deleteSubstitutableNodeType() { + this.getServiceTemplate().setSubstitutableNodeType(null); + BackendUtils.persist(this); + return Response.noContent().build(); + } + + public TServiceTemplate getServiceTemplate() { + return (TServiceTemplate) this.getElement(); + } + + @Override + protected TExtensibleElements createNewElement() { + return new TServiceTemplate(); + } + + @Override + protected void copyIdToFields() { + this.getServiceTemplate().setId(this.getId().getXmlId().getDecoded()); + this.getServiceTemplate().setTargetNamespace(this.getId().getNamespace().getDecoded()); + } + + /** + * Synchronizes the known plans with the data in the XML. When there is a + * stored file, but no known entry in the XML, we guess "BPEL" as language + * and "build plan" as type. + * + * @throws IOException + */ + @Override + public void synchronizeReferences() { + // locally stored plans + TPlans plans = this.getServiceTemplate().getPlans(); + + // plans stored in the repository + PlansId plansContainerId = new PlansId((ServiceTemplateId) this.getId()); + SortedSet nestedPlans = Repository.INSTANCE.getNestedIds(plansContainerId, PlanId.class); + + Set plansToAdd = new HashSet(); + plansToAdd.addAll(nestedPlans); + + if (nestedPlans.isEmpty()) { + if (plans == null) { + // data on the file system equals the data -> no plans + return; + } else { + // we have to check for equality later + } + } + + if (plans == null) { + plans = new TPlans(); + this.getServiceTemplate().setPlans(plans); + } + + for (Iterator iterator = plans.getPlan().iterator(); iterator.hasNext();) { + TPlan plan = iterator.next(); + if (plan.getPlanModel() != null) { + // in case, a plan is directly contained in a Model element, we do not need to do anything + continue; + } + PlanModelReference planModelReference = plan.getPlanModelReference(); + if ((planModelReference = plan.getPlanModelReference()) != null) { + String ref = planModelReference.getReference(); + if ((ref == null) || ref.startsWith("../")) { + // references to local plans start with "../" + // special case (due to errors in the importer): empty PlanModelReference field + if (plan.getId() == null) { + // invalid plan entry: no id. + // we remove the entry + iterator.remove(); + continue; + } + PlanId planId = new PlanId(plansContainerId, new XMLId(plan.getId(), false)); + if (nestedPlans.contains(planId)) { + // everything allright + // we do NOT need to add the plan on the HDD to the XML + plansToAdd.remove(planId); + } else { + // no local storage for the plan, we remove it from the XML + iterator.remove(); + } + } + } + } + + // add all plans locally stored, but not contained in the XML, as plan element to the plans of the service template. + List thePlans = plans.getPlan(); + for (PlanId planId : plansToAdd) { + SortedSet files = Repository.INSTANCE.getContainedFiles(planId); + if (files.size() != 1) { + throw new IllegalStateException("Currently, only one file per plan is supported."); + } + RepositoryFileReference ref = files.iterator().next(); + + TPlan plan = new TPlan(); + plan.setId(planId.getXmlId().getDecoded()); + plan.setName(planId.getXmlId().getDecoded()); + plan.setPlanType(org.eclipse.winery.repository.Constants.TOSCA_PLANTYPE_BUILD_PLAN); + plan.setPlanLanguage(org.eclipse.winery.common.constants.Namespaces.URI_BPEL20_EXECUTABLE); + + // create a PlanModelReferenceElement pointing to that file + String path = Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(ref)); + // path is relative from the definitions element + path = "../" + path; + PlanModelReference pref = new PlanModelReference(); + pref.setReference(path); + + plan.setPlanModelReference(pref); + thePlans.add(plan); + } + + try { + this.persist(); + } catch (IOException e) { + throw new IllegalStateException("Could not persist resource", e); + } + return; + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/ServiceTemplatesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/ServiceTemplatesResource.java new file mode 100644 index 0000000..fd8b82c --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/ServiceTemplatesResource.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates; + +import org.eclipse.winery.repository.resources.AbstractComponentsResource; + +public class ServiceTemplatesResource extends AbstractComponentsResource { + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/BoundaryDefinitionsJSPData.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/BoundaryDefinitionsJSPData.java new file mode 100644 index 0000000..0d4b141 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/BoundaryDefinitionsJSPData.java @@ -0,0 +1,113 @@ +package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.SortedSet; + +import javax.xml.namespace.QName; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.taglibs.standard.functions.Functions; +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.common.ids.definitions.PolicyTypeId; +import org.eclipse.winery.model.tosca.TBoundaryDefinitions; +import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Properties; +import org.eclipse.winery.model.tosca.TPlan; +import org.eclipse.winery.model.tosca.TPlans; +import org.eclipse.winery.model.tosca.TServiceTemplate; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.datatypes.TypeWithShortName; +import org.eclipse.winery.repository.datatypes.select2.Select2DataItem; +import org.eclipse.winery.repository.resources.admin.types.ConstraintTypesManager; + +public class BoundaryDefinitionsJSPData { + + private final TServiceTemplate ste; + private final TBoundaryDefinitions defs; + private URI baseURI; + + + /** + * + * @param ste the service template of the boundary definitions. Required to + * get a list of all plans + * @param baseURI the base URI of the service. Requried for rendering the + * topology template for the selections + */ + public BoundaryDefinitionsJSPData(TServiceTemplate ste, URI baseURI) { + this.ste = ste; + this.defs = ste.getBoundaryDefinitions(); + this.baseURI = baseURI; + } + + private String getDefinedProperties() { + Properties p = ModelUtilities.getProperties(this.defs); + Object o = p.getAny(); + if (o == null) { + // nothing stored -> return empty string + return ""; + } else { + // something stored --> return that + return Utils.getXMLAsString(p.getAny()); + } + } + + /** + * Helper method to return an initialized properties object only containing + * the user-defined properties. The TOSCA properties-element is not returned + * as the TOSCA XSD allows a single element only + */ + public String getDefinedPropertiesAsEscapedHTML() { + String s = this.getDefinedProperties(); + s = StringEscapeUtils.escapeHtml4(s); + return s; + } + + public String getDefinedPropertiesAsJSONString() { + String s = this.getDefinedProperties(); + s = StringEscapeUtils.escapeEcmaScript(s); + return s; + } + + public TBoundaryDefinitions getDefs() { + return this.defs; + } + + public String getBoundaryDefinitionsAsXMLStringEncoded() { + String res = Utils.getXMLAsString(this.defs); + return Functions.escapeXml(res); + } + + public Collection getConstraintTypes() { + return ConstraintTypesManager.INSTANCE.getTypes(); + } + + public Collection getAllPolicyTypes() { + SortedSet allTOSCAComponentIds = Repository.INSTANCE.getAllTOSCAComponentIds(PolicyTypeId.class); + return BackendUtils.convertTOSCAComponentIdCollectionToQNameCollection(allTOSCAComponentIds); + } + + public String getRepositoryURL() { + return this.baseURI.toString(); + } + + public List getlistOfAllPlans() { + TPlans plans = this.ste.getPlans(); + if (plans == null) { + return null; + } else { + List res = new ArrayList<>(plans.getPlan().size()); + for (TPlan plan : plans.getPlan()) { + String id = plan.getId(); + String name = ModelUtilities.getNameWithIdFallBack(plan); + Select2DataItem di = new Select2DataItem(id, name); + res.add(di); + } + return res; + } + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/BoundaryDefinitionsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/BoundaryDefinitionsResource.java new file mode 100644 index 0000000..58dfbe9 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/BoundaryDefinitionsResource.java @@ -0,0 +1,144 @@ +/******************************************************************************* + * Copyright (c) 2013-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.model.tosca.TBoundaryDefinitions; +import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Capabilities; +import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Interfaces; +import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Policies; +import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Properties; +import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Properties.PropertyMappings; +import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Requirements; +import org.eclipse.winery.model.tosca.TCapabilityRef; +import org.eclipse.winery.model.tosca.TRequirementRef; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource; +import org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.interfaces.InterfacesResource; +import org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.policies.PoliciesResource; +import org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps.CapabilitiesResource; +import org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps.RequirementsResource; +import org.restdoc.annotations.RestDoc; +import org.restdoc.annotations.RestDocParam; +import org.w3c.dom.Document; + +import com.sun.jersey.api.view.Viewable; + +public class BoundaryDefinitionsResource { + + private final ServiceTemplateResource serviceTemplateResource; + private final TBoundaryDefinitions boundaryDefinitions; + + + public BoundaryDefinitionsResource(ServiceTemplateResource serviceTemplateResource, TBoundaryDefinitions boundaryDefinitions) { + this.serviceTemplateResource = serviceTemplateResource; + this.boundaryDefinitions = boundaryDefinitions; + } + + @GET + @Produces(MediaType.TEXT_HTML) + public Viewable getHTML(@Context UriInfo uriInfo) { + return new Viewable("/jsp/servicetemplates/boundarydefinitions/boundarydefinitions.jsp", new BoundaryDefinitionsJSPData(this.serviceTemplateResource.getServiceTemplate(), uriInfo.getBaseUri())); + } + + @PUT + @RestDoc(methodDescription = "Replaces the boundary definitions by the information given in the XML") + @Consumes(MediaType.TEXT_XML) + public Response setModel(TBoundaryDefinitions boundaryDefinitions) { + this.serviceTemplateResource.getServiceTemplate().setBoundaryDefinitions(boundaryDefinitions); + return BackendUtils.persist(this.serviceTemplateResource); + } + + @Path("properties/") + @PUT + @Consumes(MediaType.TEXT_XML) + @RestDoc(resourceDescription = "Models the user-defined properties. The property mappings go into a separate resource propertymappings.") + public Response putProperties(@RestDocParam(description = "Stored properties. The XSD allows a single element only. Therefore, we go for the contained element") Document doc) { + org.eclipse.winery.model.tosca.TBoundaryDefinitions.Properties properties = ModelUtilities.getProperties(this.boundaryDefinitions); + properties.setAny(doc.getDocumentElement()); + return BackendUtils.persist(this.serviceTemplateResource); + } + + @Path("requirements/") + public RequirementsResource getRequiremensResource() { + Requirements requirements = this.boundaryDefinitions.getRequirements(); + if (requirements == null) { + requirements = new Requirements(); + this.boundaryDefinitions.setRequirements(requirements); + } + List refs = requirements.getRequirement(); + return new RequirementsResource(this.serviceTemplateResource, refs); + } + + @Path("capabilities/") + public CapabilitiesResource getCapabilitiesResource() { + Capabilities caps = this.boundaryDefinitions.getCapabilities(); + if (caps == null) { + caps = new Capabilities(); + this.boundaryDefinitions.setCapabilities(caps); + } + List refs = caps.getCapability(); + return new CapabilitiesResource(this.serviceTemplateResource, refs); + } + + @Path("policies/") + public PoliciesResource getPoliciesResource() { + Policies policies = this.boundaryDefinitions.getPolicies(); + if (policies == null) { + policies = new Policies(); + this.boundaryDefinitions.setPolicies(policies); + } + return new PoliciesResource(policies.getPolicy(), this.serviceTemplateResource); + } + + /** + * This path is below "boundary definitions" to ease implementation If it + * was modeled following the XSD, it would have been nested below + * "properties". We did not do that + */ + @Path("propertymappings/") + public PropertyMappingsResource getPropertyMappings() { + Properties properties = this.boundaryDefinitions.getProperties(); + if (properties == null) { + properties = new Properties(); + this.boundaryDefinitions.setProperties(properties); + } + PropertyMappings propertyMappings = properties.getPropertyMappings(); + if (propertyMappings == null) { + propertyMappings = new PropertyMappings(); + properties.setPropertyMappings(propertyMappings); + } + return new PropertyMappingsResource(propertyMappings, this.serviceTemplateResource); + } + + @Path("interfaces/") + public InterfacesResource getInterfacesResource() { + Interfaces interfaces = this.boundaryDefinitions.getInterfaces(); + if (interfaces == null) { + interfaces = new Interfaces(); + this.boundaryDefinitions.setInterfaces(interfaces); + } + return new InterfacesResource(interfaces.getInterface(), this.serviceTemplateResource); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/PropertyMappingsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/PropertyMappingsResource.java new file mode 100644 index 0000000..a6872e0 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/PropertyMappingsResource.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2013-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions; + +import java.util.Iterator; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.model.tosca.TBoundaryDefinitions.Properties.PropertyMappings; +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.model.tosca.TPropertyMapping; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource; +import org.restdoc.annotations.RestDoc; + +public class PropertyMappingsResource { + + private final PropertyMappings propertyMappings; + private final ServiceTemplateResource res; + + + public PropertyMappingsResource(PropertyMappings propertyMappings, ServiceTemplateResource res) { + this.propertyMappings = propertyMappings; + this.res = res; + } + + @Path("{serviceTemplatePropertyRef}") + @DELETE + public Response onDelete(@PathParam("serviceTemplatePropertyRef") String serviceTemplatePropertyRef) { + serviceTemplatePropertyRef = Util.URLdecode(serviceTemplatePropertyRef); + Iterator iterator = this.propertyMappings.getPropertyMapping().iterator(); + while (iterator.hasNext()) { + TPropertyMapping propertyMapping = iterator.next(); + if (propertyMapping.getServiceTemplatePropertyRef().equals(serviceTemplatePropertyRef)) { + iterator.remove(); + return BackendUtils.persist(this.res); + } + } + // if the property mapping was not found, we reach this point + // otherwise "iterator.remove()" has called and the resource persisted + return Response.status(Status.NOT_FOUND).build(); + } + + private void updatePropertyMapping(TPropertyMapping propertyMapping, String serviceTemplatePropertyRef, TEntityTemplate template, String targetPropertyRef) { + propertyMapping.setServiceTemplatePropertyRef(serviceTemplatePropertyRef); + propertyMapping.setTargetObjectRef(template); + propertyMapping.setTargetPropertyRef(targetPropertyRef); + } + + @RestDoc(methodDescription = "Creates or updates a property mapping with the given fields") + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + // @formatter:off + public Response onPost( + @FormParam("serviceTemplatePropertyRef") String serviceTemplatePropertyRef, + @FormParam("targetObjectRef") String targetObjectRef, + @FormParam("targetPropertyRef") String targetPropertyRef + ) { + // @formatter:on + if (StringUtils.isEmpty(serviceTemplatePropertyRef)) { + return Response.status(Status.BAD_REQUEST).entity("serviceTemplatePropertyRef must not be empty").build(); + } + if (StringUtils.isEmpty(targetObjectRef)) { + return Response.status(Status.BAD_REQUEST).entity("targetObjectRef must not be empty").build(); + } + if (StringUtils.isEmpty(targetPropertyRef)) { + return Response.status(Status.BAD_REQUEST).entity("targetPropertyRef must not be empty").build(); + } + + TEntityTemplate template = ModelUtilities.findNodeTemplateOrRequirementOfNodeTemplateOrCapabilityOfNodeTemplateOrRelationshipTemplate(this.res.getServiceTemplate().getTopologyTemplate(), targetObjectRef); + if (template == null) { + return Response.status(Status.BAD_REQUEST).entity("targetObjectRef " + targetObjectRef + " could not be resolved.").build(); + } + + // replace propertyMapping if it exists + Iterator iterator = this.propertyMappings.getPropertyMapping().iterator(); + while (iterator.hasNext()) { + TPropertyMapping propertyMapping = iterator.next(); + if (propertyMapping.getServiceTemplatePropertyRef().equals(serviceTemplatePropertyRef)) { + // we found a property with the same mapping + // just update it ... + this.updatePropertyMapping(propertyMapping, serviceTemplatePropertyRef, template, targetPropertyRef); + // ... and finish processing + return BackendUtils.persist(this.res); + } + } + + // the property mapping didn't exist, + // we create a new one + TPropertyMapping newPropertyMapping = new TPropertyMapping(); + this.updatePropertyMapping(newPropertyMapping, serviceTemplatePropertyRef, template, targetPropertyRef); + return BackendUtils.persist(this.res); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedInterfaceResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedInterfaceResource.java new file mode 100644 index 0000000..b69e802 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedInterfaceResource.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.interfaces; + +import java.util.List; + +import javax.ws.rs.Path; + +import org.eclipse.winery.model.tosca.TExportedInterface; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource; + +public class ExportedInterfaceResource extends EntityWithIdResource { + + public ExportedInterfaceResource(IIdDetermination idDetermination, TExportedInterface o, int idx, List list, IPersistable res) { + super(idDetermination, o, idx, list, res); + } + + @Path("exportedoperations/") + public ExportedOperationsResource getExportedOperationsResource() { + return new ExportedOperationsResource(this.o.getOperation(), this.res); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedOperationResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedOperationResource.java new file mode 100644 index 0000000..dd10751 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedOperationResource.java @@ -0,0 +1,249 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.interfaces; + +import java.io.StringWriter; +import java.util.List; + +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.model.tosca.TExportedOperation; +import org.eclipse.winery.model.tosca.TExportedOperation.NodeOperation; +import org.eclipse.winery.model.tosca.TExportedOperation.Plan; +import org.eclipse.winery.model.tosca.TExportedOperation.RelationshipOperation; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TPlan; +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.model.tosca.TServiceTemplate; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource; +import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; + +public class ExportedOperationResource extends EntityWithIdResource { + + private static final Logger logger = LoggerFactory.getLogger(ExportedOperationResource.class); + + + public ExportedOperationResource(IIdDetermination idDetermination, TExportedOperation o, int idx, List list, IPersistable res) { + super(idDetermination, o, idx, list, res); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + public String getJSONRepresentation() { + JsonFactory jsonFactory = new JsonFactory(); + StringWriter sw = new StringWriter(); + try { + JsonGenerator jg = jsonFactory.createGenerator(sw); + jg.writeStartObject(); + String type = this.getType(); + jg.writeStringField("type", type); + jg.writeStringField("ref", this.getReference()); + if ((type != null) && (!type.equals("Plan"))) { + jg.writeStringField("interfacename", this.getInterfaceName()); + jg.writeStringField("operationname", this.getOperationName()); + } + jg.writeEndObject(); + jg.close(); + } catch (Exception e) { + ExportedOperationResource.logger.error(e.getMessage(), e); + throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(e).build()); + } + String res = sw.toString(); + return res; + } + + /** + * + * @return "NodeOperation" | "RelationshipOperation" | "Plan" | null. null + * is returned if no type is set + */ + @Path("type") + @GET + public String getType() { + if (this.o.getNodeOperation() != null) { + return "NodeOperation"; + } else if (this.o.getRelationshipOperation() != null) { + return "RelationshipOperation"; + } else if (this.o.getPlan() != null) { + return "Plan"; + } else { + return null; + } + } + + @Path("type") + @PUT + public Response setType(String type) { + switch (type) { + case "NodeOperation": + if (this.o.getNodeOperation() == null) { + // only do something, if the type is really changed + this.o.setRelationshipOperation(null); + this.o.setPlan(null); + NodeOperation no = new NodeOperation(); + this.o.setNodeOperation(no); + } + break; + case "RelationshipOperation": + if (this.o.getRelationshipOperation() == null) { + // only do something, if the type is really changed + this.o.setNodeOperation(null); + this.o.setPlan(null); + RelationshipOperation ro = new RelationshipOperation(); + this.o.setRelationshipOperation(ro); + } + break; + case "Plan": + if (this.o.getPlan() == null) { + // only do something, if the type is really changed + this.o.setNodeOperation(null); + this.o.setRelationshipOperation(null); + Plan plan = new Plan(); + this.o.setPlan(plan); + } + break; + default: + return Response.status(Status.BAD_REQUEST).entity("Unknown type " + type).build(); + } + return BackendUtils.persist(this.res); + } + + /** + * @return null if no reference is set + */ + @Path("ref") + @GET + public String getReference() { + if (this.o.getNodeOperation() != null) { + TNodeTemplate nt = (TNodeTemplate) this.o.getNodeOperation().getNodeRef(); + if (nt == null) { + return null; + } + return nt.getId(); + } else if (this.o.getRelationshipOperation() != null) { + TRelationshipTemplate rt = (TRelationshipTemplate) this.o.getRelationshipOperation().getRelationshipRef(); + if (rt == null) { + return null; + } + return rt.getId(); + } else if (this.o.getPlan() != null) { + TPlan plan = (TPlan) this.o.getPlan().getPlanRef(); + if (plan == null) { + return null; + } + return plan.getId(); + } else { + // no type set -> no reference can be returned + return null; + } + } + + @Path("ref") + @PUT + public Response setReference(String ref) { + TServiceTemplate ste = ((ServiceTemplateResource) this.res).getServiceTemplate(); + + // we assume that a correctly set type also means that getX (getNodeOperation, ...) returns non null + switch (this.getType()) { + case "NodeOperation": + TNodeTemplate nodeTemplate = ModelUtilities.resolveNodeTemplate(ste, ref); + this.o.getNodeOperation().setNodeRef(nodeTemplate); + break; + case "RelationshipOperation": + TRelationshipTemplate relationshipTemplate = ModelUtilities.resolveRelationshipTemplate(ste, ref); + this.o.getRelationshipOperation().setRelationshipRef(relationshipTemplate); + break; + case "Plan": + TPlan plan = ModelUtilities.resolvePlan(ste, ref); + this.o.getPlan().setPlanRef(plan); + break; + default: + return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Unknown type " + this.getType()).build(); + } + return BackendUtils.persist(this.res); + } + + @Path("interfacename") + @GET + public String getInterfaceName() { + if (this.o.getNodeOperation() != null) { + return this.o.getNodeOperation().getInterfaceName(); + } else if (this.o.getRelationshipOperation() != null) { + return this.o.getRelationshipOperation().getInterfaceName(); + } else if (this.o.getPlan() != null) { + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity("A plan does not carry an interface").build()); + } else { + throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity("Unsupported state of ExportedOperation").build()); + } + } + + @Path("interfacename") + @PUT + public Response setInterfaceName(String interfacename) { + if (this.o.getNodeOperation() != null) { + this.o.getNodeOperation().setInterfaceName(interfacename); + } else if (this.o.getRelationshipOperation() != null) { + this.o.getRelationshipOperation().setInterfaceName(interfacename); + } else if (this.o.getPlan() != null) { + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity("A plan does not carry an interface").build()); + } else { + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity("No type set").build()); + } + return BackendUtils.persist(this.res); + } + + @Path("operationname") + @GET + public String getOperationName() { + if (this.o.getNodeOperation() != null) { + return this.o.getNodeOperation().getOperationName(); + } else if (this.o.getRelationshipOperation() != null) { + return this.o.getRelationshipOperation().getOperationName(); + } else if (this.o.getPlan() != null) { + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity("A plan does not carry an operation").build()); + } else { + throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity("Unsupported state of ExportedOperation").build()); + } + } + + @Path("operationname") + @PUT + public Response setOperationName(String name) { + if (this.o.getNodeOperation() != null) { + this.o.getNodeOperation().setOperationName(name); + } else if (this.o.getRelationshipOperation() != null) { + this.o.getRelationshipOperation().setOperationName(name); + } else if (this.o.getPlan() != null) { + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity("A plan does not carry an operation").build()); + } else { + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity("No type set").build()); + } + return BackendUtils.persist(this.res); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedOperationsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedOperationsResource.java new file mode 100644 index 0000000..d8788fd --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/ExportedOperationsResource.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.interfaces; + +import java.util.List; + +import org.eclipse.winery.model.tosca.TExportedOperation; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource; + +import com.sun.jersey.api.view.Viewable; + +public class ExportedOperationsResource extends EntityWithIdCollectionResource { + + public ExportedOperationsResource(List list, IPersistable res) { + super(ExportedOperationResource.class, TExportedOperation.class, list, res); + } + + @Override + public String getId(TExportedOperation entity) { + return entity.getName(); + } + + @Override + public Viewable getHTML() { + throw new IllegalStateException("No implementation required: boundarydefinitions.jsp contains all required html."); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/InterfacesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/InterfacesResource.java new file mode 100644 index 0000000..301f457 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/InterfacesResource.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.interfaces; + +import java.util.List; + +import org.eclipse.winery.model.tosca.TExportedInterface; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource; + +import com.sun.jersey.api.view.Viewable; + +public class InterfacesResource extends EntityWithIdCollectionResource { + + public InterfacesResource(List list, IPersistable res) { + super(ExportedInterfaceResource.class, TExportedInterface.class, list, res); + } + + @Override + public String getId(TExportedInterface entity) { + return entity.getName(); + } + + @Override + public Viewable getHTML() { + throw new IllegalStateException("No implementation required: boundarydefinitions.jsp contains all required html."); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/package-info.java new file mode 100644 index 0000000..6a342ea --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/interfaces/package-info.java @@ -0,0 +1,16 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ + +/** + * This package models exported interfaces nested in a boundary definitions. + */ +package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.interfaces; \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/PoliciesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/PoliciesResource.java new file mode 100644 index 0000000..b18341f --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/PoliciesResource.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.policies; + +import java.util.List; + +import javax.ws.rs.PUT; +import javax.ws.rs.core.Response; + +import org.eclipse.winery.model.tosca.TPolicy; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdCollectionResource; + +import com.sun.jersey.api.view.Viewable; + +public class PoliciesResource extends EntityWithoutIdCollectionResource { + + public PoliciesResource(List list, IPersistable res) { + super(PolicyResource.class, TPolicy.class, list, res); + } + + @Override + public Viewable getHTML() { + throw new IllegalStateException("Not required: boundarydefinitions.jsp also includes the content of the Policy tab."); + } + + @PUT + public Response replaceAll(List newList) { + this.list.clear(); + for (TPolicy policy : newList) { + this.list.add(policy); + } + return BackendUtils.persist(this.res); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/PolicyResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/PolicyResource.java new file mode 100644 index 0000000..08fbd8d --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/PolicyResource.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.policies; + +import java.util.List; + +import org.eclipse.winery.model.tosca.TPolicy; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdResource; + +public class PolicyResource extends EntityWithoutIdResource { + + public PolicyResource(TPolicy o, int idx, List list, IPersistable res) { + super(o, idx, list, res); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/package-info.java new file mode 100644 index 0000000..45bc0c7 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/policies/package-info.java @@ -0,0 +1,16 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ + +/** + * This package models policies nested in a boundary definitions. It could be resued for the topology modeler, but currently, this is not necessary. + */ +package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.policies; \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/CapabilitiesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/CapabilitiesResource.java new file mode 100644 index 0000000..80f2640 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/CapabilitiesResource.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.model.tosca.TCapability; +import org.eclipse.winery.model.tosca.TCapabilityRef; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.CollectionsHelper; +import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdCollectionResource; +import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource; + +import com.sun.jersey.api.view.Viewable; + +/** + * This class is an adaption from + * {@link org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps.RequirementsResource} + */ +public class CapabilitiesResource extends EntityWithoutIdCollectionResource { + + public CapabilitiesResource(IPersistable res, List refs) { + super(CapabilityResource.class, TCapabilityRef.class, refs, res); + } + + @Override + public Viewable getHTML() { + throw new IllegalStateException("Not yet required: boundarydefinitions.jsp renders all tab content."); + } + + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public Response addNewElement(@FormParam("name") String name, @FormParam("ref") String reference) { + // Implementation adapted from super addNewElement + + if (reference == null) { + return Response.status(Status.BAD_REQUEST).entity("A reference has to be provided").build(); + } + + TCapabilityRef ref = new TCapabilityRef(); + ref.setName(name); // may also be null + + // The XML model fordces us to put a reference to the object and not just the string + ServiceTemplateResource rs = (ServiceTemplateResource) this.res; + TCapability resolved = ModelUtilities.resolveCapability(rs.getServiceTemplate(), reference); + // In case nothing was found: report back to the user + if (resolved == null) { + return Response.status(Status.BAD_REQUEST).entity("Reference could not be resolved").build(); + } + + ref.setRef(resolved); + + // "this.alreadyContains(ref)" cannot be called as this leads to a mappable exception: The data does not contain an id where the given ref attribute may point to + + this.list.add(ref); + return CollectionsHelper.persist(this.res, this, ref); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/CapabilityResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/CapabilityResource.java new file mode 100644 index 0000000..7cb7b49 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/CapabilityResource.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps; + +import java.util.List; + +import org.eclipse.winery.model.tosca.TCapabilityRef; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdResource; + +public class CapabilityResource extends EntityWithoutIdResource { + + public CapabilityResource(TCapabilityRef o, int idx, List list, IPersistable res) { + super(o, idx, list, res); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/RequirementResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/RequirementResource.java new file mode 100644 index 0000000..72a7476 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/RequirementResource.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps; + +import java.util.List; + +import org.eclipse.winery.model.tosca.TRequirementRef; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdResource; + +public class RequirementResource extends EntityWithoutIdResource { + + public RequirementResource(TRequirementRef o, int idx, List list, IPersistable res) { + super(o, idx, list, res); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/RequirementsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/RequirementsResource.java new file mode 100644 index 0000000..dc6ad94 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/RequirementsResource.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.eclipse.winery.common.ModelUtilities; +import org.eclipse.winery.model.tosca.TRequirement; +import org.eclipse.winery.model.tosca.TRequirementRef; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.CollectionsHelper; +import org.eclipse.winery.repository.resources._support.collections.withoutid.EntityWithoutIdCollectionResource; +import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource; + +import com.sun.jersey.api.view.Viewable; + +/** + * This class is mirrored at + * {@link org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps.CapabilitiesResource} + */ +public class RequirementsResource extends EntityWithoutIdCollectionResource { + + public RequirementsResource(IPersistable res, List refs) { + super(RequirementResource.class, TRequirementRef.class, refs, res); + } + + @Override + public Viewable getHTML() { + throw new IllegalStateException("Not yet required: boundarydefinitions.jsp renders all tab content."); + } + + /** + * Adds an element using form-encoding + * + * This is necessary as TRequirementRef contains an IDREF and the XML + * snippet itself does not contain the target id + * + * @param name the optional name of the requirement + * @param reference the reference to a requirement in the topology + */ + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public Response addNewElement(@FormParam("name") String name, @FormParam("ref") String reference) { + // Implementation adapted from super addNewElement + + if (reference == null) { + return Response.status(Status.BAD_REQUEST).entity("A reference has to be provided").build(); + } + + TRequirementRef ref = new TRequirementRef(); + ref.setName(name); // may also be null + + // The XML model forces us to put a reference to the object and not just the string + ServiceTemplateResource rs = (ServiceTemplateResource) this.res; + TRequirement resolved = ModelUtilities.resolveRequirement(rs.getServiceTemplate(), reference); + // In case nothing was found: report back to the user + if (resolved == null) { + return Response.status(Status.BAD_REQUEST).entity("Reference could not be resolved").build(); + } + + ref.setRef(resolved); + + // "this.alreadyContains(ref)" cannot be called as this leads to a mappable exception: The data does not contain an id where the given ref attribute may point to + + this.list.add(ref); + return CollectionsHelper.persist(this.res, this, ref); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/package-info.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/package-info.java new file mode 100644 index 0000000..f6a3c5d --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/boundarydefinitions/reqscaps/package-info.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ + +/** + * This package contains all classes for requirement refs and capability refs + * + * They are nested as "Requirements" / "Capabilities" in the boundary definitions, but the things itself are called "...Ref" + */ +package org.eclipse.winery.repository.resources.servicetemplates.boundarydefinitions.reqscaps; \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlanFileResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlanFileResource.java new file mode 100644 index 0000000..5a4b56f --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlanFileResource.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2014-2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.plans; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.PUT; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.ids.elements.PlanId; +import org.eclipse.winery.model.tosca.TPlan; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource; +import org.restdoc.annotations.RestDoc; + +import com.sun.jersey.core.header.FormDataContentDisposition; +import com.sun.jersey.multipart.FormDataBodyPart; +import com.sun.jersey.multipart.FormDataParam; + +public class PlanFileResource { + + private final PlanId planId; + private TPlan plan; + private ServiceTemplateResource res; + + + public PlanFileResource(ServiceTemplateResource res, PlanId planId, TPlan plan) { + this.res = res; + this.planId = planId; + this.plan = plan; + } + + /** + * Extracts the file reference from plan's planModelReference + */ + private RepositoryFileReference getFileRef() { + String reference = this.plan.getPlanModelReference().getReference(); + File f = new File(reference); + return new RepositoryFileReference(this.planId, f.getName()); + } + + @PUT + @Consumes({MediaType.MULTIPART_FORM_DATA}) + @RestDoc(methodDescription = "Resource currently works for BPMN4TOSCA plans only") + // @formatter:off + public Response onPutFile( + @FormDataParam("file") InputStream uploadedInputStream, + @FormDataParam("file") FormDataContentDisposition fileDetail, + @FormDataParam("file") FormDataBodyPart body + ) { + // @formatter:on + + String fileName = fileDetail.getFileName(); + RepositoryFileReference ref = new RepositoryFileReference(this.planId, fileName); + RepositoryFileReference oldRef = this.getFileRef(); + boolean persistanceNecessary; + if (ref.equals(oldRef)) { + // nothing todo, file will be replaced + persistanceNecessary = false; + } else { + // new filename sent + BackendUtils.delete(oldRef); + PlansResource.setPlanModelReference(this.plan, this.planId, fileName); + persistanceNecessary = true; + } + + // Really store it + try { + Repository.INSTANCE.putContentToFile(ref, uploadedInputStream, body.getMediaType()); + } catch (IOException e1) { + return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not store plan. " + e1.getMessage()).build(); + } + + if (persistanceNecessary) { + return BackendUtils.persist(this.res); + } else { + return Response.noContent().build(); + } + } + + @PUT + @Consumes({MediaType.APPLICATION_JSON}) + // @formatter:off + public Response onPutJSON(InputStream is) { + RepositoryFileReference ref = this.getFileRef(); + return BackendUtils.putContentToFile(ref, is, MediaType.APPLICATION_JSON_TYPE); + } + + /** + * Returns the stored file. + */ + @GET + public Response getFile(@HeaderParam("If-Modified-Since") String modified) { + RepositoryFileReference ref = this.getFileRef(); + return BackendUtils.returnRepoPath(ref, modified); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlanResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlanResource.java new file mode 100644 index 0000000..704c831 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlanResource.java @@ -0,0 +1,203 @@ +/******************************************************************************* + * Copyright (c) 2012-2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.plans; + +import java.io.IOException; +import java.net.URI; +import java.util.List; + +import javax.ws.rs.DELETE; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriInfo; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.common.ids.definitions.ServiceTemplateId; +import org.eclipse.winery.common.ids.definitions.TOSCAComponentId; +import org.eclipse.winery.common.ids.elements.PlanId; +import org.eclipse.winery.common.ids.elements.PlansId; +import org.eclipse.winery.model.tosca.TPlan; +import org.eclipse.winery.model.tosca.TPlan.InputParameters; +import org.eclipse.winery.model.tosca.TPlan.OutputParameters; +import org.eclipse.winery.repository.Prefs; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.resources.IHasName; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource; +import org.eclipse.winery.repository.resources.interfaces.ParametersResource; +import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Does not implement + * {@link org.eclipse.winery.repository.resources.IHasTypeReference}, because + * the type of a plan is outside the system of TOSCA. + */ +public class PlanResource extends EntityWithIdResource implements IHasName { + + private static final Logger logger = LoggerFactory.getLogger(PlanResource.class); + + + public PlanResource(IIdDetermination idDetermination, TPlan o, int idx, List list, ServiceTemplateResource res) { + super(idDetermination, o, idx, list, res); + } + + /** + * Ugly hack to get the parent service template resource + * + */ + public ServiceTemplateResource getServiceTemplateResource() { + // Solution proposal 1: Each sub-resource should know its parent service + // template + // + // Solution proposal 2 (Generic solution): Each resource should know its + // parent resource + // + // Does not work when plan is used at as component instance (then, + // serviceTemplateResource is null). In this case, a plan is not associated + // with a service template. + + // we cannot use "((PlanId) id).getParent()" as this "only" returns an + // ID + // we could create a newly resource based on that ID + // However, the parent resource has already been created when the + // PlanResource has been generated: + // Jersey crawls down from the main resource through the service + // template resource to the plan resource + return (ServiceTemplateResource) this.res; + } + + /** + * Determines the id of the current resource + */ + private PlanId getId() { + ServiceTemplateId sId = (ServiceTemplateId) this.getServiceTemplateResource().getId(); + PlansId psId = new PlansId(sId); + PlanId pId = new PlanId(psId, new XMLId(this.o.getId(), false)); + return pId; + } + + @Override + @DELETE + public Response onDelete() { + Response res = super.onDelete(); + if (Utils.isSuccessFulResponse(res)) { + try { + Repository.INSTANCE.forceDelete(this.getId()); + } catch (IOException e) { + return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not remove plan file").build(); + } + return BackendUtils.persist(this.res); + } else { + return res; + } + } + + @GET + @Produces(MediaType.TEXT_HTML) + public Response getHTML(@Context UriInfo uriInfo) { + boolean isBPMN4TOSCA = this.o.getPlanLanguage().equals(org.eclipse.winery.common.constants.Namespaces.URI_BPMN4TOSCA_20); + String bpmn4toscaBaseURL = Prefs.INSTANCE.getBPMN4TOSCABaseURL(); + if (isBPMN4TOSCA && (!StringUtils.isEmpty(bpmn4toscaBaseURL))) { + String uri = bpmn4toscaBaseURL; + URI repositoryURI = uriInfo.getBaseUri(); + uri += "?repositoryURL=" + Util.URLencode(repositoryURI.toString()); + TOSCAComponentId serviceTemplateId = this.getServiceTemplateResource().getId(); + uri += "&namespace=" + serviceTemplateId.getNamespace().getEncoded(); + uri += "&id=" + serviceTemplateId.getXmlId().getEncoded(); + uri += "&plan=" + this.getName(); + return Response.temporaryRedirect(Utils.createURI(uri)).build(); + } else { + // return Response.ok().entity("No editor plugin found for plan language " + this.o.getPlanLanguage()).build(); + URI fileURI = uriInfo.getAbsolutePath().resolve("file"); + return Response.seeOther(fileURI).build(); + } + } + + @Override + public String getName() { + String name = this.o.getName(); + if (name == null) { + name = this.o.getId(); + } + return name; + } + + @Override + public Response setName(@FormParam("value") String name) { + this.o.setName(name); + return BackendUtils.persist(this.res); + } + + @Path("file") + public PlanFileResource getPlanFileResource() { + return new PlanFileResource((ServiceTemplateResource) this.res, this.getId(), this.o); + } + + @GET + @Path("type") + public String getType() { + return this.o.getPlanType(); + } + + @PUT + @Path("type") + public Response setType(@FormParam("type") String type) { + this.o.setPlanType(type); + return BackendUtils.persist(this.res); + } + + @GET + @Path("language") + public String getLanguage() { + return this.o.getPlanLanguage(); + } + + @PUT + @Path("language") + public Response setLanguage(@FormParam("language") String language) { + this.o.setPlanType(language); + return BackendUtils.persist(this.res); + } + + @Path("inputparameters/") + public ParametersResource getInputParametersResource() { + InputParameters inputParameters = this.o.getInputParameters(); + if (inputParameters == null) { + inputParameters = new InputParameters(); + this.o.setInputParameters(inputParameters); + } + return new ParametersResource(inputParameters.getInputParameter(), this.getServiceTemplateResource()); + } + + @Path("outputparameters/") + public ParametersResource getOutputParametersResource() { + OutputParameters outputParameters = this.o.getOutputParameters(); + if (outputParameters == null) { + outputParameters = new OutputParameters(); + this.o.setOutputParameters(outputParameters); + } + return new ParametersResource(outputParameters.getOutputParameter(), this.getServiceTemplateResource()); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlansResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlansResource.java new file mode 100644 index 0000000..13a8420 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlansResource.java @@ -0,0 +1,205 @@ +/******************************************************************************* + * Copyright (c) 2012-2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.plans; + +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.Util; +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.common.ids.definitions.ServiceTemplateId; +import org.eclipse.winery.common.ids.elements.PlanId; +import org.eclipse.winery.common.ids.elements.PlansId; +import org.eclipse.winery.model.tosca.TPlan; +import org.eclipse.winery.model.tosca.TPlan.PlanModelReference; +import org.eclipse.winery.repository.Constants; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource; +import org.eclipse.winery.repository.resources.admin.types.PlanLanguagesManager; +import org.eclipse.winery.repository.resources.admin.types.PlanTypesManager; +import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource; +import org.restdoc.annotations.RestDoc; +import org.restdoc.annotations.RestDocParam; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonGenerator; +import com.sun.jersey.api.view.Viewable; +import com.sun.jersey.core.header.FormDataContentDisposition; +import com.sun.jersey.multipart.FormDataBodyPart; +import com.sun.jersey.multipart.FormDataParam; + +/** + * Presents the plans nested in one Service Template + */ +public class PlansResource extends EntityWithIdCollectionResource { + + private static final Logger logger = LoggerFactory.getLogger(PlansResource.class); + + + public PlansResource(List plans, ServiceTemplateResource res) { + super(PlanResource.class, TPlan.class, plans, res); + } + + @Override + public Viewable getHTML() { + return new Viewable("/jsp/servicetemplates/plans/plans.jsp", new PlansResourceData(this.list)); + } + + @POST + @RestDoc(methodDescription = "

Linked plans are currently not supported. Existing plans with the same id are overwritten

@return JSON with .tableData: Array with row data for dataTable

") + @Consumes({MediaType.MULTIPART_FORM_DATA}) + @Produces(MediaType.APPLICATION_JSON) + // the supertype consumes JSON and XML at org.eclipse.winery.repository.resources._support.collections.EntityCollectionResource.addNewElement(EntityT) + // @formatter:off + public Response onPost( + @FormDataParam("planName") String name, + @FormDataParam("planType") String type, + @FormDataParam("planLanguage") @RestDocParam(description = "the plan language (e..g, BPMN or BPEL). Full URL.") String language, + @FormDataParam("file") @RestDocParam(description="(optional in the case of BPMN4TOSCA) file containing the plan.") InputStream uploadedInputStream, + @FormDataParam("file") FormDataContentDisposition fileDetail, + @FormDataParam("file") FormDataBodyPart body + ) { + // @formatter:on + if (StringUtils.isEmpty(name)) { + return Response.status(Status.BAD_REQUEST).entity("planName must be given").build(); + } + if (StringUtils.isEmpty(type)) { + return Response.status(Status.BAD_REQUEST).entity("planType must be given").build(); + } + if (StringUtils.isEmpty(language)) { + return Response.status(Status.BAD_REQUEST).entity("planLanguage must be given").build(); + } + + boolean bpmn4toscaMode = org.eclipse.winery.common.constants.Namespaces.URI_BPMN4TOSCA_20.equals(language); + if (!bpmn4toscaMode) { + if (uploadedInputStream == null) { + return Response.status(Status.BAD_REQUEST).entity("file must be given").build(); + } + } + + // A plan carries both a name and an ID + // To be user-friendly, we create the ID based on the name + // the drawback is, that we do not allow two plans with the same name + // during creation, but allow renaming plans to the same name (as we do + // not allow ID renaming) + String xmlId = Utils.createXMLidAsString(name); + + // BEGIN: Store plan file + + // Determine Id + PlansId plansId = new PlansId((ServiceTemplateId) ((ServiceTemplateResource) this.res).getId()); + PlanId planId = new PlanId(plansId, new XMLId(xmlId, false)); + // Ensure overwriting + if (Repository.INSTANCE.exists(planId)) { + try { + Repository.INSTANCE.forceDelete(planId); + // Quick hack to remove the deleted plan from the plans element + ((ServiceTemplateResource) this.res).synchronizeReferences(); + } catch (IOException e) { + return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + } + } + + String fileName; + if (bpmn4toscaMode) { + fileName = xmlId + Constants.SUFFIX_BPMN4TOSCA; + RepositoryFileReference ref = new RepositoryFileReference(planId, fileName); + try { + Repository.INSTANCE.putContentToFile(ref, "{}", MediaType.APPLICATION_JSON_TYPE); + } catch (IOException e1) { + return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not create empty plan. " + e1.getMessage()).build(); + } + } else { + // We use the filename also as local file name. Alternatively, we could use the xml id + // With URL encoding, this should not be an issue + fileName = Util.URLencode(fileDetail.getFileName()); + + // Really store it + RepositoryFileReference ref = new RepositoryFileReference(planId, fileName); + try { + Repository.INSTANCE.putContentToFile(ref, uploadedInputStream, body.getMediaType()); + } catch (IOException e1) { + return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not store plan. " + e1.getMessage()).build(); + } + } + // END: Store plan file + + TPlan plan = new TPlan(); + plan.setId(xmlId); + plan.setName(name); + plan.setPlanType(type); + plan.setPlanLanguage(language); + PlansResource.setPlanModelReference(plan, planId, fileName); + this.list.add(plan); + + // prepare result + JsonFactory jsonFactory = new JsonFactory(); + StringWriter sw = new StringWriter(); + try { + JsonGenerator jGenerator = jsonFactory.createGenerator(sw); + jGenerator.writeStartObject(); + jGenerator.writeFieldName("tableData"); + jGenerator.writeStartArray(); + jGenerator.writeString(xmlId); + jGenerator.writeString(""); // precondition + jGenerator.writeString(name); + jGenerator.writeString(PlanTypesManager.INSTANCE.getShortName(type)); + jGenerator.writeString(PlanLanguagesManager.INSTANCE.getShortName(language)); + jGenerator.writeEndArray(); + jGenerator.writeEndObject(); + jGenerator.close(); + sw.close(); + } catch (JsonGenerationException e) { + PlansResource.logger.error(e.getMessage(), e); + return Response.serverError().build(); + } catch (IOException e) { + PlansResource.logger.error(e.getMessage(), e); + return Response.serverError().build(); + } + + Response res = BackendUtils.persist(this.res); + if (res.getStatus() == 204) { + // everything OK, return created + return Response.created(Utils.createURI(Util.URLencode(xmlId))).entity(sw.toString()).build(); + } else { + return res; + } + } + + static void setPlanModelReference(TPlan plan, PlanId planId, String fileName) { + PlanModelReference pref = new PlanModelReference(); + // Set path relative to Definitions/ path inside CSAR. + pref.setReference("../" + Utils.getURLforPathInsideRepo(BackendUtils.getPathInsideRepo(planId)) + fileName); + plan.setPlanModelReference(pref); + } + + @Override + public String getId(TPlan plan) { + return plan.getId(); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlansResourceData.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlansResourceData.java new file mode 100644 index 0000000..8527eb4 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/plans/PlansResourceData.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.plans; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Collection; +import java.util.List; + +import org.eclipse.winery.model.tosca.TPlan; +import org.eclipse.winery.model.tosca.TPlan.PlanModelReference; +import org.eclipse.winery.repository.datatypes.TypeWithShortName; +import org.eclipse.winery.repository.resources.admin.types.PlanLanguagesManager; +import org.eclipse.winery.repository.resources.admin.types.PlanTypesManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonGenerator; + +public class PlansResourceData { + + private static final Logger logger = LoggerFactory.getLogger(PlansResourceData.class); + + // data: [ [id, pre, name, type, lang]* ] + private String embeddedPlansTableData; + + // data: [ [id, pre, name, type, lang, reference]* ] + private String linkedPlansTableData; + + + /** + * Data object for the JSP + * + * @param serviceTemplateResource the service template the plans belong to + */ + public PlansResourceData(List plans) { + if (plans.isEmpty()) { + this.embeddedPlansTableData = "[]"; + this.linkedPlansTableData = "[]"; + return; + } + JsonFactory jsonFactory = new JsonFactory(); + StringWriter embeddedPlansTableDataSW = new StringWriter(); + StringWriter linkedPlansTableDataSW = new StringWriter(); + try { + JsonGenerator jGeneratorEmbedded = jsonFactory.createGenerator(embeddedPlansTableDataSW); + JsonGenerator jGeneratorLinked = jsonFactory.createGenerator(linkedPlansTableDataSW); + + jGeneratorEmbedded.writeStartArray(); + jGeneratorLinked.writeStartArray(); + + for (TPlan plan : plans) { + String name = plan.getName(); + if (name == null) { + // name defaults to id + name = plan.getId(); + } + String type = PlanTypesManager.INSTANCE.getShortName(plan.getPlanType()); + String language = PlanLanguagesManager.INSTANCE.getShortName(plan.getPlanLanguage()); + PlanModelReference planModelReference = plan.getPlanModelReference(); + String reference = planModelReference != null ? planModelReference.getReference() : null; + JsonGenerator gen; + boolean writeReference; + if (reference == null) { + gen = jGeneratorEmbedded; + writeReference = false; + } else if (reference.startsWith("../")) { + gen = jGeneratorEmbedded; + writeReference = false; + } else { + gen = jGeneratorLinked; + writeReference = true; + } + + gen.writeStartArray(); + gen.writeString(plan.getId()); + gen.writeString(""); // precondition + gen.writeString(name); + gen.writeString(type); + gen.writeString(language); + if (writeReference) { + gen.writeString(reference); + } + gen.writeEndArray(); + } + + jGeneratorEmbedded.writeEndArray(); + jGeneratorLinked.writeEndArray(); + + jGeneratorEmbedded.close(); + embeddedPlansTableDataSW.close(); + jGeneratorLinked.close(); + linkedPlansTableDataSW.close(); + } catch (JsonGenerationException e) { + PlansResourceData.logger.error(e.getMessage(), e); + this.embeddedPlansTableData = "[]"; + this.linkedPlansTableData = "[]"; + return; + } catch (IOException e) { + PlansResourceData.logger.error("", e); + this.embeddedPlansTableData = "[]"; + this.linkedPlansTableData = "[]"; + return; + } + this.embeddedPlansTableData = embeddedPlansTableDataSW.toString(); + this.linkedPlansTableData = linkedPlansTableDataSW.toString(); + } + + public String getEmbeddedPlansTableData() { + return this.embeddedPlansTableData; + } + + public String getLinkedPlansTableData() { + return this.linkedPlansTableData; + } + + public Collection getPlanTypes() { + return PlanTypesManager.INSTANCE.getTypes(); + } + + public Collection getPlanLanguages() { + return PlanLanguagesManager.INSTANCE.getTypes(); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/OptionResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/OptionResource.java new file mode 100644 index 0000000..9ce11f9 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/OptionResource.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.selfserviceportal; + +import java.io.IOException; +import java.util.List; + +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.eclipse.winery.model.selfservice.ApplicationOption; +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.datatypes.ids.elements.SelfServiceMetaDataId; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OptionResource extends EntityWithIdResource { + + private static final Logger logger = LoggerFactory.getLogger(OptionResource.class); + + static final String ICON_JPG = "icon.jpg"; + static final String PLAN_INPUT_XML = "plan.input.xml"; + private SelfServiceMetaDataId ssmdId; + + + public OptionResource(IIdDetermination idDetermination, ApplicationOption o, int idx, List list, SelfServicePortalResource res) { + super(idDetermination, o, idx, list, res); + this.ssmdId = ((SelfServicePortalResource) this.res).getId(); + } + + private String getFileNamePrefix() { + return OptionResource.getFileNamePrefix(this.o.getId()); + } + + public static String getFileNamePrefix(String id) { + return "option_" + id + "_"; + } + + @Path(OptionResource.ICON_JPG) + @GET + public Response getIcon(@HeaderParam("If-Modified-Since") String modified) { + RepositoryFileReference ref = new RepositoryFileReference(this.ssmdId, this.getFileNamePrefix() + OptionResource.ICON_JPG); + return BackendUtils.returnRepoPath(ref, modified); + } + + @Path("planinputmessage") + @GET + public Response getPlanInputMessage(@HeaderParam("If-Modified-Since") String modified) { + RepositoryFileReference ref = new RepositoryFileReference(this.ssmdId, this.getFileNamePrefix() + OptionResource.PLAN_INPUT_XML); + return BackendUtils.returnRepoPath(ref, modified); + } + + @Override + public Response onDelete() { + // delete icon and plan model reference ... + + // delete icon + // we use the URL stored in the data instead of the generated URL to be compatible with manually edits + RepositoryFileReference ref = new RepositoryFileReference(this.ssmdId, this.o.getIconUrl()); + try { + Repository.INSTANCE.forceDelete(ref); + } catch (IOException e) { + OptionResource.logger.error("Could not remove file", e); + return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + } + + // delete plan input + // we use the URL stored in the data instead of the generated URL to be compatible with manually edits + ref = new RepositoryFileReference(this.ssmdId, this.o.getPlanInputMessageUrl()); + try { + Repository.INSTANCE.forceDelete(ref); + } catch (IOException e) { + OptionResource.logger.error("Could not remove file", e); + return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + } + + // after deleting files, continue with list deletion + return super.onDelete(); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/OptionsResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/OptionsResource.java new file mode 100644 index 0000000..86fa102 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/OptionsResource.java @@ -0,0 +1,131 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.selfserviceportal; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.winery.model.selfservice.ApplicationOption; +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.datatypes.ids.elements.SelfServiceMetaDataId; +import org.eclipse.winery.repository.resources._support.collections.withid.EntityWithIdCollectionResource; +import org.restdoc.annotations.RestDoc; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jersey.api.view.Viewable; +import com.sun.jersey.core.header.FormDataContentDisposition; +import com.sun.jersey.multipart.FormDataBodyPart; +import com.sun.jersey.multipart.FormDataParam; + +public class OptionsResource extends EntityWithIdCollectionResource { + + private static final Logger logger = LoggerFactory.getLogger(OptionsResource.class); + + + public OptionsResource(List list, SelfServicePortalResource res) { + super(OptionResource.class, ApplicationOption.class, list, res); + } + + @Override + public String getId(ApplicationOption entity) { + return entity.getId(); + } + + @Override + public Viewable getHTML() { + throw new IllegalStateException("Not yet implemented."); + } + + @POST + @RestDoc(methodDescription = "Adds a new option

TODO: @return JSON with .tableData: Array with row data for dataTable

") + @Consumes(MediaType.MULTIPART_FORM_DATA) + // @formatter:off + public Response onPost( + @FormDataParam("name") String name, + @FormDataParam("description") String description, + @FormDataParam("planServiceName") String planServiceName, + @FormDataParam("planInputMessage") String planInputMessage, + @FormDataParam("file") InputStream uploadedInputStream, + @FormDataParam("file") FormDataContentDisposition fileDetail, + @FormDataParam("file") FormDataBodyPart body + ) { + // @formatter:on + if (StringUtils.isEmpty(name)) { + return Response.status(Status.BAD_REQUEST).entity("planName must be given").build(); + } + if (StringUtils.isEmpty(description)) { + return Response.status(Status.BAD_REQUEST).entity("description must be given").build(); + } + if (StringUtils.isEmpty(planServiceName)) { + return Response.status(Status.BAD_REQUEST).entity("planServiceName must be given").build(); + } + if (StringUtils.isEmpty(planInputMessage)) { + return Response.status(Status.BAD_REQUEST).entity("planInputMessage must be given").build(); + } + if (uploadedInputStream == null) { + return Response.status(Status.BAD_REQUEST).entity("file has to be provided").build(); + } + ApplicationOption option = new ApplicationOption(); + + String id = Utils.createXMLidAsString(name); + + String fileNamePrefix = OptionResource.getFileNamePrefix(id); + String iconFileName = fileNamePrefix + OptionResource.ICON_JPG; + String planInputMessageFileName = fileNamePrefix + OptionResource.PLAN_INPUT_XML; + + // create option data + option.setId(id); + option.setName(name); + option.setDescription(description); + option.setIconUrl(iconFileName); + option.setPlanInputMessageUrl(planInputMessageFileName); + option.setPlanServiceName(planServiceName); + + // BEGIN: store icon and planInputMessage + + SelfServiceMetaDataId ssmdId = ((SelfServicePortalResource) this.res).getId(); + + RepositoryFileReference iconRef = new RepositoryFileReference(ssmdId, iconFileName); + try { + Repository.INSTANCE.putContentToFile(iconRef, uploadedInputStream, body.getMediaType()); + } catch (IOException e) { + OptionsResource.logger.error(e.getMessage(), e); + return Response.serverError().entity(e.getMessage()).build(); + } + + RepositoryFileReference planInputMessageRef = new RepositoryFileReference(ssmdId, planInputMessageFileName); + try { + Repository.INSTANCE.putContentToFile(planInputMessageRef, planInputMessage, MediaType.TEXT_XML_TYPE); + } catch (IOException e) { + OptionsResource.logger.error(e.getMessage(), e); + return Response.serverError().entity(e.getMessage()).build(); + } + + // END: store icon and planInputMessage + + this.list.add(option); + Response response = BackendUtils.persist(this.res); + return response; + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/SelfServicePortalResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/SelfServicePortalResource.java new file mode 100644 index 0000000..98e1dcf --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/selfserviceportal/SelfServicePortalResource.java @@ -0,0 +1,223 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.selfserviceportal; + +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import org.apache.commons.io.IOUtils; +import org.apache.taglibs.standard.functions.Functions; +import org.eclipse.winery.common.RepositoryFileReference; +import org.eclipse.winery.common.ids.definitions.ServiceTemplateId; +import org.eclipse.winery.model.selfservice.Application; +import org.eclipse.winery.model.selfservice.Application.Options; +import org.eclipse.winery.model.tosca.TDocumentation; +import org.eclipse.winery.repository.JAXBSupport; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.datatypes.ids.elements.SelfServiceMetaDataId; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jersey.api.view.Viewable; +import com.sun.jersey.multipart.FormDataBodyPart; +import com.sun.jersey.multipart.FormDataParam; + +public class SelfServicePortalResource implements IPersistable { + + private static final Logger logger = LoggerFactory.getLogger(SelfServicePortalResource.class); + + private final ServiceTemplateResource serviceTemplateResource; + + public final RepositoryFileReference data_xml_ref; + public final RepositoryFileReference icon_jpg_ref; + public final RepositoryFileReference image_jpg_ref; + + private final Application application; + + private final SelfServiceMetaDataId id; + + + public SelfServicePortalResource(ServiceTemplateId serviceTemplateId) { + this(null, serviceTemplateId); + } + + public SelfServicePortalResource(ServiceTemplateResource serviceTemplateResource) { + this(serviceTemplateResource, (ServiceTemplateId) serviceTemplateResource.getId()); + } + + SelfServiceMetaDataId getId() { + return this.id; + } + + /** + * @param serviceTemplateResource may be null + * @param serviceTemplateId the id, must not be null + */ + private SelfServicePortalResource(ServiceTemplateResource serviceTemplateResource, ServiceTemplateId serviceTemplateId) { + this.serviceTemplateResource = serviceTemplateResource; + this.id = new SelfServiceMetaDataId(serviceTemplateId); + this.data_xml_ref = new RepositoryFileReference(this.id, "data.xml"); + this.icon_jpg_ref = new RepositoryFileReference(this.id, "icon.jpg"); + this.image_jpg_ref = new RepositoryFileReference(this.id, "image.jpg"); + this.application = this.getData(); + } + + private Application getData() { + if (Repository.INSTANCE.exists(this.data_xml_ref)) { + Unmarshaller u = JAXBSupport.createUnmarshaller(); + try (InputStream is = Repository.INSTANCE.newInputStream(this.data_xml_ref);) { + return (Application) u.unmarshal(is); + } catch (IOException | JAXBException e) { + SelfServicePortalResource.logger.error("Could not read from " + this.data_xml_ref, e); + return new Application(); + } + } else { + return this.getDefaultApplicationData(); + } + } + + private Application getDefaultApplicationData() { + Application app = new Application(); + app.setIconUrl("icon.jpg"); + app.setImageUrl("image.jpg"); + if (this.serviceTemplateResource != null) { + app.setDisplayName(this.serviceTemplateResource.getName()); + List documentation = this.serviceTemplateResource.getServiceTemplate().getDocumentation(); + if ((documentation != null) && (!documentation.isEmpty())) { + TDocumentation doc = documentation.get(0); + List content = doc.getContent(); + if ((content != null) && (!content.isEmpty())) { + app.setDescription(content.get(0).toString()); + } + } + } + return app; + } + + @GET + @Produces(MediaType.TEXT_HTML) + public Viewable getHTML() { + return new Viewable("/jsp/servicetemplates/selfservicemetadata/selfservicemetadata.jsp", this); + } + + @Override + public void persist() throws IOException { + BackendUtils.persist(this.application, this.data_xml_ref, MediaType.TEXT_XML_TYPE); + } + + @PUT + @Consumes(MediaType.TEXT_XML) + public Response onPutXML(Application data) { + String content = Utils.getXMLAsString(data); + return BackendUtils.putContentToFile(this.data_xml_ref, content, MediaType.TEXT_XML_TYPE); + } + + @Path("icon.jpg") + @GET + public Response getIcon(@HeaderParam("If-Modified-Since") String modified) { + RepositoryFileReference ref = new RepositoryFileReference(this.id, "icon.jpg"); + return BackendUtils.returnRepoPath(ref, modified); + } + + @Path("icon.jpg") + @PUT + @Consumes(MediaType.MULTIPART_FORM_DATA) + public Response putIcon(@FormDataParam("file") InputStream uploadedInputStream, @FormDataParam("file") FormDataBodyPart body) { + RepositoryFileReference ref = new RepositoryFileReference(this.id, "icon.jpg"); + return BackendUtils.putContentToFile(ref, uploadedInputStream, body.getMediaType()); + } + + @Path("image.jpg") + @GET + public Response getImage(@HeaderParam("If-Modified-Since") String modified) { + RepositoryFileReference ref = new RepositoryFileReference(this.id, "image.jpg"); + return BackendUtils.returnRepoPath(ref, modified); + } + + @Path("image.jpg") + @PUT + @Consumes(MediaType.MULTIPART_FORM_DATA) + public Response putImage(@FormDataParam("file") InputStream uploadedInputStream, @FormDataParam("file") FormDataBodyPart body) { + RepositoryFileReference ref = new RepositoryFileReference(this.id, "image.jpg"); + return BackendUtils.putContentToFile(ref, uploadedInputStream, body.getMediaType()); + } + + @Path("displayname") + @PUT + public Response onPutOnDisplayName(@FormParam("value") String value) { + this.application.setDisplayName(value); + return BackendUtils.persist(this); + } + + @Path("description") + @PUT + public Response onPutOnDescription(@FormParam("value") String value) { + this.application.setDescription(value); + return BackendUtils.persist(this); + } + + @Path("options/") + public OptionsResource getOptionsResource() { + Options options = this.application.getOptions(); + if (options == null) { + options = new Options(); + this.application.setOptions(options); + } + return new OptionsResource(options.getOption(), this); + } + + /** + * @return the internal application object. Used for the export. + */ + public Application getApplication() { + return this.application; + } + + /** + * Used in JSP only + */ + public String getApplicationAsXMLStringEncoded() { + String res; + if (Repository.INSTANCE.exists(this.data_xml_ref)) { + StringWriter sw = new StringWriter(); + try (InputStream is = Repository.INSTANCE.newInputStream(this.data_xml_ref);) { + IOUtils.copy(is, sw); + } catch (IOException e) { + SelfServicePortalResource.logger.error("Could not read from file", e); + } + res = sw.toString(); + } else { + // return skeleton for application + // application object is already filled with default values if no file exists in repo + res = Utils.getXMLAsString(this.getApplication()); + } + return Functions.escapeXml(res); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/NodeTemplateResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/NodeTemplateResource.java new file mode 100644 index 0000000..2a59aa5 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/NodeTemplateResource.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * Copyright (c) 2012-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.topologytemplates; + +import java.util.List; +import java.util.Map; + +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.HEAD; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; +import javax.xml.namespace.QName; + +import org.eclipse.winery.common.constants.Namespaces; +import org.eclipse.winery.common.ids.Namespace; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.resources.INodeTemplateResourceOrNodeTypeImplementationResource; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; +import org.eclipse.winery.repository.resources.artifacts.DeploymentArtifactsResource; +import org.eclipse.winery.repository.resources.entitytemplates.TEntityTemplateResource; +import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource; +import org.restdoc.annotations.RestDoc; + +public class NodeTemplateResource extends TEntityTemplateResource implements INodeTemplateResourceOrNodeTypeImplementationResource { + + public NodeTemplateResource(IIdDetermination idDetermination, TNodeTemplate o, int idx, List list, IPersistable res) { + super(idDetermination, o, idx, list, res); + } + + @Path("deploymentartifacts/") + public DeploymentArtifactsResource getDeploymentArtifacts() { + return new DeploymentArtifactsResource(this.o, this); + } + + @GET + @RestDoc(methodDescription = "* The following methods are currently *not* used by the topology modeler.
" + "The modeler is using the repository client to interact with the repository") + @Path("minInstances") + public String getMinInstances() { + return Integer.toString(this.o.getMinInstances()); + } + + @PUT + @Path("minInstances") + public Response setMinInstances(@FormParam(value = "minInstances") String minInstances) { + int min = Integer.parseInt(minInstances); + this.o.setMinInstances(min); + return BackendUtils.persist(this.res); + } + + @GET + @Path("maxInstances") + public String getMaxInstances() { + return this.o.getMaxInstances(); + } + + @PUT + @Path("maxInstances") + public Response setMaxInstances(@FormParam(value = "maxInstances") String maxInstances) { + // TODO: check for valid integer | "unbound" + this.o.setMaxInstances(maxInstances); + return BackendUtils.persist(this.res); + } + + + /* * * + * The visual appearance + * + * We do not use a subresource "visualappearance" here to avoid generation of more objects + * * */ + + private final QName qnameX = new QName(Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "x"); + private final QName qnameY = new QName(Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "y"); + + + @Path("x") + @GET + @RestDoc(methodDescription = "@return the x coordinate of the node template") + public String getX() { + Map otherAttributes = this.o.getOtherAttributes(); + return otherAttributes.get(this.qnameX); + } + + @Path("x") + @PUT + public Response setX(String x) { + this.o.getOtherAttributes().put(this.qnameX, x); + return BackendUtils.persist(this.res); + } + + @Path("y") + @GET + @RestDoc(methodDescription = "@return the y coordinate of the node template") + public String getY() { + Map otherAttributes = this.o.getOtherAttributes(); + return otherAttributes.get(this.qnameY); + } + + @Path("y") + @PUT + public Response setY(String y) { + this.o.getOtherAttributes().put(this.qnameY, y); + return BackendUtils.persist(this.res); + } + + @Override + public Namespace getNamespace() { + // TODO Auto-generated method stub + throw new IllegalStateException("Not yet implemented."); + } + + /** + * Required for persistence after a change of the deployment artifact. + * Required by DeploymentArtifactResource to be able to persist + * + * @return the service template this node template belongs to + */ + public ServiceTemplateResource getServiceTemplateResource() { + return (ServiceTemplateResource) this.res; + } + + /** + * required for topology modeler to check for existence of a node template + * at the server + * + * @return empty response + */ + @HEAD + public Response getHEAD() { + return Response.noContent().build(); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/NodeTemplatesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/NodeTemplatesResource.java new file mode 100644 index 0000000..64c5de8 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/NodeTemplatesResource.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2012-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.topologytemplates; + +import java.util.List; + +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources.entitytemplates.TEntityTemplatesResource; + +import com.sun.jersey.api.view.Viewable; + +public class NodeTemplatesResource extends TEntityTemplatesResource { + + public NodeTemplatesResource(List list, IPersistable res) { + super(NodeTemplateResource.class, TNodeTemplate.class, list, res); + } + + @Override + public String getId(TNodeTemplate entity) { + return entity.getId(); + } + + @Override + public Viewable getHTML() { + // TODO Auto-generated method stub + throw new IllegalStateException("Not yet implemented."); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/RelationshipTemplateResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/RelationshipTemplateResource.java new file mode 100644 index 0000000..a3eaed5 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/RelationshipTemplateResource.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.topologytemplates; + +import java.util.List; + +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources._support.collections.IIdDetermination; +import org.eclipse.winery.repository.resources.entitytemplates.TEntityTemplateResource; + +public class RelationshipTemplateResource extends TEntityTemplateResource { + + public RelationshipTemplateResource(IIdDetermination idDetermination, TRelationshipTemplate o, int idx, List list, IPersistable res) { + super(idDetermination, o, idx, list, res); + } +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/RelationshipTemplatesResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/RelationshipTemplatesResource.java new file mode 100644 index 0000000..8073e83 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/RelationshipTemplatesResource.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2012-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.topologytemplates; + +import java.util.List; + +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.repository.resources._support.IPersistable; +import org.eclipse.winery.repository.resources.entitytemplates.TEntityTemplatesResource; + +import com.sun.jersey.api.view.Viewable; + +public class RelationshipTemplatesResource extends TEntityTemplatesResource { + + public RelationshipTemplatesResource(List list, IPersistable res) { + super(RelationshipTemplateResource.class, TRelationshipTemplate.class, list, res); + } + + @Override + public String getId(TRelationshipTemplate entity) { + return entity.getId(); + } + + @Override + public Viewable getHTML() { + // TODO Auto-generated method stub + throw new IllegalStateException("Not yet implemented."); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/TopologyTemplateResource.java b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/TopologyTemplateResource.java new file mode 100644 index 0000000..b4b3646 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/servicetemplates/topologytemplates/TopologyTemplateResource.java @@ -0,0 +1,280 @@ +/******************************************************************************* + * Copyright (c) 2012-2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.servicetemplates.topologytemplates; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.eclipse.winery.common.Util; +import org.eclipse.winery.common.ids.definitions.ServiceTemplateId; +import org.eclipse.winery.model.tosca.TEntityTemplate; +import org.eclipse.winery.model.tosca.TNodeTemplate; +import org.eclipse.winery.model.tosca.TRelationshipTemplate; +import org.eclipse.winery.model.tosca.TTopologyTemplate; +import org.eclipse.winery.repository.Prefs; +import org.eclipse.winery.repository.Utils; +import org.eclipse.winery.repository.backend.BackendUtils; +import org.eclipse.winery.repository.client.IWineryRepositoryClient; +import org.eclipse.winery.repository.client.WineryRepositoryClientFactory; +import org.eclipse.winery.repository.json.TopologyTemplateModule; +import org.eclipse.winery.repository.resources.servicetemplates.ServiceTemplateResource; +import org.restdoc.annotations.RestDoc; +import org.restdoc.annotations.RestDocParam; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.WebResource.Builder; +import com.sun.jersey.api.view.Viewable; + +public class TopologyTemplateResource { + + private static final Logger logger = LoggerFactory.getLogger(TopologyTemplateResource.class); + + private final TTopologyTemplate topologyTemplate; + + private final ServiceTemplateResource serviceTemplateRes; + + + /** + * A topology template is always nested in a service template + */ + public TopologyTemplateResource(ServiceTemplateResource parent) { + this.topologyTemplate = parent.getServiceTemplate().getTopologyTemplate(); + this.serviceTemplateRes = parent; + } + + + public static class DataForJSP { + + private String location; + private TTopologyTemplate topologyTemplate; + private URI repositoryURI; + private String additonalCSS; + private Boolean autoLayoutOnLoad; + private String additionalScript; + + + public DataForJSP(String location, URI repositoryURI, TTopologyTemplate topologyTemplate, String additonalCSS, String additionalScript, Boolean autoLayoutOnLoad) { + this.location = location; + this.repositoryURI = repositoryURI; + this.topologyTemplate = topologyTemplate; + this.additonalCSS = additonalCSS; + this.additionalScript = additionalScript; + this.autoLayoutOnLoad = autoLayoutOnLoad; + } + + public String getLocation() { + return this.location; + } + + public TTopologyTemplate getTopologyTemplate() { + return this.topologyTemplate; + } + + public String getAdditonalCSS() { + return this.additonalCSS; + } + + public String getAdditionalScript() { + return this.additionalScript; + } + + public Boolean getAutoLayoutOnLoad() { + return this.autoLayoutOnLoad; + } + + public IWineryRepositoryClient getClient() { + // Quick hack + // IWineryRepository is not implemented by Prefs.INSTANCE.getRepository() + // Therefore, we have to generate a real WineryRepositoryClient even if that causes more http load + IWineryRepositoryClient client = WineryRepositoryClientFactory.getWineryRepositoryClient(); + client.addRepository(this.repositoryURI.toString()); + return client; + } + + } + + + @GET + @RestDoc(methodDescription = "?edit is used in the URL to get the jsPlumb-based editor") + @Produces(MediaType.TEXT_HTML) + // @formatter:off + public Response getHTML( + @QueryParam(value = "edit") String edit, + @QueryParam(value = "script") @RestDocParam(description = "the script to include in a \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/addComponentInstance.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/addComponentInstance.tag new file mode 100644 index 0000000..a82901a --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/addComponentInstance.tag @@ -0,0 +1,147 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag description="used by genericcomponentpage.jsp and by implementations.jsp to create a component instance" pageEncoding="UTF-8"%> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> +<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions"%> +<%-- +function createResource(nameOfResource, fields, url, onSuccess) cannot be used as this method is more diverse +--%> + +<%@attribute name="label" required="true" description="The lable to display"%> + +<%@attribute name="URL" description=""%> +<%@attribute name="onSuccess" description=""%> +<%@attribute name="type" description="added to dataToSend when doing a POST"%> +<%@attribute name="typeSelectorData" type="java.util.Collection" description="All available types when creating a template. We do not support types with names (additional to the id) as the current TOSCA specification does not foresee the usage of both name and id at types"%> +<%@attribute name="openinnewwindow" description="if true, the editor for the created component instance is openend in a new window"%> + + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/colorwheel.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/colorwheel.tag new file mode 100644 index 0000000..1b7fede --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/colorwheel.tag @@ -0,0 +1,36 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag description="displays a color wheel" pageEncoding="UTF-8"%> + +<%@attribute name="id" required="true" description="id of the div to initialize"%> +<%@attribute name="url" required="true" description="URL to put to"%> +<%@attribute name="color" required="true" description="the initial color"%> +<%@attribute name="label" required="true" description="the label"%> + +
+ +
+
+
+ +

Enter the hex value above

+ +
+
+
+ + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/componentinstance.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/componentinstance.tag new file mode 100644 index 0000000..c5c2b4f --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/componentinstance.tag @@ -0,0 +1,163 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013, 2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag description="Wrapper for resources, which are backed by definitions and thus offer an XML div" pageEncoding="UTF-8"%> + +<%-- + quick hack to avoid specifying windowtitle at elements having it.name, too. + TODO: check why in this class a check on it.name is done, although there is componentinstancewithname.tag +--%> +<%@attribute name="windowtitle" description="If it.name is not available, this parameter should be given"%> + +<%@attribute name="selected" required="true"%> + +<%@attribute name="cssClass" required="true"%> + +<%@attribute name="image" required="false"%> + +<%@attribute name="libs" fragment="true" %> + +<%@attribute name="subMenus" required="false" type="java.util.List" description="list of SubMenuData objects stating the content of the submenus. The first submenu is used as default page. Subpage #xml must not be included, it is added automatically."%> + +<%@attribute name="implementationFor" description="In case the component instance is an implementation for another type, the link (a href) to the type is put here"%> + +<%@attribute name="type" description="In case the component instance is a template, the link (a href) to the type is put here"%> + +<%@attribute name="twolines" required="false" description="if set, two lines are required for the tabs"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions" %> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + + + + + + + +
twolines"> + + + + + <%-- Quick hack to enable usage of this tag at adminresource --%> + + + <%@ include file="/jsp/componentnaming.jspf" %> +
+
+ + XML + CSAR + + + +
+ +
+ Implementation for ${implementationFor} +
+
+ +
+ Type ${type} +
+
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/componentinstancewithName.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/componentinstancewithName.tag new file mode 100644 index 0000000..f970b99 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/componentinstancewithName.tag @@ -0,0 +1,33 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag import="org.eclipse.winery.repository.resources.SubMenuData"%> +<%@tag description="Wrapper for component instances with a name. Name is also used for window title." pageEncoding="UTF-8"%> + +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + +<%@tag import="java.util.ArrayList"%> + + +<%@attribute name="selected" required="true"%> +<%@attribute name="cssClass" required="true"%> +<%@attribute name="image" required="false"%> +<%@attribute name="libs" fragment="true" %> +<%@attribute name="implementationFor" %> +<%@attribute name="twolines" required="false" description="if set, two lines are required for the tabs"%> +<%@attribute name="type" description="In case the component instance is a template, the link (a href) to the type is put here"%> + +<%@attribute name="subMenus" required="false" type="java.util.List" %> + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/componentinstancewithNameDerivedFromAbstractFinal.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/componentinstancewithNameDerivedFromAbstractFinal.tag new file mode 100644 index 0000000..a8ea212 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/componentinstancewithNameDerivedFromAbstractFinal.tag @@ -0,0 +1,45 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag import="org.eclipse.winery.repository.resources.SubMenuData"%> +<%@tag description="Wrapper for component instances with name, derived from, abstract, final (equivalent to AbstractComponentInstanceWithName..." pageEncoding="UTF-8"%> + +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + +<%@tag import="java.util.ArrayList"%> + + +<%@attribute name="selected" required="true"%> +<%@attribute name="cssClass" required="true"%> +<%@attribute name="image" required="false"%> +<%@attribute name="libs" fragment="true" %> +<%@attribute name="implementationFor" %> +<%@attribute name="twolines" required="false" description="if set, two lines are required for the tabs"%> + +<%@attribute name="subMenus" required="false" type="java.util.List" description="list of SubMenuData objects stating the content of the submenus. The first submenu is used as default page. Subpage #xml must not be included, it is added automatically."%> + + +<% + +if (subMenus == null) { + subMenus = new ArrayList(1); +} + +SubMenuData data; + +data = new SubMenuData("#inheritance", "Inheritance"); +subMenus.add(data); +%> + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/constraints/constraint.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/constraints/constraint.tag new file mode 100644 index 0000000..30607b6 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/constraints/constraint.tag @@ -0,0 +1,83 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag description="Models editing a single constraint" pageEncoding="UTF-8"%> + +<%@taglib prefix="o" tagdir="/WEB-INF/tags/common/orioneditor"%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags"%> + + + + +<%-- +Quick hack to get the representation of an empty constraint +TODO: A resource should provide the empty representation (?!) + +The alternative is not to use the complete XML as the specification only allows the content of the XML wrapper to be modified. +If we use that method, this textarea is not required, but the sending of an existing constraint has to be modified to send only lines 2 to n-1, i.e., send without the wrapping lines. +This is not possible if the stored constraint is empty, then there are 2 lines only. +--%> + + + \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/entitytemplate.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/entitytemplate.tag new file mode 100644 index 0000000..781e2d8 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/entitytemplate.tag @@ -0,0 +1,43 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag description="Wrapper for instances of entity types" pageEncoding="UTF-8"%> + +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + +<%@tag import="java.util.ArrayList"%> +<%@tag import="org.eclipse.winery.repository.resources.SubMenuData"%> + + +<%@attribute name="selected" required="true"%> +<%@attribute name="cssClass" required="true"%> +<%@attribute name="image" required="false"%> +<%@attribute name="libs" fragment="true" %> + +<%@attribute name="subMenus" required="false" type="java.util.List" description="list of SubMenuData objects stating the content of the submenus. The first submenu is used as default page. Subpage #xml must not be included, it is added automatically."%> + + +<% + +if (subMenus == null) { + subMenus = new ArrayList(2); +} + +SubMenuData data; + +data = new SubMenuData("#properties", "Properties"); +subMenus.add(data); +%> + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/entitytype.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/entitytype.tag new file mode 100644 index 0000000..6bd1d3d --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/entitytype.tag @@ -0,0 +1,49 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag description="Wrapper for instances of entity types" pageEncoding="UTF-8"%> + +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + +<%@tag import="java.util.ArrayList"%> +<%@tag import="org.eclipse.winery.repository.resources.SubMenuData"%> + + +<%@attribute name="selected" required="true"%> +<%@attribute name="cssClass" required="true"%> +<%@attribute name="image" required="false"%> +<%@attribute name="twolines" required="false" description="if set, two lines are required for the tabs"%> +<%@attribute name="libs" fragment="true" %> + +<%@attribute name="subMenus" required="false" type="java.util.List" description="list of SubMenuData objects stating the content of the submenus. The first submenu is used as default page. Subpage #xml must not be included, it is added automatically."%> + + +<% + +if (subMenus == null) { + subMenus = new ArrayList(2); +} + +SubMenuData data; + +data = new SubMenuData("#propertiesdefinition", "Properties Definition"); +subMenus.add(data); + +// Tags are currently not implemented -> Don't confuse users by showing the tab +// has to be enabled again, when tags are implemented +//data = new SubMenuData("#tags", "Tags"); +//subMenus.add(data); +%> + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/entitytypes/nodetypes/reqandcapdefs/reqandcapdefs.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/entitytypes/nodetypes/reqandcapdefs/reqandcapdefs.tag new file mode 100644 index 0000000..3748bd6 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/entitytypes/nodetypes/reqandcapdefs/reqandcapdefs.tag @@ -0,0 +1,334 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + * Yves Schubert - switch to bootstrap 3, integration with spinnerwithinphty + *******************************************************************************/ +--%> +<%@tag description="Models Requirement and Capability Definitions" pageEncoding="UTF-8"%> + +<%@attribute name="labelForSingleItem" required="true" %> +<%@attribute name="url" required="true"%> +<%@attribute name="allSubResources" required="true" type="java.util.List" description="All available req-/cap-defs" %> +<%@attribute name="allTypes" required="true" type="java.util.Collection" description="All available types of req-/cap-def" %> +<%@attribute name="typeClass" required="true" type="java.lang.Class" description="The class of the type" %> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="ct" tagdir="/WEB-INF/tags/common" %> +<%@taglib prefix="con" tagdir="/WEB-INF/tags/constraints" %> +<%@taglib prefix="o" tagdir="/WEB-INF/tags/common/orioneditor"%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> +<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions"%> +<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions"%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
nametypelower boundupper boundconstraints
${r.def.name}${wc:qname2href(pageContext.request.contextPath, typeClass, r.type)}${w:renderMinInstances(r.def.lowerBound)}${w:renderMaxInstances(r.def.upperBound)}
+ +<%-- Editing a set of constraints --%> + + + + + + +<%-- Editing a single constraint --%> + + + + + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/genericpage.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/genericpage.tag new file mode 100644 index 0000000..7063697 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/genericpage.tag @@ -0,0 +1,349 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + * Yves Schubert - switch to bootstrap 3 + *******************************************************************************/ +--%> +<%@tag description="Global Wrapper" pageEncoding="UTF-8"%> + +<%@attribute name="windowtitle" required="true" description="String to be used as window title"%> +<%@attribute name="selected" required="true"%> +<%@attribute name="cssClass" required="true"%> + +<%@attribute name="libs" fragment="true" %> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="ct" tagdir="/WEB-INF/tags/common"%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags"%> +<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions"%> + +<%@tag import="org.eclipse.winery.repository.Prefs" %> + + + + + + ${windowtitle} + + + + + + + <%-- CSS to style the file input field as button and adjust the Bootstrap progress bars --%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + +
+ +
+ +
+
+ + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/imageUpload.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/imageUpload.tag new file mode 100644 index 0000000..6ef5d18 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/imageUpload.tag @@ -0,0 +1,42 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag description="form div to upload an icon" pageEncoding="UTF-8"%> + +<%@attribute name="label" required="true" description="LAbel to be used. Also used as title of the dialog"%> +<%@attribute name="URL" required="true" description="URL to post to"%> +<%@attribute name="id" required="true" description="id to form basis for ...Diag: id of diag; ...Form: id of input field used for file upload; ...Img: Image to refresh"%> +<%@attribute name="accept" description="if not null/'': list of accepted MIME file types"%> +<%@attribute name="width" required="true" description="Width of the image to display"%> +<%@attribute name="resize" description="if not null/'': enables image resizing. Currently not supported"%> + +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + + + +
+ +
+
+ n/a +
+ or drop the image in this area. +
+
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/namespaceChooser.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/namespaceChooser.tag new file mode 100644 index 0000000..56b0712 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/namespaceChooser.tag @@ -0,0 +1,52 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag description="places a bootstrap form control to chooose a namespace. A new namespace can be created" pageEncoding="UTF-8"%> + + + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + +<%@attribute name="allNamespaces" required="true" type="java.util.Collection" description="All known namespaces"%> +<%@attribute name="idOfInput" required="true" description="The id if the input field storing the namespace. Also used as name"%> +<%@attribute name="nameOfInput" required="false" description="The name if the input field storing the namespace. If not provided, ifOfInput is used"%> +<%@attribute name="selected" description="The currently selected namespace (optional)"%> + + + + +
+ + +
+ + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/parameters/parametersHTML.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/parameters/parametersHTML.tag new file mode 100644 index 0000000..7474851 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/parameters/parametersHTML.tag @@ -0,0 +1,38 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag description="Input or Output parameters" pageEncoding="UTF-8"%> + +<%@attribute name="label" required="true" %> +<%@attribute name="inOrOut" required="true" %> +<%@attribute name="tableId" required="true" %> +<%@attribute name="baseURL" required="true" description="JavaScript expression for determining the baseURL"%> + +
+
+ + + +
+ + + + + + + + + + +
NameTypeRequired
+
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/parameters/parametersInput.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/parameters/parametersInput.tag new file mode 100644 index 0000000..73b8c1b --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/parameters/parametersInput.tag @@ -0,0 +1,20 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag pageEncoding="UTF-8"%> + +<%@attribute name="baseURL" required="true" description="JavaScript expression for determining the baseURL"%> + +<%@ taglib prefix="p" tagdir="/WEB-INF/tags/parameters" %> + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/parameters/parametersJS.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/parameters/parametersJS.tag new file mode 100644 index 0000000..021c8c0 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/parameters/parametersJS.tag @@ -0,0 +1,177 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag description="Input and Output parameters handling. Used at interface/operation and plan" pageEncoding="UTF-8"%> + +<%@attribute name="afterLoad" description="JavaScript code to be executed after successfully loading/initialization"%> + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/parameters/parametersOutput.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/parameters/parametersOutput.tag new file mode 100644 index 0000000..32a5565 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/parameters/parametersOutput.tag @@ -0,0 +1,20 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag pageEncoding="UTF-8"%> + +<%@attribute name="baseURL" required="true" description="JavaScript expression for determining the baseURL"%> + +<%@ taglib prefix="p" tagdir="/WEB-INF/tags/parameters" %> + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/relationshiptype/validnodetypeendingsselect.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/relationshiptype/validnodetypeendingsselect.tag new file mode 100644 index 0000000..1e0702d --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/relationshiptype/validnodetypeendingsselect.tag @@ -0,0 +1,43 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag description="Offers choice for valid endings" pageEncoding="UTF-8"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> + +<%@attribute name="shortName" required="true" description="source|target"%> +<%@attribute name="currentSelection" required="false"%> +<%@attribute name="possibleValidEndings" type="java.util.Collection" %> + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/servicetemplates/boundarydefinitions/browseForReqOrCap.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/servicetemplates/boundarydefinitions/browseForReqOrCap.tag new file mode 100644 index 0000000..5195f9b --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/servicetemplates/boundarydefinitions/browseForReqOrCap.tag @@ -0,0 +1,161 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> + +<%@tag pageEncoding="UTF-8"%> + +<%@attribute name="label" description="Requirement|Capability" required="true" %> +<%@attribute name="requirementsOrCapabilities" description="requirements|capabilities" required="true" %> +<%@attribute name="reqOrCap" description="requirement|capability" required="true" %> + +<%@taglib prefix="b" tagdir="/WEB-INF/tags/servicetemplates/boundarydefinitions"%> + + + + + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/servicetemplates/boundarydefinitions/browseForServiceTemplatePropertyReqOrCap.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/servicetemplates/boundarydefinitions/browseForServiceTemplatePropertyReqOrCap.tag new file mode 100644 index 0000000..430d4db --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/servicetemplates/boundarydefinitions/browseForServiceTemplatePropertyReqOrCap.tag @@ -0,0 +1,166 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2013-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> + +<%@tag pageEncoding="UTF-8"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="bd" tagdir="/WEB-INF/tags/servicetemplates/boundarydefinitions" %> + +<%@attribute name="definedPropertiesAsJSONString" required="true" %> + + + +<%-- Browse for property --%> +<%-- +The following cannot be used as we return TWO things: the template and the property + +--%> + + + + + + \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/servicetemplates/boundarydefinitions/browseForX.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/servicetemplates/boundarydefinitions/browseForX.tag new file mode 100644 index 0000000..4b38b62 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/servicetemplates/boundarydefinitions/browseForX.tag @@ -0,0 +1,49 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> + +<%@tag pageEncoding="UTF-8"%> + +<%@attribute name="XShort" description="The X to browse for. Short form. E.g., Req, Cap, ..." required="true" %> +<%@attribute name="XLong" description="The X to browse for. Long form. E.g., Requirement, Capability, ..." required="true" %> + + +<%-- Browse for property --%> + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/simpleSingleFileUpload.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/simpleSingleFileUpload.tag new file mode 100644 index 0000000..9774ba3 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/simpleSingleFileUpload.tag @@ -0,0 +1,114 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + * Yves Schubert - switch to bootstrap 3 + *******************************************************************************/ +--%> +<%@tag description="Global Wrapper" pageEncoding="UTF-8"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> + +<%@attribute name="title" required="true" description="title of the dialog"%> +<%@attribute name="text" required="true" description="text to show before upload box"%> +<%@attribute name="URL" required="true" description="URL to post to"%> +<%@attribute name="type" required="true" description="PUT|POST"%> +<%@attribute name="additionalDropZone" required="false" description="jQuery selector for an additional dropzone"%> +<%@attribute name="id" required="true" description="id to form basis for ...Diag: id of diag; ...Form: id of input field used for file upload; ...Img: Image to refresh"%> +<%@attribute name="accept" description="if not null/'': list of accepted MIME file types"%> +<%@attribute name="resize" description="if not null/'': enables image resizing. Currently not supported"%> + + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/submenu.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/submenu.tag new file mode 100644 index 0000000..0e6a320 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/submenu.tag @@ -0,0 +1,26 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> + +<%@tag description="submenu" pageEncoding="UTF-8"%> + +<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + +<%@attribute name="subMenuData" required="true" type="org.eclipse.winery.repository.resources.SubMenuData"%> +<%@attribute name="selected" required="true"%> + + selected"> +
+
${subMenuData.text}
+
+
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/topologyTemplateRenderer.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/topologyTemplateRenderer.tag new file mode 100644 index 0000000..5f0aaa4 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/topologyTemplateRenderer.tag @@ -0,0 +1,208 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Pascal Hirmer - skeletton for topology rendering + * Oliver Kopp - converted to .tag and integrated in the repository + *******************************************************************************/ +--%> +<%@tag description="Renders a toplogytemplate. This tag is used to render a topology template readonly. The topoology modeler does the rendering on itself." pageEncoding="UTF-8" %> + +<%@tag import="java.lang.Math"%> +<%@tag import="java.util.ArrayList"%> +<%@tag import="java.util.Collection"%> +<%@tag import="java.util.Map"%> +<%@tag import="java.util.HashMap"%> +<%@tag import="java.util.UUID"%> +<%@tag import="javax.xml.namespace.QName"%> +<%@tag import="org.eclipse.winery.common.ModelUtilities"%> +<%@tag import="org.eclipse.winery.model.tosca.TEntityTemplate"%> +<%@tag import="org.eclipse.winery.model.tosca.TNodeTemplate"%> +<%@tag import="org.eclipse.winery.model.tosca.TNodeType"%> +<%@tag import="org.eclipse.winery.model.tosca.TRelationshipTemplate"%> +<%@tag import="org.eclipse.winery.model.tosca.TRelationshipTemplate.SourceElement"%> +<%@tag import="org.eclipse.winery.model.tosca.TRelationshipTemplate.TargetElement"%> +<%@tag import="org.eclipse.winery.model.tosca.TRelationshipType"%> +<%@tag import="org.eclipse.winery.model.tosca.TTopologyTemplate"%> +<%@tag import="org.eclipse.winery.repository.Utils"%> + +<%@attribute name="topology" required="true" description="the topology template to be rendered" type="org.eclipse.winery.model.tosca.TTopologyTemplate" %> +<%@attribute name="repositoryURL" required="true" %> +<%@attribute name="client" required="true" type="org.eclipse.winery.common.interfaces.IWineryRepository" %> +<%@attribute name="fullscreen" required="false" type="java.lang.Boolean" %> +<%@attribute name="additonalCSS" required="false"%> +<%@attribute name="autoLayoutOnLoad" required="false" type="java.lang.Boolean" %> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="tmpl" tagdir="/WEB-INF/tags/common/templates" %> +<%@taglib prefix="nt" tagdir="/WEB-INF/tags/common/templates/nodetemplates" %> +<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions"%> + +<%-- required for vShowError --%> + + + +<%-- required for vShowError --%> + + + +<%-- winery-common.css also contains definitions for properties --%> + + + + + + +<% + Collection relationshipTypes = client.getAllTypes(TRelationshipType.class); + + // quick hack + // better would be to collect all types used in the curren topoloy template + Collection nodeTypes = client.getAllTypes(TNodeType.class); +%> + + + + + +<% + // used for the position of the NodeTemplates + int topCounter = 0; +%> + +
+
+ + +
+
+<%-- div #editorArea required for layouter --%> +
+
+ + + +<% + // can be used later to call a doLayout() + boolean somethingWithoutPosition = false; + + Collection relationshipTemplates = new ArrayList(); + Collection nodeTemplates = new ArrayList(); + + // the minimum x/y coordinates. + // used to move the content to the top left corner + int minTop = Integer.MAX_VALUE; + int minLeft = Integer.MAX_VALUE; + + for (TEntityTemplate entity: topology.getNodeTemplateOrRelationshipTemplate()) { + if (entity instanceof TNodeTemplate) { + TNodeTemplate nodeTemplate = (TNodeTemplate) entity; + nodeTemplates.add(nodeTemplate); + + // determine minTop and minLeft + String top = ModelUtilities.getTop(nodeTemplate); + if (top != null) { + int intTop = Utils.convertStringToInt(top); + if (intTop != 0) { + minTop = Math.min(minTop, intTop); + } + } + + String left = ModelUtilities.getLeft(nodeTemplate); + if (left != null) { + int intLeft = Utils.convertStringToInt(left); + if (intLeft != 0) { + minLeft = Math.min(minLeft, intLeft); + } + } + + } else { + assert(entity instanceof TRelationshipTemplate); + relationshipTemplates.add((TRelationshipTemplate) entity); + } + } + + for (TNodeTemplate nodeTemplate: nodeTemplates) { + // assuming the topology can be displayed as a stack, else call doLayout() afterwards + topCounter = topCounter + 150; + + String left = ModelUtilities.getLeft(nodeTemplate); + if (left == null) { + left = "0"; + somethingWithoutPosition = true; + } else { + // calulate offset + // we could hash the coordinate in the loop before + // but that would obfuscate the code and currently, we don't have speed issues here + left = Integer.toString(Utils.convertStringToInt(left) - minLeft); + } + String top = ModelUtilities.getTop(nodeTemplate); + if (top == null) { + top = Integer.toString(topCounter); + somethingWithoutPosition = true; + } else { + // calulate offset + top = Integer.toString(Utils.convertStringToInt(top) - minTop); + } +%> + +<% + } + if (somethingWithoutPosition) { + autoLayoutOnLoad = true; + } +%> + + + +
+
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/typeswithshortnameasselect.tag b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/typeswithshortnameasselect.tag new file mode 100644 index 0000000..f658b2b --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/tags/typeswithshortnameasselect.tag @@ -0,0 +1,46 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@tag description="Renders pairs of types with shortname as select element" pageEncoding="UTF-8"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + +<%@attribute name="label" required="true"%> +<%@attribute name="selectname" required="true" description="Used as Name and as Id"%> +<%@attribute name="typesWithShortNames" required="true" type="java.util.Collection"%> +<%@attribute name="type" required="true" description="The type of all types. E.g., planlanguage"%> + +
+ + +
+ + + Manage +
+
+ + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/web.xml b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..b5eb167 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,95 @@ + + + + Winery Repository + + WineryResources + com.sun.jersey.spi.container.servlet.ServletContainer + + com.sun.jersey.spi.container.ContainerResponseFilters + + org.eclipse.winery.repository.RestDocFilter;org.eclipse.winery.repository.CORSFilter + + + com.sun.jersey.config.property.packages + org.eclipse.winery.repository.resources + + + com.sun.jersey.config.feature.FilterForwardOn404 + false + + + com.sun.jersey.config.feature.CanonicalizeURIPath + true + + + com.sun.jersey.config.feature.NormalizeURI + true + + + com.sun.jersey.config.feature.Redirect + true + + + + + com.sun.jersey.api.json.POJOMappingFeature + true + + + + + WineryResources + + + + + + /imports/* + /servicetemplates/* + /nodetypes/* + /nodetypeimplementations/* + /relationshiptypes/* + /relationshiptypeimplementations/* + /requirementtypes/* + /capabilitytypes/* + /artifacttypes/* + /artifacttemplates/* + /policytypes/* + /policytemplates/* + + + / + /admin/* + /API/* + /other/* + /test/* + + + + org.eclipse.winery.repository.Prefs + + + + COOKIE + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/css/topologyTemplateRenderer.css b/winery/org.eclipse.winery.repository/src/main/webapp/css/topologyTemplateRenderer.css new file mode 100644 index 0000000..f24db2c --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/css/topologyTemplateRenderer.css @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Uwe Breitenbücher - initial implementation + * Pascal Hirmer - improvements + * Oliver Kopp - improvements + *******************************************************************************/ + +#templateDrawingArea { + height: 500px; + position: relative; + overflow-y: scroll; +} + +#templateEditorArea { + width: 100%; + height: 100%; + margin-top: 45px; +} + +div.NodeTemplateShape { + cursor: default; +} + +div.topbar { + position: absolute; + height: 30px; + width: 100%; + z-index: 1000; +} + +div.topbarbuttons { + display: none; +} + +div.topbar:hover > div.topbarbuttons { + display: inherit; +} + +/* hide the area to add a deployment artifact */ +div.addDA { + display: none; +} \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/css/topologyTemplateRendererFullscreen.css b/winery/org.eclipse.winery.repository/src/main/webapp/css/topologyTemplateRendererFullscreen.css new file mode 100644 index 0000000..b5535ba --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/css/topologyTemplateRendererFullscreen.css @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial implementation + *******************************************************************************/ + +#templateDrawingArea { + height: 100%; + background: white; +} + +#templateEditorArea { + margin-top: 0px; +} + +/* + * used if elements should be hidden forever. Cannot be undone with $(...).show() + * + * not globally defined + */ +.hidden { + display: none; +} + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/CapSelection.css b/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/CapSelection.css new file mode 100644 index 0000000..1032dd2 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/CapSelection.css @@ -0,0 +1,15 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial implementation + *******************************************************************************/ + +div.NodeTemplateShape > div.capabilitiesContainer { + display: inherit; +} diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/NodeTemplateSelection.css b/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/NodeTemplateSelection.css new file mode 100644 index 0000000..53b69ef --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/NodeTemplateSelection.css @@ -0,0 +1,13 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial implementation + *******************************************************************************/ + +/* nothing special needed */ \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/RelationshipTemplateSelection.css b/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/RelationshipTemplateSelection.css new file mode 100644 index 0000000..53b69ef --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/RelationshipTemplateSelection.css @@ -0,0 +1,13 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial implementation + *******************************************************************************/ + +/* nothing special needed */ \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/ReqSelection.css b/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/ReqSelection.css new file mode 100644 index 0000000..f4bcfae --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/ReqSelection.css @@ -0,0 +1,15 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial implementation + *******************************************************************************/ + +div.NodeTemplateShape > div.requirementsContainer { + display: inherit; +} diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/propertySelection.css b/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/propertySelection.css new file mode 100644 index 0000000..f3673eb --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/propertySelection.css @@ -0,0 +1,15 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial implementation + *******************************************************************************/ + +div.NodeTemplateShape > div.propertiesContainer { + display: inherit; +} diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/small.css b/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/small.css new file mode 100644 index 0000000..d7f298c --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/css/topologytemplaterendering/small.css @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Uwe Breitenbücher - initial implementation + *******************************************************************************/ +div.relationshipTypeLabel { + display:none; +} + +div.nodetemplate.name { + display: none; +} +div.NodeTemplateShape > .headerContainer > div.type { + top: 15px; + left: 34px; + width: 111px; + text-align: center; + font-size: 11px; +} + +div.NodeTemplateShape > .headerContainer > img.icon { + height: 35px; + margin: 4px 4px; +} + +div.NodeTemplateShape { + border-width: 1px; + height: 45px; + width: 150px; + border-radius: 8px; +} diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/css/winery-repository.css b/winery/org.eclipse.winery.repository/src/main/webapp/css/winery-repository.css new file mode 100644 index 0000000..11441b4 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/css/winery-repository.css @@ -0,0 +1,868 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Uwe Breitenbücher - initial implementation + * Oliver Kopp - improvements + *******************************************************************************/ + +/* override jquery redmond theme */ + +.hidden { + display: none; +} + +.ui-widget { + font-size: 11px; +} + +body { + width: 1000px; + background: #eaeaea; +} + +#header { + width: 100%; + height: 87px; + background: url('../images/header_background.png'); + background-repeat: no-repeat; +} + +#showabout { + float: right +} + +#header > div#buttonContainer { + + height: 30px; + top: 40px; + position: relative; +} + +#header > div#buttonContainer > a { + height: 30px; + float: left; + display: block; + margin-left: 30px; + padding-left: 10px; + padding-right: 10px; + border-radius: 10px 10px 0px 0px; + line-height: 27px; + text-decoration: none; + font-family: arial; + color: #787878; + font-size: 14px; + text-shadow: 1px 1px 0px white; +} + +#header > span { + position: relative; + top: 42px; + left: 10px; +} + +#headerelements { + position: relative; + bottom: 0px; +} + +#tabs { + box-shadow: 3px 3px 9px #888888; + min-height: 350px; +} + +#mainContainer { + border-left: 1px solid #AEAEAE; + position: absolute; + left: 50%; + margin: 10px 0 0 -500px; + padding-bottom: 15px; + border-radius: 0px 0px 18px 18px; + border-bottom: 1px solid #AEAEAE; + border-right: 1px solid #AEAEAE; + box-shadow: 3px 3px 9px #888888; + background: white; + width: 1000px; +} + +/* bootstrap removes scrollbar making the content moving. Undo that effect: + 15 / 2 = 7.5. We choose 8. 500+8=508 */ +body.modal-open > #mainContainer.overflown { + margin: 10px 0 0 -508px; +} + +/* resulting in the same alignment if a scrollbar is shown or not (two browser tabs with different tabs) */ +#mainContainer.notoverflown { + margin: 10px 0 0 -508px; +} + + +#mainContent { + padding-left: 5px; + min-height: 350px; +} + +#naming { + margin-bottom: 15px; +} + +#namespacesListContainer { + width: 300px; + float: left; +} + +.listheading { + margin: 0px 0px 15px 0px; +} + +.listcontent { + width: 100%; +} + +#buttonList { + width: 140px; +} + +#buttonList > a { + width: 85px; + float: left; + margin-top: 10px; +} + +.rightbutton { + float: right; + margin: 0 0 2px 2px; +} + +.label { + font-family: sans-serif; +} + +a.squareButton { + border: 1px solid #aeaeae; + background: #eaeaea; + height: 20px; + width: 20px; + text-align: center; + text-decoration: none; + line-height: 20px; + margin-left: 4px; + float: left; +} + +a.button { + border: 1px solid #aeaeae; + background: #eaeaea; + height: 20px; + padding-left: 4px; + padding-right: 4px; + text-align: center; + text-decoration: none; + line-height: 20px; + margin-left: 4px; + float: left; +} + +table tr.even.row_selected td { + background-color: #B0BED9; +} + +table tr.odd.row_selected td { + background-color: #9FAFD1; +} + +table tr.even.row_selected td.sorting_1 { + background-color: #B0BED9; +} + +table tr.odd.row_selected td.sorting_1 { + background-color: #9FAFD1; +} + + +div#mainMenuContainer { + height: 28px; + position: relative; + top: 38px; +} + +/* jquery file upload styling */ +.fileupload-buttonbar .ui-progressbar-value { + background: url(../images/jquery-fileupload/progressbar.gif); +} +.fileupload-loading { + background: url(../images/jquery-fileupload/loading.gif) center no-repeat; +} + + +/* tabs */ + +a.styledTabMenuButton { + margin-bottom: 3px; + float: left; +} + +a.styledTabMenuButton > div { + height: 28px; + float: left; +} + +a.styledTabMenuButton > div.left { + width: 19px; +} + +a.styledTabMenuButton > div.center { + line-height: 29px; + text-decoration: none; + font-family: arial; + color: #787878; + font-size: 14px; + text-shadow: 1px 1px 0px white; + padding-left: 5px; +} + +a.styledTabMenuButton > div.right { + width: 29px; +} + +a.styledTabMenuButton.selected > div.left, a.styledTabMenuButton:hover > div.left { + background: url('../images/styledTabMenuButtonLeft.jpg'); + width: 19px; +} + +a.styledTabMenuButton.selected > div.center, a.styledTabMenuButton:hover > div.center { + background: url('../images/styledTabMenuButtonCenter.jpg'); +} + +a.styledTabMenuButton.selected > div.right, a.styledTabMenuButton:hover > div.right { + background: url('../images/styledTabMenuButtonRight.jpg'); + width: 29px; +} + +/* main containers */ + +div.mainContentContainer, div.mainContentContainer > div { + float: left; + width: 989px; +} +div.mainContentContainer > div.top { + height: 150px; +} + +div.mainContentContainer > div.top.twolines { + height: 179px; +} + +div.mainContentContainer > div.middle { + width: 987px; + min-height: 350px; + padding: 0px 35px 0px 35px; + font-family: arial, verdana; + font-size: 12px; + line-height: 19px; + color: #494949; +} +div.mainContentContainer > div.bottom { + height: 40px; +} + +div.mainContentContainer.serviceTemplate > div.top { + background: url('../images/containers/st/FrameTop.jpg'); +} +div.mainContentContainer.serviceTemplate > div.middle { + background: url('../images/containers/st/FrameMiddle.jpg'); +} +div.mainContentContainer.serviceTemplate > div.bottom { + background: url('../images/containers/st/FrameBottom.jpg'); +} + +div.mainContentContainer.relationshipType > div.top { + background: url('../images/containers/rt/FrameTopLarge.jpg'); +} +div.mainContentContainer.relationshipType > div.middle { + background: url('../images/containers/rt/FrameMiddle.jpg'); +} +div.mainContentContainer.relationshipType > div.bottom { + background: url('../images/containers/rt/FrameBottom.jpg'); +} + +div.mainContentContainer.nodeType > div.top { + background: url('../images/containers/nt/FrameTopLarge.jpg'); +} +div.mainContentContainer.nodeType > div.middle { + background: url('../images/containers/nt/FrameMiddle.jpg'); +} +div.mainContentContainer.nodeType > div.bottom { + background: url('../images/containers/nt/FrameBottom.jpg'); +} + +div.mainContentContainer.admin > div.top { + background: url('../images/containers/admin/FrameTop.jpg'); +} +div.mainContentContainer.admin > div.middle { + background: url('../images/containers/admin/FrameMiddle.jpg'); +} +div.mainContentContainer.admin > div.bottom { + background: url('../images/containers/admin/FrameBottom.jpg'); +} + + +/* quick hack for new types: just use the administration */ + +div.mainContentContainer.artifactTemplate > div.top { + background: url('../images/containers/admin/FrameTop.jpg'); +} +div.mainContentContainer.artifactTemplate > div.middle { + background: url('../images/containers/admin/FrameMiddle.jpg'); +} +div.mainContentContainer.artifactTemplate > div.bottom { + background: url('../images/containers/admin/FrameBottom.jpg'); +} + +div.mainContentContainer.artifactType > div.top { + background: url('../images/containers/admin/FrameTop.jpg'); +} +div.mainContentContainer.artifactType > div.middle { + background: url('../images/containers/admin/FrameMiddle.jpg'); +} +div.mainContentContainer.artifactType > div.bottom { + background: url('../images/containers/admin/FrameBottom.jpg'); +} + +div.mainContentContainer.nodeTypeImplementation > div.top { + background: url('../images/containers/admin/FrameTop.jpg'); +} +div.mainContentContainer.nodeTypeImplementation > div.middle { + background: url('../images/containers/admin/FrameMiddle.jpg'); +} +div.mainContentContainer.nodeTypeImplementation > div.bottom { + background: url('../images/containers/admin/FrameBottom.jpg'); +} + +div.mainContentContainer.relationshipTypeImplementation > div.top { + background: url('../images/containers/admin/FrameTop.jpg'); +} +div.mainContentContainer.relationshipTypeImplementation > div.middle { + background: url('../images/containers/admin/FrameMiddle.jpg'); +} +div.mainContentContainer.relationshipTypeImplementation > div.bottom { + background: url('../images/containers/admin/FrameBottom.jpg'); +} + +div.mainContentContainer.requirementType > div.top { + background: url('../images/containers/admin/FrameTop.jpg'); +} +div.mainContentContainer.requirementType > div.middle { + background: url('../images/containers/admin/FrameMiddle.jpg'); +} +div.mainContentContainer.requirementType > div.bottom { + background: url('../images/containers/admin/FrameBottom.jpg'); +} + +div.mainContentContainer.capabilityType > div.top { + background: url('../images/containers/admin/FrameTop.jpg'); +} +div.mainContentContainer.capabilityType > div.middle { + background: url('../images/containers/admin/FrameMiddle.jpg'); +} +div.mainContentContainer.capabilityType > div.bottom { + background: url('../images/containers/admin/FrameBottom.jpg'); +} + +div.mainContentContainer.policyTemplate > div.top { + background: url('../images/containers/admin/FrameTop.jpg'); +} +div.mainContentContainer.policyTemplate > div.middle { + background: url('../images/containers/admin/FrameMiddle.jpg'); +} +div.mainContentContainer.policyTemplate > div.bottom { + background: url('../images/containers/admin/FrameBottom.jpg'); +} + +div.mainContentContainer.policyType > div.top { + background: url('../images/containers/admin/FrameTop.jpg'); +} +div.mainContentContainer.policyType > div.middle { + background: url('../images/containers/admin/FrameMiddle.jpg'); +} +div.mainContentContainer.policyType > div.bottom { + background: url('../images/containers/admin/FrameBottom.jpg'); +} + +div.mainContentContainer.xsdimport > div.top { + background: url('../images/containers/admin/FrameTop.jpg'); +} +div.mainContentContainer.xsdimport > div.middle { + background: url('../images/containers/admin/FrameMiddle.jpg'); +} +div.mainContentContainer.xsdimport > div.bottom { + background: url('../images/containers/admin/FrameBottom.jpg'); +} + + + + +div.mainContentContainer > div.top > div.informationContainer { + position: relative; + top: 30px; + left: 120px; + height: 45px; + width: 100%; + + color: #787878; + font-family: arial; + font-size: 14px; + padding-left: 5px; + text-decoration: none; + text-shadow: 1px 1px 0 white; +} + + +div.mainContentContainer > div.top > div.informationContainer > div.name { + font-size: 17px; + font-weight: bold; + height: 22px; +} + +div.mainContentContainer > div.top > div.informationContainer > div.namespace { +} + + +div.mainContentContainer > div.top { + position: relative; +} + +div.mainContentContainer > div.top > div.subMenu { + position: absolute; + top: 97px; + left: 20px; +} + +/** lists of components (service templates, node types, relationship types) **/ + +div.entityContainer { + float: left; + margin-bottom: 10px; + cursor: pointer; +} + +div.entityContainer > div { + float: left; + height: 86px; +} + +div.entityContainer > div.left { + width: 117px; +} + +div.entityContainer > div.center { + width: 500px; +} + +div.entityContainer > div.right { + width: 33px; +} + +div.entityContainer > div.center > div.informationContainer { + margin-top: 25px; + height: 45px; + color: #787878; + font-family: arial; + font-size: 12px; + padding-left: 5px; + text-decoration: none; + text-shadow: 1px 1px 0 white; + float: left; + max-width: 313px; +} + + +div.entityContainer > div.center > div.informationContainer > div.name { + font-size: 14px; + font-weight: bold; + height: 18px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} + +div.entityContainer > div.center > div.informationContainer > div.namespace { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} + +div.entityContainer.serviceTemplate > div.left { + background: url('../images/entityBox/serviceTemplate/left.jpg'); +} + +div.entityContainer.serviceTemplate > div.center { + background: url('../images/entityBox/serviceTemplate/center.jpg'); +} + +div.entityContainer.serviceTemplate > div.right { + background: url('../images/entityBox/serviceTemplate/right.jpg'); +} + +div.entityContainer.nodeType > div.left { + background: url('../images/entityBox/nodeType/left.jpg'); +} + +div.entityContainer.nodeType > div.center { + background: url('../images/entityBox/nodeType/center.jpg'); +} + +div.entityContainer.nodeType > div.right { + background: url('../images/entityBox/nodeType/right.jpg'); +} + +div.entityContainer.relationshipType > div.left { + background: url('../images/entityBox/relationshipType/left.jpg'); +} + +div.entityContainer.relationshipType > div.center { + background: url('../images/entityBox/relationshipType/center.jpg'); +} + +div.entityContainer.relationshipType > div.right { + background: url('../images/entityBox/relationshipType/right.jpg'); +} + +div.entityContainer.admin > div.left { + background: url('../images/entityBox/admin/left.jpg'); +} + +div.entityContainer.admin > div.center { + background: url('../images/entityBox/admin/center.jpg'); +} + +div.entityContainer.admin > div.right { + background: url('../images/entityBox/admin/right.jpg'); +} + + +div.entityContainer.artifactTemplate > div.left { + background: url('../images/entityBox/admin/left.jpg'); +} + +div.entityContainer.artifactTemplate > div.center { + background: url('../images/entityBox/admin/center.jpg'); +} + +div.entityContainer.artifactTemplate > div.right { + background: url('../images/entityBox/admin/right.jpg'); +} + + +div.entityContainer.artifactType > div.left { + background: url('../images/entityBox/admin/left.jpg'); +} + +div.entityContainer.artifactType > div.center { + background: url('../images/entityBox/admin/center.jpg'); +} + +div.entityContainer.artifactType > div.right { + background: url('../images/entityBox/admin/right.jpg'); +} + + +div.entityContainer.nodeTypeImplementation > div.left { + background: url('../images/entityBox/admin/left.jpg'); +} + +div.entityContainer.nodeTypeImplementation > div.center { + background: url('../images/entityBox/admin/center.jpg'); +} + +div.entityContainer.nodeTypeImplementation > div.right { + background: url('../images/entityBox/admin/right.jpg'); +} + + +div.entityContainer.relationshipTypeImplementation > div.left { + background: url('../images/entityBox/admin/left.jpg'); +} + +div.entityContainer.relationshipTypeImplementation > div.center { + background: url('../images/entityBox/admin/center.jpg'); +} + +div.entityContainer.relationshipTypeImplementation > div.right { + background: url('../images/entityBox/admin/right.jpg'); +} + +div.entityContainer.requirementType > div.left { + background: url('../images/entityBox/admin/left.jpg'); +} + +div.entityContainer.requirementType > div.center { + background: url('../images/entityBox/admin/center.jpg'); +} + +div.entityContainer.requirementType > div.right { + background: url('../images/entityBox/admin/right.jpg'); +} + +div.entityContainer.capabilityType > div.left { + background: url('../images/entityBox/admin/left.jpg'); +} + +div.entityContainer.capabilityType > div.center { + background: url('../images/entityBox/admin/center.jpg'); +} + +div.entityContainer.capabilityType > div.right { + background: url('../images/entityBox/admin/right.jpg'); +} + +div.entityContainer.policyTemplate > div.left { + background: url('../images/entityBox/admin/left.jpg'); +} + +div.entityContainer.policyTemplate > div.center { + background: url('../images/entityBox/admin/center.jpg'); +} + +div.entityContainer.policyTemplate > div.right { + background: url('../images/entityBox/admin/right.jpg'); +} + +div.entityContainer.policyType > div.left { + background: url('../images/entityBox/admin/left.jpg'); +} + +div.entityContainer.policyType > div.center { + background: url('../images/entityBox/admin/center.jpg'); +} + +div.entityContainer.policyType > div.right { + background: url('../images/entityBox/admin/right.jpg'); +} + +div.entityContainer.xSDImport > div.left { + background: url('../images/entityBox/admin/left.jpg'); +} + +div.entityContainer.xSDImport > div.center { + background: url('../images/entityBox/admin/center.jpg'); +} + +div.entityContainer.xSDImport > div.right { + background: url('../images/entityBox/admin/right.jpg'); +} + + +/* buttons */ +div.entityContainer > div.center > div.buttonContainer { + float: right; + height: 42px; + + margin-top: 23px; + margin-left: 40px; +} + +div.entityContainer > div.center > div.buttonContainer > a { + float: left; + height: 42px; + margin-right: 5px; +} + +div.entityContainer > div.center > div.buttonContainer > a.editButton { + background: url('../images/entityBox/editButton.jpg'); + width: 41px; +} +div.entityContainer > div.center > div.buttonContainer > a.editButton:hover { + background: url('../images/entityBox/editButtonHover.jpg'); +} + +div.entityContainer > div.center > div.buttonContainer > a.exportButton { + background: url('../images/entityBox/exportButton.jpg'); + width: 53px; +} +div.entityContainer > div.center > div.buttonContainer > a.exportButton:hover { + background: url('../images/entityBox/exportButtonHover.jpg'); +} + +div.entityContainer > div.center > div.buttonContainer > a.deleteButton { + background: url('../images/entityBox/deleteButton.jpg'); + width: 33px; +} +div.entityContainer > div.center > div.buttonContainer > a.deleteButton:hover { + background: url('../images/entityBox/deleteButtonHover.jpg'); +} + +input.highlight { + background-color: lightskyblue; +} + +input.qnameinput { + width: 600px; +} + +/* fixes wrong z-index of autocompleter in jQuery UI 1.10.3 */ +.ui-autocomplete { + z-index: 1000; +} + +#warning { + color: blue; + font-weight: bold; + cursor: default; + float: right; + margin-right: 10px; + /* 0px is required to have the tabs below not being pushed down */ + height: 0px; +} + +#constraintlist { + cursor: pointer; +} + +#searchBox { + background: url("../images/searchBoxBackground.jpg") no-repeat scroll 2px -4px transparent; + border: 2px solid #BEBEBE; + border-radius: 15px 15px 15px 15px; + box-shadow: 5px 5px 5px #EAEAEA; + color: #676767; + font-size: 15px; + height: 35px; + margin-bottom: 30px; + padding: 5px 5px 5px 70px; + width: 660px; +} + +#gcprightcolumn { + background: url('../images/overviewShadowMiddle.jpg'); + width: 35px; + position: relative; + padding:0px; +} + +#overviewtopshadow { + top: 0px; + background-image: url("../images/overviewShadowTop.jpg"); + height: 269px; +} + +#overviewbottomshadow { + bottom: 0px; + background-image: url("../images/overviewShadowBottom.jpg"); + height: 269px; + position: absolute; + width: 35px; +} + +span.cursorpointer { + cursor: pointer; +} + +div.otherelements > a.btn { + width: 250px; +} + +#bigIconDiv { + height: 50px; +} + +div.colorpickerdiv { + height: 35px; + width: 35px; + background: url("../components/colorPicker/images/select.png") +} + +#applicationDescriptionDiv { + overflow-x: hidden; + overflow-y: scroll; + height: 200px; +} + +.XMLtextarea { + height: 300px; +} + +div.col-xs-4.bordered { + width: 32%; + border: 1px solid #DADADA; + padding: 0px; + +} + +div.col-xs-4.bordered div.listheading { + height: 36px; + padding-right: 3px; +} + +div.col-xs-4.middlebox { + margin-left: 18px; + margin-right: 18px; +} + +div.col-xs-4.bordered div.listheading > button { + margin-top: 3px; +} + +table.dataTable { + font-size: 12px; +} + +table.dataTable thead th { + font-size: 11px; + color: #3F3F3F; +} + +div.titledTableBox { + box-shadow: 2px 2px 5px #AEAEAE; + margin-bottom: 5px; + margin-right: 10px; + border: 1px solid #aeaeae; + padding: 0px; + margin-left: 0px; + padding-left: 0px !important; +} +.listheading { + background: url("../images/header_background.png") repeat scroll 0 -39px transparent; + height: 30px; + margin: 0px; + padding-left: 7px; + line-height: 30px; + font-size: 12px; + color: #606060; + text-shadow: 1px 1px 0 white; +} + +#names { + width: 200px; + overflow: hidden; + padding-left: 10px; + float: left; +} + +.listcontent { + border: 0px; + width: 100%; + margin: 0px; + border-top: 0px; +} + +.topologyTemplatePreviewSizing { + height:400px; + width:921px; +} + +#topologyTemplatePreview { + border: 0; +} + +div.policiesContainer > div.header { + display: none; +} + +div.policiesContainer > div.content > div.policy > textarea.policy_xml { + display: none; +} diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/back_disabled.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/back_disabled.png new file mode 100644 index 0000000..881de79 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/back_disabled.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/back_enabled.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/back_enabled.png new file mode 100644 index 0000000..c608682 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/back_enabled.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/back_enabled_hover.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/back_enabled_hover.png new file mode 100644 index 0000000..d300f10 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/back_enabled_hover.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/FrameBottom.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/FrameBottom.jpg new file mode 100644 index 0000000..b4a6162 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/FrameBottom.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/FrameMiddle.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/FrameMiddle.jpg new file mode 100644 index 0000000..7aa2d8f Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/FrameMiddle.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/FrameTop.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/FrameTop.jpg new file mode 100644 index 0000000..3abcd7d Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/FrameTop.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/styledTabMenuButtonCenter.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/styledTabMenuButtonCenter.jpg new file mode 100644 index 0000000..06867f4 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/styledTabMenuButtonCenter.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/styledTabMenuButtonLeft.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/styledTabMenuButtonLeft.jpg new file mode 100644 index 0000000..507e738 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/styledTabMenuButtonLeft.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/styledTabMenuButtonRight.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/styledTabMenuButtonRight.jpg new file mode 100644 index 0000000..0727686 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/admin/styledTabMenuButtonRight.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/nt/FrameBottom.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/nt/FrameBottom.jpg new file mode 100644 index 0000000..6adfebc Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/nt/FrameBottom.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/nt/FrameMiddle.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/nt/FrameMiddle.jpg new file mode 100644 index 0000000..ef3ea5b Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/nt/FrameMiddle.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/nt/FrameTop.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/nt/FrameTop.jpg new file mode 100644 index 0000000..59041c8 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/nt/FrameTop.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/nt/FrameTopLarge.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/nt/FrameTopLarge.jpg new file mode 100644 index 0000000..0cf4f27 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/nt/FrameTopLarge.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/rt/FrameBottom.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/rt/FrameBottom.jpg new file mode 100644 index 0000000..adf92ce Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/rt/FrameBottom.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/rt/FrameMiddle.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/rt/FrameMiddle.jpg new file mode 100644 index 0000000..8ca58dd Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/rt/FrameMiddle.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/rt/FrameTop.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/rt/FrameTop.jpg new file mode 100644 index 0000000..0bb76f1 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/rt/FrameTop.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/rt/FrameTopLarge.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/rt/FrameTopLarge.jpg new file mode 100644 index 0000000..c0875c9 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/rt/FrameTopLarge.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/st/FrameBottom.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/st/FrameBottom.jpg new file mode 100644 index 0000000..eb5bac3 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/st/FrameBottom.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/st/FrameMiddle.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/st/FrameMiddle.jpg new file mode 100644 index 0000000..009c9da Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/st/FrameMiddle.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/st/FrameTop.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/st/FrameTop.jpg new file mode 100644 index 0000000..4c37ebf Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/containers/st/FrameTop.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/admin/center.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/admin/center.jpg new file mode 100644 index 0000000..b22c1ff Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/admin/center.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/admin/left.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/admin/left.jpg new file mode 100644 index 0000000..e9e6559 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/admin/left.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/admin/right.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/admin/right.jpg new file mode 100644 index 0000000..a1d34b4 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/admin/right.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/deleteButton.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/deleteButton.jpg new file mode 100644 index 0000000..042ea00 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/deleteButton.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/deleteButtonHover.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/deleteButtonHover.jpg new file mode 100644 index 0000000..ba275b3 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/deleteButtonHover.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/editButton.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/editButton.jpg new file mode 100644 index 0000000..0a58fa4 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/editButton.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/editButtonHover.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/editButtonHover.jpg new file mode 100644 index 0000000..2fdfc34 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/editButtonHover.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/exportButton.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/exportButton.jpg new file mode 100644 index 0000000..b1ddd75 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/exportButton.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/exportButtonHover.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/exportButtonHover.jpg new file mode 100644 index 0000000..f58de95 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/exportButtonHover.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/nodeType/center.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/nodeType/center.jpg new file mode 100644 index 0000000..3951c2b Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/nodeType/center.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/nodeType/left.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/nodeType/left.jpg new file mode 100644 index 0000000..dda69ce Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/nodeType/left.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/nodeType/right.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/nodeType/right.jpg new file mode 100644 index 0000000..9d796c9 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/nodeType/right.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/relationshipType/center.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/relationshipType/center.jpg new file mode 100644 index 0000000..c66dbf0 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/relationshipType/center.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/relationshipType/left.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/relationshipType/left.jpg new file mode 100644 index 0000000..5945f80 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/relationshipType/left.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/relationshipType/right.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/relationshipType/right.jpg new file mode 100644 index 0000000..f49ddff Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/relationshipType/right.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/serviceTemplate/center.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/serviceTemplate/center.jpg new file mode 100644 index 0000000..385327a Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/serviceTemplate/center.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/serviceTemplate/left.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/serviceTemplate/left.jpg new file mode 100644 index 0000000..eda0c8b Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/serviceTemplate/left.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/serviceTemplate/right.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/serviceTemplate/right.jpg new file mode 100644 index 0000000..8d4cd7e Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/entityBox/serviceTemplate/right.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/favicon.ico b/winery/org.eclipse.winery.repository/src/main/webapp/images/favicon.ico new file mode 100644 index 0000000..823222e Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/favicon.ico differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/forward_disabled.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/forward_disabled.png new file mode 100644 index 0000000..6a6ded7 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/forward_disabled.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/forward_enabled.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/forward_enabled.png new file mode 100644 index 0000000..a4e6b53 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/forward_enabled.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/forward_enabled_hover.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/forward_enabled_hover.png new file mode 100644 index 0000000..fc46c5e Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/forward_enabled_hover.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/header_background.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/header_background.png new file mode 100644 index 0000000..0a797ac Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/header_background.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/jquery-fileupload/loading.gif b/winery/org.eclipse.winery.repository/src/main/webapp/images/jquery-fileupload/loading.gif new file mode 100644 index 0000000..90f28cb Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/jquery-fileupload/loading.gif differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/jquery-fileupload/progressbar.gif b/winery/org.eclipse.winery.repository/src/main/webapp/images/jquery-fileupload/progressbar.gif new file mode 100644 index 0000000..fbcce6b Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/jquery-fileupload/progressbar.gif differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/overviewShadowBottom.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/overviewShadowBottom.jpg new file mode 100644 index 0000000..28ae493 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/overviewShadowBottom.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/overviewShadowMiddle.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/overviewShadowMiddle.jpg new file mode 100644 index 0000000..ab770b2 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/overviewShadowMiddle.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/overviewShadowTop.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/overviewShadowTop.jpg new file mode 100644 index 0000000..9b6afec Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/overviewShadowTop.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/DiamondSource.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/DiamondSource.png new file mode 100644 index 0000000..4e43840 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/DiamondSource.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/DiamondTarget.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/DiamondTarget.png new file mode 100644 index 0000000..18b50ba Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/DiamondTarget.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/PlainArrowSource.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/PlainArrowSource.png new file mode 100644 index 0000000..8fd1883 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/PlainArrowSource.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/PlainArrowTarget.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/PlainArrowTarget.png new file mode 100644 index 0000000..cb66797 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/PlainArrowTarget.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/circleSource.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/circleSource.png new file mode 100644 index 0000000..c897794 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/circleSource.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/circleTarget.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/circleTarget.png new file mode 100644 index 0000000..aec0926 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/circleTarget.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/dotted2Line.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/dotted2Line.png new file mode 100644 index 0000000..a5d774d Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/dotted2Line.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/dottedLine.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/dottedLine.png new file mode 100644 index 0000000..aaa49a7 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/dottedLine.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/doubleArrowSource.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/doubleArrowSource.png new file mode 100644 index 0000000..62d40b8 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/doubleArrowSource.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/doubleArrowTarget.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/doubleArrowTarget.png new file mode 100644 index 0000000..d9b6bd6 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/doubleArrowTarget.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/noneSource.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/noneSource.png new file mode 100644 index 0000000..2ef91c2 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/noneSource.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/noneTarget.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/noneTarget.png new file mode 100644 index 0000000..0505eb1 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/noneTarget.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/plainLine.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/plainLine.png new file mode 100644 index 0000000..b4c4c6b Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/plainLine.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/simpleArrowSource.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/simpleArrowSource.png new file mode 100644 index 0000000..c8a0323 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/simpleArrowSource.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/simpleArrowTarget.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/simpleArrowTarget.png new file mode 100644 index 0000000..ccddf69 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/simpleArrowTarget.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/squareSource.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/squareSource.png new file mode 100644 index 0000000..74d045b Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/squareSource.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/squareTarget.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/squareTarget.png new file mode 100644 index 0000000..95b4add Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/relationshiptype/squareTarget.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/searchBoxBackground.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/searchBoxBackground.jpg new file mode 100644 index 0000000..9d76525 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/searchBoxBackground.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/sort_asc.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/sort_asc.png new file mode 100644 index 0000000..a88d797 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/sort_asc.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/sort_asc_disabled.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/sort_asc_disabled.png new file mode 100644 index 0000000..4e144cf Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/sort_asc_disabled.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/sort_both.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/sort_both.png new file mode 100644 index 0000000..1867040 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/sort_both.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/sort_desc.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/sort_desc.png new file mode 100644 index 0000000..def071e Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/sort_desc.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/sort_desc_disabled.png b/winery/org.eclipse.winery.repository/src/main/webapp/images/sort_desc_disabled.png new file mode 100644 index 0000000..7824973 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/sort_desc_disabled.png differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/styledTabMenuButtonCenter.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/styledTabMenuButtonCenter.jpg new file mode 100644 index 0000000..e5b87d9 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/styledTabMenuButtonCenter.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/styledTabMenuButtonLeft.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/styledTabMenuButtonLeft.jpg new file mode 100644 index 0000000..fa0c989 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/styledTabMenuButtonLeft.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/images/styledTabMenuButtonRight.jpg b/winery/org.eclipse.winery.repository/src/main/webapp/images/styledTabMenuButtonRight.jpg new file mode 100644 index 0000000..3329d70 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/main/webapp/images/styledTabMenuButtonRight.jpg differ diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/js/.gitignore b/winery/org.eclipse.winery.repository/src/main/webapp/js/.gitignore new file mode 100644 index 0000000..23c1477 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/js/.gitignore @@ -0,0 +1,3 @@ +# copied from topology modeler at mvn generate-sources +winery-common-topologyrendering.js +winery-support-common.js \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/js/boundaryDefinitionsXSelection.js b/winery/org.eclipse.winery.repository/src/main/webapp/js/boundaryDefinitionsXSelection.js new file mode 100644 index 0000000..afefc8c --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/js/boundaryDefinitionsXSelection.js @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + * Tobias Binz - communication with the parent window + *******************************************************************************/ + + /** + * Called from the renderer as soon as the whole topology is loaded + */ + function wineryViewExternalScriptOnLoad() { + + function getIdOfNodeTemplateShape(element) { + var nodeTemplate = element.closest("div.NodeTemplateShape"); + var id = nodeTemplate.children("div.headerContainer").children("div.id").text(); + return id; + } + + jsPlumb.bind("ready", function() { + jsPlumb.bind("click", function(conn, originalEvent) { + var id = winery.connections[conn.id].id; + var message = { + targetRelationshipTemplateRef: id + } + sendMessage(message); + }); + }); + + + $("div.NodeTemplateShape").on("click", function(e) { + var id = getIdOfNodeTemplateShape($(e.target)); + // send id and empty property as no property has been clicked + var message = { + targetObjectRef: id, + targetPropertyRef: "" + }; + sendMessage(message); + + return false; + }); + + $("tr.KVProperty").on("click", function(e) { + var trKVProperty = $(e.target).closest("tr.KVProperty"); + var key = trKVProperty.children("td").children("span.KVPropertyKey").text(); + + var content = trKVProperty.closest("div.content"); + var elementName = content.children("span.elementName").text(); + + // form namespace-unaware XPath + var xpath = "/*[local-name()='" + elementName + "']/*[local-name()='" + key + "']"; + + var message = { + targetPropertyRef: xpath, + targetObjectRef: getIdOfNodeTemplateShape(trKVProperty) + }; + sendMessage(message); + + // do not trigger click on NodeTemplateShape -> we included both values in the message + return false; + }); + + $("div.requirements").on("click", function(e) { + var reqorcap = $(e.target).closest("div.requirements"); + var id = reqorcap.children("div.id").text(); + + var message = { + reqRef: id + }; + sendMessage(message); + + return false; + }); + + $("div.capabilities").on("click", function(e) { + var reqorcap = $(e.target).closest("div.capabilities"); + var id = reqorcap.children("div.id").text(); + + var message = { + capRef: id + }; + sendMessage(message); + + return false; + }); + + } + +function sendMessage(message) { + window.parent.postMessage(message, "*"); +} diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/js/jquery.fileupload-audio.js b/winery/org.eclipse.winery.repository/src/main/webapp/js/jquery.fileupload-audio.js new file mode 100644 index 0000000..9b68349 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/js/jquery.fileupload-audio.js @@ -0,0 +1,12 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +// dummy as we don't need the functionality, but jquery.fileupload-ui.js requires it \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/js/jquery.fileupload-image.js b/winery/org.eclipse.winery.repository/src/main/webapp/js/jquery.fileupload-image.js new file mode 100644 index 0000000..9b68349 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/js/jquery.fileupload-image.js @@ -0,0 +1,12 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +// dummy as we don't need the functionality, but jquery.fileupload-ui.js requires it \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/js/jquery.fileupload-validate.js b/winery/org.eclipse.winery.repository/src/main/webapp/js/jquery.fileupload-validate.js new file mode 100644 index 0000000..9b68349 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/js/jquery.fileupload-validate.js @@ -0,0 +1,12 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +// dummy as we don't need the functionality, but jquery.fileupload-ui.js requires it \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/js/jquery.fileupload-video.js b/winery/org.eclipse.winery.repository/src/main/webapp/js/jquery.fileupload-video.js new file mode 100644 index 0000000..9b68349 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/js/jquery.fileupload-video.js @@ -0,0 +1,12 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +// dummy as we don't need the functionality, but jquery.fileupload-ui.js requires it \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/js/nextselect.js b/winery/org.eclipse.winery.repository/src/main/webapp/js/nextselect.js new file mode 100644 index 0000000..050fcb1 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/js/nextselect.js @@ -0,0 +1,144 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +/* + +Script for dependent selection boxes. + +One object for stating a map from value to content. The value is globally unique. + +Verbose example: + + + + + + + + + */ + +/** + * + * @param value the current selected value + * @param targetElement the select to update + * @param dependendSelects the data structure for subsequently dependent select elements + * @param completeData the data structure with the complete data + */ +function updateListContent(value, targetElement, dependendSelects, completeData) { + jQuery(targetElement).empty(); + var listData = completeData[value]; + if (listData !== undefined) { + for (var i=0; i < listData.options.length; i++) { + var optionName = listData.options[i]; + var label = completeData[optionName].label; + var selected; + if (i == 0) { + selected = ' selected="selected"'; + } else { + selected = ''; + } + var toAppend = ''; + jQuery(targetElement).append(toAppend); + } + nextSelect = dependendSelects[targetElement]; + if (nextSelect !== undefined) { + // We assume listData is not empty + updateListContent(listData.options[0], nextSelect, dependendSelects, completeData); + } + } + jQuery(targetElement).trigger("change"); +} diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/js/winery-support-non-AMD.js b/winery/org.eclipse.winery.repository/src/main/webapp/js/winery-support-non-AMD.js new file mode 100644 index 0000000..f1f1cfa --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/js/winery-support-non-AMD.js @@ -0,0 +1,223 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ + +function addResourceInstance() { + if (highlightRequiredFields()) { + vShowError("Please fill in all required fields"); + return; + } + + var dataToSend = $('#createResourceForm').serialize(); + var cr = $('#createResource'); + $.ajax({ + type: "POST", + async: false, + "data": dataToSend, + "url": cr.data("url"), + dataType: "text", + error: function(jqXHR, textStatus, errorThrown) { + vShowAJAXError("Could not create resource", jqXHR, errorThrown); + cr.modal("hide"); + }, + success: function(resData, textStatus, jqXHR) { + cr.data("onSuccess")($('#createResourceForm').serializeArray(), resData, textStatus, jqXHR); + cr.modal('hide'); + } + }); +} + +/** + * This function creates a dialog, where the user can add key/value pairs. + * These pairs are then sent to the given URL via POST. + * + * REQUIRES + + + +
+
+ + + +
+ + + + + + + + + + + + + + + +
PrefixNamespace
${w:getPrefix(ns.decoded)}${ns.decoded}
+
+ + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/admin/repository.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/admin/repository.jsp new file mode 100644 index 0000000..446bd46 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/admin/repository.jsp @@ -0,0 +1,101 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + +

General Repository Commands

+
+ Dump Repository + + +
+ +<% +org.eclipse.winery.repository.backend.IRepository rep; +rep = org.eclipse.winery.repository.Prefs.INSTANCE.getRepository(); +boolean isGitBasedRepo = (rep instanceof org.eclipse.winery.repository.backend.filebased.GitBasedRepository); + +org.eclipse.winery.repository.backend.filebased.GitBasedRepository repo = null; +if (isGitBasedRepo) { + repo = (org.eclipse.winery.repository.backend.filebased.GitBasedRepository) rep; +} + +// We only support the commit and reset buttons if we can authenticate at the repository +// This is a hack to offer different versions of winery at dev.winery.opentosca.org and winery.opentosca.org +isGitBasedRepo = isGitBasedRepo && (repo.authenticationInfoAvailable()); + +if (isGitBasedRepo) { +%> +

Versioning

+
+ + +
+ + +<% +} +%> + + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/admin/types/types.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/admin/types/types.jsp new file mode 100644 index 0000000..25b2e0f --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/admin/types/types.jsp @@ -0,0 +1,105 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + * Yves Schubert - switch to bootstrap 3 + *******************************************************************************/ +--%> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + +
+ + +
+ + + + + + + + + + + + + + + + + + + +
Short nameLong Name
${type.shortName}${type.type}
+ + + + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/artifacts/artifacts.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/artifacts/artifacts.jsp new file mode 100644 index 0000000..89b6fca --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/artifacts/artifacts.jsp @@ -0,0 +1,141 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + * Yves Schubert - switch to bootstrap 3 + *******************************************************************************/ +--%> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%> +<%@taglib prefix="v" uri="http://www.eclipse.org/winery/repository/functions"%> +<%@taglib prefix="ct" tagdir="/WEB-INF/tags/common" %> + +<%-- +Parameter +isDeploymentArtifact: true/false +--%> + + + + + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameInterface NameOperation NameArtifact TemplateArtifact TypeSpecific Content
${a.a.name}${a.a.interfaceName}${a.a.operationName}${a.a.artifactRef.localPart}${a.a.artifactType.localPart} + + (exists) +
+
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/componentnaming.jspf b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/componentnaming.jspf new file mode 100644 index 0000000..877e60c --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/componentnaming.jspf @@ -0,0 +1,28 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%-- + +Heading for a selected component (service template, node type, relationship type) + +Displays name + namespace + +--%> +
+
+ ${it.name} +
+
+ ${it.namespace} +
+
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/documentation.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/documentation.jsp new file mode 100644 index 0000000..55946a1 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/documentation.jsp @@ -0,0 +1,87 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions" %> + +<%-- TODO: source (external documentation) and lang attributes not yet supported --%> + + +
+
+
+ +
+ + + + + +
+ <%-- we only print a heading if we have multiple documentations. Otherwise, the documentation itself should be displayed --%> + +
+ ${content} +
+
+ + "> + +
+
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytemplates/artifacttemplates/artifacttemplate.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytemplates/artifacttemplates/artifacttemplate.jsp new file mode 100644 index 0000000..60f95f2 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytemplates/artifacttemplates/artifacttemplate.jsp @@ -0,0 +1,32 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> +<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions" %> + +<%@page import="org.eclipse.winery.repository.resources.SubMenuData"%> + +<% +java.util.List subMenus = new java.util.ArrayList(); + +SubMenuData data; + +data = new SubMenuData("#files", "Files"); +subMenus.add(data); + +data = new SubMenuData("#properties", "Properties"); +subMenus.add(data); +%> + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytemplates/artifacttemplates/files.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytemplates/artifacttemplates/files.jsp new file mode 100644 index 0000000..1c06254 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytemplates/artifacttemplates/files.jsp @@ -0,0 +1,18 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> + +<%@taglib prefix="fup" tagdir="/WEB-INF/tags/common"%> + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytemplates/policytemplates/policytemplate.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytemplates/policytemplates/policytemplate.jsp new file mode 100644 index 0000000..e0e340c --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytemplates/policytemplates/policytemplate.jsp @@ -0,0 +1,29 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> +<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions" %> + +<%@page import="org.eclipse.winery.repository.resources.SubMenuData"%> + +<% +java.util.List subMenus = new java.util.ArrayList(); + +SubMenuData data; + +data = new SubMenuData("#properties", "Properties"); +subMenus.add(data); +%> + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytemplates/properties.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytemplates/properties.jsp new file mode 100644 index 0000000..61134f2 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytemplates/properties.jsp @@ -0,0 +1,92 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> + +<%@page import="org.eclipse.winery.model.tosca.TEntityTemplate"%> +<%@page import="org.eclipse.winery.model.tosca.TEntityType"%> +<%@page import="org.eclipse.winery.common.ModelUtilities"%> +<%@page import="org.eclipse.winery.repository.Utils"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="props" tagdir="/WEB-INF/tags/common/templates" %> +<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions"%> +<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions" %> + + + + + + + + + +
+
<%-- This div is required by props:properties to be consistent with a node template. This mirrors div class="content" --%> + + +
+
+ + + + + + + The type does not have a “properties definition”. + + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypeimplementations/nodetypeimplementations/nodetypeimplementation.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypeimplementations/nodetypeimplementations/nodetypeimplementation.jsp new file mode 100644 index 0000000..eec30c2 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypeimplementations/nodetypeimplementations/nodetypeimplementation.jsp @@ -0,0 +1,33 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> +<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions" %> + +<%@page import="org.eclipse.winery.repository.resources.SubMenuData"%> + +<% +java.util.List subMenus = new java.util.ArrayList(); + +SubMenuData data; + +data = new SubMenuData("#implementationartifacts", "Implementation Artifacts"); +subMenus.add(data); + +data = new SubMenuData("#deploymentartifacts", "Deployment Artifacts"); +subMenus.add(data); + +%> + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypeimplementations/relationshiptypeimplementations/relationshiptypeimplementation.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypeimplementations/relationshiptypeimplementations/relationshiptypeimplementation.jsp new file mode 100644 index 0000000..97a9ad5 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypeimplementations/relationshiptypeimplementations/relationshiptypeimplementation.jsp @@ -0,0 +1,29 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> +<%@ taglib uri="http://www.eclipse.org/winery/repository/functions" prefix="w" %> + +<%@page import="org.eclipse.winery.repository.resources.SubMenuData"%> + +<% +java.util.List subMenus = new java.util.ArrayList(); + +SubMenuData data; + +data = new SubMenuData("#implementationartifacts", "Implementation Artifacts"); +subMenus.add(data); +%> + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/artifacttypes/artifacttype.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/artifacttypes/artifacttype.jsp new file mode 100644 index 0000000..c51630a --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/artifacttypes/artifacttype.jsp @@ -0,0 +1,26 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + +<%-- +TODO: implement update / subresource "file extension" +
Associated File Extension
+ +
+ value="${it.associatedFileExtension}" /> +
+--%> + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/capabilitytypes/capabilitytype.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/capabilitytypes/capabilitytype.jsp new file mode 100644 index 0000000..2e2b2f0 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/capabilitytypes/capabilitytype.jsp @@ -0,0 +1,17 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/implementations.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/implementations.jsp new file mode 100644 index 0000000..46ef5a8 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/implementations.jsp @@ -0,0 +1,63 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + * Yves Schubert - switch to bootstrap 3 + *******************************************************************************/ +--%> +<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + + + + + +

+This page shows implementations available for this type. +Go to Other Elements to get an overview on all implementations stored in this repository. +

+ +
+ + + + + +
+
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/instancestates.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/instancestates.jsp new file mode 100644 index 0000000..059ae55 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/instancestates.jsp @@ -0,0 +1,86 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + * Yves Schubert - switch to bootstrap 3 + *******************************************************************************/ +--%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + + + +
+ + + + + + + + + + + + + + + + +
State
${t}
+
+ + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/nodetypes/nodetype.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/nodetypes/nodetype.jsp new file mode 100644 index 0000000..f9d52d7 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/nodetypes/nodetype.jsp @@ -0,0 +1,44 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + +<%@page import="org.eclipse.winery.repository.resources.SubMenuData"%> + +<% +java.util.List subMenus = new java.util.ArrayList(); + +SubMenuData data; + +data = new SubMenuData("#visualappearance", "Visual Appearance"); +subMenus.add(data); + +data = new SubMenuData("#instancestates", "Instance States"); +subMenus.add(data); + +data = new SubMenuData("#interfaces", "Interfaces"); +subMenus.add(data); + +data = new SubMenuData("#implementations", "Implementations"); +subMenus.add(data); + +data = new SubMenuData("#requirementdefinitions", "Requirement Definitions"); +subMenus.add(data); + +data = new SubMenuData("#capabilitydefinitions", "Capability Definitions"); +subMenus.add(data); + +%> + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/nodetypes/reqandcapdefs/capdefs.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/nodetypes/reqandcapdefs/capdefs.jsp new file mode 100644 index 0000000..7f2cc7d --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/nodetypes/reqandcapdefs/capdefs.jsp @@ -0,0 +1,17 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags/entitytypes/nodetypes/reqandcapdefs" %> + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/nodetypes/reqandcapdefs/reqdefs.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/nodetypes/reqandcapdefs/reqdefs.jsp new file mode 100644 index 0000000..08657a1 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/nodetypes/reqandcapdefs/reqdefs.jsp @@ -0,0 +1,17 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2014 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags/entitytypes/nodetypes/reqandcapdefs" %> + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/nodetypes/visualappearance.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/nodetypes/visualappearance.jsp new file mode 100644 index 0000000..b432be6 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/nodetypes/visualappearance.jsp @@ -0,0 +1,68 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + * Yves Schubert - switch to bootstrap 3 + *******************************************************************************/ +--%> +<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + + + + + + + + +
+
+
+ + + +
+
+
+
+
+ +
+
+
+
+ + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/policytypes/appliesto.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/policytypes/appliesto.jsp new file mode 100644 index 0000000..ff15a39 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/policytypes/appliesto.jsp @@ -0,0 +1,25 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + + + +
    + +
  • ${nodeTypeReference.typeRef}
  • +
    +
+ + +Update not yet implemented. diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/policytypes/language.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/policytypes/language.jsp new file mode 100644 index 0000000..c1815bd --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/policytypes/language.jsp @@ -0,0 +1,21 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + + + + ${it.language} + + +Update not yet implemented. diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/policytypes/policytype.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/policytypes/policytype.jsp new file mode 100644 index 0000000..694abad --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/policytypes/policytype.jsp @@ -0,0 +1,32 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + +<%@page import="org.eclipse.winery.repository.resources.SubMenuData"%> + +<% +java.util.List subMenus = new java.util.ArrayList(); + +SubMenuData data; + +data = new SubMenuData("#language", "Language"); +subMenus.add(data); + +data = new SubMenuData("#appliesto", "Applies To"); +subMenus.add(data); + +%> + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/properties/propertiesDefinition.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/properties/propertiesDefinition.jsp new file mode 100644 index 0000000..a0e22df --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/properties/propertiesDefinition.jsp @@ -0,0 +1,320 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + * Yves Schubert - switch to bootstrap 3 + *******************************************************************************/ +--%> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags"%> +<%@taglib prefix="ct" tagdir="/WEB-INF/tags/common"%> +<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions"%> + +<%-- createResource of winery-support.js could be used. However, currently selects are not supported --%> + + + + +

+ <%-- TODO: if clicked on the "label" of the input field (i.e., the content of the input tag), the input should be selected. This is not the default at HTML5 - see http://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_input_type_radio --%> + + checked="checked">(none) +
+ + checked="checked">XML element + ${it.entityType.propertiesDefinition.element.localPart} +
+ + checked="checked">XML type + ${it.entityType.propertiesDefinition.type.localPart} +
+ + + checked="checked">Custom key/value pairs +

+ + + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/relationshiptypes/relationshiptype.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/relationshiptypes/relationshiptype.jsp new file mode 100644 index 0000000..ba2e6cc --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/relationshiptypes/relationshiptype.jsp @@ -0,0 +1,44 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + +<%@page import="org.eclipse.winery.repository.resources.SubMenuData"%> + +<% +java.util.List subMenus = new java.util.ArrayList(); + +SubMenuData data; + +data = new SubMenuData("#visualappearance", "Visual Appearance"); +subMenus.add(data); + +data = new SubMenuData("#instancestates", "Instance States"); +subMenus.add(data); + +data = new SubMenuData("#sourceinterfaces", "Source Interfaces"); +subMenus.add(data); + +data = new SubMenuData("#targetinterfaces", "Target Interfaces"); +subMenus.add(data); + +data = new SubMenuData("#validendings", "Valid Sources and Targets"); +subMenus.add(data); + +data = new SubMenuData("#implementations", "Implementations"); +subMenus.add(data); + +%> + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/relationshiptypes/validendings.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/relationshiptypes/validendings.jsp new file mode 100644 index 0000000..4bf2145 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/relationshiptypes/validendings.jsp @@ -0,0 +1,39 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + * Yves Schubert - switch to bootstrap 3 + *******************************************************************************/ +--%> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="rt" tagdir="/WEB-INF/tags/relationshiptype" %> + +

Valid Source

+Node Type: + + +
+Requirement Type: + + + +
+
+

Valid Target

+Node Type: + + +
+Capability Type: + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/relationshiptypes/visualappearance.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/relationshiptypes/visualappearance.jsp new file mode 100644 index 0000000..d30ea01 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/relationshiptypes/visualappearance.jsp @@ -0,0 +1,193 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + * Yves Schubert - switch to bootstrap 3 + *******************************************************************************/ +--%> +<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + + + + + + +
+
+
+ +
+ +
+
+
+
+ + +
+
+
+ +
+
+
+
+
+ +
+
+ + +
+
+ +
+
+ +
+
+
+
+
+
+
+ + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/requirementtypes/requiredcapabilitytype.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/requirementtypes/requiredcapabilitytype.jsp new file mode 100644 index 0000000..0b10277 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/requirementtypes/requiredcapabilitytype.jsp @@ -0,0 +1,56 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="ct" tagdir="/WEB-INF/tags/common" %> + + + + + + + + + + + + + \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/requirementtypes/requirementtype.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/requirementtypes/requirementtype.jsp new file mode 100644 index 0000000..a8b6f43 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/entitytypes/requirementtypes/requirementtype.jsp @@ -0,0 +1,30 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + +<%@page import="org.eclipse.winery.repository.resources.SubMenuData"%> + +<% +java.util.List subMenus = new java.util.ArrayList(); + +SubMenuData data; + +data = new SubMenuData("#requiredcapabilitytype", "Required Capability Type"); +subMenus.add(data); + +%> + + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/genericcomponentpage.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/genericcomponentpage.jsp new file mode 100644 index 0000000..0439904 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/genericcomponentpage.jsp @@ -0,0 +1,209 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="v" uri="http://www.eclipse.org/winery/repository/functions" %> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> +<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions" %> + +<%-- In English, one can usually form a plural by adding an "s". Therefore, we resue the label to form the window title --%> + + + + + + + + + + + + + + +
+
+ + + + + + + +
+ +
+ + + + + +
+ + + <%-- even though the id is an invalid XML, it is used for a simple implementation on a click on the graphical rendering to trigger opening the editor --%> +
+
+ + + + + +
+
+
+
+ ${wc:escapeHtml4(t.xmlId.decoded)} +
+
+ ${wc:escapeHtml4(t.namespace.decoded)} +
+
+
+ + + <%-- we need double encoding of the URL as the passing to javascript: decodes the given string once --%> + +
+
+
+
+
+
+
+
+
+
+ + +
+
+
+ + + +
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/hashloading.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/hashloading.jsp new file mode 100644 index 0000000..eb5bbfa --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/hashloading.jsp @@ -0,0 +1,140 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/imports/xsdimports/xsdimport.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/imports/xsdimports/xsdimport.jsp new file mode 100644 index 0000000..452e7ad --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/imports/xsdimports/xsdimport.jsp @@ -0,0 +1,50 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + +<%-- Quick hack without XML view --%> + +<%-- +FIXME: parameters cssClass and selected are somehow ignored, but replaced by the data provided by GenericComponentPageData or similar... +Symptom: in header.jsp "param.selected" is "XSDImport" instead of "xsdimport" +--%> + + +
+ <%@ include file="/jsp/componentnaming.jspf" %> + +
+ +
+ +Associated file: +none +${it.location} + +
+ +Modification not yet implemented + +
+ +
+ + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/inheritance.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/inheritance.jsp new file mode 100644 index 0000000..8d1d535 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/inheritance.jsp @@ -0,0 +1,55 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> + +
+ + +
+ +
+ + +
+ +
+ +
+ + +
+
+ + \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/interfaces/interfaces.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/interfaces/interfaces.jsp new file mode 100644 index 0000000..07ed928 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/interfaces/interfaces.jsp @@ -0,0 +1,489 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + * Yves Schubert - port to bootstrap 3 + *******************************************************************************/ +--%> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> +<%@taglib prefix="ct" tagdir="/WEB-INF/tags/common" %> +<%@taglib prefix="p" tagdir="/WEB-INF/tags/parameters" %> +<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions"%> + +<%@page import="org.eclipse.winery.common.Util" %> +<%@page import="org.eclipse.winery.repository.Constants" %> + + + + +<%-- include basic parameters support --%> + + + + + + + +
+
+
+ + + +
+ + + +
+ +
+
+ + + +
+ +
+ +
+ +

+ +
+
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/otherElements.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/otherElements.jsp new file mode 100644 index 0000000..15d3e7d --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/otherElements.jsp @@ -0,0 +1,44 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + + + +

+The following items list TOSCA elements contained in TOSCA's Definitions element, which are not listed as separate tabs. +

+ +

Artifacts

+Artifact Types +Artifact Templates + +

Requirements and Capabilities

+Requirement Types +Capability Types + +

Implementations

+Node Type Implementations +Relationship Type Implementations + +

Policies

+Policy Types +Policy Templates + +

Imports

+XML Schema Definitions +WSDLs + +
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/boundarydefinitions/boundarydefinitions.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/boundarydefinitions/boundarydefinitions.jsp new file mode 100644 index 0000000..aadec72 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/boundarydefinitions/boundarydefinitions.jsp @@ -0,0 +1,1080 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + * Tobias Binz - communication with the nested iframe + *******************************************************************************/ +--%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="w" tagdir="/WEB-INF/tags"%> +<%@taglib prefix="o" tagdir="/WEB-INF/tags/common/orioneditor"%> +<%@taglib prefix="b" tagdir="/WEB-INF/tags/servicetemplates/boundarydefinitions"%> +<%@taglib prefix="pol" tagdir="/WEB-INF/tags/common/policies" %> +<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions"%> +<%@taglib prefix="wr" uri="http://www.eclipse.org/winery/repository/functions"%> + +<%@page import="org.eclipse.winery.common.ModelUtilities"%> + + + + + + + + + + + +
+ + +
+ +
+ <%-- reloadAfterSuccess is necessary as the XMLtree has to be changed --%> + ${it.definedPropertiesAsEscapedHTML} +
+ +
+ + +

No properties available. Thus, no properties can be mapped. Please define properties.

+
+ + + + + + + + + + + + + + + + + + <%-- .name cannot be used as it is not an Id. Future work: Store the id in a seperate field and show the name to the user --%> + + + + + +
Service Template PropertyTargetTarget Property
${propertyMapping.serviceTemplatePropertyRef}${propertyMapping.targetObjectRef.id}${propertyMapping.targetPropertyRef}
+
+
+
+ + <%-- TODO: provide this as .tag. The property constraint resource should also be provided as tag --%> +
+ + + + + + + + + + + + + + + + + + + + +
(internal id)Service Template PropertyConstraint TypeConstraint
example/demohttp://www.example.com/accessrestrictions(not yet implemented)
+
+ +
+ + + + + + + <%-- of the boundary requirement, also used as the id of this element--%> + + + + + + + + + + + + + +
(Id)NameReference
${wr:determineIdUsingHashCode(item)}${item.name}${item.ref.id}
+
+ +
+ <%-- mirrored from requirements --%> + + + + + + + <%-- of the boundary requirement, also used as the id of this element--%> + + + + + + + + + + + + + +
(Id)NameReference
${wr:determineIdUsingHashCode(item)}${item.name}${item.ref.id}
+
+ +
+ +
+ +
+ + + + + + + + + + +
+

Provided Interface and Operation

+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +

Target

+ +
+ + + +
+ +
+
+ +
+ +
+ +
+ + + + +
+ +

Target Interface and Operation

+
+
+ +
+ +
+
+ +
+ +
+ +
+
+
+ + + +
+ + + +
+ ${it.boundaryDefinitionsAsXMLStringEncoded} +
+
+
+ + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/plans/plans.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/plans/plans.jsp new file mode 100644 index 0000000..ca50be4 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/plans/plans.jsp @@ -0,0 +1,266 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + * Yves Schubert - switch to bootstrap 3 + *******************************************************************************/ +--%> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@taglib prefix="p" tagdir="/WEB-INF/tags/parameters" %> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + + + + + + + + + + + +
+

Embedded Plans

+ + + + +<% +if (org.eclipse.winery.repository.Prefs.INSTANCE.isPlanBuilderAvailable()) { +%> + + +<% +} +%> +
+ +

+

Linked Plans

+
+
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/selfservicemetadata/selfservicemetadata.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/selfservicemetadata/selfservicemetadata.jsp new file mode 100644 index 0000000..d4d9233 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/selfservicemetadata/selfservicemetadata.jsp @@ -0,0 +1,256 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="o" tagdir="/WEB-INF/tags/common/orioneditor"%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> +<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions"%> + +<%-- Upload functionality inspired by plans.jsp. That code could be generalized somehow in a .tag file --%> + + + +
+ +
+ + +
+ +
${it.application.description}
+
+
+ +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
IdNameIconPlan Service Name
${option.id}${option.name}${option.planServiceName}
+
+ +
+ ${it.applicationAsXMLStringEncoded} +
+ +
+ + + + + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/servicetemplate.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/servicetemplate.jsp new file mode 100644 index 0000000..b5349d6 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/servicetemplate.jsp @@ -0,0 +1,43 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013, 2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@page import="org.eclipse.winery.repository.resources.SubMenuData"%> + +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + +<%-- add submenus after the submenus defined for the type --%> +<% +java.util.List subMenus = new java.util.ArrayList(5); + +SubMenuData data; + +data = new SubMenuData("#topologytemplate", "Topology Template"); +subMenus.add(data); + +data = new SubMenuData("#plans", "Plans"); +subMenus.add(data); + +data = new SubMenuData("#selfserviceportal", "Self-service Portal"); +subMenus.add(data); + +data = new SubMenuData("#boundarydefinitions", "Boundary Definitions"); +subMenus.add(data); + +//Tags are currently not implemented -> Don't confuse users by showing the tab +//has to be enabled again, when tags are implemented +//data = new SubMenuData("#tags", "Tags"); +//subMenus.add(data); +%> + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplate.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplate.jsp new file mode 100644 index 0000000..b5424ae --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplate.jsp @@ -0,0 +1,23 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> + +
+ Open Editor + Open View +
+
+
Loading preview...
+ +
diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplateview.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplateview.jsp new file mode 100644 index 0000000..789c174 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/servicetemplates/topologytemplates/topologytemplateview.jsp @@ -0,0 +1,67 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> +<%@page buffer="none" %> + +<%@page import="org.eclipse.winery.common.interfaces.IWineryRepository"%> +<%@page import="org.eclipse.winery.repository.Prefs" %> +<%@page import="org.eclipse.winery.repository.client.WineryRepositoryClientFactory"%> +<%@page import="org.eclipse.winery.repository.client.IWineryRepositoryClient"%> +<%@page import="org.eclipse.winery.repository.client.WineryRepositoryClient"%> + +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> +<%@taglib prefix="w" uri="http://www.eclipse.org/winery/repository/functions"%> + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/setupTriggerRemoveByDELKey.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/setupTriggerRemoveByDELKey.jsp new file mode 100644 index 0000000..ea47832 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/setupTriggerRemoveByDELKey.jsp @@ -0,0 +1,28 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%-- +JavaScript snippet binding the delete button to a trigger of the "Remove" button in case there is only one such button and that no input field is selected +--%> + + var removeButtons = $("button:contains('Remove')"); + if (removeButtons.length == 1) { + requirejs(["keyboardjs"], function(KeyboardJS) { + KeyboardJS.on("del", function() { + if ($(document.activeElement).is("body")) { + // we are not in an input field etc. + removeButtons.trigger("click"); + } + }); + }); + } diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/tags/tags.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/tags/tags.jsp new file mode 100644 index 0000000..c47271d --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/tags/tags.jsp @@ -0,0 +1,14 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +Not yet implemented diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/test.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/test.jsp new file mode 100644 index 0000000..2fbfb99 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/test.jsp @@ -0,0 +1,33 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> +<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> + + + + + + + + + diff --git a/winery/org.eclipse.winery.repository/src/main/webapp/jsp/xmlSource.jsp b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/xmlSource.jsp new file mode 100644 index 0000000..bec5e11 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/main/webapp/jsp/xmlSource.jsp @@ -0,0 +1,20 @@ +<%-- +/******************************************************************************* + * Copyright (c) 2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation and/or initial documentation + *******************************************************************************/ +--%> + +<%@taglib prefix="wc" uri="http://www.eclipse.org/winery/functions" %> +<%@taglib prefix="o" tagdir="/WEB-INF/tags/common/orioneditor"%> + +${wc:escapeHtml4(it.definitionsAsXMLString)} + +

Save leads to a synchronization with the other tabs

\ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/psd/Sorting icons.psd b/winery/org.eclipse.winery.repository/src/psd/Sorting icons.psd new file mode 100644 index 0000000..53b2e06 Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/psd/Sorting icons.psd differ diff --git a/winery/org.eclipse.winery.repository/src/psd/header_background_plain.png b/winery/org.eclipse.winery.repository/src/psd/header_background_plain.png new file mode 100644 index 0000000..41015fe Binary files /dev/null and b/winery/org.eclipse.winery.repository/src/psd/header_background_plain.png differ diff --git a/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/librarytests/DateTest.java b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/librarytests/DateTest.java new file mode 100644 index 0000000..db4aea4 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/librarytests/DateTest.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.librarytests; + +import java.text.ParseException; +import java.util.Date; +import java.util.Locale; + +import org.apache.commons.lang3.time.DateUtils; + +/** + * Date parsing test, when the system locale is not ENGLISH + */ +public class DateTest { + + public static void main(String[] args) throws ParseException { + // In case the following line is commented, this method throws a ParseException + Locale.setDefault(Locale.ENGLISH); + String modified = "Fri, 23 Mar 2012 11:04:56 GMT"; + Date modifiedDate = DateUtils.parseDate(modified, org.apache.http.impl.cookie.DateUtils.DEFAULT_PATTERNS); + System.out.println(modifiedDate); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/librarytests/InheritanceIllustration.java b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/librarytests/InheritanceIllustration.java new file mode 100644 index 0000000..95601d7 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/librarytests/InheritanceIllustration.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.librarytests; +/** + * This class is intended to demonstrate static resolution of overloaded methods + * + * The output of this class is "Doing sth. with a followed by "Doing sth. with + * b" even if the passed "theObject" is of type B + */ +public class InheritanceIllustration { + + private static class A { + }; + + private static class B extends A { + }; + + private static class X { + + public static void doSomething(A a) { + System.out.println("Doing sth. with a"); + } + + public static void doSomething(B b) { + System.out.println("Doing sth. with b"); + } + } + + + /** + * @param args + */ + public static void main(String[] args) { + A theObject = new B(); + X.doSomething(theObject); + X.doSomething((B) theObject); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/PrefsTestEnabled.java b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/PrefsTestEnabled.java new file mode 100644 index 0000000..3e48592 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/PrefsTestEnabled.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository; + +import java.io.IOException; + +public abstract class PrefsTestEnabled extends Prefs { + + /** + * @param initializeRepository true if the repository should be initialized + * as provided in winery.properties + * @throws IOException + */ + protected PrefsTestEnabled(boolean initializeRepository) throws IOException { + super(initializeRepository); + } + + @Override + public String getResourcePath() { + return "http://www.example.org/winery/test"; + } + +} diff --git a/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/PrefsTestEnabledGitBackedRepository.java b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/PrefsTestEnabledGitBackedRepository.java new file mode 100644 index 0000000..fc702d8 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/PrefsTestEnabledGitBackedRepository.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository; + +import java.io.IOException; + +import org.eclipse.winery.repository.backend.filebased.GitBasedRepository; + +public class PrefsTestEnabledGitBackedRepository extends PrefsTestEnabled { + + public PrefsTestEnabledGitBackedRepository() throws IOException { + super(false); + // TODO: we should to a new clone of the repository + // currently, we rely on the right configuration of the preferences to use a file-based repository + + // code similar to org.eclipse.winery.repository.Prefs.doRepositoryInitialization() + String repositoryLocation = this.properties.getProperty("repositoryPath"); + this.repository = new GitBasedRepository(repositoryLocation); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/PrefsTestEnabledUsingConfiguredRepository.java b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/PrefsTestEnabledUsingConfiguredRepository.java new file mode 100644 index 0000000..0aea8ed --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/PrefsTestEnabledUsingConfiguredRepository.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository; + +import java.io.IOException; + +/** + * Initializes the preferences with the repository given in winery.preferences + * + * FIXME: no test should use this one. Each test should configure the repository + * by itself. + */ +public class PrefsTestEnabledUsingConfiguredRepository extends PrefsTestEnabled { + + public PrefsTestEnabledUsingConfiguredRepository() throws IOException { + super(true); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/TestWithRepositoryConnection.java b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/TestWithRepositoryConnection.java new file mode 100644 index 0000000..d2a2f88 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/TestWithRepositoryConnection.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository; + +import java.io.IOException; + +import org.junit.BeforeClass; + +public abstract class TestWithRepositoryConnection { + + @BeforeClass + public static void connectToProvider() throws IOException { + // Initialize preferences + // We do not need them, but constructing them has the side effect that Repository.INSTANCE is != null + new PrefsTestEnabledUsingConfiguredRepository(); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/UtilsTest.java b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/UtilsTest.java new file mode 100644 index 0000000..02f04f9 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/UtilsTest.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository; + +import org.junit.Assert; +import org.junit.Test; + +public class UtilsTest { + + @Test + public void testCreateID() { + Assert.assertEquals("Frank_s_test", Utils.createXMLid("Frank's test").getDecoded()); + Assert.assertEquals("MyNodeType", Utils.createXMLid("MyNodeType").getDecoded()); + Assert.assertEquals("A_Node_Type", Utils.createXMLid("A Node Type").getDecoded()); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/export/TestToscaExporter.java b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/export/TestToscaExporter.java new file mode 100644 index 0000000..5411cec --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/export/TestToscaExporter.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.export; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.HashMap; +import java.util.Map; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.StreamingOutput; +import javax.xml.bind.JAXBException; + +import org.apache.commons.io.output.NullOutputStream; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.eclipse.winery.common.ids.definitions.ServiceTemplateId; +import org.eclipse.winery.repository.PrefsTestEnabledGitBackedRepository; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.backend.filebased.GitBasedRepository; + +public class TestToscaExporter { + + //private static final TOSCAExportUtil toscaExporter = new TOSCAExportUtil(); + private static final CSARExporter csarExporter = new CSARExporter(); + + private static final ServiceTemplateId serviceTemplateId = new ServiceTemplateId("http://www.example.com/tosca/ServiceTemplates/Moodle", "Moodle", false); + + + /** + * Quick hack as we currently don't have a dedicated test service template + */ + @BeforeClass + public static void setServiceTemplateId() throws Exception { + // Initialize preferences + // We do not need them, but constructing them has the side effect that Repository.INSTANCE is != null + new PrefsTestEnabledGitBackedRepository(); + } + + @Before + public void setRevision() throws Exception { + ((GitBasedRepository) Repository.INSTANCE).setRevisionTo("97fa997b92965d8bc84e86274b0203f1db7495c5"); + } + + @Test + public void checkTOSCAExport() throws Exception { + @SuppressWarnings("unused") + StreamingOutput so = new StreamingOutput() { + + @Override + public void write(OutputStream output) throws IOException, WebApplicationException { + TOSCAExportUtil exporter = new TOSCAExportUtil(); + // we include everything related + Map conf = new HashMap<>(); + try { + exporter.exportTOSCA(TestToscaExporter.serviceTemplateId, output, conf); + } catch (JAXBException e) { + throw new WebApplicationException(e); + } + } + }; + + // TODO: check output contained in SO + } + + @Test + public void checkCSARExport() throws Exception { + NullOutputStream out = new NullOutputStream(); + TestToscaExporter.csarExporter.writeCSAR(TestToscaExporter.serviceTemplateId, out); + } +} diff --git a/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/importing/TestCSARImporter.java b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/importing/TestCSARImporter.java new file mode 100644 index 0000000..f2778df --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/importing/TestCSARImporter.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2012-2013,2015 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.importing; + +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.winery.repository.PrefsTestEnabledUsingConfiguredRepository; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TestCSARImporter { + + /** + * Ensure that Repository.INSTANCE exists + */ + @BeforeClass + public static void setupPrefs() throws Exception { + // Initialize preferences + // We do not need them directly, but constructing them has the side effect that Repository.INSTANCE is != null + new PrefsTestEnabledUsingConfiguredRepository(); + } + + /** + * Quick hack to test Moodle Import + * + * Currently, no CSARs are put into the test resources, we rely on local + * CSARs + */ + @Test + public void testMoodleImport() throws Exception { + CSARImporter i = new CSARImporter(); + Path p = FileSystems.getDefault().getPath("C:\\Users\\Oliver\\BTSync\\Projects\\OpenTOSCA\\MoodleInteropCSAR\\trunk"); + List errors = new ArrayList(); + i.importFromDir(p, errors, true, false); + } +} diff --git a/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/TestAbstractComponentInstanceResourceDefinitionsBacked.java b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/TestAbstractComponentInstanceResourceDefinitionsBacked.java new file mode 100644 index 0000000..1e65954 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/TestAbstractComponentInstanceResourceDefinitionsBacked.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import java.io.IOException; + +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.common.ids.definitions.CapabilityTypeId; +import org.eclipse.winery.repository.backend.MockXMLElement; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.resources.entitytypes.capabilitytypes.CapabilityTypeResource; +import org.junit.Assert; +import org.junit.Test; + +public class TestAbstractComponentInstanceResourceDefinitionsBacked extends TestResource { + + private static final CapabilityTypeId id = new CapabilityTypeId(TestResource.NS, new XMLId("testCapabilityType", false)); + + + @Test + public void testPlainPersist() throws IOException { + // ensure that no test object exists + Repository.INSTANCE.forceDelete(TestAbstractComponentInstanceResourceDefinitionsBacked.id); + + CapabilityTypeResource res = new CapabilityTypeResource(TestAbstractComponentInstanceResourceDefinitionsBacked.id); + res.persist(); + Assert.assertTrue("Element has to exist", Repository.INSTANCE.exists(TestAbstractComponentInstanceResourceDefinitionsBacked.id)); + } + + @Test + public void testPersistWithData() throws IOException { + // ensure that no test object exists + Repository.INSTANCE.forceDelete(TestAbstractComponentInstanceResourceDefinitionsBacked.id); + + CapabilityTypeResource res = new CapabilityTypeResource(TestAbstractComponentInstanceResourceDefinitionsBacked.id); + res.getElement().getAny().add(new MockXMLElement()); + res.persist(); + Assert.assertTrue("Element has to exist", Repository.INSTANCE.exists(TestAbstractComponentInstanceResourceDefinitionsBacked.id)); + + // reload data + res = new CapabilityTypeResource(TestAbstractComponentInstanceResourceDefinitionsBacked.id); + + Assert.assertEquals(1, res.getElement().getAny().size()); + } +} diff --git a/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/TestResource.java b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/TestResource.java new file mode 100644 index 0000000..2841942 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/TestResource.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources; + +import org.eclipse.winery.common.ids.Namespace; +import org.eclipse.winery.repository.TestWithRepositoryConnection; + +public abstract class TestResource extends TestWithRepositoryConnection { + + protected static final String TESTNS = "http://www.example.org/winery/test/resources"; + protected static final Namespace NS = new Namespace(TestResource.TESTNS, false); + +} diff --git a/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/TestArtifactTemplateResource.java b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/TestArtifactTemplateResource.java new file mode 100644 index 0000000..e7e3e5a --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/entitytemplates/artifacttemplates/TestArtifactTemplateResource.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytemplates.artifacttemplates; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.eclipse.winery.common.ids.definitions.ArtifactTemplateId; +import org.eclipse.winery.repository.PrefsTestEnabledGitBackedRepository; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.backend.filebased.GitBasedRepository; +import org.eclipse.winery.repository.resources.AbstractComponentsResource; + +public class TestArtifactTemplateResource { + + @BeforeClass + public static void init() throws Exception { + // enable git-backed repository + new PrefsTestEnabledGitBackedRepository(); + } + + @Before + public void setRevision() throws Exception { + ((GitBasedRepository) Repository.INSTANCE).setRevisionTo("97fa997b92965d8bc84e86274b0203f1db7495c5"); + } + + @Test + public void countMatches() { + ArtifactTemplateId id = new ArtifactTemplateId("http%3A%2F%2Fdocs.oasis-open.org%2Ftosca%2Fns%2F2011%2F12%2FToscaSpecificTypes", "at-0cd9ab5d-6c2e-4fc2-9cb0-3fee1e431f9f", true); + ArtifactTemplateResource res = (ArtifactTemplateResource) AbstractComponentsResource.getComponentInstaceResource(id); + Assert.assertEquals(1, res.getReferenceCount()); + } +} diff --git a/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/TestCapabilityTypeResource.java b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/TestCapabilityTypeResource.java new file mode 100644 index 0000000..098d59a --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/entitytypes/capabilitytypes/TestCapabilityTypeResource.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.capabilitytypes; + +import java.io.IOException; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.eclipse.winery.common.ids.Namespace; +import org.eclipse.winery.common.ids.XMLId; +import org.eclipse.winery.common.ids.definitions.CapabilityTypeId; +import org.eclipse.winery.repository.PrefsTestEnabledGitBackedRepository; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.backend.filebased.GitBasedRepository; +import org.eclipse.winery.repository.resources.TestResource; + +public class TestCapabilityTypeResource extends TestResource { + + private static final CapabilityTypeId id = new CapabilityTypeId(new Namespace("http://docs.oasis-open.org/tosca/ns/2011/12/ToscaBaseTypes", false), new XMLId("ContainerCapability", false)); + + + @BeforeClass + public static void init() throws Exception { + // enable git-backed repository + new PrefsTestEnabledGitBackedRepository(); + } + + @Before + public void setRevision() throws Exception { + ((GitBasedRepository) Repository.INSTANCE).setRevisionTo("97fa997b92965d8bc84e86274b0203f1db7495c5"); + } + + @Test + public void getElementAsXMLString() throws IOException { + // ensure that no test object exists + Repository.INSTANCE.forceDelete(TestCapabilityTypeResource.id); + + CapabilityTypeResource res = new CapabilityTypeResource(TestCapabilityTypeResource.id); + String s = res.getDefinitionsAsXMLString(); + Assert.assertNotNull(s); + } +} diff --git a/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/TestRequirementDefinitions.java b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/TestRequirementDefinitions.java new file mode 100644 index 0000000..47ee3d0 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/java/org/eclipse/winery/repository/resources/entitytypes/nodetypes/reqandcapdefs/TestRequirementDefinitions.java @@ -0,0 +1,144 @@ +/******************************************************************************* + * Copyright (c) 2012-2013 University of Stuttgart. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and the Apache License 2.0 which both accompany this distribution, + * and are available at http://www.eclipse.org/legal/epl-v10.html + * and http://www.apache.org/licenses/LICENSE-2.0 + * + * Contributors: + * Oliver Kopp - initial API and implementation + *******************************************************************************/ +package org.eclipse.winery.repository.resources.entitytypes.nodetypes.reqandcapdefs; + +import javax.ws.rs.core.MediaType; + +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; +import org.eclipse.winery.repository.PrefsTestEnabledGitBackedRepository; +import org.eclipse.winery.repository.backend.Repository; +import org.eclipse.winery.repository.backend.filebased.GitBasedRepository; + +import com.jayway.restassured.RestAssured; +import com.jayway.restassured.http.ContentType; +import com.jayway.restassured.path.json.JsonPath; +import com.jayway.restassured.response.Response; + +//@formatter:off + +/* + * import static com.jayway.restassured.RestAssured.*; import static + * com.jayway.restassured.matcher.RestAssuredMatchers.*; import static + * org.hamcrest.Matchers.*; import static + * com.jayway.restassured.path.json.JsonPath.*; + */ + + +/** + * REST-based testing of requirement definitions + * + * We use a fixed method sort order as we create resources in one test and work + * with them in the next step + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestRequirementDefinitions { + + @BeforeClass + public static void init() throws Exception { + // enable git-backed repository + new PrefsTestEnabledGitBackedRepository(); + + // we use a half-filled repository + ((GitBasedRepository) Repository.INSTANCE).setRevisionTo("97fa997b92965d8bc84e86274b0203f1db7495c5"); + + // we test on the Amazon EC2 node type + // could be any other node type without requirement definitions + // + // the following URI is already encoded (copied from the browser URL field) + RestAssured.urlEncodingEnabled = false; + RestAssured.basePath = "/org.eclipse.winery.repository/nodetypes/http%253A%252F%252Fwww.example.org%252Ftosca%252Fnodetypes/Amazon_EC2/requirementdefinitions"; + } + + @Test + public void test01_NoRequirementDefinitions() throws Exception { + RestAssured.given() + .header("Accept", MediaType.APPLICATION_JSON) + .expect() + .body(Matchers.equalTo("[]")) + .when() + .get(""); + } + + @Test + public void test02_CreateRequirementDefinition() throws Exception { + RestAssured.given() + .parameter("name", "test") + .expect() + .statusCode(204) + .when() + .post("/"); + } + + @Test + public void test03_NoConstraints() throws Exception { + RestAssured.given() + .header("Accept", MediaType.APPLICATION_JSON) + .expect() + .body(Matchers.equalTo("[]")) + .when() + .get("test/constraints/"); + } + + @Test + public void test04_CreateConstraint() throws Exception { + RestAssured.given() + .body("") + .contentType(ContentType.XML) + .expect() + .statusCode(200) + .body(Matchers.notNullValue()) + .when() + .post("test/constraints/"); + } + + @Test + public void test05_GetConstraint() throws Exception { + Response response = RestAssured + .given() + .header("Accept", MediaType.APPLICATION_JSON) + .expect() + .statusCode(200) + .when() + .get("test/constraints/"); + + // extract answer + JsonPath jsonPath = JsonPath.from(response.asString()); + + Assert.assertEquals("One id", jsonPath.getList("").size(), 1); + + String id = jsonPath.getString("[0]"); + + // TODO: check content + RestAssured + .given() + .header("Accept", MediaType.TEXT_XML) + .expect() + .statusCode(200) + .when() + .get("test/constraints/{id}/", id); + + // we also test the sub resource here + // otherwise we had to transport the id throught the code via a global variable + RestAssured + .expect() + .statusCode(200) + .body(Matchers.is("http://www.example.org/constrainttype")) + .when() + .get("test/constraints/{id}/type", id); + } + +} diff --git a/winery/org.eclipse.winery.repository/src/test/resources/.gitignore b/winery/org.eclipse.winery.repository/src/test/resources/.gitignore new file mode 100644 index 0000000..1249577 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/resources/.gitignore @@ -0,0 +1 @@ +/winery.properties diff --git a/winery/org.eclipse.winery.repository/src/test/resources/logback-test.xml b/winery/org.eclipse.winery.repository/src/test/resources/logback-test.xml new file mode 100644 index 0000000..8633194 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/resources/logback-test.xml @@ -0,0 +1,15 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}:%line %method - %msg%n + + + + + + + + + \ No newline at end of file diff --git a/winery/org.eclipse.winery.repository/src/test/resources/servicetemplate.tosca b/winery/org.eclipse.winery.repository/src/test/resources/servicetemplate.tosca new file mode 100644 index 0000000..5fd2a72 --- /dev/null +++ b/winery/org.eclipse.winery.repository/src/test/resources/servicetemplate.tosca @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit 1.2.3-korg