001/* 002 * (C) Copyright 2006-2008 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * matic 018 */ 019package org.nuxeo.runtime.management; 020 021import java.io.IOException; 022import java.lang.management.ManagementFactory; 023import java.net.InetAddress; 024import java.net.MalformedURLException; 025import java.net.UnknownHostException; 026import java.rmi.RemoteException; 027import java.rmi.registry.LocateRegistry; 028import java.util.HashMap; 029import java.util.Map; 030 031import javax.management.MBeanServer; 032import javax.management.MBeanServerFactory; 033import javax.management.ObjectName; 034import javax.management.remote.JMXServiceURL; 035import javax.management.remote.rmi.RMIConnectorServer; 036 037import org.apache.commons.logging.Log; 038import org.apache.commons.logging.LogFactory; 039import org.nuxeo.runtime.model.ComponentInstance; 040import org.nuxeo.runtime.model.DefaultComponent; 041 042public class ServerLocatorService extends DefaultComponent implements ServerLocator { 043 044 public static final String LOCATORS_EXT_KEY = "locators"; 045 046 private static final Log log = LogFactory.getLog(ServerLocatorService.class); 047 048 protected final Map<String, MBeanServer> servers = new HashMap<String, MBeanServer>(); 049 050 protected MBeanServer defaultServer = ManagementFactory.getPlatformMBeanServer(); 051 052 protected String hostname; 053 054 @Override 055 public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 056 if (extensionPoint.equals(LOCATORS_EXT_KEY)) { 057 doRegisterLocator((ServerLocatorDescriptor) contribution); 058 } 059 } 060 061 @Override 062 public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 063 if (extensionPoint.equals(LOCATORS_EXT_KEY)) { 064 doUnregisterLocator((ServerLocatorDescriptor) contribution); 065 } 066 } 067 068 protected void doRegisterLocator(ServerLocatorDescriptor descriptor) { 069 MBeanServer server = descriptor.isExisting ? doFindServer(descriptor.domainName) : doCreateServer(descriptor); 070 servers.put(descriptor.domainName, server); 071 if (descriptor.isDefault) { 072 defaultServer = server; 073 } 074 } 075 076 protected String doGetHostname() { 077 if (hostname != null) { 078 return hostname; 079 } 080 try { 081 InetAddress addr = InetAddress.getLocalHost(); 082 hostname = addr.getHostName(); 083 } catch (UnknownHostException e) { 084 hostname = "localhost"; 085 } 086 return hostname; 087 } 088 089 protected JMXServiceURL doFormatServerURL(ServerLocatorDescriptor descriptor) { 090 try { 091 return new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + descriptor.rmiPort + "/" 092 + descriptor.domainName + "/jmxrmi"); 093 } catch (MalformedURLException e) { 094 throw new ManagementRuntimeException("Cannot format url for " + descriptor.domainName); 095 } 096 } 097 098 protected String doFormatThreadName(ServerLocatorDescriptor descriptor) { 099 return "mbeanServer-" + descriptor.domainName; 100 } 101 102 protected MBeanServer doCreateServer(final ServerLocatorDescriptor descriptor) { 103 MBeanServer server = MBeanServerFactory.createMBeanServer(); 104 JMXServiceURL url = doFormatServerURL(descriptor); 105 if (!descriptor.remote) { 106 return server; 107 } 108 final RMIConnectorServer connector; 109 try { 110 connector = new RMIConnectorServer(url, null, server); 111 } catch (IOException e) { 112 throw new ManagementRuntimeException("Cannot start connector for " + descriptor.domainName, e); 113 } 114 try { 115 connector.start(); 116 } catch (IOException e) { 117 try { 118 LocateRegistry.createRegistry(descriptor.rmiPort); 119 } catch (RemoteException e2) { 120 throw new ManagementRuntimeException("Cannot start RMI connector for " + descriptor.domainName, e); 121 } 122 try { 123 connector.start(); 124 } catch (IOException e2) { 125 throw new ManagementRuntimeException("Cannot start RMI connector for " + descriptor.domainName, e2); 126 } 127 } 128 assert connector.isActive(); 129 log.info("Started a mbean server : " + url); 130 return server; 131 } 132 133 @SuppressWarnings("cast") 134 protected MBeanServer doFindServer(String domainName) { 135 for (MBeanServer server : MBeanServerFactory.findMBeanServer(null)) { 136 String domain = server.getDefaultDomain(); 137 if (domain == null || !domain.equals(domainName)) { 138 continue; 139 } 140 return server; 141 } 142 return defaultServer; 143 } 144 145 protected void doUnregisterLocator(ServerLocatorDescriptor descriptor) { 146 servers.remove(descriptor.domainName); 147 if (descriptor.isDefault) { 148 defaultServer = ManagementFactory.getPlatformMBeanServer(); 149 } 150 } 151 152 @Override 153 @SuppressWarnings("cast") 154 public MBeanServer lookupServer(ObjectName qualifiedName) { 155 if (defaultServer.isRegistered(qualifiedName)) { 156 return defaultServer; 157 } 158 for (MBeanServer server : MBeanServerFactory.findMBeanServer(null)) { 159 if (server.isRegistered(qualifiedName)) { 160 return server; 161 } 162 } 163 throw new ManagementRuntimeException(qualifiedName + " is not registered"); 164 } 165 166 @Override 167 public MBeanServer lookupServer() { 168 return defaultServer; 169 } 170 171 @Override 172 public MBeanServer lookupServer(String domainName) { 173 return doFindServer(domainName); 174 } 175 176 public void registerLocator(String domain, boolean isDefault) { 177 doRegisterLocator(new ServerLocatorDescriptor(domain, isDefault)); 178 } 179 180}