Return-Path: X-Original-To: apmail-qpid-commits-archive@www.apache.org Delivered-To: apmail-qpid-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 76FCE175FB for ; Mon, 16 Mar 2015 01:31:56 +0000 (UTC) Received: (qmail 978 invoked by uid 500); 16 Mar 2015 01:31:56 -0000 Delivered-To: apmail-qpid-commits-archive@qpid.apache.org Received: (qmail 944 invoked by uid 500); 16 Mar 2015 01:31:56 -0000 Mailing-List: contact commits-help@qpid.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@qpid.apache.org Delivered-To: mailing list commits@qpid.apache.org Received: (qmail 935 invoked by uid 99); 16 Mar 2015 01:31:56 -0000 Received: from eris.apache.org (HELO hades.apache.org) (140.211.11.105) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 16 Mar 2015 01:31:56 +0000 Received: from hades.apache.org (localhost [127.0.0.1]) by hades.apache.org (ASF Mail Server at hades.apache.org) with ESMTP id CA9A6AC0397 for ; Mon, 16 Mar 2015 01:31:55 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1666850 - in /qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java: org/apache/qpid/server/management/plugin/ org/apache/qpid/server/management/plugin/servlet/rest/ resources/css/ Date: Mon, 16 Mar 2015 01:31:55 -0000 To: commits@qpid.apache.org From: rgodfrey@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20150316013155.CA9A6AC0397@hades.apache.org> Author: rgodfrey Date: Mon Mar 16 01:31:54 2015 New Revision: 1666850 URL: http://svn.apache.org/r1666850 Log: QPID-6454 : [Java Broker] Provide mechanism to view REST API interface definition Added: qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ApiDocsServlet.java - copied, changed from r1666814, qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/resources/css/apidocs.css (with props) Modified: qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MetaDataServlet.java Modified: qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java?rev=1666850&r1=1666849&r2=1666850&view=diff ============================================================================== --- qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java (original) +++ qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java Mon Mar 16 01:31:54 2015 @@ -64,6 +64,7 @@ import org.apache.qpid.server.management import org.apache.qpid.server.management.plugin.servlet.DefinedFileServlet; import org.apache.qpid.server.management.plugin.servlet.FileServlet; import org.apache.qpid.server.management.plugin.servlet.LogFileServlet; +import org.apache.qpid.server.management.plugin.servlet.rest.ApiDocsServlet; import org.apache.qpid.server.management.plugin.servlet.rest.HelperServlet; import org.apache.qpid.server.management.plugin.servlet.rest.LogFileListingServlet; import org.apache.qpid.server.management.plugin.servlet.rest.LogRecordsServlet; @@ -278,6 +279,7 @@ public class HttpManagement extends Abst FilterHolder restAuthorizationFilter = new FilterHolder(new ForbiddingAuthorisationFilter()); restAuthorizationFilter.setInitParameter(ForbiddingAuthorisationFilter.INIT_PARAM_ALLOWED, "/service/sasl"); root.addFilter(restAuthorizationFilter, "/api/*", EnumSet.of(DispatcherType.REQUEST)); + root.addFilter(restAuthorizationFilter, "/apidocs/*", EnumSet.of(DispatcherType.REQUEST)); root.addFilter(restAuthorizationFilter, "/service/*", EnumSet.of(DispatcherType.REQUEST)); root.addFilter(new FilterHolder(new RedirectingAuthorisationFilter()), HttpManagementUtil.ENTRY_POINT_PATH, EnumSet.of(DispatcherType.REQUEST)); root.addFilter(new FilterHolder(new RedirectingAuthorisationFilter()), "/index.html", EnumSet.of(DispatcherType.REQUEST)); @@ -316,7 +318,7 @@ public class HttpManagement extends Abst root.addServlet(new ServletHolder(new LogRecordsServlet()), "/service/logrecords"); - root.addServlet(new ServletHolder(new MetaDataServlet()), "/service/metadata"); + root.addServlet(new ServletHolder(new MetaDataServlet(getModel())), "/service/metadata"); root.addServlet(new ServletHolder(new SaslServlet()), "/service/sasl"); @@ -454,6 +456,13 @@ public class HttpManagement extends Abst getContextValue(Integer.class, MAX_HTTP_FILE_UPLOAD_SIZE_CONTEXT_NAME))); root.addServlet(servletHolder, "/api/latest/" + name + "/*"); root.addServlet(servletHolder, "/api/v" + BrokerModel.MODEL_MAJOR_VERSION + "/" + name + "/*"); + ServletHolder docServletHolder = new ServletHolder(name+"docs", new ApiDocsServlet(getModel(),hierarchy)); + root.addServlet(docServletHolder, "/apidocs/latest/" + name + "/"); + root.addServlet(docServletHolder, "/apidocs/v" + BrokerModel.MODEL_MAJOR_VERSION + "/" + name +"/"); + root.addServlet(docServletHolder, "/apidocs/latest/" + name ); + root.addServlet(docServletHolder, "/apidocs/v" + BrokerModel.MODEL_MAJOR_VERSION + "/" + name); + + } private void logOperationalListenMessages(Collection> ports) Copied: qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ApiDocsServlet.java (from r1666814, qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java) URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ApiDocsServlet.java?p2=qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ApiDocsServlet.java&p1=qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java&r1=1666814&r2=1666850&rev=1666850&view=diff ============================================================================== --- qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java (original) +++ qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ApiDocsServlet.java Mon Mar 16 01:31:54 2015 @@ -17,12 +17,14 @@ package org.apache.qpid.server.management.plugin.servlet.rest; import java.io.IOException; +import java.io.PrintWriter; import java.io.Writer; import java.security.AccessControlException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -30,6 +32,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.UUID; import javax.servlet.ServletConfig; import javax.servlet.ServletException; @@ -37,29 +40,28 @@ import javax.servlet.http.HttpServletReq import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; -import org.apache.qpid.server.model.AbstractConfiguredObject; -import org.apache.qpid.server.model.IllegalStateTransitionException; -import org.apache.qpid.server.model.IntegrityViolationException; -import org.apache.qpid.server.virtualhost.ExchangeExistsException; -import org.apache.qpid.server.virtualhost.QueueExistsException; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializationConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.AbstractConfiguredObject; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.ConfiguredObjectAttribute; +import org.apache.qpid.server.model.IllegalStateTransitionException; +import org.apache.qpid.server.model.IntegrityViolationException; +import org.apache.qpid.server.model.ManagedObject; +import org.apache.qpid.server.model.Model; import org.apache.qpid.server.util.urlstreamhandler.data.Handler; +import org.apache.qpid.server.virtualhost.ExchangeExistsException; +import org.apache.qpid.server.virtualhost.QueueExistsException; import org.apache.qpid.util.DataUrlUtils; -public class RestServlet extends AbstractServlet +public class ApiDocsServlet extends AbstractServlet { - private static final Logger LOGGER = LoggerFactory.getLogger(RestServlet.class); - /** - * An initialization parameter to specify hierarchy - */ - private static final String HIERARCHY_INIT_PARAMETER = "hierarchy"; + private static final Logger LOGGER = LoggerFactory.getLogger(ApiDocsServlet.class); public static final String DEPTH_PARAM = "depth"; public static final String OVERSIZE_PARAM = "oversize"; @@ -85,663 +87,245 @@ public class RestServlet extends Abstrac EXTRACT_INITIAL_CONFIG_PARAM, INHERITED_ACTUALS_PARAM, CONTENT_DISPOSITION_ATTACHMENT_FILENAME_PARAM)); + private final Model _model; + private final Collection> _types; private Class[] _hierarchy; - private final ConfiguredObjectToMapConverter _objectConverter = new ConfiguredObjectToMapConverter(); - private final boolean _hierarchyInitializationRequired; + private static final Set VOWELS = new HashSet<>(Arrays.asList('a','e','i','o','u')); - public RestServlet() - { - super(); - _hierarchyInitializationRequired = true; - } - public RestServlet(Class... hierarchy) + public ApiDocsServlet(final Model model, Class... hierarchy) { super(); + _model = model; _hierarchy = hierarchy; - _hierarchyInitializationRequired = false; - } + _types = _model.getTypeRegistry().getTypeSpecialisations(getConfiguredClass()); - @Override - public void init() throws ServletException - { - super.init(); - if (_hierarchyInitializationRequired) - { - doInitialization(); - } - Handler.register(); } - @SuppressWarnings("unchecked") - private void doInitialization() throws ServletException - { - ServletConfig config = getServletConfig(); - String hierarchy = config.getInitParameter(HIERARCHY_INIT_PARAMETER); - if (hierarchy != null && !"".equals(hierarchy)) - { - List> classes = new ArrayList>(); - String[] hierarchyItems = hierarchy.split(","); - for (String item : hierarchyItems) - { - Class itemClass = null; - try - { - itemClass = Class.forName(item); - } - catch (ClassNotFoundException e) - { - try - { - itemClass = Class.forName("org.apache.qpid.server.model." + item); - } - catch (ClassNotFoundException e1) - { - throw new ServletException("Unknown configured object class '" + item - + "' is specified in hierarchy for " + config.getServletName()); - } - } - Class clazz = (Class)itemClass; - classes.add(clazz); - } - Class[] hierarchyClasses = (Class[])new Class[classes.size()]; - _hierarchy = classes.toArray(hierarchyClasses); - } - else - { - _hierarchy = (Class[])new Class[0]; - } - } - - protected Collection> getObjects(HttpServletRequest request) + @Override + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - String[] pathInfoElements = getPathInfoElements(request); - List names = new ArrayList(); - if(pathInfoElements != null) - { - if(pathInfoElements.length > _hierarchy.length) - { - throw new IllegalArgumentException("Too many entries in path for REST servlet " - + getServletName() + ". Expected hierarchy length: " + _hierarchy.length - + "; Request hierarchy length: " + pathInfoElements.length - + "; Path Elements: " + Arrays.toString(pathInfoElements)); - } - names.addAll(Arrays.asList(pathInfoElements)); - } - - Collection> parents = new ArrayList>(); - parents.add(getBroker()); - Collection> children = new ArrayList>(); - - Map, String> filters = - new HashMap, String>(); - - for(int i = 0; i < _hierarchy.length; i++) - { - if(i == 0 || getBroker().getModel().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((Collection>) 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>(); - } - - if(!filters.isEmpty()) - { - Collection> potentials = parents; - parents = new ArrayList>(); - - for(ConfiguredObject o : potentials) - { - - boolean match = true; - - for(Map.Entry, String> entry : filters.entrySet()) - { - Collection ancestors = - getAncestors(getConfiguredClass(),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); - } + response.setContentType("text/html"); + response.setStatus(HttpServletResponse.SC_OK); - } - } - return filter(parents, request); + PrintWriter writer = response.getWriter(); + writePreamble(writer); + writeHead(writer); + writeUsage(writer, request); + writeTypes(writer); + writeAttributes(writer); + writeFoot(writer); } - private Collection> filter(Collection> objects, HttpServletRequest request) + private void writePreamble(final PrintWriter writer) { + writer.println(""); + writer.println(""); + writer.println(""); - - Map> filters = new HashMap>(); - - for(String param : (Collection) Collections.list(request.getParameterNames())) - { - if(!RESERVED_PARAMS.contains(param)) - { - filters.put(param, Arrays.asList(request.getParameterValues(param))); - } - } - - if(filters.isEmpty()) - { - return objects; - } - - Collection> filteredObj = new ArrayList>(objects); - - Iterator> iter = filteredObj.iterator(); - - while(iter.hasNext()) - { - ConfiguredObject obj = iter.next(); - for(Map.Entry> entry : filters.entrySet()) - { - Object value = obj.getAttribute(entry.getKey()); - if(!entry.getValue().contains(String.valueOf(value))) - { - iter.remove(); - } - } - - } - - return filteredObj; } - private Collection getAncestors(Class childType, - Class ancestorType, - ConfiguredObject child) + private void writeHead(final PrintWriter writer) { - Collection ancestors = new HashSet(); - Collection> parentTypes = child.getModel().getParentTypes(childType); - - for(Class 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)); - } - } - } + writer.println(""); + writer.println(""); + writer.print(""); + writer.print("Qpid API : " + getConfiguredClass().getSimpleName()); + writer.println(""); - return ancestors; + writer.println(""); } - @Override - protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + private void writeUsage(final PrintWriter writer, final HttpServletRequest request) { - // TODO - sort special params, everything else should act as a filter - String attachmentFilename = request.getParameter(CONTENT_DISPOSITION_ATTACHMENT_FILENAME_PARAM); - boolean extractInitialConfig = getBooleanParameterFromRequest(request, EXTRACT_INITIAL_CONFIG_PARAM); - - response.setContentType("application/json"); - response.setStatus(HttpServletResponse.SC_OK); + writer.println("

