You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by rm...@apache.org on 2012/09/19 18:27:27 UTC

svn commit: r1387669 - in /openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb: assembler/classic/Assembler.java core/stateless/StatelessContainer.java monitoring/remote/ monitoring/remote/RemoteResourceMonitor.java

Author: rmannibucau
Date: Wed Sep 19 16:27:26 2012
New Revision: 1387669

URL: http://svn.apache.org/viewvc?rev=1387669&view=rev
Log:
TOMEE-421 ping of datasources from JMX

Added:
    openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/monitoring/remote/
    openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/monitoring/remote/RemoteResourceMonitor.java
Modified:
    openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
    openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java

Modified: openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java?rev=1387669&r1=1387668&r2=1387669&view=diff
==============================================================================
--- openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java (original)
+++ openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java Wed Sep 19 16:27:26 2012
@@ -82,6 +82,7 @@ import org.apache.openejb.loader.SystemI
 import org.apache.openejb.monitoring.DynamicMBeanWrapper;
 import org.apache.openejb.monitoring.LocalMBeanServer;
 import org.apache.openejb.monitoring.ObjectNameBuilder;
+import org.apache.openejb.monitoring.remote.RemoteResourceMonitor;
 import org.apache.openejb.observer.Observes;
 import org.apache.openejb.persistence.JtaEntityManagerRegistry;
 import org.apache.openejb.persistence.PersistenceClassLoaderHandler;
@@ -150,6 +151,8 @@ import java.lang.instrument.Instrumentat
 import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.sql.Connection;
+import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -194,7 +197,8 @@ public class Assembler extends Assembler
     protected OpenEjbConfigurationFactory configFactory;
     private final Map<String, AppInfo> deployedApplications = new HashMap<String, AppInfo>();
     private final Set<String> moduleIds = new HashSet<String>();
-    private final Set<ObjectName> containersObjectNames = new HashSet<ObjectName>();
+    private final Set<ObjectName> containerObjectNames = new HashSet<ObjectName>();
+    private final RemoteResourceMonitor remoteResourceMonitor = new RemoteResourceMonitor();
 
 
     @Override
@@ -1092,7 +1096,7 @@ public class Assembler extends Assembler
             }
         }
 
-        final Iterator<ObjectName> it = containersObjectNames.iterator();
+        final Iterator<ObjectName> it = containerObjectNames.iterator();
         final MBeanServer server = LocalMBeanServer.get();
         while (it.hasNext()) {
             try {
@@ -1102,6 +1106,11 @@ public class Assembler extends Assembler
             }
             it.remove();
         }
+        try {
+            remoteResourceMonitor.unregister();
+        } catch (Exception ignored) {
+            // no-op
+        }
 
         NamingEnumeration<Binding> namingEnumeration = null;
         try {
@@ -1514,7 +1523,7 @@ public class Assembler extends Assembler
             final ObjectName objectName = ObjectNameBuilder.uniqueName("containers", serviceInfo.id, service);
             try {
                 LocalMBeanServer.get().registerMBean(new DynamicMBeanWrapper(new JMXContainer(serviceInfo, (Container) service)), objectName);
-                containersObjectNames.add(objectName);
+                containerObjectNames.add(objectName);
             } catch (Exception e) {
                 // no-op
             } catch (NoClassDefFoundError ncdfe) { // OSGi
@@ -1739,17 +1748,32 @@ public class Assembler extends Assembler
             // service becomes a ConnectorReference which merges connection manager and mcf
             service = new ConnectorReference(connectionManager, managedConnectionFactory);
         } else if (service instanceof DataSource) {
-                ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
-                if (classLoader == null) {
-                    classLoader = getClass().getClassLoader();
-                }
+            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+            if (classLoader == null) {
+                classLoader = getClass().getClassLoader();
+            }
 
-                final ImportSql importer = new ImportSql(classLoader, serviceInfo.id, (DataSource) service);
-                if (importer.hasSomethingToImport()) {
-                    importer.doImport();
-                }
+            final ImportSql importer = new ImportSql(classLoader, serviceInfo.id, (DataSource) service);
+            if (importer.hasSomethingToImport()) {
+                importer.doImport();
+            }
 
             logUnusedProperties(DataSourceFactory.forgetRecipe(service, serviceRecipe), serviceInfo);
+
+            final Properties prop = serviceInfo.properties;
+            String url = prop.getProperty("JdbcUrl", prop.getProperty("url"));
+            if (url == null) {
+                url = prop.getProperty("jdbcUrl");
+            }
+            if (url == null) {
+                logger.info("can't find url for " + serviceInfo.id + " will not monitor it");
+            } else {
+                final String host = extractHost(url);
+                if (host != null) {
+                    remoteResourceMonitor.addHost(host);
+                    remoteResourceMonitor.registerIfNot();
+                }
+            }
         } else {
             logUnusedProperties(serviceRecipe, serviceInfo);
         }
@@ -1775,6 +1799,27 @@ public class Assembler extends Assembler
         logger.getChildLogger("service").debug("createService.success", serviceInfo.service, serviceInfo.id, serviceInfo.className);
     }
 
