diff options
Diffstat (limited to 'winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/NamespacesResource.java')
-rw-r--r-- | winery/org.eclipse.winery.repository/src/main/java/org/eclipse/winery/repository/resources/admin/NamespacesResource.java | 253 |
1 files changed, 253 insertions, 0 deletions
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<String> getAllPrefixes() { + Iterator<String> keys = this.configuration.getKeys(); + HashSet<String> res = new HashSet<String>(); + 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<String> 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<String> 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<Namespace> getRegisteredNamespaces() { + HashSet<Namespace> res = new HashSet<Namespace>(); + Iterator<String> 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<Namespace> getNamespaces() { + HashSet<Namespace> 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<Namespace> 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<Namespace> namespaces = NamespacesResource.getNamespaces(); + + // We now have all namespaces + // We need to convert from Namespace to String + + TreeSet<String> stringNamespaces = new TreeSet<String>(); + 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); + } +} |