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 }