Author: ieb Date: Tue Mar 5 03:44:55 2013 New Revision: 1452654 URL: http://svn.apache.org/r1452654 Log: Re-factored to provide information on the DispatcherQueue size, number added, number removed, rate added, rate removed. Last 2 using a simple first order finite difference approach. Uses reflection and JDKProxy to insert instrumentation arround the queue. Can be added to a instance to expose the metrics, and unloaded.
Added: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/DispatcherQueueMBean.java (contents, props changed) - copied, changed from r1451503, sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/Statistics.java sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/DispatcherQueueMBeanImpl.java (with props) sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/ObservationDispatchAccess.java (with props) sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/TimeDifferential.java (with props) sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/http/ sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/http/StatisticsServletDirect.java (with props) sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/jmx/ sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/jmx/MultiMBeanServer.java (with props) sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/ sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/CGLibCallbackProxy.java (with props) sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/Introspect.java (with props) sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/JDKCallbackProxy.java (with props) sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/ProxyCallback.java (contents, props changed) - copied, changed from r1451503, sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/StatisticsFactory.java Removed: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/Statistics.java sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/StatisticsFactory.java sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/StatisticsImpl.java sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/StatisticsServlet.java sling/whiteboard/ieb/monitor/src/test/java/org/apache/sling/commons/monitor/impl/CounterTest.java sling/whiteboard/ieb/monitor/src/test/java/org/apache/sling/commons/monitor/impl/StatisticsServletTest.java Modified: sling/whiteboard/ieb/monitor/pom.xml sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/package-info.java Modified: sling/whiteboard/ieb/monitor/pom.xml URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/monitor/pom.xml?rev=1452654&r1=1452653&r2=1452654&view=diff ============================================================================== --- sling/whiteboard/ieb/monitor/pom.xml (original) +++ sling/whiteboard/ieb/monitor/pom.xml Tue Mar 5 03:44:55 2013 @@ -41,6 +41,9 @@ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/whiteboard/ieb/monitor</developerConnection> <url>http://svn.apache.org/viewvc/sling/whiteboard/ieb/monitor</url> </scm> + <properties> + <sling.java.version>6</sling.java.version> + </properties> <build> @@ -56,8 +59,17 @@ <configuration> <instructions> <Import-Package> + net.sf.cglib.asm.util;resolution:=optional, + org.apache.bcel.*;resolution:=optional, + !org.apache.tools.*, * </Import-Package> + <Embed-Transitive>true</Embed-Transitive> + <Embed-Dependency> + json-simple, + cglib-nodep, + cglib-asm + </Embed-Dependency> </instructions> </configuration> </plugin> @@ -71,6 +83,41 @@ <scope>provided</scope> </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.api</artifactId> + <version>2.3.0</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>cglib</groupId> + <artifactId>cglib-nodep</artifactId> + <version>2.2.2</version> + </dependency> + + <dependency> + <groupId>cglib</groupId> + <artifactId>cglib-asm</artifactId> + <version>1.0</version> + </dependency> + + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.jcr.api</artifactId> + <version>2.1.1-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>javax.jcr</groupId> + <artifactId>jcr</artifactId> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.commons.json</artifactId> + <version>2.0.6</version> + </dependency> + <!-- OSGi Libraries not included here --> <dependency> <groupId>org.osgi</groupId> @@ -94,7 +141,7 @@ <groupId>biz.aQute</groupId> <artifactId>bndlib</artifactId> </dependency> - + <!-- testing --> <!-- using mockito because its a bit more relaxed and makes it easier to maintain the test cases if dependencies change --> @@ -110,12 +157,6 @@ <scope>test</scope> </dependency> <dependency> - <groupId>org.apache.sling</groupId> - <artifactId>org.apache.sling.commons.json</artifactId> - <version>2.0.6</version> - <scope>test</scope> - </dependency> - <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> Copied: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/DispatcherQueueMBean.java (from r1451503, sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/Statistics.java) URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/DispatcherQueueMBean.java?p2=sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/DispatcherQueueMBean.java&p1=sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/Statistics.java&r1=1451503&r2=1452654&rev=1452654&view=diff ============================================================================== --- sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/Statistics.java (original) +++ sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/DispatcherQueueMBean.java Tue Mar 5 03:44:55 2013 @@ -17,21 +17,21 @@ */ package org.apache.sling.commons.monitor; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; - /** - * A Collection of statistics registered by the user of the interface. + * Interface of exposed mmonitoring data on the DispatcherQueue. This must be + * exposed by the OSGi classloade so that the StandardMBean can introspect it to + * build methods. */ -public interface Statistics { - /** - * Get a statistic by name of type T. Type is not checked. - * @param name the name of the statistic - * @return return the statistic. - */ - <T> AtomicLong get(String name); - /** - * @return an read only map of all statistics at the time the call method was invoked. - */ - Map<String, AtomicLong> all(); +public interface DispatcherQueueMBean { + + long getSize(); + + long getAdded(); + + double getAddedRate(); + + long getRemoved(); + + double getRemovedRate(); + } Propchange: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/DispatcherQueueMBean.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/DispatcherQueueMBeanImpl.java URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/DispatcherQueueMBeanImpl.java?rev=1452654&view=auto ============================================================================== --- sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/DispatcherQueueMBeanImpl.java (added) +++ sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/DispatcherQueueMBeanImpl.java Tue Mar 5 03:44:55 2013 @@ -0,0 +1,141 @@ +/* + * 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 SF 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.commons.monitor.impl; + +import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +import javax.management.DynamicMBean; +import javax.management.NotCompliantMBeanException; +import javax.management.StandardMBean; + +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Properties; +import org.apache.felix.scr.annotations.Property; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.Service; +import org.apache.sling.commons.monitor.DispatcherQueueMBean; +import org.apache.sling.commons.monitor.impl.reflect.JDKCallbackProxy; +import org.apache.sling.commons.monitor.impl.reflect.ProxyCallback; +import org.apache.sling.jcr.api.SlingRepository; +import org.osgi.service.component.ComponentContext; + +import aQute.bnd.annotation.component.Activate; +import aQute.bnd.annotation.component.Deactivate; + +@Component(immediate = true) +@Service(value = DynamicMBean.class) +@Properties({ @Property(name = "jmx.objectname", propertyPrivate = true, value = "org.apache.sling:type=Repository,name=DispatcherQueue") }) +public class DispatcherQueueMBeanImpl extends StandardMBean + implements DispatcherQueueMBean { + + + @Reference + private SlingRepository slingRepository; + + private boolean active; + + private ObservationDispatchAccess observationDispatchAccess; + + private AtomicInteger queueSize; + + private Object originalQueue; + + private JDKCallbackProxy proxiedQueue; + + private TimeDifferential added = new TimeDifferential(1000, new AtomicLong()); + + private TimeDifferential removed = new TimeDifferential(1000, new AtomicLong()); + + + + + public DispatcherQueueMBeanImpl() throws NotCompliantMBeanException { + super(DispatcherQueueMBean.class, false); + } + + @Activate + protected void activate(ComponentContext context) + throws IllegalArgumentException, IllegalAccessException, + InvocationTargetException, NoSuchMethodException, + NoSuchFieldException { + observationDispatchAccess = new ObservationDispatchAccess(slingRepository); + queueSize = (AtomicInteger) observationDispatchAccess.getDispatcherField("eventQueueSize"); + originalQueue = observationDispatchAccess.getDispatcherField("eventQueue"); + proxiedQueue = new JDKCallbackProxy(originalQueue, new ProxyCallback() { + public void callback(String name, Object[] args) { + if ( "add".equals(name) ) { + added.increment(1); + } else if ( "remove".equals(name)) { + removed.increment(1); + } + } + }); + observationDispatchAccess.setDispatcherField("eventQueue", proxiedQueue.getProxy()); + active = true; + } + + @Deactivate + protected void deactivate(ComponentContext context) + throws IllegalArgumentException, NoSuchFieldException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { + active = true; + observationDispatchAccess.setDispatcherField("eventQueue", originalQueue); + observationDispatchAccess = null; + proxiedQueue = null; + } + + + + + public long getSize() { + if (!active) { + return 0; + } + return (long) queueSize.get(); + } + + public long getAdded() { + if (!active) { + return 0; + } + return (long) added.getValue(); + } + + public double getAddedRate() { + if (!active) { + return 0; + } + return added.getRate(); + } + + public long getRemoved() { + if (!active) { + return 0; + } + return (long) removed.getValue(); + } + + public double getRemovedRate() { + if (!active) { + return 0; + } + return removed.getRate(); + } + +} Propchange: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/DispatcherQueueMBeanImpl.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/ObservationDispatchAccess.java URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/ObservationDispatchAccess.java?rev=1452654&view=auto ============================================================================== --- sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/ObservationDispatchAccess.java (added) +++ sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/ObservationDispatchAccess.java Tue Mar 5 03:44:55 2013 @@ -0,0 +1,72 @@ +/* + * 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 SF 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.commons.monitor.impl; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; + +import org.apache.sling.commons.monitor.impl.reflect.Introspect; +import org.apache.sling.jcr.api.SlingRepository; + +public class ObservationDispatchAccess { + + private SlingRepository slingRepository; + + public ObservationDispatchAccess(SlingRepository slingRepository) { + this.slingRepository = slingRepository; + } + + public Object getDispatcherField(String name) + throws IllegalArgumentException, IllegalAccessException, + InvocationTargetException, NoSuchMethodException, + NoSuchFieldException { + Object repositoryImpl = Introspect.safeGetMethod(slingRepository, + "getRepository").invoke(slingRepository, (Object[]) null); + Object repConfig = Introspect.safeGetField(repositoryImpl, "repConfig").get( + repositoryImpl); + Object defaultWorkspaceName = Introspect.safeGetMethod(repConfig, + "getDefaultWorkspaceName").invoke(repConfig, (Object[]) null); + Object workspaceInfo = Introspect.safeGetMethod(repositoryImpl, + "getWorkspaceInfo", String.class).invoke(repositoryImpl, + new Object[] { defaultWorkspaceName }); + Object observationDispatcher = Introspect.safeGetMethod(workspaceInfo, + "getObservationDispatcher").invoke(workspaceInfo, (Object[]) null); + Field field = Introspect.safeGetField(observationDispatcher, name); + return field.get(observationDispatcher); + } + + public void setDispatcherField(String name, Object obj) + throws NoSuchFieldException, IllegalArgumentException, + IllegalAccessException, InvocationTargetException, + NoSuchMethodException { + Object repositoryImpl = Introspect.safeGetMethod(slingRepository, + "getRepository").invoke(slingRepository, (Object[]) null); + Object repConfig = Introspect.safeGetField(repositoryImpl, "repConfig").get( + repositoryImpl); + Object defaultWorkspaceName = Introspect.safeGetMethod(repConfig, + "getDefaultWorkspaceName").invoke(repConfig, (Object[]) null); + Object workspaceInfo = Introspect.safeGetMethod(repositoryImpl, + "getWorkspaceInfo", String.class).invoke(repositoryImpl, + new Object[] { defaultWorkspaceName }); + Object observationDispatcher = Introspect.safeGetMethod(workspaceInfo, + "getObservationDispatcher").invoke(workspaceInfo, (Object[]) null); + Field field = Introspect.safeGetField(observationDispatcher, name); + field.set(observationDispatcher, obj); + } + +} Propchange: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/ObservationDispatchAccess.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/TimeDifferential.java URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/TimeDifferential.java?rev=1452654&view=auto ============================================================================== --- sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/TimeDifferential.java (added) +++ sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/TimeDifferential.java Tue Mar 5 03:44:55 2013 @@ -0,0 +1,61 @@ +/* + * 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 SF 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.commons.monitor.impl; + +import java.util.concurrent.atomic.AtomicLong; + +public class TimeDifferential { + + private long last = 0; + private long vlast; + private double diff; + private double period; + private AtomicLong counter; + + public TimeDifferential(double d, AtomicLong counter) { + period = d; + this.counter = counter; + } + public void differentiate() { + long now = System.currentTimeMillis(); + long vnow = counter.longValue(); + if ( (now - last) > period ) { + if ( last > 0 ) { + diff = ((vnow - vlast)*period)/(double)(now-last); + } + vlast = vnow; + last = System.currentTimeMillis(); + } + } + + public double getRate() { + differentiate(); + return diff; + } + + public long getValue() { + differentiate(); + return vlast; + } + + public void increment(int delta) { + counter.addAndGet(delta); + } + + +} Propchange: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/TimeDifferential.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/http/StatisticsServletDirect.java URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/http/StatisticsServletDirect.java?rev=1452654&view=auto ============================================================================== --- sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/http/StatisticsServletDirect.java (added) +++ sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/http/StatisticsServletDirect.java Tue Mar 5 03:44:55 2013 @@ -0,0 +1,88 @@ +/* + * 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 SF 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.commons.monitor.impl.http; + +import java.io.IOException; +import java.util.Iterator; + +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.servlet.ServletException; + +import org.apache.felix.scr.annotations.sling.SlingServlet; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.SlingHttpServletResponse; +import org.apache.sling.api.servlets.SlingSafeMethodsServlet; +import org.apache.sling.commons.json.JSONException; +import org.apache.sling.commons.json.JSONObject; +import org.apache.sling.commons.monitor.impl.jmx.MultiMBeanServer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SlingServlet(methods = { "GET" }, paths = { "/system/stats" }) +public class StatisticsServletDirect extends SlingSafeMethodsServlet { + + /** + * + */ + private static final long serialVersionUID = 8473046624953080315L; + + private static final Logger LOGGER = LoggerFactory.getLogger(StatisticsServletDirect.class); + + @Override + protected void doGet(SlingHttpServletRequest request, + SlingHttpServletResponse response) throws ServletException, + IOException { + try { + MBeanServerConnection servers = new MultiMBeanServer(); + String[] targets = request.getParameterValues("q"); + JSONObject jsonOutput = new JSONObject(); + jsonOutput.put("timestamp", System.currentTimeMillis()); + jsonOutput.put("_query", targets); + for (String t : targets) { + String[] n = t.split("/", 2); + String[] attributes = n[1].split(","); + JSONObject obj = new JSONObject(); + jsonOutput.put(n[0], obj); + AttributeList list = servers.getAttributes( + new ObjectName(n[0]), attributes); + Iterator<Object> i = list.iterator(); + while (i.hasNext()) { + Attribute a = (Attribute) i.next(); + try { + obj.put(a.getName(), a.getValue()); + } catch (JSONException e) { + LOGGER.debug(e.getMessage(), e); + } + } + } + String r = jsonOutput.toString(2); + response.setContentType("application/json; charset=utf8"); + response.setHeader("Cache-Control", "no-cache"); + response.setCharacterEncoding("UTF-8"); + response.setContentLength(r.length()); + response.getWriter().write(r); + } catch (Exception e) { + throw new ServletException(e.getMessage(), e); + } + + } + +} Propchange: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/http/StatisticsServletDirect.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/jmx/MultiMBeanServer.java URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/jmx/MultiMBeanServer.java?rev=1452654&view=auto ============================================================================== --- sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/jmx/MultiMBeanServer.java (added) +++ sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/jmx/MultiMBeanServer.java Tue Mar 5 03:44:55 2013 @@ -0,0 +1,243 @@ +/* + * 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 SF 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.commons.monitor.impl.jmx; + +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.AttributeNotFoundException; +import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; +import javax.management.IntrospectionException; +import javax.management.InvalidAttributeValueException; +import javax.management.ListenerNotFoundException; +import javax.management.MBeanException; +import javax.management.MBeanInfo; +import javax.management.MBeanRegistrationException; +import javax.management.MBeanServer; +import javax.management.MBeanServerConnection; +import javax.management.MBeanServerFactory; +import javax.management.NotCompliantMBeanException; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; +import javax.management.ObjectInstance; +import javax.management.ObjectName; +import javax.management.QueryExp; +import javax.management.ReflectionException; + +public class MultiMBeanServer implements MBeanServerConnection { + + private List<MBeanServer> servers = new ArrayList<MBeanServer>(); + + public MultiMBeanServer() { + servers.addAll(MBeanServerFactory.findMBeanServer(null)); + servers.add(ManagementFactory.getPlatformMBeanServer()); + + } + + public Object getAttribute(ObjectName name, String attribute) + throws MBeanException, AttributeNotFoundException, + InstanceNotFoundException, ReflectionException, IOException { + return getServer(name).getAttribute(name, attribute); + } + + public AttributeList getAttributes(ObjectName name, String[] attributes) + throws InstanceNotFoundException, ReflectionException, IOException { + return getServer(name).getAttributes(name, attributes); + } + + public String getDefaultDomain() throws IOException { + return servers.get(servers.size() - 1).getDefaultDomain(); + } + + public String[] getDomains() throws IOException { + Set<String> domains = new LinkedHashSet<String>(); + for (MBeanServer c : servers) { + for (String d : c.getDomains()) { + domains.add(d); + } + } + return domains.toArray(new String[domains.size()]); + } + + public Integer getMBeanCount() throws IOException { + int i = 0; + for (MBeanServer c : servers) { + i += c.getMBeanCount(); + } + return i; + } + + public MBeanInfo getMBeanInfo(ObjectName name) + throws InstanceNotFoundException, IntrospectionException, + ReflectionException, IOException { + return getServer(name).getMBeanInfo(name); + } + + public ObjectInstance getObjectInstance(ObjectName name) + throws InstanceNotFoundException, IOException { + return getServer(name).getObjectInstance(name); + } + + public boolean isInstanceOf(ObjectName name, String className) + throws InstanceNotFoundException, IOException { + try { + return getServer(name).isInstanceOf(name, className); + } catch (InstanceNotFoundException e) { + return false; + } + } + + public boolean isRegistered(ObjectName name) throws IOException { + try { + return getServer(name).isRegistered(name); + } catch (InstanceNotFoundException e) { + return false; + } + } + + public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) + throws IOException { + Set<ObjectInstance> instances = new LinkedHashSet<ObjectInstance>(); + for (MBeanServer c : servers) { + instances.addAll(c.queryMBeans(name, query)); + } + return instances; + } + + public Set<ObjectName> queryNames(ObjectName name, QueryExp query) + throws IOException { + Set<ObjectName> names = new LinkedHashSet<ObjectName>(); + for (MBeanServer c : servers) { + names.addAll(c.queryNames(name, query)); + } + return names; + } + + private MBeanServer getServer(ObjectName name) + throws InstanceNotFoundException { + for (MBeanServer c : servers) { + if (c.isRegistered(name)) { + return c; + } + } + throw new InstanceNotFoundException(name.getCanonicalName()); + } + + // the implementation is read only and doesnt suppor the following methods. + + public void addNotificationListener(ObjectName name, + NotificationListener listener, NotificationFilter filter, + Object handback) throws InstanceNotFoundException, IOException { + throw new UnsupportedOperationException(); + } + + public void addNotificationListener(ObjectName name, ObjectName listener, + NotificationFilter filter, Object handback) + throws InstanceNotFoundException, IOException { + throw new UnsupportedOperationException(); + } + + public ObjectInstance createMBean(String className, ObjectName name) + throws ReflectionException, InstanceAlreadyExistsException, + MBeanRegistrationException, MBeanException, + NotCompliantMBeanException, IOException { + throw new UnsupportedOperationException(); + } + + public ObjectInstance createMBean(String className, ObjectName name, + ObjectName loaderName) throws ReflectionException, + InstanceAlreadyExistsException, MBeanRegistrationException, + MBeanException, NotCompliantMBeanException, + InstanceNotFoundException, IOException { + throw new UnsupportedOperationException(); + } + + public ObjectInstance createMBean(String className, ObjectName name, + Object[] params, String[] signature) throws ReflectionException, + InstanceAlreadyExistsException, MBeanRegistrationException, + MBeanException, NotCompliantMBeanException, IOException { + throw new UnsupportedOperationException(); + } + + public ObjectInstance createMBean(String className, ObjectName name, + ObjectName loaderName, Object[] params, String[] signature) + throws ReflectionException, InstanceAlreadyExistsException, + MBeanRegistrationException, MBeanException, + NotCompliantMBeanException, InstanceNotFoundException, IOException { + throw new UnsupportedOperationException(); + } + + public Object invoke(ObjectName name, String operationName, + Object[] params, String[] signature) + throws InstanceNotFoundException, MBeanException, + ReflectionException, IOException { + throw new UnsupportedOperationException(); + } + + public void removeNotificationListener(ObjectName name, ObjectName listener) + throws InstanceNotFoundException, ListenerNotFoundException, + IOException { + throw new UnsupportedOperationException(); + } + + public void removeNotificationListener(ObjectName name, + NotificationListener listener) throws InstanceNotFoundException, + ListenerNotFoundException, IOException { + throw new UnsupportedOperationException(); + } + + public void removeNotificationListener(ObjectName name, + ObjectName listener, NotificationFilter filter, Object handback) + throws InstanceNotFoundException, ListenerNotFoundException, + IOException { + throw new UnsupportedOperationException(); + } + + public void removeNotificationListener(ObjectName name, + NotificationListener listener, NotificationFilter filter, + Object handback) throws InstanceNotFoundException, + ListenerNotFoundException, IOException { + throw new UnsupportedOperationException(); + } + + public void setAttribute(ObjectName name, Attribute attribute) + throws InstanceNotFoundException, AttributeNotFoundException, + InvalidAttributeValueException, MBeanException, + ReflectionException, IOException { + throw new UnsupportedOperationException(); + } + + public AttributeList setAttributes(ObjectName name, AttributeList attributes) + throws InstanceNotFoundException, ReflectionException, IOException { + throw new UnsupportedOperationException(); + } + + public void unregisterMBean(ObjectName name) + throws InstanceNotFoundException, MBeanRegistrationException, + IOException { + throw new UnsupportedOperationException(); + } + +} Propchange: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/jmx/MultiMBeanServer.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/CGLibCallbackProxy.java URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/CGLibCallbackProxy.java?rev=1452654&view=auto ============================================================================== --- sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/CGLibCallbackProxy.java (added) +++ sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/CGLibCallbackProxy.java Tue Mar 5 03:44:55 2013 @@ -0,0 +1,70 @@ +/* + * 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 SF 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.commons.monitor.impl.reflect; + +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Set; + +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +/** + * Proxy a class including all non final methods + */ +public class CGLibCallbackProxy { + + + private Object proxiedAtomic; + private Object proxy; + + public CGLibCallbackProxy(Object object, final ProxyCallback proxyCallback) { + proxiedAtomic = object; + + Enhancer e = new Enhancer(); + e.setSuperclass(object.getClass()); + Class<?> cls = object.getClass(); + Set<Class<?>> classes = new HashSet<Class<?>>(); + Introspect.getInterfaces(cls,classes); + Class<?>[] toImplement = classes.toArray(new Class<?>[classes.size()]); + e.setInterfaces(toImplement); + e.setCallback(new MethodInterceptor() { + + public Object intercept(Object obj, Method method, Object[] args, + MethodProxy methodProxy) throws Throwable { + proxyCallback.callback(method.getName(), args); + return methodProxy.invokeSuper(obj, args); + } + }); + proxy = e.create(); + + } + + + public Object getProxy() { + return proxy; + } + + public Object getProxied() { + return proxiedAtomic; + } + + + +} Propchange: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/CGLibCallbackProxy.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/Introspect.java URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/Introspect.java?rev=1452654&view=auto ============================================================================== --- sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/Introspect.java (added) +++ sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/Introspect.java Tue Mar 5 03:44:55 2013 @@ -0,0 +1,90 @@ +/* + * 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 SF 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.commons.monitor.impl.reflect; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Introspect { + + private static final Logger LOGGER = LoggerFactory.getLogger(Introspect.class); + + public static Method safeGetMethod(Object obj, String method) throws NoSuchMethodException { + return safeGetMethod(obj, method, (Class<?>[])null); + } + + public static Method safeGetMethod(Object obj, String method, + Class<?> ... params) throws NoSuchMethodException { + Method m = null; + Class<?> cls = obj.getClass(); + while (m == null && cls != null && !Object.class.equals(cls)) { + try { + m = cls.getDeclaredMethod(method, params); + LOGGER.debug("Got method {} on class {} with params {} ",new Object[]{ m, cls, Arrays.toString(params)}); + } catch (NoSuchMethodException e) { + LOGGER.debug("No method on class {} with params {} ",new Object[]{ cls, Arrays.toString(params)}); + cls = cls.getSuperclass(); + } + } + if (m == null) { + throw new NoSuchMethodException(method); + } + if (!m.isAccessible()) { + m.setAccessible(true); + } + return m; + } + + public static Field safeGetField(Object obj, String field) + throws NoSuchFieldException { + Field m = null; + Class<?> cls = obj.getClass(); + while (m == null && cls != null && !Object.class.equals(cls)) { + try { + m = cls.getDeclaredField(field); + LOGGER.debug("Got method {} on class {} ", m, cls); + } catch (NoSuchFieldException e) { + LOGGER.debug("No method, trying super {} ", cls); + cls = cls.getSuperclass(); + } + } + if (m == null) { + throw new NoSuchFieldException(field); + } + if (!m.isAccessible()) { + m.setAccessible(true); + } + return m; + } + + public static void getInterfaces(Class<?> cls, Set<Class<?>> classes) { + if ( cls != null ) { + for (Class<?> c : cls.getInterfaces()) { + classes.add(c); + } + getInterfaces(cls.getSuperclass(), classes); + } + } + + +} Propchange: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/Introspect.java ------------------------------------------------------------------------------ svn:eol-style = native Added: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/JDKCallbackProxy.java URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/JDKCallbackProxy.java?rev=1452654&view=auto ============================================================================== --- sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/JDKCallbackProxy.java (added) +++ sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/JDKCallbackProxy.java Tue Mar 5 03:44:55 2013 @@ -0,0 +1,69 @@ +/* + * 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 SF 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.commons.monitor.impl.reflect; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.HashSet; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Proxy a objects interface. + */ +public class JDKCallbackProxy { + + + protected static final Logger LOGGER = LoggerFactory.getLogger(JDKCallbackProxy.class); + private Object proxied; + private Object proxy; + + public JDKCallbackProxy(Object object, final ProxyCallback proxyCallback) { + proxied = object; + Class<?> cls = object.getClass(); + Set<Class<?>> classes = new HashSet<Class<?>>(); + Introspect.getInterfaces(cls,classes); + Class<?>[] toImplement = classes.toArray(new Class<?>[classes.size()]); + proxy = Proxy.newProxyInstance(cls.getClassLoader(), toImplement , new InvocationHandler() { + + public Object invoke(Object obj, Method method, Object[] args) + throws Throwable { + proxyCallback.callback(method.getName(), args); + return method.invoke(proxied, args); + } + }); + + } + + + + + public Object getProxy() { + return proxy; + } + + public Object getProxied() { + return proxied; + } + + + +} Propchange: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/JDKCallbackProxy.java ------------------------------------------------------------------------------ svn:eol-style = native Copied: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/ProxyCallback.java (from r1451503, sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/StatisticsFactory.java) URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/ProxyCallback.java?p2=sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/ProxyCallback.java&p1=sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/StatisticsFactory.java&r1=1451503&r2=1452654&rev=1452654&view=diff ============================================================================== --- sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/StatisticsFactory.java (original) +++ sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/ProxyCallback.java Tue Mar 5 03:44:55 2013 @@ -15,26 +15,10 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -package org.apache.sling.commons.monitor; +package org.apache.sling.commons.monitor.impl.reflect; -import org.apache.sling.commons.monitor.impl.StatisticsImpl; +public interface ProxyCallback { - -/** - * A statistics factory that manages a singleton collection of statistics. - */ -public abstract class StatisticsFactory { - - public static final Statistics statisticsSingleton = new StatisticsImpl(); - - private StatisticsFactory() { - // cant create a factory class. - } - /** - * @return the singleton instance of the collection of statistics. - */ - public static Statistics instance() { - return statisticsSingleton; - } + void callback(String name, Object[] args); } Propchange: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/impl/reflect/ProxyCallback.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/package-info.java URL: http://svn.apache.org/viewvc/sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/package-info.java?rev=1452654&r1=1452653&r2=1452654&view=diff ============================================================================== --- sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/package-info.java (original) +++ sling/whiteboard/ieb/monitor/src/main/java/org/apache/sling/commons/monitor/package-info.java Tue Mar 5 03:44:55 2013 @@ -1,22 +1,7 @@ -/* - * 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 SF 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. - */ -@Version("1.0.0") +@Export() +@Version(value="1.0.0") package org.apache.sling.commons.monitor; +import aQute.bnd.annotation.Export; import aQute.bnd.annotation.Version;