View Javadoc

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