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
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
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
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 }