Author: rgodfrey Date: Tue Apr 24 08:57:57 2012 New Revision: 1329597 URL: http://svn.apache.org/viewvc?rev=1329597&view=rev Log: NO-JIRA : [Java Config] tidy up REST servlets
Added: qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java Removed: qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingServlet.java qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionServlet.java qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ConsumerServlet.java qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeServlet.java qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/PortServlet.java qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueServlet.java qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SessionServlet.java qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostServlet.java Modified: qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/Management.java qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java Modified: qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/Management.java URL: http://svn.apache.org/viewvc/qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/Management.java?rev=1329597&r1=1329596&r2=1329597&view=diff ============================================================================== --- qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/Management.java (original) +++ qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/Management.java Tue Apr 24 08:57:57 2012 @@ -25,15 +25,17 @@ import org.apache.qpid.server.management import org.apache.qpid.server.management.plugin.servlet.FileServlet; import org.apache.qpid.server.management.plugin.servlet.api.ExchangesServlet; import org.apache.qpid.server.management.plugin.servlet.api.VhostsServlet; -import org.apache.qpid.server.management.plugin.servlet.rest.BindingServlet; -import org.apache.qpid.server.management.plugin.servlet.rest.ConnectionServlet; -import org.apache.qpid.server.management.plugin.servlet.rest.ExchangeServlet; -import org.apache.qpid.server.management.plugin.servlet.rest.PortServlet; -import org.apache.qpid.server.management.plugin.servlet.rest.QueueServlet; +import org.apache.qpid.server.management.plugin.servlet.rest.RestServlet; import org.apache.qpid.server.management.plugin.servlet.rest.SaslServlet; -import org.apache.qpid.server.management.plugin.servlet.rest.SessionServlet; -import org.apache.qpid.server.management.plugin.servlet.rest.VirtualHostServlet; +import org.apache.qpid.server.model.Binding; import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Connection; +import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.Session; +import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.registry.ApplicationRegistry; import org.mortbay.jetty.Server; import org.mortbay.jetty.SessionManager; @@ -48,6 +50,7 @@ public class Management private Broker _broker; private Server _server; + private Context _root; public Management() { @@ -57,42 +60,47 @@ public class Management _server = new Server(8080); - Context root = new Context(_server,"/", Context.SESSIONS); - root.addServlet(new ServletHolder(new VhostsServlet(_broker)), "/api/vhosts/*"); - root.addServlet(new ServletHolder(new ExchangesServlet(_broker)), "/api/exchanges/*"); - - root.addServlet(new ServletHolder(new VirtualHostServlet(_broker)), "/rest/virtualhost/*"); - root.addServlet(new ServletHolder(new ExchangeServlet(_broker)), "/rest/exchange/*"); - root.addServlet(new ServletHolder(new QueueServlet(_broker)), "/rest/queue/*"); - root.addServlet(new ServletHolder(new ConnectionServlet(_broker)), "/rest/connection/*"); - root.addServlet(new ServletHolder(new BindingServlet(_broker)), "/rest/binding/*"); - root.addServlet(new ServletHolder(new PortServlet(_broker)), "/rest/port/*"); - root.addServlet(new ServletHolder(new SessionServlet(_broker)), "/rest/session/*"); - - root.addServlet(new ServletHolder(new SaslServlet(_broker)), "/rest/sasl"); - - root.addServlet(new ServletHolder(new DefinedFileServlet("queue.html")),"/queue"); - root.addServlet(new ServletHolder(new DefinedFileServlet("exchange.html")),"/exchange"); - root.addServlet(new ServletHolder(new DefinedFileServlet("vhost.html")),"/vhost"); - root.addServlet(new ServletHolder(new DefinedFileServlet("broker.html")),"/broker"); - root.addServlet(new ServletHolder(new DefinedFileServlet("connection.html")),"/connection"); - - - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.js"); - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.css"); - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.html"); - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.png"); - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.gif"); - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.jpg"); - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.jpeg"); - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.json"); + _root = new Context(_server,"/", Context.SESSIONS); + _root.addServlet(new ServletHolder(new VhostsServlet(_broker)), "/api/vhosts/*"); + _root.addServlet(new ServletHolder(new ExchangesServlet(_broker)), "/api/exchanges/*"); + + addRestServlet("virtualhost", VirtualHost.class); + addRestServlet("exchange", VirtualHost.class, Exchange.class); + addRestServlet("queue", VirtualHost.class, Queue.class); + addRestServlet("connection", VirtualHost.class, Connection.class); + addRestServlet("binding", VirtualHost.class, Exchange.class, Queue.class, Binding.class); + addRestServlet("port", Port.class); + addRestServlet("session", VirtualHost.class, Connection.class, Session.class); + + _root.addServlet(new ServletHolder(new SaslServlet(_broker)), "/rest/sasl"); + + _root.addServlet(new ServletHolder(new DefinedFileServlet("queue.html")),"/queue"); + _root.addServlet(new ServletHolder(new DefinedFileServlet("exchange.html")),"/exchange"); + _root.addServlet(new ServletHolder(new DefinedFileServlet("vhost.html")),"/vhost"); + _root.addServlet(new ServletHolder(new DefinedFileServlet("broker.html")),"/broker"); + _root.addServlet(new ServletHolder(new DefinedFileServlet("connection.html")),"/connection"); + + + _root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.js"); + _root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.css"); + _root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.html"); + _root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.png"); + _root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.gif"); + _root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.jpg"); + _root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.jpeg"); + _root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.json"); - final SessionManager sessionManager = root.getSessionHandler().getSessionManager(); + final SessionManager sessionManager = _root.getSessionHandler().getSessionManager(); sessionManager.setMaxCookieAge(60 * 30); sessionManager.setMaxInactiveInterval(60 * 15); } + private void addRestServlet(String name, Class<? extends ConfiguredObject>... hierarchy) + { + _root.addServlet(new ServletHolder(new RestServlet(_broker, hierarchy)), "/rest/"+name+"/*"); + } + public void start() throws Exception { _server.start(); Modified: qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java URL: http://svn.apache.org/viewvc/qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java?rev=1329597&r1=1329596&r2=1329597&view=diff ============================================================================== --- qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java (original) +++ qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java Tue Apr 24 08:57:57 2012 @@ -22,6 +22,9 @@ package org.apache.qpid.server.managemen import java.io.IOException; import java.io.InputStream; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; @@ -31,6 +34,22 @@ import javax.servlet.http.HttpServletRes public class FileServlet extends HttpServlet { public static final FileServlet INSTANCE = new FileServlet(); + + private static final Map<String, String> CONTENT_TYPES; + + static + { + + Map<String, String> contentTypes = new HashMap<String, String>(); + contentTypes.put("js", "application/javascript"); + contentTypes.put("html", "text/html"); + contentTypes.put("css", "text/css"); + contentTypes.put("json", "application/json"); + contentTypes.put("jpg", "image/jpg"); + contentTypes.put("png", "image/png"); + contentTypes.put("gif", "image/gif"); + CONTENT_TYPES = Collections.unmodifiableMap(contentTypes); + } public FileServlet() @@ -41,21 +60,14 @@ public class FileServlet extends HttpSer { String filename = request.getServletPath(); - if(filename.endsWith(".js")) + if(filename.contains(".")) { - response.setContentType("application/javascript"); - } - else if(filename.endsWith(".html")) - { - response.setContentType("text/html"); - } - else if(filename.endsWith(".css")) - { - response.setContentType("text/css"); - } - else if(filename.endsWith(".json")) - { - response.setContentType("application/json"); + String suffix = filename.substring(filename.lastIndexOf('.')+1); + String contentType = CONTENT_TYPES.get(suffix); + if(contentType != null) + { + response.setContentType(contentType); + } } final ServletOutputStream output = response.getOutputStream(); Modified: qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java URL: http://svn.apache.org/viewvc/qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java?rev=1329597&r1=1329596&r2=1329597&view=diff ============================================================================== --- qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java (original) +++ qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java Tue Apr 24 08:57:57 2012 @@ -21,46 +21,29 @@ package org.apache.qpid.server.management.plugin.servlet.rest; -import org.apache.commons.codec.binary.Base64; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.Model; -import org.apache.qpid.server.model.Statistics; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.auth.AuthenticationResult; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.map.SerializationConfig; - +import java.io.IOException; +import java.security.Principal; +import java.util.Collections; import javax.security.auth.Subject; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import java.io.IOException; -import java.io.PrintWriter; -import java.security.Principal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import org.apache.commons.codec.binary.Base64; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.manager.AuthenticationManager; public abstract class AbstractServlet extends HttpServlet { private Subject _subject; private final Broker _broker; - private Class<? extends ConfiguredObject>[] _hierarchy; - protected AbstractServlet(Broker broker, Class<? extends ConfiguredObject>... hierarchy) + protected AbstractServlet(Broker broker) { _broker = broker; - _hierarchy = hierarchy; } @Override @@ -77,6 +60,11 @@ public abstract class AbstractServlet ex } } + protected void onGet(HttpServletRequest request, HttpServletResponse resp) throws IOException, ServletException + { + super.doGet(request, resp); + } + private void clearAuthorizedSubject() { _subject = null; @@ -167,6 +155,11 @@ public abstract class AbstractServlet ex } } + protected void onPut(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException + { + super.doPut(req,resp); + } + @Override protected final void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException @@ -193,332 +186,5 @@ public abstract class AbstractServlet ex return _broker; } - protected Collection<ConfiguredObject> getObjects(HttpServletRequest request) - { - List<String> names = new ArrayList<String>(); - if(request.getPathInfo() != null && request.getPathInfo().length()>0) - { - String path = request.getPathInfo().substring(1); - names.addAll(Arrays.asList(path.split("/"))); - - if(names.size() > _hierarchy.length) - { - throw new IllegalArgumentException("Too many entries in path"); - } - } - - Collection<ConfiguredObject> parents = Collections.singleton((ConfiguredObject) _broker); - Collection<ConfiguredObject> children = new ArrayList<ConfiguredObject>(); - - Map<Class<? extends ConfiguredObject>, String> filters = - new HashMap<Class<? extends ConfiguredObject>, String>(); - - for(int i = 0; i < _hierarchy.length; i++) - { - if(i == 0 || Model.getChildTypes(_hierarchy[i-1]).contains(_hierarchy[i])) - { - - for(ConfiguredObject parent : parents) - { - if(names.size() > i - && names.get(i) != null - && !names.get(i).equals("*") - && names.get(i).trim().length() != 0) - { - for(ConfiguredObject child : parent.getChildren(_hierarchy[i])) - { - if(child.getName().equals(names.get(i))) - { - children.add(child); - } - } - } - else - { - children.addAll(parent.getChildren(_hierarchy[i])); - } - } - } - else - { - children = parents; - if(names.size() > i - && names.get(i) != null - && !names.get(i).equals("*") - && names.get(i).trim().length() != 0) - { - filters.put(_hierarchy[i], names.get(i)); - } - } - - parents = children; - children = new ArrayList<ConfiguredObject>(); - } - - if(!filters.isEmpty()) - { - Collection<ConfiguredObject> potentials = parents; - parents = new ArrayList<ConfiguredObject>(); - - for(ConfiguredObject o : potentials) - { - - boolean match = true; - - for(Map.Entry<Class<? extends ConfiguredObject>, String> entry : filters.entrySet()) - { - Collection<? extends ConfiguredObject> ancestors = - getAncestors(_hierarchy[_hierarchy.length-1],entry.getKey(), o); - match = false; - for(ConfiguredObject ancestor : ancestors) - { - if(ancestor.getName().equals(entry.getValue())) - { - match = true; - break; - } - } - if(!match) - { - break; - } - } - if(match) - { - parents.add(o); - } - - } - } - - return parents; - } - - private Collection<? extends ConfiguredObject> getAncestors(Class<? extends ConfiguredObject> childType, - Class<? extends ConfiguredObject> ancestorType, - ConfiguredObject child) - { - Collection<ConfiguredObject> ancestors = new HashSet<ConfiguredObject>(); - Collection<Class<? extends ConfiguredObject>> parentTypes = Model.getParentTypes(childType); - - for(Class<? extends ConfiguredObject> parentClazz : parentTypes) - { - if(parentClazz == ancestorType) - { - ConfiguredObject parent = child.getParent(parentClazz); - if(parent != null) - { - ancestors.add(parent); - } - } - else - { - ConfiguredObject parent = child.getParent(parentClazz); - if(parent != null) - { - ancestors.addAll(getAncestors(parentClazz, ancestorType, parent)); - } - } - } - - return ancestors; - } - - - protected Map<String, Object> convertObjectToMap(final ConfiguredObject confObject, - Class<? extends ConfiguredObject> clazz, - int depth) - { - Map<String, Object> object = new LinkedHashMap<String, Object>(); - - for(String name : confObject.getAttributeNames()) - { - Object value = confObject.getAttribute(name); - if(value != null) - { - object.put(name, value); - } - } - - Statistics statistics = confObject.getStatistics(); - Map<String, Object> statMap = new HashMap<String, Object>(); - for(String name : statistics.getStatisticNames()) - { - Object value = statistics.getStatistic(name); - if(value != null) - { - statMap.put(name, value); - } - } - - if(!statMap.isEmpty()) - { - object.put("statistics", statMap); - } - - if(depth > 0) - { - for(Class<? extends ConfiguredObject> childClass : Model.getChildTypes(clazz)) - { - Collection<? extends ConfiguredObject> children = confObject.getChildren(childClass); - if(children != null) - { - List<Map<String, Object>> childObjects = new ArrayList<Map<String, Object>>(); - - for(ConfiguredObject child : children) - { - childObjects.add(convertObjectToMap(child, childClass, depth-1)); - } - - if(!childObjects.isEmpty()) - { - object.put(childClass.getSimpleName().toLowerCase()+"s",childObjects); - } - } - } - } - return object; - } - - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException - { - response.setContentType("application/json"); - response.setStatus(HttpServletResponse.SC_OK); - - response.setHeader("Cache-Control","no-cache"); - response.setHeader("Pragma","no-cache"); - response.setDateHeader ("Expires", 0); - - Collection<ConfiguredObject> allObjects = getObjects(request); - - @SuppressWarnings("unchecked") - Map params = new HashMap(request.getParameterMap()); - - int depth = 1; - try - { - depth = Integer.parseInt(String.valueOf(params.remove("depth"))); - } - catch (NumberFormatException e) - { - // Ignore - } - - List<Map<String, Object>> output = new ArrayList<Map<String, Object>>(); - - if(!params.isEmpty()) - { - // TODO - depth and sort special params, everything else should act as a filter - } - - for(ConfiguredObject configuredObject : allObjects) - { - output.add(convertObjectToMap(configuredObject, _hierarchy[_hierarchy.length-1],depth)); - } - - final PrintWriter writer = response.getWriter(); - ObjectMapper mapper = new ObjectMapper(); - mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); - mapper.writeValue(writer, output); - - response.setContentType("application/json"); - response.setStatus(HttpServletResponse.SC_OK); - - } - - protected void onPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException - { - response.setContentType("application/json"); - - ObjectMapper mapper = new ObjectMapper(); - - @SuppressWarnings("unchecked") - Map<String,Object> providedObject = mapper.readValue(request.getInputStream(), LinkedHashMap.class); - - - List<String> names = new ArrayList<String>(); - if(request.getPathInfo() != null && request.getPathInfo().length()>0) - { - String path = request.getPathInfo().substring(1); - names.addAll(Arrays.asList(path.split("/"))); - - if(names.size() != _hierarchy.length) - { - throw new IllegalArgumentException("Path to object to create must be fully specified"); - } - } - - - providedObject.put("name", names.get(names.size()-1)); - - @SuppressWarnings("unchecked") - Collection<ConfiguredObject>[] objects = new Collection[_hierarchy.length]; - if(_hierarchy.length == 1) - { - _broker.createChild(_hierarchy[0], providedObject); - } - else - { - for(int i = 0; i < _hierarchy.length-1; i++) - { - objects[i] = new HashSet<ConfiguredObject>(); - if(i == 0) - { - for(ConfiguredObject object : _broker.getChildren(_hierarchy[0])) - { - if(object.getName().equals(names.get(0))) - { - objects[0].add(object); - break; - } - } - } - else - { - for(int j = i-1; j >=0; j--) - { - if(Model.getChildTypes(_hierarchy[j]).contains(_hierarchy[i])) - { - for(ConfiguredObject parent : objects[j]) - { - for(ConfiguredObject object : parent.getChildren(_hierarchy[i])) - { - if(object.getName().equals(names.get(i))) - { - objects[i].add(object); - } - } - } - break; - } - } - } - - } - List<ConfiguredObject> parents = new ArrayList<ConfiguredObject>(); - Class<? extends ConfiguredObject> objClass = _hierarchy[_hierarchy.length - 1]; - Collection<Class<? extends ConfiguredObject>> parentClasses = Model.getParentTypes(objClass); - for(int i = _hierarchy.length-2; i >=0 ; i--) - { - if(parentClasses.contains(_hierarchy[i])) - { - if(objects[i].size() == 1) - { - parents.add(objects[i].iterator().next()); - } - else - { - throw new IllegalArgumentException("Cannot deduce parent of class " - + _hierarchy[i].getSimpleName()); - } - } - - } - ConfiguredObject theParent = parents.remove(0); - ConfiguredObject[] otherParents = parents.toArray(new ConfiguredObject[parents.size()]); - - theParent.createChild(objClass, providedObject, otherParents); - } - } } Added: qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java URL: http://svn.apache.org/viewvc/qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java?rev=1329597&view=auto ============================================================================== --- qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java (added) +++ qpid/branches/java-config-and-management/qpid/java/broker-plugins/management/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java Tue Apr 24 08:57:57 2012 @@ -0,0 +1,380 @@ +package org.apache.qpid.server.management.plugin.servlet.rest; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Model; +import org.apache.qpid.server.model.Statistics; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; + +/** + * 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 + * <p/> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p/> + * 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. + */ +public class RestServlet extends AbstractServlet +{ + private Class<? extends ConfiguredObject>[] _hierarchy; + + public RestServlet(Broker broker, Class<? extends ConfiguredObject>... hierarchy) + { + super(broker); + _hierarchy = hierarchy; + } + + protected Collection<ConfiguredObject> getObjects(HttpServletRequest request) + { + List<String> names = new ArrayList<String>(); + if(request.getPathInfo() != null && request.getPathInfo().length()>0) + { + String path = request.getPathInfo().substring(1); + names.addAll(Arrays.asList(path.split("/"))); + + if(names.size() > _hierarchy.length) + { + throw new IllegalArgumentException("Too many entries in path"); + } + } + + Collection<ConfiguredObject> parents = Collections.singleton((ConfiguredObject) getBroker()); + Collection<ConfiguredObject> children = new ArrayList<ConfiguredObject>(); + + Map<Class<? extends ConfiguredObject>, String> filters = + new HashMap<Class<? extends ConfiguredObject>, String>(); + + for(int i = 0; i < _hierarchy.length; i++) + { + if(i == 0 || Model.getChildTypes(_hierarchy[i - 1]).contains(_hierarchy[i])) + { + + for(ConfiguredObject parent : parents) + { + if(names.size() > i + && names.get(i) != null + && !names.get(i).equals("*") + && names.get(i).trim().length() != 0) + { + for(ConfiguredObject child : parent.getChildren(_hierarchy[i])) + { + if(child.getName().equals(names.get(i))) + { + children.add(child); + } + } + } + else + { + children.addAll(parent.getChildren(_hierarchy[i])); + } + } + } + else + { + children = parents; + if(names.size() > i + && names.get(i) != null + && !names.get(i).equals("*") + && names.get(i).trim().length() != 0) + { + filters.put(_hierarchy[i], names.get(i)); + } + } + + parents = children; + children = new ArrayList<ConfiguredObject>(); + } + + if(!filters.isEmpty()) + { + Collection<ConfiguredObject> potentials = parents; + parents = new ArrayList<ConfiguredObject>(); + + for(ConfiguredObject o : potentials) + { + + boolean match = true; + + for(Map.Entry<Class<? extends ConfiguredObject>, String> entry : filters.entrySet()) + { + Collection<? extends ConfiguredObject> ancestors = + getAncestors(_hierarchy[_hierarchy.length-1],entry.getKey(), o); + match = false; + for(ConfiguredObject ancestor : ancestors) + { + if(ancestor.getName().equals(entry.getValue())) + { + match = true; + break; + } + } + if(!match) + { + break; + } + } + if(match) + { + parents.add(o); + } + + } + } + + return parents; + } + + private Collection<? extends ConfiguredObject> getAncestors(Class<? extends ConfiguredObject> childType, + Class<? extends ConfiguredObject> ancestorType, + ConfiguredObject child) + { + Collection<ConfiguredObject> ancestors = new HashSet<ConfiguredObject>(); + Collection<Class<? extends ConfiguredObject>> parentTypes = Model.getParentTypes(childType); + + for(Class<? extends ConfiguredObject> parentClazz : parentTypes) + { + if(parentClazz == ancestorType) + { + ConfiguredObject parent = child.getParent(parentClazz); + if(parent != null) + { + ancestors.add(parent); + } + } + else + { + ConfiguredObject parent = child.getParent(parentClazz); + if(parent != null) + { + ancestors.addAll(getAncestors(parentClazz, ancestorType, parent)); + } + } + } + + return ancestors; + } + + + protected Map<String, Object> convertObjectToMap(final ConfiguredObject confObject, + Class<? extends ConfiguredObject> clazz, + int depth) + { + Map<String, Object> object = new LinkedHashMap<String, Object>(); + + for(String name : confObject.getAttributeNames()) + { + Object value = confObject.getAttribute(name); + if(value != null) + { + object.put(name, value); + } + } + + Statistics statistics = confObject.getStatistics(); + Map<String, Object> statMap = new HashMap<String, Object>(); + for(String name : statistics.getStatisticNames()) + { + Object value = statistics.getStatistic(name); + if(value != null) + { + statMap.put(name, value); + } + } + + if(!statMap.isEmpty()) + { + object.put("statistics", statMap); + } + + if(depth > 0) + { + for(Class<? extends ConfiguredObject> childClass : Model.getChildTypes(clazz)) + { + Collection<? extends ConfiguredObject> children = confObject.getChildren(childClass); + if(children != null) + { + List<Map<String, Object>> childObjects = new ArrayList<Map<String, Object>>(); + + for(ConfiguredObject child : children) + { + childObjects.add(convertObjectToMap(child, childClass, depth-1)); + } + + if(!childObjects.isEmpty()) + { + object.put(childClass.getSimpleName().toLowerCase()+"s",childObjects); + } + } + } + } + return object; + } + + @Override + protected void onGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + response.setContentType("application/json"); + response.setStatus(HttpServletResponse.SC_OK); + + response.setHeader("Cache-Control","no-cache"); + response.setHeader("Pragma","no-cache"); + response.setDateHeader ("Expires", 0); + + Collection<ConfiguredObject> allObjects = getObjects(request); + + @SuppressWarnings("unchecked") + Map params = new HashMap(request.getParameterMap()); + + int depth = 1; + try + { + depth = Integer.parseInt(String.valueOf(params.remove("depth"))); + } + catch (NumberFormatException e) + { + // Ignore + } + + List<Map<String, Object>> output = new ArrayList<Map<String, Object>>(); + + if(!params.isEmpty()) + { + // TODO - depth and sort special params, everything else should act as a filter + } + + for(ConfiguredObject configuredObject : allObjects) + { + output.add(convertObjectToMap(configuredObject, _hierarchy[_hierarchy.length-1],depth)); + } + + final PrintWriter writer = response.getWriter(); + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); + mapper.writeValue(writer, output); + + response.setContentType("application/json"); + response.setStatus(HttpServletResponse.SC_OK); + + } + + @Override + protected void onPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + response.setContentType("application/json"); + + ObjectMapper mapper = new ObjectMapper(); + + @SuppressWarnings("unchecked") + Map<String,Object> providedObject = mapper.readValue(request.getInputStream(), LinkedHashMap.class); + + + List<String> names = new ArrayList<String>(); + if(request.getPathInfo() != null && request.getPathInfo().length()>0) + { + String path = request.getPathInfo().substring(1); + names.addAll(Arrays.asList(path.split("/"))); + + if(names.size() != _hierarchy.length) + { + throw new IllegalArgumentException("Path to object to create must be fully specified"); + } + } + + + providedObject.put("name", names.get(names.size()-1)); + + @SuppressWarnings("unchecked") + Collection<ConfiguredObject>[] objects = new Collection[_hierarchy.length]; + if(_hierarchy.length == 1) + { + getBroker().createChild(_hierarchy[0], providedObject); + } + else + { + for(int i = 0; i < _hierarchy.length-1; i++) + { + objects[i] = new HashSet<ConfiguredObject>(); + if(i == 0) + { + for(ConfiguredObject object : getBroker().getChildren(_hierarchy[0])) + { + if(object.getName().equals(names.get(0))) + { + objects[0].add(object); + break; + } + } + } + else + { + for(int j = i-1; j >=0; j--) + { + if(Model.getChildTypes(_hierarchy[j]).contains(_hierarchy[i])) + { + for(ConfiguredObject parent : objects[j]) + { + for(ConfiguredObject object : parent.getChildren(_hierarchy[i])) + { + if(object.getName().equals(names.get(i))) + { + objects[i].add(object); + } + } + } + break; + } + } + } + + } + List<ConfiguredObject> parents = new ArrayList<ConfiguredObject>(); + Class<? extends ConfiguredObject> objClass = _hierarchy[_hierarchy.length - 1]; + Collection<Class<? extends ConfiguredObject>> parentClasses = Model.getParentTypes(objClass); + for(int i = _hierarchy.length-2; i >=0 ; i--) + { + if(parentClasses.contains(_hierarchy[i])) + { + if(objects[i].size() == 1) + { + parents.add(objects[i].iterator().next()); + } + else + { + throw new IllegalArgumentException("Cannot deduce parent of class " + + _hierarchy[i].getSimpleName()); + } + } + + } + ConfiguredObject theParent = parents.remove(0); + ConfiguredObject[] otherParents = parents.toArray(new ConfiguredObject[parents.size()]); + + theParent.createChild(objClass, providedObject, otherParents); + } + } + +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org