Usage

"); + writer.println(""); + writer.println(""); + writer.print(""); - Collection> allObjects = getObjects(request); - - int depth; - boolean actuals; - boolean includeSystemContext; - boolean inheritedActuals; - int oversizeThreshold; - - if(extractInitialConfig) + writer.print(""); + writer.println("
ReadGET" + request.getServletPath() + .replace("apidocs", "api")); - if (attachmentFilename == null) + for (final Class category : _hierarchy) { - setCachingHeadersOnResponse(response); + writer.print("[/<" + category.getSimpleName().toLowerCase() + " name or id>"); } - else + for(int i = 0; i < _hierarchy.length; i++) { - setContentDispositionHeaderIfNecessary(response, attachmentFilename); + writer.print("] "); } + writer.println("
UpdatePUT or POST" + + request.getServletPath().replace("apidocs", "api")); + for (final Class category : _hierarchy) { - depth = Integer.MAX_VALUE; - oversizeThreshold = Integer.MAX_VALUE; - actuals = true; - includeSystemContext = false; - inheritedActuals = false; - } - else - { - depth = getIntParameterFromRequest(request, DEPTH_PARAM, 1); - oversizeThreshold = getIntParameterFromRequest(request, OVERSIZE_PARAM, 120); - actuals = getBooleanParameterFromRequest(request, ACTUALS_PARAM); - includeSystemContext = getBooleanParameterFromRequest(request, INCLUDE_SYS_CONTEXT_PARAM); - inheritedActuals = getBooleanParameterFromRequest(request, INHERITED_ACTUALS_PARAM); + writer.print("/<" + category.getSimpleName().toLowerCase() + " name or id>"); } - List> output = new ArrayList<>(); - for(ConfiguredObject configuredObject : allObjects) + if(_hierarchy.length>1) { + writer.print( + "
CreatePUT or POST" + + request.getServletPath().replace("apidocs", "api")); + for (int i = 0; i < _hierarchy.length - 1; i++) + { + writer.print("/<" + _hierarchy[i].getSimpleName().toLowerCase() + " name or id>"); + } - output.add(_objectConverter.convertObjectToMap(configuredObject, getConfiguredClass(), - depth, actuals, inheritedActuals, includeSystemContext, extractInitialConfig, oversizeThreshold, request.isSecure())); + writer.print("
DeleteDELETE" + + request.getServletPath().replace("apidocs", "api")); + for (final Class category : _hierarchy) + { + writer.print("/<" + category.getSimpleName().toLowerCase() + " name or id>"); + } } + writer.println("
"); - Writer writer = getOutputWriter(request, response); - ObjectMapper mapper = new ObjectMapper(); - mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); - mapper.writeValue(writer, extractInitialConfig && output.size() == 1 ? output.get(0) : output); } - private void setContentDispositionHeaderIfNecessary(final HttpServletResponse response, - final String attachmentFilename) + + private void writeTypes(final PrintWriter writer) { - if (attachmentFilename != null) + if(!_types.isEmpty() && !(_types.size() == 1 && getTypeName(_types.iterator().next()).trim().equals(""))) { - String filenameRfc2183 = ensureFilenameIsRfc2183(attachmentFilename); - if (filenameRfc2183.length() > 0) - { - response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", filenameRfc2183)); - } - else + writer.println("

Types

"); + writer.println(""); + writer.println(""); + writer.println(""); + writer.println(""); + + writer.println(""); + for (Class type : _types) { - response.setHeader("Content-disposition", String.format("attachment")); // Agent will allow user to choose a name + writer.print(""); + } + writer.println(""); } - } - private Class getConfiguredClass() - { - return _hierarchy.length == 0 ? Broker.class : _hierarchy[_hierarchy.length-1]; + writer.println("
TypeDescription
"); + writer.print(getTypeName(type)); + writer.print(""); + writer.print(type.getAnnotation(ManagedObject.class).description()); + writer.println("
"); } - @Override - protected void doPutWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + private String getTypeName(final Class type) { - performCreateOrUpdate(request, response); + return type.getAnnotation(ManagedObject.class).type() == null + ? _model.getTypeRegistry().getTypeClass(type).getSimpleName() + : type.getAnnotation(ManagedObject.class).type(); } - private void performCreateOrUpdate(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + private void writeAttributes(final PrintWriter writer) { - response.setContentType("application/json"); + writer.println("

Attributes

"); + writer.println("

Common Attributes

"); - List names = new ArrayList(); - String[] pathInfoElements = getPathInfoElements(request); + writeAttributesTable(writer, _model.getTypeRegistry().getAttributeTypes(getConfiguredClass()).values()); - boolean parentRequest = false; - if (pathInfoElements != null) + for(Class type : _types) { - parentRequest = _hierarchy.length > 0 && pathInfoElements.length == _hierarchy.length - 1; - if (pathInfoElements.length != _hierarchy.length && !parentRequest) - { - throw new IllegalArgumentException("Path to object to create must be fully specified. " - + "Found " - + names - + " of size " - + names.size() - + " expecting " - + _hierarchy.length); - } - names.addAll(Arrays.asList(pathInfoElements)); - } - else - { - parentRequest = _hierarchy.length == 1; - } - - Map providedObject; - ArrayList headers = Collections.list(request.getHeaderNames()); - ObjectMapper mapper = new ObjectMapper(); - - if(headers.contains("Content-Type") && request.getHeader("Content-Type").startsWith("multipart/form-data")) - { - providedObject = new HashMap<>(); - Map fileUploads = new HashMap<>(); - Collection parts = request.getParts(); - for(Part part : parts) + ManagedObject typeAnnotation = type.getAnnotation(ManagedObject.class); + String typeName = typeAnnotation.type() == null ? _model.getTypeRegistry().getTypeClass(type).getSimpleName() : typeAnnotation.type(); + Collection> typeSpecificAttributes = + _model.getTypeRegistry().getTypeSpecificAttributes(type); + if(!typeSpecificAttributes.isEmpty()) { - if("data".equals(part.getName()) && "application/json".equals(part.getContentType())) - { - providedObject = mapper.readValue(part.getInputStream(), LinkedHashMap.class); - } - else - { - byte[] data = new byte[(int) part.getSize()]; - part.getInputStream().read(data); - String inlineURL = DataUrlUtils.getDataUrlForBytes(data); - fileUploads.put(part.getName(),inlineURL.toString()); - } + writer.println("

"+typeName+" Specific Attributes

"); + writeAttributesTable(writer, typeSpecificAttributes); } - providedObject.putAll(fileUploads); - } - else - { - providedObject = mapper.readValue(request.getInputStream(), LinkedHashMap.class); - } - if (names.isEmpty()) - { - if (_hierarchy.length == 0) - { - try - { - getBroker().setAttributes(providedObject); - response.setStatus(HttpServletResponse.SC_OK); - } - catch (RuntimeException e) - { - setResponseStatus(request, response, e); - } - return; - } - else if (!parentRequest) - { - throw new ServletException("Cannot identify request target object"); - } } - if (!parentRequest) - { - providedObject.put("name", names.get(names.size() - 1)); - } + } - @SuppressWarnings("unchecked") - Collection[] objects = new Collection[_hierarchy.length]; - if (_hierarchy.length == 1) - { - createOrUpdate(providedObject, _hierarchy[0], getBroker(), null, request, response, parentRequest); - } - else + private void writeAttributesTable(final PrintWriter writer, + final Collection> attributeTypes) + { + writer.println(""); + writer.println(""); + writer.println(""); + writer.println(""); + writer.println(""); + + for(ConfiguredObjectAttribute attribute : attributeTypes) { - for (int i = 0; i < _hierarchy.length - 1; i++) + if(!attribute.isDerived()) { - objects[i] = new HashSet(); - 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 (getBroker().getModel().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; - } - } - } - + writer.println(""); } - List parents = new ArrayList(); - Class objClass = getConfiguredClass(); - Collection> parentClasses = - getBroker().getModel().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()); - } - } + } + writer.println(""); - } - ConfiguredObject theParent = parents.remove(0); - ConfiguredObject[] otherParents = parents.toArray(new ConfiguredObject[parents.size()]); + writer.println("
Attribute NameTypeDescription
" + + attribute.getName() + + "" + + renderType(attribute) + + "" + + attribute.getDescription() + + "
"); - createOrUpdate(providedObject, objClass, theParent, otherParents, request, response, parentRequest); - } } - private void createOrUpdate(Map providedObject, Class objClass, - ConfiguredObject theParent, ConfiguredObject[] otherParents, HttpServletRequest request, - HttpServletResponse response, boolean parentRequest) throws IOException + private String renderType(final ConfiguredObjectAttribute attribute) { - try + final Class type = attribute.getType(); + if(Number.class.isAssignableFrom(type)) { - Collection existingChildren = theParent.getChildren(objClass); - - if (!parentRequest) - { - for (ConfiguredObject obj : existingChildren) - { - if ((providedObject.containsKey("id") && String.valueOf(providedObject.get("id")).equals(obj.getId().toString())) - || (obj.getName().equals(providedObject.get("name")) && equalParents(obj, otherParents, objClass))) - { - obj.setAttributes(providedObject); - response.setStatus(HttpServletResponse.SC_OK); - return; - } - } - - if ("POST".equalsIgnoreCase(request.getMethod())) - { - sendErrorResponse(request, response, HttpServletResponse.SC_NOT_FOUND, "Object with " - + (providedObject.containsKey("id") ? " id '" + providedObject.get("id") : " name '" + providedObject.get("name")) - + "' does not exist!" ); - return; - } - } - - ConfiguredObject co = theParent.createChild(objClass, providedObject, otherParents); - StringBuffer requestURL = request.getRequestURL(); - if (parentRequest) - { - requestURL.append("/").append(co.getName()); - } - response.setHeader("Location", requestURL.toString()); - response.setStatus(HttpServletResponse.SC_CREATED); + return "number"; } - catch (RuntimeException e) + else if(Enum.class.isAssignableFrom(type)) { - setResponseStatus(request, response, e); + return "string"; } - } - - private boolean equalParents(ConfiguredObject obj, ConfiguredObject[] otherParents, Class objClass) - { - if(otherParents == null || otherParents.length == 0) + else if(Boolean.class == type) { - return true; + return "boolean"; } - - Collection> parentClasses = obj.getModel().getParentTypes(objClass); - - for (ConfiguredObject parent : otherParents) + else if(String.class == type) { - boolean found = false; - for (Class parentClass : parentClasses) - { - if (parent == obj.getParent(parentClass)) - { - found = true; - break; - } - } - - if (!found) - { - return false; - } + return "string"; } - - return true; - } - - private void setResponseStatus(HttpServletRequest request, HttpServletResponse response, RuntimeException e) throws IOException - { - if (e instanceof AccessControlException) + else if(UUID.class == type) { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("AccessControlException, sending " + HttpServletResponse.SC_FORBIDDEN, e); - } - response.setStatus(HttpServletResponse.SC_FORBIDDEN); + return "string"; } - else + else if(List.class.isAssignableFrom(type)) { - int responseCode = HttpServletResponse.SC_BAD_REQUEST; - String message = e.getMessage(); - if (e instanceof ExchangeExistsException || e instanceof QueueExistsException - || e instanceof AbstractConfiguredObject.DuplicateIdException - || e instanceof AbstractConfiguredObject.DuplicateNameException - || e instanceof IntegrityViolationException - || e instanceof IllegalStateTransitionException) - { - responseCode = HttpServletResponse.SC_CONFLICT; - } - else if (e instanceof IllegalConfigurationException || e instanceof IllegalArgumentException) - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug(e.getClass().getSimpleName() + " processing request : " + message); - } - else if (LOGGER.isTraceEnabled()) - { - LOGGER.trace(e.getClass().getSimpleName() + " processing request", e); - } - responseCode = SC_UNPROCESSABLE_ENTITY; - } - else - { - LOGGER.warn("Unexpected exception processing request ", e); - } - - - sendErrorResponse(request, response, responseCode, message); - + // TODO - generate a description of the type in the array + return "array"; } - } - - private void sendErrorResponse(HttpServletRequest request, HttpServletResponse response, int responseCode, String message) throws IOException - { - response.setStatus(responseCode); - - response.setContentType("application/json"); - response.setCharacterEncoding("UTF-8"); - - Writer out = getOutputWriter(request, response); - ObjectMapper mapper = new ObjectMapper(); - mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); - mapper.writeValue(out, Collections.singletonMap("errorMessage", message)); - } - - @Override - protected void doDeleteWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException - { - response.setContentType("application/json"); - response.setStatus(HttpServletResponse.SC_OK); - - setCachingHeadersOnResponse(response); - try + else if(Map.class.isAssignableFrom(type)) { - Collection> allObjects = getObjects(request); - for(ConfiguredObject o : allObjects) - { - o.delete(); - } - - response.setStatus(HttpServletResponse.SC_OK); + // TODO - generate a description of the type in the object + return "object"; } - catch(RuntimeException e) + else if(ConfiguredObject.class.isAssignableFrom(type)) { - setResponseStatus(request, response, e); + return "string"; } + return type.getSimpleName(); } - @Override - protected void doPostWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + private void writeFoot(final PrintWriter writer) { - performCreateOrUpdate(request, response); + writer.println(""); + writer.println(""); } - - private void setCachingHeadersOnResponse(HttpServletResponse response) + private Class getConfiguredClass() { - response.setHeader("Cache-Control","no-cache"); - response.setHeader("Pragma","no-cache"); - response.setDateHeader ("Expires", 0); + return _hierarchy.length == 0 ? Broker.class : _hierarchy[_hierarchy.length-1]; } + private int getIntParameterFromRequest(final HttpServletRequest request, final String paramName, final int defaultValue) @@ -767,10 +351,5 @@ public class RestServlet extends Abstrac return Boolean.parseBoolean(request.getParameter(paramName)); } - private String ensureFilenameIsRfc2183(final String requestedFilename) - { - String fileNameRfc2183 = requestedFilename.replaceAll("[\\P{InBasic_Latin}\\\\:/]", ""); - return fileNameRfc2183; - } } Modified: qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MetaDataServlet.java URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MetaDataServlet.java?rev=1666850&r1=1666849&r2=1666850&view=diff ============================================================================== --- qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MetaDataServlet.java (original) +++ qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MetaDataServlet.java Mon Mar 16 01:31:54 2015 @@ -51,14 +51,15 @@ public class MetaDataServlet extends Abs private Model _instance; + public MetaDataServlet(final Model model) + { + _instance = model; + } + @Override public void init() throws ServletException { super.init(); - - _instance = BrokerModel.getInstance(); - - } Added: qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/resources/css/apidocs.css URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/resources/css/apidocs.css?rev=1666850&view=auto ============================================================================== --- qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/resources/css/apidocs.css (added) +++ qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/resources/css/apidocs.css Mon Mar 16 01:31:54 2015 @@ -0,0 +1,52 @@ +/* + * + * 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. + * + */ +html, body { + margin-top: 20px; + margin-left: 40px; + margin-right: 40px; + padding: 0; + font-family: Lucida Sans,Lucida Grande,Arial,sans-serif !important; + font-size: 13px !important; + background: white; + color: #333; +} + +th, td { + text-align: left; +} + +.type { + font-family: "Courier New", courier, monospace; +} + +table.types td.name { + width: 20em; +} + +table.attributes td.name { + font-family: "Courier New", courier, monospace; + width: 20em; +} + + +table.attributes td.type { + width: 7em; +} Propchange: qpid/trunk/qpid/java/broker-plugins/management-http/src/main/java/resources/css/apidocs.css ------------------------------------------------------------------------------ svn:eol-style = native --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org For additional commands, e-mail: commits-help@qpid.apache.org