+    private static String extractHost(final String url) { // can be enhanced
+        if (url == null || !url.contains("://")) {
+            return null;
+        }
+
+        final int idx = url.indexOf("://");
+        final String subUrl = url.substring(idx + 3);
+        final int port = subUrl.indexOf(':');
+        final int slash = subUrl.indexOf('/');
+
+        int end = port;
+        if (end < 0 ||  (slash > 0 && slash < end)) {
+            end = slash;
+        }
+        if (end > 0) {
+            return subUrl.substring(0, end);
+        }
+
+        return subUrl;
+    }
+
     private int getIntProperty(Properties properties, String propertyName, int defaultValue) {
         String propertyValue = getStringProperty(properties, propertyName, Integer.toString(defaultValue));
         if (propertyValue == null) {

Modified: openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java?rev=1387669&r1=1387668&r2=1387669&view=diff
==============================================================================
--- openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java (original)
+++ openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java Wed Sep 19 16:27:26 2012
@@ -32,7 +32,6 @@ import javax.ejb.EJBLocalHome;
 import javax.ejb.EJBLocalObject;
 import javax.ejb.EJBObject;
 import javax.interceptor.AroundInvoke;
-import javax.management.ObjectName;
 
 import org.apache.openejb.ApplicationException;
 import org.apache.openejb.BeanContext;

Added: openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/monitoring/remote/RemoteResourceMonitor.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/monitoring/remote/RemoteResourceMonitor.java?rev=1387669&view=auto
==============================================================================
--- openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/monitoring/remote/RemoteResourceMonitor.java (added)
+++ openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/monitoring/remote/RemoteResourceMonitor.java Wed Sep 19 16:27:26 2012
@@ -0,0 +1,166 @@
+/*
+ * 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.openejb.monitoring.remote;
+
+import org.apache.openejb.OpenEJBRuntimeException;
+import org.apache.openejb.monitoring.LocalMBeanServer;
+import org.apache.openejb.monitoring.ObjectNameBuilder;
+import org.fusesource.mqtt.codec.PINGREQ;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.TimeUnit;
+
+public class RemoteResourceMonitor implements DynamicMBean {
+    private static final String PING = "ping";
+    private static final AttributeList ATTRIBUTE_LIST = new AttributeList();
+    private static final MBeanAttributeInfo[] EMPTY_ATTRIBUTES = new MBeanAttributeInfo[0];
+    private static final MBeanNotificationInfo[] EMPTY_NOTIFICATIONS = new MBeanNotificationInfo[0];
+    private static final MBeanParameterInfo[] EMPTY_PARAMETERS = new MBeanParameterInfo[0];
+    private static final MBeanOperationInfo PING_INFO = new MBeanOperationInfo("ping", "ping the parameter host", new MBeanParameterInfo[] {
+                                                                new MBeanParameterInfo("host", String.class.getName(), "the host to ping")
+                                                            }, String.class.getName(), MBeanOperationInfo.INFO);
+
+    private final Collection<String> hosts = new CopyOnWriteArraySet<String>();
+    private ObjectName objectName = null;
+    private MBeanInfo info = null;
+
+    public synchronized void addHost(final String host) {
+        hosts.add(host);
+        buildMBeanInfo();
+    }
+
+    public synchronized void removeHost(final String host) {
+        hosts.remove(host);
+        buildMBeanInfo();
+    }
+
+    public void registerIfNot() { // do it lazily
+        if (objectName != null) {
+            return;
+        }
+
+        final ObjectNameBuilder jmxName = new ObjectNameBuilder("openejb.management");
+        jmxName.set("ObjectType", "hosts");
+        objectName = jmxName.build();
+
+        try {
+            LocalMBeanServer.get().registerMBean(this, objectName);
+        } catch (Exception e) {
+            throw new OpenEJBRuntimeException(e);
+        }
+    }
+
+    public void unregister() {
+        try {
+            LocalMBeanServer.get().unregisterMBean(objectName);
+        } catch (Exception e) {
+            throw new OpenEJBRuntimeException(e);
+        }
+    }
+
+    @Override
+    public Object invoke(final String actionName, final Object[] params, final String[] signature) throws MBeanException, ReflectionException {
+        if (hosts.contains(actionName)) {
+            return ping(actionName);
+        } else if (PING.equals(actionName) && params != null && params.length == 1) {
+            return ping((String) params[0]);
+        }
+        throw new MBeanException(new IllegalArgumentException(), actionName + " doesn't exist");
+    }
+
+    @Override
+    public MBeanInfo getMBeanInfo() {
+        if (info == null) {
+            buildMBeanInfo();
+        }
+        return info;
+    }
+
+    @Override
+    public Object getAttribute(final String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException {
+        throw new AttributeNotFoundException();
+    }
+
+    @Override
+    public void setAttribute(final Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
+        throw new AttributeNotFoundException();
+    }
+
+    @Override
+    public AttributeList getAttributes(String[] attributes) {
+        return ATTRIBUTE_LIST;
+    }
+
+    @Override
+    public AttributeList setAttributes(AttributeList attributes) {
+        return ATTRIBUTE_LIST;
+    }
+
+    private void buildMBeanInfo() {
+        final List<MBeanOperationInfo> operationInfos = new ArrayList<MBeanOperationInfo>();
+        for (String host: hosts) {
+            operationInfos.add(new MBeanOperationInfo(host, "ping host " + host, EMPTY_PARAMETERS, String.class.getName(), MBeanOperationInfo.INFO));
+        }
+        operationInfos.add(PING_INFO);
+        info = new MBeanInfo(RemoteResourceMonitor.class.getName(),
+                "Monitor remote resources",
+                EMPTY_ATTRIBUTES,
+                null,
+                operationInfos.toArray(new MBeanOperationInfo[operationInfos.size()]),
+                EMPTY_NOTIFICATIONS);
+    }
+
+    private static String ping(final String host) {
+        try {
+            final InetAddress address = InetAddress.getByName(host);
+            final long start = System.nanoTime();
+            boolean ok = address.isReachable(30000);
+            final long end = System.nanoTime();
+            if (!ok) {
+                return "Can't ping host, timeout (30s)";
+            }
+            return Long.toString(TimeUnit.NANOSECONDS.toMillis(end - start));
+        } catch (UnknownHostException e) {
+            return "Can't find host: " + e.getMessage();
+        } catch (IOException e) {
+            return "Can't ping host: " + e.getMessage();
+        }
+    }
+}