View Javadoc

1   package org.controlhaus.xfire.client;
2   
3   import java.io.IOException;
4   import java.lang.annotation.Annotation;
5   import java.lang.reflect.Method;
6   import java.util.ArrayList;
7   import java.util.List;
8   
9   import javax.xml.stream.XMLStreamException;
10  import javax.xml.stream.XMLStreamReader;
11  import javax.xml.stream.XMLStreamWriter;
12  
13  import org.apache.beehive.controls.api.context.Context;
14  import org.apache.beehive.controls.api.context.ResourceContext;
15  import org.apache.beehive.controls.api.context.ControlBeanContext;
16  import org.apache.beehive.controls.api.events.Client;
17  import org.apache.beehive.controls.api.events.EventHandler;
18  import org.apache.beehive.controls.api.bean.ControlImplementation;
19  import org.apache.beehive.controls.api.bean.Extensible;
20  import org.apache.xmlbeans.XmlObject;
21  import org.apache.xmlbeans.XmlOptions;
22  import org.codehaus.xfire.client.ClientHandler;
23  import org.codehaus.xfire.client.http.SoapHttpClient;
24  import org.codehaus.xfire.fault.XFireFault;
25  import org.codehaus.xfire.xmlbeans.client.XMLBeansClientHandler;
26  import org.controlhaus.xfire.client.XFireClientControl.ServiceUrl;
27  
28  /***
29   * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
30   * @since Nov 5, 2004
31   */
32  @ControlImplementation
33  public class XFireClientControlImpl
34      implements XFireClientControl, Extensible
35  {
36      @Context ControlBeanContext context;
37      @Context ResourceContext resourceContext;
38      @Client EndInvokeCallback callback;
39      
40      private String encoding;
41      private String serviceUrl;
42      
43      private XmlOptions options;
44      private SoapHttpClient client;
45  
46      @EventHandler (field="resourceContext", 
47                     eventSet=ResourceContext.ResourceEvents.class, 
48                     eventName="onAcquire")
49      public void onAcquire()
50      {
51          options = new XmlOptions();
52          options.setCharacterEncoding( getEncoding() );
53          
54          ServiceUrl destProp = 
55              (ServiceUrl) context.getControlPropertySet(XFireClientControl.ServiceUrl.class);
56          if ( destProp != null )
57          {
58              serviceUrl = destProp.value();
59          }
60          
61          Encoding encProp = 
62              (Encoding) context.getControlPropertySet(XFireClientControl.Encoding.class);
63          if ( encProp != null )
64          {
65              encoding = encProp.value();
66          }
67      }
68  
69      public XmlObject[] invoke(XmlObject[] request) 
70          throws IOException, XFireFault
71      {
72          return invoke(request, null);
73      }
74      
75      public XmlObject[] invoke(XmlObject[] request, XmlObject[] reqHeaders) 
76          throws IOException, XFireFault
77      {
78          XMLBeansClientHandler handler = new XMLBeansClientHandler(options);
79          handler.setRequest(request);
80          
81          XMLBeansClientHandler headHandler = new XMLBeansClientHandler(options);
82          headHandler.setRequest(reqHeaders);
83          
84          SoapHttpClient client = new SoapHttpClient(handler, headHandler, getServiceUrl());
85          client.invoke();
86          
87          return handler.getResponse();
88      }
89      
90      public void beginInvoke(XmlObject[] request, XmlObject[] reqHeaders) 
91  	{
92          ServiceInvokerThread thread = 
93              new ServiceInvokerThread(request, reqHeaders, options, getServiceUrl(), callback );
94          
95          thread.run();
96  	}
97      
98      public String getServiceUrl()
99      {
100         return serviceUrl;
101     }
102     
103     public String getEncoding()
104     {
105         return encoding;
106     }
107     
108     /***
109      * Gets the HeaderHandler.  Override this or fill this in
110      * to provide your own HeaderHandler.
111      * @return null by default.
112      */
113     public ClientHandler getHeaderHandler()
114     {
115         return null;
116     }
117     
118     public Object invoke(Method m, Object [] args) throws Throwable
119     {
120         if ( getServiceUrl() == null )
121         {
122             ServiceUrl a = m.getDeclaringClass().getAnnotation(ServiceUrl.class);
123             serviceUrl = a.value();
124         }
125 
126         List<XmlObject> reqArgs = new ArrayList<XmlObject>(args.length);
127         List<XmlObject> headerArgs = new ArrayList<XmlObject>();
128         
129         // Find the SoapHeaders
130         for ( int i = 0; i < args.length; i++ )
131         {
132             if ( isSoapHeader(m, i) )
133                 headerArgs.add((XmlObject)args[i]);
134             else
135                 reqArgs.add((XmlObject)args[i]);
136         }
137 
138         XmlObject[] arr = (XmlObject[]) reqArgs.toArray(new XmlObject[reqArgs.size()]);
139         XmlObject[] headers = (XmlObject[]) headerArgs.toArray(new XmlObject[headerArgs.size()]);
140         
141         if ( !m.isAnnotationPresent(Asynchronous.class) )
142         {
143             // Invoke synchronously
144 	        if ( m.getReturnType().isArray() )
145 	            return invoke( (XmlObject[]) arr, headers );
146 	        else
147 	            return invoke( (XmlObject[]) arr, headers )[0];
148         }
149         else
150         {
151             // Invoke asynchronously
152             beginInvoke( (XmlObject[]) arr, headers );
153             return null;
154         }
155     }
156     
157     private boolean isSoapHeader(Method m, int i)
158     {
159         Annotation[] annots = m.getParameterAnnotations()[i];
160         
161         for ( int j = 0; j < annots.length; j++ )
162         {
163             if ( annots[j].annotationType().equals(SoapHeader.class) )
164                 return true;
165         }
166         
167         return false;
168     }
169 
170     public class ServiceInvokerThread
171     	extends Thread
172 	{
173         private EndInvokeCallback callback;
174         private SoapHttpClient client;
175         private XMLBeansClientHandler handler;
176         private XMLBeansClientHandler headHandler;
177         
178         public ServiceInvokerThread( XmlObject[] request, 
179                                      XmlObject[] reqHeaders, 
180                                      XmlOptions options,
181                                      String serviceUrl,
182                                      EndInvokeCallback callback )
183         {
184             if (callback == null)
185                 throw new IllegalArgumentException("Callback cannot be null.");
186 
187             this.callback = callback;
188             
189             handler = new XMLBeansClientHandler(options);
190             handler.setRequest(request);
191             
192             headHandler = new XMLBeansClientHandler(options);
193             headHandler.setRequest(reqHeaders);
194             
195             client = new SoapHttpClient(handler, headHandler, getServiceUrl());
196         }
197         
198         public void run()
199         {
200             try
201             {
202 	            client.invoke();
203 	            
204 	            callback.endInvoke(handler.getResponse(), headHandler.getResponse());
205             }
206             catch ( IOException e )
207             {
208                 callback.handleFault( new XFireFault("Couldn't connect to the service.", e, XFireFault.SENDER) );
209             }
210             catch ( XFireFault fault )
211             {
212                 callback.handleFault(fault);
213             }
214         }
215 	}
216 }