View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.transport.rmi;
8   
9   import org.mule.api.MuleEvent;
10  import org.mule.api.MuleException;
11  import org.mule.api.MuleMessage;
12  import org.mule.api.construct.FlowConstruct;
13  import org.mule.api.endpoint.EndpointURI;
14  import org.mule.api.endpoint.InboundEndpoint;
15  import org.mule.api.lifecycle.CreateException;
16  import org.mule.api.transport.Connector;
17  import org.mule.transport.AbstractMessageReceiver;
18  import org.mule.transport.ConnectException;
19  import org.mule.transport.rmi.i18n.RmiMessages;
20  import org.mule.util.ClassUtils;
21  
22  import java.lang.reflect.Method;
23  import java.net.InetAddress;
24  
25  import javax.naming.Context;
26  
27  /** TODO */
28  
29  public class RmiCallbackMessageReceiver extends AbstractMessageReceiver
30  {
31      /**
32       * The property name for the service object implementing the callback interface
33       * RmiAble This should be set on the inbound endpoint
34       */
35      public static final String PROPERTY_SERVICE_CLASS_NAME = "serviceClassName";
36  
37      protected RmiConnector connector;
38  
39      protected RmiAble remoteObject = null;
40  
41      private Context jndi = null;
42  
43      private String bindName = null;
44  
45      private int port;
46  
47  
48      public RmiCallbackMessageReceiver(Connector connector, FlowConstruct flowConstruct, InboundEndpoint endpoint)
49              throws CreateException
50      {
51          super(connector, flowConstruct, endpoint);
52          this.connector = (RmiConnector) connector;
53  
54          logger.debug("Initializing with endpoint " + endpoint);
55  
56          String rmiPolicyPath = this.connector.getSecurityPolicy();
57  
58          System.setProperty("java.security.policy", rmiPolicyPath);
59  
60          EndpointURI endpointUri = endpoint.getEndpointURI();
61  
62          port = endpointUri.getPort();
63  
64          if (port < 1)
65          {
66              port = RmiConnector.DEFAULT_RMI_muleRegistry_PORT;
67          }
68  
69  
70          logger.debug("Initialized successfully");
71      }
72  
73      @Override
74      protected void doDispose()
75      {
76          // template method
77      }
78  
79  
80      /**
81       * Initializes endpoint
82       *
83       * @throws org.mule.transport.ConnectException
84       *
85       */
86      @Override
87      protected void doConnect() throws ConnectException
88      {
89          try
90          {
91              // Do not reinit if RMI is already bound to JNDI!!!
92              // TODO Test how things work under heavy load!!!
93              // Do we need threadlocals or so!?!?
94  
95              // TODO [aperepel] consider AtomicBooleans here
96              // for 'initialised/initialising' status, etc.
97              if (null == remoteObject)
98              {
99                  try
100                 {
101                     InetAddress inetAddress = InetAddress.getByName(endpoint.getEndpointURI().getHost());
102 
103                     bindName = endpoint.getEndpointURI().getPath();
104 
105                     remoteObject = getRmiObject();
106 
107                     Method theMethod = remoteObject.getClass().getMethod("setReceiver",
108                             new Class[]{RmiCallbackMessageReceiver.class});
109                     theMethod.invoke(remoteObject, new Object[]{this});
110 
111                     jndi = connector.getJndiContext(inetAddress.getHostAddress() + ":" + port);
112 
113                     jndi.rebind(bindName, remoteObject);
114                 }
115                 catch (Exception e)
116                 {
117                     throw new ConnectException(e, this);
118                 }
119 
120             }
121         }
122         catch (Exception e)
123         {
124             throw new ConnectException(e, this);
125         }
126     }
127 
128     /** Unbinds Rmi class from registry */
129     @Override
130     protected void doDisconnect()
131     {
132         logger.debug("Disconnecting...");
133 
134         try
135         {
136             jndi.unbind(bindName);
137         }
138         catch (Exception e)
139         {
140             logger.error(e);
141         }
142 
143         logger.debug("Disconnected successfully.");
144     }
145 
146     @Override
147     protected void doStart() throws MuleException
148     {
149         // nothing to do
150     }
151 
152     @Override
153     protected void doStop() throws MuleException
154     {
155         // nothing to do
156     }
157 
158     /**
159      * Gets RmiAble objetc for registry to add in.
160      *
161      * @return java.rmi.Remote and RmiAble implementing class
162      * @throws org.mule.api.lifecycle.ConnectException
163      */
164     private RmiAble getRmiObject() throws ConnectException
165     {
166         String className = (String) endpoint.getProperty(PROPERTY_SERVICE_CLASS_NAME);
167 
168         if (null == className)
169         {
170             throw new ConnectException(RmiMessages.messageReceiverNeedsRmiAble(), this);
171         }
172 
173         RmiAble remote;
174 
175         try
176         {
177             remote = (RmiAble) ClassUtils.instanciateClass(className, new Object[]{}, this.getClass());
178         }
179         catch (Exception e)
180         {
181             throw new ConnectException(RmiMessages.serviceClassInvocationFailed(), e, this);
182         }
183 
184         return (remote);
185     }
186 
187     public MuleEvent routeMessage(Object payload) throws MuleException
188     {
189         MuleMessage messageToRoute = createMuleMessage(payload, endpoint.getEncoding());
190         return routeMessage(messageToRoute);
191     }
192 }