1 /* 2 * #%L 3 * Nuiton Utils 4 * %% 5 * Copyright (C) 2004 - 2010 CodeLutin 6 * %% 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU Lesser General Public License as 9 * published by the Free Software Foundation, either version 3 of the 10 * License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Lesser Public License for more details. 16 * 17 * You should have received a copy of the GNU General Lesser Public 18 * License along with this program. If not, see 19 * <http://www.gnu.org/licenses/lgpl-3.0.html>. 20 * #L% 21 */ 22 package org.nuiton.util.rmi; 23 24 import org.apache.commons.logging.Log; 25 import org.apache.commons.logging.LogFactory; 26 27 import java.rmi.ConnectException; 28 import java.rmi.NotBoundException; 29 import java.rmi.Remote; 30 import java.rmi.RemoteException; 31 import java.rmi.registry.LocateRegistry; 32 import java.rmi.registry.Registry; 33 import java.rmi.server.ExportException; 34 import java.rmi.server.UnicastRemoteObject; 35 36 /** 37 * This class allows to make some service available throw RMI. For each service, 38 * a wrapper will be created which will be put in the RMI registry. This wrapper 39 * will intercept calls to the service and delegate them to it. 40 * 41 * @author Arnaud Thimel - thimel@codelutin.com 42 */ 43 public final class ServiceExporter { 44 45 private static final Log log = LogFactory.getLog(ServiceExporter.class); 46 47 // TODO AThimel 12/01/2011 This settings has to be externalized 48 private static final int PORT = 12345; 49 50 /** Does some checks on RMI configuration */ 51 protected static void testRmiConfig() { 52 String rmiHost = System.getProperty("java.rmi.server.hostname"); 53 if ((rmiHost == null || "".equals(rmiHost.trim())) 54 && log.isWarnEnabled()) { 55 log.warn("Server might not have been initialized properly, " + 56 "please specify '-Djava.rmi.server.hostname=<IP-address>'"); 57 } 58 } 59 60 /** 61 * Will look for the RMI registry. It an external registry cannot be found, 62 * a new one will be created. 63 * 64 * @return the registry found or created 65 * @throws RemoteException in case it is not possible to get the registry 66 */ 67 protected static Registry getRegistry() throws RemoteException { 68 Registry result; 69 try { 70 result = LocateRegistry.getRegistry(PORT); 71 // To test that registry has been created. An exception will be 72 // thrown if registry cannot be called 73 result.list(); 74 } catch (ConnectException ce) { 75 if (log.isWarnEnabled()) { 76 log.warn("Registry not found, creating a new one"); 77 } 78 try { 79 result = LocateRegistry.createRegistry(PORT); 80 } catch (ExportException ee) { // This is the particular case when a registry is already running but not on the correct port. 81 if (log.isWarnEnabled()) { 82 log.warn("Unable to create registry, try using the default one", ee); 83 } 84 85 // Try the default port 86 result = LocateRegistry.getRegistry(); 87 } 88 } 89 return result; 90 } 91 92 /** 93 * Will register a service using the default name. 94 * 95 * @param serviceInterface the interface used to bind the service. The RMI 96 * name will be generated from this class name 97 * @param instance the service instance to bind 98 * @param <E> some interface class 99 * @throws RemoteException in case the registry is not reachable 100 */ 101 public static <E> void registerService(Class<E> serviceInterface, E instance) 102 throws RemoteException { 103 String rmiName = serviceInterface.getName(); 104 registerService(rmiName, instance); 105 } 106 107 /** 108 * Will register a service using the given RMI name. 109 * 110 * @param rmiName the RMI name used to bind the service in the registry 111 * @param instance the service instance to bind 112 * @param <E> some interface class 113 * @throws RemoteException in case the registry is not reachable 114 */ 115 public static <E> void registerService(String rmiName, E instance) 116 throws RemoteException { 117 118 testRmiConfig(); 119 120 // Create the proxy and let him be a stub 121 RemoteMethodExecutorImpl<E> executor = 122 new RemoteMethodExecutorImpl<E>(instance); 123 Remote stub = UnicastRemoteObject.exportObject(executor, 0); 124 125 // Bind into the registry 126 Registry registry = getRegistry(); 127 registry.rebind(rmiName, stub); 128 } 129 130 /** 131 * Will unregister a service using the default name. 132 * 133 * @param serviceInterface the interface used to unbind the service. The RMI 134 * name will be generated from this class name 135 * @throws RemoteException in case the registry is not reachable 136 * @throws NotBoundException in case the given name is not bound 137 */ 138 public static void unregisterService(Class<?> serviceInterface) 139 throws RemoteException, NotBoundException { 140 String rmiName = serviceInterface.getName(); 141 unregisterService(rmiName); 142 } 143 144 /** 145 * Will unregister a service using the given RMI name. 146 * 147 * @param rmiName the RMI name used to unbind the service in the registry 148 * @throws RemoteException in case the registry is not reachable 149 * @throws NotBoundException in case the given name is not bound 150 */ 151 public static void unregisterService(String rmiName) 152 throws RemoteException, NotBoundException { 153 154 // Bind into the registry 155 Registry registry = getRegistry(); 156 registry.unbind(rmiName); 157 } 158 159 }