View Javadoc

1   /*
2    * $Id: RmiConnector.java 7976 2007-08-21 14:26:13Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.providers.rmi;
12  
13  import org.mule.config.MuleProperties;
14  import org.mule.config.i18n.CoreMessages;
15  import org.mule.providers.AbstractJndiConnector;
16  import org.mule.providers.rmi.i18n.RmiMessages;
17  import org.mule.umo.UMOComponent;
18  import org.mule.umo.UMOEvent;
19  import org.mule.umo.UMOException;
20  import org.mule.umo.endpoint.UMOEndpoint;
21  import org.mule.umo.endpoint.UMOEndpointURI;
22  import org.mule.umo.endpoint.UMOImmutableEndpoint;
23  import org.mule.umo.lifecycle.InitialisationException;
24  import org.mule.umo.provider.DispatchException;
25  import org.mule.umo.provider.UMOMessageReceiver;
26  import org.mule.util.ArrayUtils;
27  import org.mule.util.ClassUtils;
28  import org.mule.util.IOUtils;
29  
30  import java.io.IOException;
31  import java.lang.reflect.Method;
32  import java.net.InetAddress;
33  import java.net.URL;
34  import java.rmi.NotBoundException;
35  import java.rmi.RMISecurityManager;
36  import java.rmi.Remote;
37  import java.util.List;
38  
39  import javax.naming.NamingException;
40  
41  import org.apache.commons.collections.MapUtils;
42  
43  /**
44   * <code>RmiConnector</code> can bind or send to a given RMI port on a given host.
45   */
46  public class RmiConnector extends AbstractJndiConnector
47  {
48      public static final int DEFAULT_RMI_REGISTRY_PORT = 1099;
49  
50      public static final String PROPERTY_RMI_SECURITY_POLICY = "securityPolicy";
51  
52      public static final String PROPERTY_RMI_SERVER_CODEBASE = "serverCodebase";
53  
54      public static final String PROPERTY_SERVER_CLASS_NAME = "serverClassName";
55  
56      /**
57       * The property name that explicitly defines which argument types should be
58       * passed to a remote object method invocation. This is a comma-separate list for
59       * fully qualified classnames. If this property is not set on an outbound
60       * endpoint, the argument types will be determined automatically from the payload
61       * of the current message
62       */
63      public static final String PROPERTY_SERVICE_METHOD_PARAM_TYPES = "methodArgumentTypes";
64  
65      /**
66       * The property name for a list of objects used to call a Remote object via an
67       * RMI or EJB MessageReceiver
68       */
69      public static final String PROPERTY_SERVICE_METHOD_PARAMS_LIST = "methodArgumentsList";
70  
71      private String securityPolicy = null;
72  
73      private String serverCodebase = null;
74  
75      private String serverClassName = null;
76  
77      protected long pollingFrequency = 1000L;
78  
79      private SecurityManager securityManager = new RMISecurityManager();
80  
81      protected void doInitialise() throws InitialisationException
82      {
83  
84          if (securityPolicy != null)
85          {
86              System.setProperty("java.security.policy", securityPolicy);
87          }
88  
89          // Set security manager
90          if (securityManager != null)
91          {
92              System.setSecurityManager(securityManager);
93          }
94  
95          initJndiContext();
96      }
97  
98      protected void doDispose()
99      {
100         // template method
101     }
102 
103     protected void doConnect() throws Exception
104     {
105         // template method
106     }
107 
108     protected void doDisconnect() throws Exception
109     {
110         // template method
111     }
112 
113     protected void doStart() throws UMOException
114     {
115         // template method
116     }
117 
118     protected void doStop() throws UMOException
119     {
120         // template method
121     }
122 
123     public String getProtocol()
124     {
125         return "rmi";
126     }
127 
128     /**
129      * @return Returns the securityPolicy.
130      */
131     public String getSecurityPolicy()
132     {
133         return securityPolicy;
134     }
135 
136     /**
137      * @param path The securityPolicy to set.
138      */
139     public void setSecurityPolicy(String path)
140     {
141         // verify securityPolicy existence
142         if (path != null)
143         {
144             URL url = IOUtils.getResourceAsUrl(path, RmiConnector.class);
145             if (url == null)
146             {
147                 throw new IllegalArgumentException(
148                     "Error on initialization, RMI security policy does not exist");
149             }
150             this.securityPolicy = url.toString();
151         }
152     }
153 
154     /**
155      * Method getServerCodebase
156      *
157      * @return
158      */
159     public String getServerCodebase()
160     {
161         return (this.serverCodebase);
162     }
163 
164     /**
165      * Method setServerCodebase
166      *
167      * @param serverCodebase
168      */
169     public void setServerCodebase(String serverCodebase)
170     {
171         this.serverCodebase = serverCodebase;
172     }
173 
174     /**
175      * Method getServerClassName
176      *
177      * @return
178      */
179     public String getServerClassName()
180     {
181         return (this.serverClassName);
182     }
183 
184     /**
185      * Method setServerClassName
186      *
187      * @param serverClassName
188      */
189     public void setServerClassName(String serverClassName)
190     {
191         this.serverClassName = serverClassName;
192     }
193 
194     public SecurityManager getSecurityManager()
195     {
196         return securityManager;
197     }
198 
199     public void setSecurityManager(SecurityManager securityManager)
200     {
201         this.securityManager = securityManager;
202     }
203 
204     public UMOMessageReceiver createReceiver(UMOComponent component, UMOEndpoint endpoint) throws Exception
205     {
206         final Object[] args = new Object[]{new Long(pollingFrequency)};
207         return getServiceDescriptor().createMessageReceiver(this, component, endpoint, args);
208     }
209 
210     /**
211      * Helper method for Dispatchers and Receives to extract the correct method from
212      * a Remote object
213      *
214      * @param remoteObject The remote object on which to invoke the method
215      * @param event The current event being processed
216      * @return
217      * @throws org.mule.umo.UMOException
218      * @throws NoSuchMethodException
219      * @throws ClassNotFoundException
220      */
221     public Method getMethodObject(Remote remoteObject, UMOEvent event)
222         throws UMOException, NoSuchMethodException, ClassNotFoundException
223     {
224         UMOEndpointURI endpointUri = event.getEndpoint().getEndpointURI();
225 
226         String methodName = MapUtils.getString(endpointUri.getParams(), MuleProperties.MULE_METHOD_PROPERTY,
227             null);
228 
229         if (null == methodName)
230         {
231             methodName = (String)event.getMessage().removeProperty(MuleProperties.MULE_METHOD_PROPERTY);
232 
233             if (null == methodName)
234             {
235                 throw new DispatchException(
236                     RmiMessages.messageParamServiceMethodNotSet(), 
237                     event.getMessage(), event.getEndpoint());
238             }
239         }
240 
241         Class[] argTypes;
242 
243         // Parse method args
244 
245         Object args = event.getMessage().getProperty(RmiConnector.PROPERTY_SERVICE_METHOD_PARAM_TYPES);
246 
247         String argumentString = null;
248 
249         if (args instanceof List)
250         {
251             List arguments = (List) args;
252             argumentString = (String) arguments.get(0);
253         }
254         else if(args instanceof String)
255         {
256             argumentString = (String)args;
257         }
258 
259         if (null != argumentString)
260         {
261             String[] split = argumentString.split(",");
262 
263             argTypes = new Class[split.length];
264             for (int i = 0; i < split.length; i++)
265             {
266                 argTypes[i] = ClassUtils.loadClass(split[i].trim(), getClass());
267 
268             }
269         }
270         else
271         {
272             argTypes = ClassUtils.getClassTypes(event.getTransformedMessage());
273         }
274 
275         try
276         {
277             return remoteObject.getClass().getMethod(methodName, argTypes);
278         }
279         catch (NoSuchMethodException e)
280         {
281             throw new NoSuchMethodException(
282                 CoreMessages.methodWithParamsNotFoundOnObject(methodName, ArrayUtils.toString(argTypes),
283                     remoteObject.getClass()).toString());
284         }
285         catch (SecurityException e)
286         {
287             throw e;
288         }
289     }
290 
291     protected Object getRemoteRef(UMOImmutableEndpoint endpoint)
292         throws IOException, NotBoundException, NamingException, InitialisationException
293     {
294 
295         UMOEndpointURI endpointUri = endpoint.getEndpointURI();
296 
297         String serviceName = endpointUri.getPath();
298         try
299         {
300             // Test if we can find the object locally
301             return getJndiContext().lookup(serviceName);
302         }
303         catch (NamingException e)
304         {
305             // Strip path seperator
306         }
307 
308         try
309         {
310             serviceName = serviceName.substring(1);
311             return getJndiContext().lookup(serviceName);
312         }
313         catch (NamingException e)
314         {
315             // Try with full host and path
316         }
317 
318         int port = endpointUri.getPort();
319         if (port < 1)
320         {
321             if (logger.isWarnEnabled())
322             {
323                 logger.warn("RMI port not set on URI: " + endpointUri + ". Using default port: "
324                             + RmiConnector.DEFAULT_RMI_REGISTRY_PORT);
325             }
326             port = RmiConnector.DEFAULT_RMI_REGISTRY_PORT;
327         }
328 
329         InetAddress inetAddress = InetAddress.getByName(endpointUri.getHost());
330 
331         return getJndiContext(inetAddress.getHostAddress() + ":" + port).lookup(serviceName);
332     }
333 
334     public Remote getRemoteObject(UMOImmutableEndpoint endpoint)
335         throws IOException, NotBoundException, NamingException, InitialisationException
336     {
337         return (Remote)getRemoteRef(endpoint);
338     }
339 
340     public long getPollingFrequency()
341     {
342         return pollingFrequency;
343     }
344 
345     public void setPollingFrequency(long pollingFrequency)
346     {
347         this.pollingFrequency = pollingFrequency;
348     }
349 
350 }