View Javadoc
1   package org.andromda.cartridges.support.webservice.client;
2   
3   import org.aopalliance.intercept.MethodInterceptor;
4   import org.aopalliance.intercept.MethodInvocation;
5   import org.apache.commons.codec.binary.Base64;
6   import org.apache.commons.lang.StringUtils;
7   import org.apache.commons.logging.Log;
8   import org.apache.commons.logging.LogFactory;
9   import org.springframework.aop.support.AopUtils;
10  import org.springframework.beans.factory.InitializingBean;
11  import org.springframework.beans.factory.support.RootBeanDefinition;
12  import org.springframework.remoting.rmi.RmiClientInterceptorUtils;
13  
14  
15  /**
16   * Interceptor for accessing a specific port of a web service.
17   * Change from RootBeanDefinition to GenericBeanDefinition when using Spring 2.5
18   */
19  public class Axis2PortClientInterceptor
20      extends org.springframework.beans.factory.support.RootBeanDefinition
21      implements MethodInterceptor,
22          InitializingBean
23  {
24      private static final long serialVersionUID = 34L;
25      /**
26       * LogFactory.getLog(Axis2PortClientInterceptor.class)
27       */
28      protected final Log logger = LogFactory.getLog(Axis2PortClientInterceptor.class);
29      private final Object preparationMonitor = new Object();
30      private String username;
31  
32      /**
33       * Set the username to connect to the service.
34       * @param username
35       */
36      public void setUsername(String username)
37      {
38          this.username = username;
39      }
40  
41      /**
42       * Return the username to connect to the service.
43       * @return username
44       */
45      public String getUsername()
46      {
47          return username;
48      }
49  
50      private String password;
51  
52      /**
53       * Set the password to connect to the service.
54       * @param password
55       */
56      public void setPassword(String password)
57      {
58          this.password = password;
59      }
60  
61      /**
62       * Return the password to connect to the service.
63       * @return password
64       */
65      public String getPassword()
66      {
67          String password = this.password;
68          if (password != null && this.getBase64Password())
69          {
70              password = new String(Base64.decodeBase64(password.getBytes()));
71          }
72          return password;
73      }
74  
75      private boolean base64Password;
76  
77      /**
78       * Sets a flag indicating whether or not the password given is in Base64.
79       *
80       * @param base64Password true/false
81       */
82      public void setBase64Password(boolean base64Password)
83      {
84          this.base64Password = base64Password;
85      }
86  
87      /**
88       * Gets the flag indicating whether or not the password given is in Base64.
89       *
90       * @return true/false
91       */
92      public boolean getBase64Password()
93      {
94          return this.base64Password;
95      }
96  
97      private long timeout;
98  
99      /**
100      * Sets the timeout of the client in seconds.
101      *
102      * @param timeout
103      */
104     public void setTimeout(final long timeout)
105     {
106         this.timeout = timeout;
107     }
108 
109     /**
110      * Gets the timeout of the client in seconds.
111      *
112      * @return the timeout.
113      */
114     public long getTimeout()
115     {
116         return this.timeout;
117     }
118 
119     private Class serviceInterface;
120 
121     /**
122      * Set the interface of the service that this factory should create a proxy for.
123      * @param serviceInterface
124      */
125     public void setServiceInterface(Class serviceInterface)
126     {
127         if (serviceInterface != null && !serviceInterface.isInterface())
128         {
129             throw new IllegalArgumentException("serviceInterface must be an interface");
130         }
131         this.serviceInterface = serviceInterface;
132     }
133 
134     /**
135      * Return the interface of the service that this factory should create a proxy for.
136      * @return serviceInterface
137      */
138     public Class getServiceInterface()
139     {
140         return serviceInterface;
141     }
142 
143     private String wsdlUrl;
144 
145     /**
146      * Returns the URL to the WSDL for the service.
147      *
148      * @return the wsdlUrl
149      */
150     public String getWsdlUrl()
151     {
152         return wsdlUrl;
153     }
154 
155     /**
156      * Sets the WSDL URL for the service.
157      *
158      * @param wsdlUrl the wsdlUrl to set
159      */
160     public void setWsdlUrl(String wsdlUrl)
161     {
162         this.wsdlUrl = wsdlUrl;
163     }
164 
165     private String portAddress;
166 
167     /**
168      * Returns the port address (if not using a port address in the WSDL).
169      *
170      * @return the portAddress
171      */
172     public String getPortAddress()
173     {
174         return portAddress;
175     }
176 
177     /**
178      * Sets the port address (if to use one other than the one in the WSDL).
179      *
180      * @param portAddress the portAddress to set
181      */
182     public void setPortAddress(String portAddress)
183     {
184         this.portAddress = portAddress;
185     }
186 
187     private TypeMapper typeMapper = new DefaultTypeMapper();
188 
189     /**
190      * Sets the {@link TypeMapper} to use.  It only makes sense to set this
191      * if you want to change the default type mapping behavoir.
192      *
193      * @param typeMapper the typeMapper to set
194      * @throws IllegalAccessException
195      * @throws InstantiationException
196      */
197     public void setTypeMapper(Class typeMapper)
198         throws InstantiationException, IllegalAccessException
199     {
200         if (typeMapper == null)
201         {
202             throw new IllegalArgumentException("'typeMapper' can not be null");
203         }
204         if (!TypeMapper.class.isAssignableFrom(typeMapper))
205         {
206             throw new IllegalArgumentException("'typeMapper' must be an instance of: " + TypeMapper.class.getName());
207         }
208         this.typeMapper = (TypeMapper)typeMapper.newInstance();
209     }
210 
211     /**
212      * Prepares the JAX-RPC service and port if the "lazyInit"
213      * isn't false.
214      */
215     public void afterPropertiesSet()
216     {
217         this.prepare();
218     }
219 
220     private WebServiceClient client;
221 
222     /**
223      * Create and initialize the service for the specified WSDL.
224      */
225     public void prepare()
226     {
227         synchronized (this.preparationMonitor)
228         {
229             if (this.getServiceInterface() == null)
230             {
231                 throw new IllegalArgumentException("'serviceInterface' must be specified!");
232             }
233             if (StringUtils.isBlank(this.getPortAddress()))
234             {
235                 throw new IllegalArgumentException("'portAddress' must be specified!");
236             }
237             if (StringUtils.isBlank(this.getWsdlUrl()))
238             {
239                 throw new IllegalArgumentException("'wsdlUrl' must be specified!");
240             }
241             if (this.client == null)
242             {
243                 this.client =
244                     new WebServiceClient(
245                         this.getWsdlUrl(),
246                         this.getPortAddress(),
247                         this.getServiceInterface(),
248                         this.getUsername(),
249                         this.getPassword());
250                 this.client.setTimeout(this.getTimeout());
251                 this.client.setTypeMapper(this.typeMapper);
252             }
253         }
254     }
255 
256     /**
257      * Translates the method invocation into a JAX-RPC service invocation.
258      * Uses traditional RMI stub invocation if a JAX-RPC port stub is available;
259      * falls back to JAX-RPC dynamic calls else.
260      * @param invocation
261      * @return invoked operation return
262      * @throws Throwable
263      * @see WebServiceClient#invokeBlocking(String, Object[])
264      * @see org.springframework.remoting.rmi.RmiClientInterceptorUtils
265      */
266     public Object invoke(MethodInvocation invocation)
267         throws Throwable
268     {
269         if (AopUtils.isToStringMethod(invocation.getMethod()))
270         {
271             return "Axis2 proxy for port [" + this.getPortAddress() + "] of service [" +
272                 this.getServiceInterface().getName() + ']';
273         }
274         if (logger.isDebugEnabled())
275         {
276             logger.debug(
277                 "Invoking '" + invocation.getMethod().getName() + "' on port: '" +
278                 this.getPortAddress() + "' through interface: '" + this.getServiceInterface().getName() + '\'');
279         }
280         try
281         {
282             try
283             {
284                 return this.client.invokeBlocking(
285                     invocation.getMethod().getName(),
286                     invocation.getArguments());
287             }
288             finally
289             {
290                 this.client.cleanup();
291             }
292         }
293         catch (WebServiceClientException exception)
294         {
295             throw RmiClientInterceptorUtils.convertRmiAccessException(
296                 invocation.getMethod(),
297                 exception,
298                 this.getServiceInterface().getName());
299         }
300     }
301 
302     /**
303      * @see org.springframework.beans.factory.support.RootBeanDefinition#cloneBeanDefinition()
304      */
305     public RootBeanDefinition cloneBeanDefinition() {
306         return new RootBeanDefinition(this);
307     }
308 }