1 /*******************************************************************************
2 * Copyright (c) 2012-2013 University of Stuttgart.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * and the Apache License 2.0 which both accompany this distribution,
6 * and are available at http://www.eclipse.org/legal/epl-v10.html
7 * and http://www.apache.org/licenses/LICENSE-2.0
10 * Oliver Kopp - initial API and implementation
11 *******************************************************************************/
12 package org.eclipse.winery.repository.resources.admin;
14 import java.util.Collection;
15 import java.util.HashSet;
16 import java.util.Iterator;
17 import java.util.TreeSet;
19 import javax.ws.rs.Consumes;
20 import javax.ws.rs.DELETE;
21 import javax.ws.rs.FormParam;
22 import javax.ws.rs.GET;
23 import javax.ws.rs.POST;
24 import javax.ws.rs.Path;
25 import javax.ws.rs.PathParam;
26 import javax.ws.rs.Produces;
27 import javax.ws.rs.core.MediaType;
28 import javax.ws.rs.core.Response;
29 import javax.ws.rs.core.Response.Status;
31 import org.apache.commons.lang3.StringUtils;
32 import org.eclipse.winery.common.Util;
33 import org.eclipse.winery.common.ids.Namespace;
34 import org.eclipse.winery.repository.Utils;
35 import org.eclipse.winery.repository.backend.Repository;
36 import org.eclipse.winery.repository.datatypes.ids.admin.NamespacesId;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
40 import com.fasterxml.jackson.core.JsonProcessingException;
41 import com.sun.jersey.api.view.Viewable;
44 * Manages prefixes for the namespaces
46 public class NamespacesResource extends AbstractAdminResource {
48 private static final Logger logger = LoggerFactory.getLogger(NamespacesResource.class);
50 public final static NamespacesResource INSTANCE = new NamespacesResource();
52 private Integer nsCount = 0;
55 private NamespacesResource() {
56 super(new NamespacesId());
58 // globally set prefixes
59 // if that behavior is not desired, the code has to be moved to "generatePrefix" which checks for existence, ...
60 this.configuration.setProperty("http://www.w3.org/2001/XMLSchema", "xsd");
61 this.configuration.setProperty("http://www.w3.org/XML/1998/namespace", "xmlns");
62 this.configuration.setProperty(org.eclipse.winery.common.constants.Namespaces.TOSCA_NAMESPACE, "tosca");
63 this.configuration.setProperty(org.eclipse.winery.common.constants.Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE, "winery");
66 private Collection<String> getAllPrefixes() {
67 Iterator<String> keys = this.configuration.getKeys();
68 HashSet<String> res = new HashSet<String>();
69 while (keys.hasNext()) {
70 String key = keys.next();
71 String prefix = this.configuration.getString(key);
78 @Produces(MediaType.TEXT_HTML)
79 public Response getHTML() {
80 Viewable viewable = new Viewable("/jsp/admin/namespaces.jsp", this);
81 return Response.ok().entity(viewable).build();
85 * Sets / overwrites prefix/namespace mapping
87 * In case the prefix is already bound to another namespace, BAD_REQUEST is
91 @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
92 public Response addNamespace(@FormParam("namespace") String namespace, @FormParam("nsPrefix") String prefix) {
93 if (StringUtils.isEmpty(namespace)) {
94 return Response.status(Status.BAD_REQUEST).entity("namespace must be given.").build();
96 if (StringUtils.isEmpty(prefix)) {
97 return Response.status(Status.BAD_REQUEST).entity("prefix must be given.").build();
99 namespace = Util.URLdecode(namespace);
100 prefix = Util.URLdecode(prefix);
101 Collection<String> allPrefixes = this.getAllPrefixes();
102 if (allPrefixes.contains(prefix)) {
103 if (NamespacesResource.getPrefix(namespace).equals(prefix)) {
104 return Response.notModified().build();
106 // the requested prefix is already bound to a different namespace
107 return Response.status(Status.BAD_REQUEST).entity("prefix already bound to a different namespace.").build();
110 this.configuration.setProperty(namespace, prefix);
111 return Response.noContent().build();
115 * Deletes given namespace from the repository
117 * @param URI to delete. The namespace is URLencoded.
122 public Response onDelete(@PathParam("namespace") String URI) {
124 URI = Util.URLdecode(URI);
125 if (this.configuration.containsKey(URI)) {
126 this.configuration.clearProperty(URI);
127 res = Response.noContent().build();
129 res = Response.status(Status.NOT_FOUND).build();
135 * SIDEFFECT: URI is added to list of known namespaces if it did not exist
138 public static String getPrefix(Namespace namespace) {
139 String ns = namespace.getDecoded();
140 return NamespacesResource.getPrefix(ns);
145 @Produces(MediaType.TEXT_PLAIN)
146 public String getPrefixForEncodedNamespace(@PathParam("namespace") String URI) {
147 URI = Util.URLdecode(URI);
148 return NamespacesResource.getPrefix(URI);
152 * SIDEFFECT: URI is added to list of known namespaces if it did not exist
155 public static String getPrefix(String namespace) {
156 if (namespace == null) {
157 throw new IllegalArgumentException("Namespace must not be null");
159 String prefix = NamespacesResource.INSTANCE.configuration.getString(namespace);
160 if (prefix == null) {
161 prefix = NamespacesResource.generatePrefix(namespace);
162 NamespacesResource.INSTANCE.configuration.setProperty(namespace, prefix);
167 private static String generatePrefix(String namespace) {
168 String prefix = null;
169 Collection<String> allPrefixes = NamespacesResource.INSTANCE.getAllPrefixes();
171 // TODO: generate prefix using URI (and not "arbitrary" prefix)
173 prefix = String.format("ns%d", NamespacesResource.INSTANCE.nsCount);
174 NamespacesResource.INSTANCE.nsCount++;
175 } while (allPrefixes.contains(prefix));
180 * Returns the list of all namespaces registered with his manager. It could
181 * be incomplete, if entries have been added manually to the repository
183 * @return all namespaces registered with this manager.
185 private HashSet<Namespace> getRegisteredNamespaces() {
186 HashSet<Namespace> res = new HashSet<Namespace>();
187 Iterator<String> keys = this.configuration.getKeys();
188 while (keys.hasNext()) {
189 String key = keys.next();
190 Namespace ns = new Namespace(key, false);
197 * Returns the list of all namespaces registered with his manager and used
198 * at component instances.
200 public static Collection<Namespace> getNamespaces() {
201 HashSet<Namespace> res = NamespacesResource.INSTANCE.getRegisteredNamespaces();
202 res.addAll(Repository.INSTANCE.getUsedNamespaces());
207 * This method is required because static methods cannot be accessed by EL
209 * @return see getNamespaces()
211 public Collection<Namespace> getNamespacesForJSP() {
212 return NamespacesResource.getNamespaces();
216 * Returns the list of all namespaces registered with his manager and used
217 * at component instances.
219 * @return a JSON list containing the non-encoded URIs of each known
223 @Produces(MediaType.APPLICATION_JSON)
224 public String getNamespacesAsJSONlist() {
225 Collection<Namespace> namespaces = NamespacesResource.getNamespaces();
227 // We now have all namespaces
228 // We need to convert from Namespace to String
230 TreeSet<String> stringNamespaces = new TreeSet<String>();
231 for (Namespace ns : namespaces) {
232 stringNamespaces.add(ns.getDecoded());
237 res = Utils.mapper.writeValueAsString(stringNamespaces);
238 } catch (JsonProcessingException e) {
239 NamespacesResource.logger.error(e.getMessage(), e);
246 * Checks whether a prefix is registered for a namespace
248 * Used at CSARImporter
250 public boolean getIsPrefixKnownForNamespace(String namespace) {
251 return this.configuration.containsKey(namespace);