aboutsummaryrefslogtreecommitdiffstats
path: root/winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactsResource.java
diff options
context:
space:
mode:
Diffstat (limited to 'winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactsResource.java')
-rw-r--r--winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/artifacts/GenericArtifactsResource.java572
1 files changed, 572 insertions, 0 deletions
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<ArtifactResource extends GenericArtifactResource<ArtifactT>, ArtifactT> extends EntityWithIdCollectionResource<ArtifactResource, ArtifactT> {
+
+ private static final Logger logger = LoggerFactory.getLogger(GenericArtifactsResource.class);
+
+ protected final INodeTemplateResourceOrNodeTypeImplementationResourceOrRelationshipTypeImplementationResource resWithNamespace;
+
+
+ public GenericArtifactsResource(Class<ArtifactResource> entityResourceTClazz, Class<ArtifactT> entityTClazz, List<ArtifactT> 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 <em>overridden</em>.")
+ @SuppressWarnings("unchecked")
+ public Response onPost(
+ @FormParam("artifactName")
+ @RestDocParam(description = "This is the name of the implementation/deployment artifact. " +
+ "Is <em>also</em>used 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 <em>new</em> artifact template is created having {@code <artifactNameString>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 = "<em>XML</em> 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<TInterface> interfaces = nodeType.getInterfaces().getInterface();
+ Iterator<TInterface> 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<QName> getAllArtifactTypes() {
+ SortedSet<ArtifactTypeId> allArtifactTypes = Repository.INSTANCE.getAllTOSCAComponentIds(ArtifactTypeId.class);
+ List<QName> res = new ArrayList<QName>(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<ArtifactResource> 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;
+ }
+}