This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jmx-provider.git
commit 417713e9a6f8e0f0f5302e9ab92010903bc0f354 Author: Carsten Ziegeler <[email protected]> AuthorDate: Mon Aug 19 16:15:14 2013 +0000 SLING-2999 : JMX Resource Provider - initial support for tabular and composite data git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1515488 13f79535-47bb-0310-9956-ffa450edef68 --- .../sling/jmx/provider/impl/AttributeResource.java | 160 ++++++++++++++++++++- .../jmx/provider/impl/JMXResourceProvider.java | 52 +++++-- .../sling/jmx/provider/impl/MapResource.java | 95 ++++++++++++ 3 files changed, 296 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/apache/sling/jmx/provider/impl/AttributeResource.java b/src/main/java/org/apache/sling/jmx/provider/impl/AttributeResource.java index 1c5e1f0..1bf47a7 100644 --- a/src/main/java/org/apache/sling/jmx/provider/impl/AttributeResource.java +++ b/src/main/java/org/apache/sling/jmx/provider/impl/AttributeResource.java @@ -19,16 +19,24 @@ package org.apache.sling.jmx.provider.impl; import java.lang.reflect.Array; +import java.util.Collection; import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.Map; +import java.util.Set; +import java.util.TreeMap; import javax.management.MBeanAttributeInfo; import javax.management.MBeanServer; import javax.management.ObjectName; import javax.management.openmbean.CompositeData; +import javax.management.openmbean.CompositeType; import javax.management.openmbean.TabularData; +import javax.management.openmbean.TabularType; import org.apache.sling.api.resource.AbstractResource; +import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceMetadata; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.ValueMap; @@ -126,9 +134,9 @@ public class AttributeResource extends AbstractResource { } result.put("mbean:value", values); } else if (value instanceof TabularData) { - // TODO + // Nothing to do, value is child resource } else if (value instanceof CompositeData) { - // TODO + // Nothing to do, value is child resource } else { result.put("mbean:value", convert(value)); } @@ -154,4 +162,152 @@ public class AttributeResource extends AbstractResource { } return value.toString(); } + + public Resource getChildResource(final String subPath) { + final Map<String, Object> childStructure = this.convertData(); + if ( childStructure != null ) { + final String[] segments = subPath.split("/"); + Map<String, Object> current = childStructure; + for(final String path : segments) { + final Object child = current.get(path); + if ( child == null ) { + return null; + } + if ( !(child instanceof Map) ) { + return null; + } + current = (Map<String, Object>)child; + } + + return new MapResource(this.getResourceResolver(), this.getPath(), current); + } + return null; + } + + private Map<String, Object> convertData() { + try { + final Object value = server.getAttribute(this.on, info.getName()); + + if ( value instanceof TabularData ) { + return convertObject((TabularData)value); + } else if ( value instanceof CompositeData ) { + return convertObject((CompositeData)value); + } + } catch (final Exception ignore) { + // ignore and return null + } + return null; + } + + private Map<String, Object> convertObject(final TabularData td) { + final TabularType type = td.getTabularType(); + final Map<String, Object> result = new HashMap<String, Object>(); + result.put("sling:resourceSuperType", "mbean:attributes"); + result.put("sling:resourceType", type.getTypeName()); + + final Map<String, Map<String, Object>> rows = new LinkedHashMap<String, Map<String, Object>>(); + int index = 1; + // TODO - use index values + for(final CompositeData data : (Collection<CompositeData>)td.values()) { + rows.put(String.valueOf(index), convertObject(data)); + index++; + } + result.put("mbean:value", rows); + + return result; + } + + private Map<String, Object> convertObject(final CompositeData cd) { + final CompositeType type = cd.getCompositeType(); + final Map<String, Object> result = new HashMap<String, Object>(); + result.put("sling:resourceSuperType", "mbean:attributes"); + result.put("sling:resourceType", type.getTypeName()); + + final Map<String, Object> attrMap = new TreeMap<String, Object>(); + attrMap.put("sling:resourceType", "mbean:attributes"); + result.put("mbean:attributes", attrMap); + + final Set<String> names = type.keySet(); + for(final String name : names) { + final Map<String, Object> dataMap = new HashMap<String, Object>(); + attrMap.put(name, dataMap); + dataMap.put(ResourceResolver.PROPERTY_RESOURCE_TYPE, type.getType(name)); + dataMap.put("sling:resourceSuperType", "mbean:attributes"); + + if ( type.getDescription() != null ) { + dataMap.put("mbean:description", type.getDescription()); + } + dataMap.put("mbean:type", type.getType(name)); + + final Object value = cd.get(name); + if ( value != null ) { + if ( value.getClass().isArray() ) { + final int length = Array.getLength(value); + final Object[] values = new Object[length]; + for (int i = 0; i < length; i ++) { + final Object o = Array.get(value, i); + values[i] = convert(o); + } + dataMap.put("mbean:value", values); + } else if (value instanceof TabularData) { + dataMap.put("mbean:value", convertObject((TabularData)value)); + } else if (value instanceof CompositeData) { + dataMap.put("mbean:value", convertObject((CompositeData)value)); + } else { + dataMap.put("mbean:value", convert(value)); + } + } + } + + return result; + } + + public Iterator<Resource> getChildren(String subPath) { + final Map<String, Object> childStructure = this.convertData(); + if ( childStructure != null ) { + Map<String, Object> current = childStructure; + if ( subPath != null ) { + final String[] segments = subPath.split("/"); + for(final String path : segments) { + final Object child = current.get(path); + if ( child == null ) { + return null; + } + if ( !(child instanceof Map) ) { + return null; + } + current = (Map<String, Object>)child; + } + } + final Iterator<Map.Entry<String, Object>> removeIter = current.entrySet().iterator(); + while ( removeIter.hasNext() ) { + final Map.Entry<String, Object> c = removeIter.next(); + if ( !(c.getValue() instanceof Map) ) { + removeIter.remove(); + } + } + if ( current.size() == 0 ) { + return null; + } + final Iterator<Map.Entry<String, Object>> childIter = current.entrySet().iterator(); + + return new Iterator<Resource>() { + + public void remove() { + throw new UnsupportedOperationException("remove"); + } + + public Resource next() { + final Map.Entry<String, Object> props = childIter.next(); + + return new MapResource(getResourceResolver(), getPath() + '/' + props.getKey(), (Map)props.getValue()); + } + + public boolean hasNext() { + return childIter.hasNext(); + } + }; + } + return null; + } } diff --git a/src/main/java/org/apache/sling/jmx/provider/impl/JMXResourceProvider.java b/src/main/java/org/apache/sling/jmx/provider/impl/JMXResourceProvider.java index 5cdd7a3..bfdbd85 100644 --- a/src/main/java/org/apache/sling/jmx/provider/impl/JMXResourceProvider.java +++ b/src/main/java/org/apache/sling/jmx/provider/impl/JMXResourceProvider.java @@ -144,16 +144,28 @@ public class JMXResourceProvider implements ResourceProvider { if (info.pathInfo == null ) { return new MBeanResource(resourceResolver, this.convertObjectNameToResourcePath(info.objectName), path, info.mbeanInfo, info.objectName); } - if ( info.pathInfo.equals("attributes") ) { + if ( info.pathInfo.equals("mbean:attributes") ) { return new AttributesResource(resourceResolver, path); } - if ( info.pathInfo.startsWith("attributes/") ) { - final String attrName = info.pathInfo.substring(11); - if ( attrName.indexOf('/') == - 1) { - for(final MBeanAttributeInfo mai : info.mbeanInfo.getAttributes()) { - if ( mai.getName().equals(attrName) ) { - return new AttributeResource(mbeanServer, info.objectName, resourceResolver, path, mai); + if ( info.pathInfo.startsWith("mbean:attributes/") ) { + final String attrPath = info.pathInfo.substring("mbean:attributes/".length()); + final int pos = attrPath.indexOf('/'); + final String attrName; + final String subPath; + if ( pos == -1 ) { + attrName = attrPath; + subPath = null; + } else { + attrName = attrPath.substring(0, pos); + subPath = attrPath.substring(pos + 1); + } + for(final MBeanAttributeInfo mai : info.mbeanInfo.getAttributes()) { + if ( mai.getName().equals(attrName) ) { + final AttributeResource rsrc = new AttributeResource(mbeanServer, info.objectName, resourceResolver, path, mai); + if ( subPath != null ) { + return rsrc.getChildResource(subPath); } + return rsrc; } } } @@ -256,9 +268,9 @@ public class JMXResourceProvider implements ResourceProvider { } else { if ( info.pathInfo == null ) { final List<Resource> list = new ArrayList<Resource>(); - list.add(new AttributesResource(parent.getResourceResolver(), parent.getPath() + "/attributes")); + list.add(new AttributesResource(parent.getResourceResolver(), parent.getPath() + "/mbean:attributes")); return list.iterator(); - } else if ( info.pathInfo.equals("attributes") ) { + } else if ( info.pathInfo.equals("mbean:attributes") ) { final MBeanAttributeInfo[] infos = info.mbeanInfo.getAttributes(); final List<MBeanAttributeInfo> list = Arrays.asList(infos); final Iterator<MBeanAttributeInfo> iter = list.iterator(); @@ -277,6 +289,25 @@ public class JMXResourceProvider implements ResourceProvider { return iter.hasNext(); } }; + } else if ( info.pathInfo.startsWith("mbean:attributes/") ) { + final String attrPath = info.pathInfo.substring("mbean:attributes/".length()); + final int pos = attrPath.indexOf('/'); + final String attrName; + final String subPath; + if ( pos == -1 ) { + attrName = attrPath; + subPath = null; + } else { + attrName = attrPath.substring(0, pos); + subPath = attrPath.substring(pos + 1); + } + for(final MBeanAttributeInfo mai : info.mbeanInfo.getAttributes()) { + if ( mai.getName().equals(attrName) ) { + final AttributeResource rsrc = new AttributeResource(mbeanServer, info.objectName, parent.getResourceResolver(), parent.getPath(), mai); + return rsrc.getChildren(subPath); + } + } + } } } @@ -378,6 +409,9 @@ public class JMXResourceProvider implements ResourceProvider { sb.append(","); } final int pos = keyValue.indexOf('='); + if ( pos == -1 ) { + return null; + } sb.append(decode(keyValue.substring(0, pos))); sb.append('='); sb.append(decode(keyValue.substring(pos+1))); diff --git a/src/main/java/org/apache/sling/jmx/provider/impl/MapResource.java b/src/main/java/org/apache/sling/jmx/provider/impl/MapResource.java new file mode 100644 index 0000000..920c366 --- /dev/null +++ b/src/main/java/org/apache/sling/jmx/provider/impl/MapResource.java @@ -0,0 +1,95 @@ +/* + * 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. + */ +package org.apache.sling.jmx.provider.impl; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.sling.api.resource.AbstractResource; +import org.apache.sling.api.resource.ResourceMetadata; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ValueMap; +import org.apache.sling.api.wrappers.ValueMapDecorator; + +public class MapResource extends AbstractResource { + + private final String path; + + private final ResourceResolver resolver; + + private final Map<String, Object> properties; + + private final ResourceMetadata metadata = new ResourceMetadata(); + + public MapResource(final ResourceResolver resolver, final String path, final Map<String, Object> props) { + this.resolver = resolver; + this.path = path; + this.properties = new HashMap<String, Object>(); + for(final Map.Entry<String, Object> entry : props.entrySet() ) { + if ( !(entry.getValue() instanceof Map) ) { + this.properties.put(entry.getKey(), entry.getValue()); + } + } + } + + /** + * @see org.apache.sling.api.resource.Resource#getPath() + */ + public String getPath() { + return this.path; + } + + /** + * @see org.apache.sling.api.resource.Resource#getResourceType() + */ + public String getResourceType() { + return (String)properties.get("sling:resourceType"); + } + + /** + * @see org.apache.sling.api.resource.Resource#getResourceSuperType() + */ + public String getResourceSuperType() { + return (String)properties.get("sling:resourceSuperType"); + } + + /** + * @see org.apache.sling.api.resource.Resource#getResourceMetadata() + */ + public ResourceMetadata getResourceMetadata() { + return metadata; + } + + /** + * @see org.apache.sling.api.resource.Resource#getResourceResolver() + */ + public ResourceResolver getResourceResolver() { + return this.resolver; + } + + @Override + public <AdapterType> AdapterType adaptTo(final Class<AdapterType> type) { + if ( type == ValueMap.class || type == Map.class ) { + final Map<String, Object> propMap = Collections.unmodifiableMap(this.properties); + return (AdapterType) new ValueMapDecorator(propMap); + } + return super.adaptTo(type); + } +} \ No newline at end of file -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
