1 /****************************************************************************
2 * Copyright (c) 2005, 2006, 2007, 2008, 2009 Imola Informatica.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the LGPL License v2.1
5 * which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/lgpl.html
7 ****************************************************************************/
8 package it.imolinfo.jbi4corba.webservice.runtime;
9
10 import it.imolinfo.jbi4corba.Logger;
11 import it.imolinfo.jbi4corba.LoggerFactory;
12 import it.imolinfo.jbi4corba.exception.Jbi4CorbaException;
13 import it.imolinfo.jbi4corba.jbi.Messages;
14 import it.imolinfo.jbi4corba.webservice.descriptor.ProviderServiceDescriptor;
15 import it.imolinfo.jbi4corba.webservice.generator.MethodSignature;
16 import java.lang.reflect.Array;
17 import java.lang.reflect.InvocationTargetException;
18 import java.lang.reflect.Method;
19 import java.util.Arrays;
20 import java.util.List;
21 import net.java.hulp.measure.Probe;
22
23 import org.apache.cxf.frontend.MethodDispatcher;
24 import org.apache.cxf.helpers.CastUtils;
25 import org.apache.cxf.interceptor.Fault;
26 import org.apache.cxf.message.Exchange;
27 import org.apache.cxf.message.FaultMode;
28 import org.apache.cxf.message.MessageContentsList;
29 import org.apache.cxf.service.Service;
30 import org.apache.cxf.service.invoker.AbstractInvoker;
31 import org.apache.cxf.service.model.BindingOperationInfo;
32 import org.apache.cxf.service.model.MessageInfo;
33 import org.apache.cxf.service.model.MessagePartInfo;
34 import org.omg.CORBA.SystemException;
35
36 /**
37 * This class handle invokation of web services and forward in to a legacy
38 * service invokation.
39 */
40 public final class ProviderServiceInvoker extends AbstractInvoker {
41
42 /**
43 * Logger.
44 */
45 private static final Logger LOG = LoggerFactory.getLogger(ProviderServiceInvoker.class);
46 /**
47 * The responsible to translate localized messages.
48 */
49 private static final Messages MESSAGES = Messages.getMessages(ProviderServiceInvoker.class);
50
51 /**
52 * The object proxed by the invoker
53 */
54 Object obj = null;
55
56 private Probe mMeasurement;
57 /**
58 * The service descriptor.
59 */
60 private ProviderServiceDescriptor serviceDescriptor;
61 /**
62 * The Servant is a Corba Object.
63 */
64 boolean isCorbaServant = true;
65
66
67 /**
68 * Constructor.
69 *
70 * @param serviceDescriptor The service descriptor
71 */
72 public ProviderServiceInvoker(
73 final ProviderServiceDescriptor serviceDescriptor) {
74 this.serviceDescriptor = serviceDescriptor;
75 if (serviceDescriptor != null) {
76 obj = serviceDescriptor.getCorbaObjectReference();
77 }
78 }
79
80 /**
81 * Constructor.
82 *
83 * @param serviceDescriptor The service descriptor
84 */
85 public ProviderServiceInvoker(
86 final ProviderServiceDescriptor serviceDescriptor, boolean isCorbaServant) {
87 this.serviceDescriptor = serviceDescriptor;
88 if (serviceDescriptor != null) {
89 obj = serviceDescriptor.getCorbaObjectReference();
90 }
91 this.isCorbaServant = isCorbaServant;
92 }
93
94 /**
95 * Creates and returns a service object depending on the scope.
96 */
97 public Object getServiceObject(final Exchange context) {
98 LOG.debug("Returning object for exchange: " + context.getInMessage());
99 return obj;
100 }
101
102 /**
103 * Set the service object for testing pourpose
104 */
105 public void setServiceObject(Object obj) {
106 this.obj = obj;
107 }
108
109 /**
110 * Sets ths classloader to find the corba classes and invokes the superclass.
111 */
112 @Override
113 public Object invoke(Exchange exchange, Object o) {
114
115 Object dynamicObject=null;
116 //Is used to use the correct Object for invokatio
117 //It's the dynamic is dynamic is != null else is the obj.
118 Object currentObj=null;
119
120 //If this request is dynamic the object used for the invocation is generated from the IOR
121
122 if (exchange.get("EPR_IOR") != null) {
123 try {
124
125 String ior=exchange.get("EPR_IOR").toString();
126 dynamicObject = serviceDescriptor.getEndpoint().getCorbaObjectReference(ior);
127
128 } catch (Jbi4CorbaException e) {
129 String msg = MESSAGES.getString("CRB000766_Unable_to_get_corba_object_from_IOR");
130 LOG.error(msg, e.getMessage());
131 exchange.getOutMessage().put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT);
132 exchange.getOutFaultMessage().setContent(Exception.class, new Fault(e));
133 // e.printStackTrace();
134 throw new Fault(e);
135 }
136
137 }
138
139 LOG.debug("Invoking exchange: " + exchange + " with object: " + o.getClass().getName() + "[" + o + "] using CXF");
140
141 // Stop chrono for measure of Denormalization
142 mMeasurement = (Probe) exchange.get("Measure-deN");
143 mMeasurement.end();
144
145 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
146 Thread.currentThread().setContextClassLoader(
147 serviceDescriptor.getOriginalClassLoader());
148
149 // information needed for service to corba and corba to service object transformation
150 RuntimeInformation runtimeInfo = new RuntimeInformation(serviceDescriptor.getUrlClassLoader(),
151 serviceDescriptor.getOriginalClassLoader(), serviceDescriptor.getAllCorbaTypes(), serviceDescriptor.getEndpoint(),
152 serviceDescriptor.getEndpoint().getOrb(), serviceDescriptor.getAllIDLTypes(), serviceDescriptor.getCorbaEnumMap(),
153 serviceDescriptor.getIdToClassNameMap(), serviceDescriptor.getTypeDefs());
154
155
156 try {
157 // TODO: add i18 messages on exceptions
158 BindingOperationInfo bop = exchange.get(BindingOperationInfo.class);
159 MethodDispatcher md = (MethodDispatcher) exchange.get(Service.class).get(MethodDispatcher.class.getName());
160 Method m = md.getMethod(bop);
161
162 bop.getInput().getMessageInfo().getMessageParts();
163
164 // Extract the Params. With CXF 2.1.x, the Object param is changed and contains
165 // a wrapper of the
166 List<Object> params = extractParams(o, bop.getInput().getMessageInfo());
167
168 Object[] paramArray = new Object[]{};
169 if (params != null) {
170 paramArray = params.toArray();
171 }
172
173
174 if (LOG.isDebugEnabled()) {
175
176 LOG.debug("Parameters:");
177 for (int i = 0; i < paramArray.length; i++) {
178 if (paramArray[i] != null) {
179 LOG.debug("Parameter #" + i + " of class:" + paramArray[i].getClass().getName());
180
181 } else {
182 LOG.debug("Parameter #" + i + " is null");
183 }
184
185 }
186 }
187 try {
188
189 LOG.debug(">>>> OBJ: " + obj);
190 if (obj == null) {
191 if(serviceDescriptor.getLocalizationType()!=null){
192 if (serviceDescriptor.getCorbaObjectReference() == null) {
193 LOG.debug(">>>> Reconnect begin...");
194 serviceDescriptor.getEndpoint().locateCorbaService();
195 LOG.debug(">>>> Reconnect end...");
196 }
197
198 }
199 //get corbaObjectReference
200 obj = serviceDescriptor.getCorbaObjectReference();
201
202
203 }
204 //Change the Invokation Object if there is a valid dynamic Object
205 if(dynamicObject!=null){
206 currentObj=dynamicObject;
207 }else{
208 currentObj=obj;
209 }
210
211 //**********************************************************************
212 // INOUT Gets the Object array with the correct Holder and gets the method from the stub
213 MethodSignature methodSignature = getMetodSignatureFromMethod(m);
214
215 //**** Added for management of Array of length 0****************
216 //**** Workaroud added to manage array of length 0
217 for(int i=0;i<paramArray.length;i++){
218 if(methodSignature.getParameters().get(i).isArray()){
219 if(paramArray[i]==null){
220 LOG.debug("********************************************Instance new Array of size 0");
221 paramArray[i]=Array.newInstance(methodSignature.getParameters().get(i).getType(), 0);
222
223 }
224 }
225 }
226 //**************************************************************
227
228 if (methodSignature.isContainsHolder()) {
229 // manage holders.
230 paramArray = CorbaTransformationUtils.changeHoldersFromServiceToCorbaObjects(methodSignature, params, runtimeInfo);
231 m = getMethodFromStub(currentObj.getClass(), methodSignature);
232 LOG.debug("methodSignature:" + methodSignature.getMethod().toGenericString());
233 LOG.debug("M:" + m.toGenericString());
234
235 }
236 //**********************************************************************
237 //Runtime Generic Types
238 //**********************************************************************
239 // Get parameters about Corba Types Interface,Any or Union
240 //if (methodSignature.hasCorbaTypes()) {
241 // TODO not completed or tested
242 LOG.debug("***Retrieved Union or Any or Interfaces ***");
243 LOG.debug("Param Array LENGTH " + paramArray.length);
244
245 // LOG.debug("Param class" + paramArray[0].getClass());
246
247 paramArray = CorbaTransformationUtils.changeFromServiceToCorbaObjects(paramArray, runtimeInfo, methodSignature);
248 LOG.debug("Param " + methodSignature);
249 LOG.debug("Param " + currentObj.getClass());
250
251 m = getMethodFromStub(currentObj.getClass(), methodSignature);
252 //}
253 LOG.debug("Param " + methodSignature);
254 //**********************************************************************
255
256 try {
257 if (this.isCorbaServant && ((org.omg.CORBA.Object) currentObj)._non_existent()) {
258 LOG.debug(">>>> Reconnect begin...");
259 serviceDescriptor.getEndpoint().locateCorbaService();
260 LOG.debug(">>>> Reconnect end...");
261 //get corbaObjectReference
262 currentObj = serviceDescriptor.getCorbaObjectReference();
263 }
264 } catch (SystemException se) {
265 LOG.debug(">>>> Reconnect begin...");
266 serviceDescriptor.getEndpoint().locateCorbaService();
267 LOG.debug(">>>> Reconnect end...");
268 //get corbaObjectReference
269 currentObj = serviceDescriptor.getCorbaObjectReference();
270 }
271
272 // Invocation
273 // Invoke the stub method and pass the correct params
274 //ADDED FOR Array OCTET TEST
275
276 //LOG.debug("Param " + paramArray[0]);
277 //LOG.debug("Param " + paramArray[0].getClass().getName());
278 //byte[] par = ((byte[]) paramArray[0]);
279 //LOG.info("PARAM ARRAY:" + par);
280 //for (int i = 0; i < par.length; i++) {
281 //LOG.info("PARAM ARRAY:" + i + ":" + par[i]);
282 //}
283
284
285 // LOG.debug("Param class" + paramArray[0].getClass());
286 if(LOG.isDebugEnabled()){
287 LOG.debug("ParamArray ===================> " + Arrays.toString(paramArray) + " \n **********************************************************");
288 LOG.debug("Exchange ======================> " + exchange + "\n ************************************************************");
289 LOG.debug("OBJ ===========================> " + currentObj + "\n******************************************************************");
290 LOG.debug("OBJ CLASSLOADER ===============> " + currentObj.getClass().getClassLoader() + "\n******************************************************************");
291 // LOG.debug("PARAM CLASSLOADER ===============> " + paramArray[0].getClass().getClassLoader() + "\n******************************************************************");
292
293 LOG.debug("METHOD SIGNATURE ==============> " + m + "\n********************************************************************");
294
295 LOG.debug("**********************INVOCATION*****************************************************************************");
296 if (paramArray != null) {
297 LOG.debug("ParamArray ====>" + paramArray.length);
298 }
299
300 // LOG.debug("Param ====>"+paramArray[0].getClass().getField("fieldEcho2").toString());
301 // LOG.debug("Field Number " + paramArray[0].getClass().getFields().length);
302 // for (Field f : paramArray[0].getClass().getFields()) {
303 // LOG.debug("field ===>" + f.getName() + " -- value: " + f.get(paramArray[0]));
304 // LOG.debug("field ===>" + f.toGenericString());
305 // LOG.debug("field ===>" + f.getType());
306 // LOG.debug("field ===>" + f.toString());
307 // LOG.debug("field ===>" + f.getClass().getClassLoader());
308 // }
309
310 LOG.debug("*************************************************************************************************************");
311 }
312 org.omg.CORBA_2_3.ORB orb=(org.omg.CORBA_2_3.ORB)serviceDescriptor.getEndpoint().getOrb();
313 //LOG.debug("RAAAF: lookup value factory per MySequence: "+orb.lookup_value_factory("IDL:3hh4.123/it/imolinfo/jbi4corba/test/testprovidercomplex/MySequence:1.0"));
314 //LOG.debug("CL stub: "+currentObj.getClass().getClassLoader());
315 //LOG.debug("RAAAF: classloader value factory per MySequence: "+orb.lookup_value_factory("IDL:3hh4.123/it/imolinfo/jbi4corba/test/testprovidercomplex/MySequence:1.0").getClass().getClassLoader());
316 Object res = performInvocation(exchange, currentObj, m, paramArray);
317
318
319 LOG.debug("!!!! invokation successful with return:" + res);
320
321 //**********************************************************************
322 // INOUT Change holder parameters
323 if (methodSignature.isContainsHolder()) {
324 LOG.debug("The method contains holders: the parameters must be changed");
325 CorbaTransformationUtils.changeHoldersFromCorbaToServiceObjects(methodSignature, params, paramArray, runtimeInfo);
326 }
327
328 if (res != null) {
329 LOG.debug("TYPE"+m.getReturnType().getName());
330 res = CorbaTransformationUtils.changeFromCorbaToServiceObject(res, runtimeInfo, m.getReturnType());
331 LOG.debug("RESULT CLASS"+res.getClass().toString());
332 LOG.debug("RESULT CLASSLOADER"+res.getClass().getClassLoader());
333 }
334 LOG.debug("!!!! transformation successful");
335
336 //Normalization timer starts
337 String topic = new String("Normalization");
338 String endpointName = (String) exchange.get("EndpointName");
339 mMeasurement = Probe.fine(getClass(), endpointName, topic);
340 //Add timer object to context, so it can be stopped in the other class
341 exchange.put("Measure-N", mMeasurement);
342
343 if (exchange.isOneWay()) {
344 return null;
345 }
346
347 return new MessageContentsList(res);
348 } catch (InvocationTargetException e) {
349 Throwable t = e.getCause();
350
351 if (t == null) {
352 t = e;
353 }
354
355
356 LOG.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAULT ");
357 for (Class classException : m.getExceptionTypes()) {
358 LOG.debug("Exception Application : " + classException.getName());
359 if (classException.isInstance(t)) {
360 // Checked
361 LOG.debug(">>>>>>>>>> CHECKED_APPLICATION_FAULT");
362 try
363 {
364 t = (Throwable)CorbaTransformationUtils.changeFromCorbaToServiceObject(t, runtimeInfo, classException);
365 } catch (Exception ex) {
366 exchange.getOutMessage().put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT);
367 exchange.getOutFaultMessage().setContent(Exception.class, new Fault(ex));
368 ex.printStackTrace();
369 throw new Fault(ex);
370 }
371
372 exchange.getOutMessage().put(FaultMode.class, FaultMode.CHECKED_APPLICATION_FAULT);
373 exchange.getOutFaultMessage().setContent(Exception.class, new Fault(t));
374 throw new Fault(t);
375 }
376 }
377 // Unchecked
378 LOG.debug(">>>>>>>>>> UNCHECKED_APPLICATION_FAULT");
379 exchange.getOutMessage().put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT);
380 exchange.getOutFaultMessage().setContent(Exception.class, new Fault(t));
381 LOG.warn("error invokating stub: ", t);
382 throw new Fault(t);
383 // VERIFICARE SE I SEGUENTI CATCH SONO NECESSARI
384 } catch (Fault f) {
385 exchange.getOutMessage().put(FaultMode.class, FaultMode.CHECKED_APPLICATION_FAULT);
386 exchange.getOutFaultMessage().setContent(Exception.class, f);
387 throw f;
388 } catch (Exception e) {
389 LOG.warn("error invokating stub: ", e);
390 exchange.getOutMessage().put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT);
391 exchange.getOutFaultMessage().setContent(Exception.class, new Fault(e));
392 // e.printStackTrace();
393 throw new Fault(e);
394 }
395
396 } finally {
397 Thread.currentThread().setContextClassLoader(oldClassLoader);
398 }
399 }
400
401
402 /**
403 * Creates the parameter arry from the parameter object (that contains a wrapper object for each part).
404 * @param o
405 * @param info
406 * @return
407 */
408 private List<Object> extractParams(Object o, MessageInfo info) {
409
410 List<MessagePartInfo> messageParts = info.getMessageParts();
411 for (int i = 0; i < messageParts.size(); i++) {
412 MessagePartInfo partInfo = messageParts.get(i);
413 }
414 List<Object> params = null;
415 if (o instanceof List) {
416 params = CastUtils.cast((List<?>) o);
417 } else if (o != null) {
418 params = new MessageContentsList(o);
419 }
420 return params;
421 }
422
423 /**
424 * Get the provider service Descriptor object.
425 * @return The provider service descriptor
426 */
427 public ProviderServiceDescriptor getServiceDescriptor() {
428 return serviceDescriptor;
429 }
430
431 /**
432 * Set the provider service Descriptor object.
433 * @param serviceDescriptor The ProviderServiceDescriptor
434 */
435 public void setServiceDescriptor(ProviderServiceDescriptor serviceDescriptor) {
436 this.serviceDescriptor = serviceDescriptor;
437 }
438
439 /**
440 * Gets the <code>MethodSignature</code> object from the <code>Method</code> class.
441 * The correspondace between the MethodSignature and the method can be saved for further optimization.
442 * @param method
443 * @return
444 */
445 private MethodSignature getMetodSignatureFromMethod(Method method) {
446 List<MethodSignature> methodSignatures = serviceDescriptor.getMethodSignatures();
447 MethodSignature methodSignature = null;
448 boolean found = false;
449 for (int i = 0; i < methodSignatures.size() && (!found); i++) {
450 methodSignature = (MethodSignature) methodSignatures.get(i);
451 LOG.debug("METHOD SIGNATURE ===>"+methodSignature);
452
453 // if(methodSignature.getChangedMethod()!=null){
454 if (compareMethodsWithNameAndParameters(method, methodSignature.getChangedMethod())) {
455 found = true;
456 break;
457 }
458 //}
459 }
460 if (methodSignature == null) {
461 String msg = MESSAGES.getString(
462 "CRB000767_No_method_signature_found_for_method",
463 new java.lang.Object[] { method.toGenericString() });
464 LOG.warn(msg);
465 }
466 return methodSignature;
467 }
468
469
470
471 /**
472 * The method saved in the <code>MethodSignature</code> is of the corba interface. The object
473 * used to invoke the method is the Stub reference. This method found the Stub method, comparing
474 * the method name and the parameter types.
475 * TODO: This operation is expensive, the correspondance between methods can be saved.
476 * @param stub
477 * @param signature
478 * @return
479 */
480 public Method getMethodFromStub(Class stub, MethodSignature signature) {
481 Method interfaceMethod = signature.getMethod();
482
483 Method matchedMethod = null;
484 // Get the stub methods
485 Method[] methods = stub.getMethods();
486 LOG.debug("********INTERFACE Method ->" + signature.getMethod());
487 LOG.debug("********INTERFACE STUB ->" + stub);
488 LOG.debug("********ClassLoader STUB ->" + stub.getClassLoader());
489 LOG.debug("********METHODS LENGTH ->" + methods.length);
490
491 for (int i = 0; i < methods.length; i++) {
492 LOG.debug("********INTERFACE METHOD ->" + methods[i].getName());
493 boolean found = compareMethodsWithNameAndParameters(methods[i], interfaceMethod);
494 if (found) {
495 matchedMethod = methods[i];
496 break;
497 }
498 }
499 LOG.debug("********MATHCED METHOD _->" + matchedMethod);
500 return matchedMethod;
501
502 }
503
504 /**
505 * Compares two method looking for the name and the parameters (not the original class).
506 * @param methodA
507 * @param methodB
508 * @return
509 */
510 private boolean compareMethodsWithNameAndParameters(Method methodA, Method methodB) {
511 boolean ret = false;
512 LOG.debug("**************Method A" + methodA.toGenericString());
513 LOG.debug("**************Method B" + methodB.toGenericString());
514 boolean paramEquals = compareParameterTypes(methodA.getParameterTypes(), methodB.getParameterTypes());
515 LOG.debug("**************Method A" + methodA.toGenericString());
516 LOG.debug("**************Method B" + methodB.toGenericString());
517 LOG.debug("**************PARAM EQUALS" + paramEquals);
518 if ((paramEquals) &&
519 (methodA.getName().equals(methodB.getName()))) {
520 ret = true;
521 }
522 return ret;
523 }
524
525 /**
526 * True if two <code>Class</code> array are of <code>Class</code> of the same type.
527 * @param typesA
528 * @param typesB
529 * @return
530 */
531 private boolean compareParameterTypes(Class[] typesA, Class[] typesB) {
532 boolean ret = true;
533 LOG.debug("***************TYpe A" + typesA.length);
534 LOG.debug("***************Type B" + typesB.length);
535 if (typesA.length != typesB.length) {
536 ret = false;
537 } else {
538 for (int i = 0; i < typesA.length; i++) {
539 if (!(typesA[i].getName().equals(typesB[i].getName()))) {
540 LOG.debug("***************Type A" + typesA[i].getName());
541 LOG.debug("***************Type B" + typesB[i].getName());
542 ret = false;
543 break;
544 }
545 }
546 }
547 return ret;
548 }
549
550
551
552 }