00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 package org.objectweb.proactive.core.mop;
00032
00033 import java.io.ByteArrayInputStream;
00034 import java.lang.reflect.InvocationTargetException;
00035 import java.lang.reflect.Method;
00036 import java.lang.reflect.Type;
00037 import java.lang.reflect.TypeVariable;
00038 import java.util.Iterator;
00039 import java.util.LinkedList;
00040 import java.util.Map;
00041
00042 import org.apache.log4j.Logger;
00043 import org.objectweb.proactive.ProActive;
00044 import org.objectweb.proactive.core.component.ComponentMethodCallMetadata;
00045 import org.objectweb.proactive.core.component.representative.ItfID;
00046 import org.objectweb.proactive.core.component.request.ComponentRequest;
00047 import org.objectweb.proactive.core.exceptions.manager.ExceptionHandler;
00048 import org.objectweb.proactive.core.util.ObjectToByteConverter;
00049 import org.objectweb.proactive.core.util.log.Loggers;
00050 import org.objectweb.proactive.core.util.log.ProActiveLogger;
00051
00052 import sun.rmi.server.MarshalInputStream;
00053
00054
00062 public class MethodCall implements java.io.Serializable, Cloneable {
00063
00064
00065
00066
00067
00068
00074 private static transient java.util.Hashtable<String, ReifiableAndExceptions> REIF_AND_EXCEP = new java.util.Hashtable<String, ReifiableAndExceptions>();
00075 static Logger logger = ProActiveLogger.getLogger(Loggers.MOP);
00076
00080 private static int RECYCLE_POOL_SIZE = 30;
00081
00085 private static MethodCall[] recyclePool;
00086
00090 private static int index;
00091
00093 private static boolean recycleMethodCallObject;
00094 private static java.util.Hashtable<String, Method> reifiedMethodsTable = new java.util.Hashtable<String, Method>();
00095
00099 static {
00100 MethodCall.setRecycleMethodCallObject(true);
00101 }
00102
00103
00104
00105
00106
00110 private Object[] effectiveArguments;
00111
00115 private LinkedList<String> tagsForBarrier = null;
00116
00120 private transient Method reifiedMethod;
00121
00125 private long methodCallID;
00126 private String key;
00127
00128 private transient MethodCallExceptionContext exceptioncontext;
00129
00130 ComponentMethodCallMetadata componentMetaData = null;
00131
00132 private transient Map<TypeVariable, Class> genericTypesMapping = null;
00133
00134
00141 private byte[] serializedEffectiveArguments = null;
00142
00146 public void transformEffectiveArgumentsIntoByteArray() {
00147 if ((serializedEffectiveArguments == null) &&
00148 (effectiveArguments != null)) {
00149 try {
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 serializedEffectiveArguments = ObjectToByteConverter.convert(effectiveArguments);
00160 } catch (Exception e) {
00161 e.printStackTrace();
00162 }
00163 effectiveArguments = null;
00164 }
00165 }
00166
00173 public static synchronized void setRecycleMethodCallObject(boolean value) {
00174 if (recycleMethodCallObject == value) {
00175 return;
00176 } else {
00177 recycleMethodCallObject = value;
00178 if (value) {
00179
00180 recyclePool = new MethodCall[RECYCLE_POOL_SIZE];
00181 index = 0;
00182 } else {
00183
00184
00185
00186 recyclePool = null;
00187 }
00188 }
00189 }
00190
00196 public static synchronized boolean getRecycleMethodCallObject() {
00197 return MethodCall.recycleMethodCallObject;
00198 }
00199
00213 public synchronized static MethodCall getMethodCall(Method reifiedMethod, Map<TypeVariable,Class> genericTypesMapping,
00214 Object[] effectiveArguments, MethodCallExceptionContext exceptioncontext) {
00215 exceptioncontext = MethodCallExceptionContext.optimize(exceptioncontext);
00216
00217 if (MethodCall.getRecycleMethodCallObject()) {
00218
00219
00220 if (MethodCall.index > 0) {
00221
00222 MethodCall.index--;
00223 MethodCall result = MethodCall.recyclePool[MethodCall.index];
00224 MethodCall.recyclePool[MethodCall.index] = null;
00225
00226 result.reifiedMethod = reifiedMethod;
00227 result.genericTypesMapping = genericTypesMapping;
00228 result.effectiveArguments = effectiveArguments;
00229 result.key = buildKey(reifiedMethod, genericTypesMapping);
00230 result.exceptioncontext = exceptioncontext;
00231 return result;
00232 }
00233 }
00234 return new MethodCall(reifiedMethod, genericTypesMapping, effectiveArguments, exceptioncontext);
00235 }
00236
00237 public synchronized static MethodCall getMethodCall(Method reifiedMethod,
00238 Object[] effectiveArguments, Map<TypeVariable,Class> genericTypesMapping) {
00239 MethodCallExceptionContext exceptioncontext = ExceptionHandler.getContextForCall(reifiedMethod);
00240 return getMethodCall(reifiedMethod, genericTypesMapping, effectiveArguments, exceptioncontext);
00241 }
00242
00252 public synchronized static MethodCall getComponentMethodCall(
00253 Method reifiedMethod, Object[] effectiveArguments, Map<TypeVariable,Class> genericTypesMapping,
00254 String interfaceName, ItfID senderItfID, short priority) {
00255 MethodCall mc = getMethodCall(reifiedMethod, effectiveArguments, genericTypesMapping);
00256
00257 mc.componentMetaData = new ComponentMethodCallMetadata();
00258 mc.componentMetaData.setComponentInterfaceName(interfaceName);
00259 mc.componentMetaData.setSenderItfID(senderItfID);
00260 mc.componentMetaData.setPriority(priority);
00261 mc.componentMetaData.setShortcut(null);
00262 return mc;
00263 }
00264
00265 public synchronized static MethodCall getComponentMethodCall(
00266 Method reifiedMethod, Object[] effectiveArguments,Map<TypeVariable,Class> genericTypesMapping,
00267 String interfaceName, ItfID senderItfID ) {
00268 return MethodCall.getComponentMethodCall(reifiedMethod,
00269 effectiveArguments, genericTypesMapping, interfaceName, senderItfID,
00270 ComponentRequest.STRICT_FIFO_PRIORITY);
00271 }
00272
00278 public synchronized static void setMethodCall(MethodCall mc) {
00279 if (MethodCall.getRecycleMethodCallObject()) {
00280
00281 if (MethodCall.recyclePool[MethodCall.index] == null) {
00282
00283
00284
00285
00286 mc.componentMetaData = null;
00287 mc.reifiedMethod = null;
00288 mc.genericTypesMapping = null;
00289 mc.effectiveArguments = null;
00290 mc.tagsForBarrier = null;
00291 mc.key = null;
00292 mc.exceptioncontext = null;
00293
00294 MethodCall.recyclePool[MethodCall.index] = mc;
00295 MethodCall.index++;
00296 if (MethodCall.index == RECYCLE_POOL_SIZE) {
00297 MethodCall.index = RECYCLE_POOL_SIZE - 1;
00298 }
00299 }
00300 }
00301 }
00302
00309
00310
00311
00312 public MethodCall(Method reifiedMethod, Map<TypeVariable,Class> genericTypesMapping, Object[] effectiveArguments,
00313 MethodCallExceptionContext exceptionContext) {
00314 this.reifiedMethod = reifiedMethod;
00315 this.genericTypesMapping = (genericTypesMapping!=null && genericTypesMapping.size()>0)?genericTypesMapping:null;
00316 this.effectiveArguments = effectiveArguments;
00317 this.key = buildKey(reifiedMethod, genericTypesMapping);
00318 this.exceptioncontext = MethodCallExceptionContext.optimize(exceptionContext);
00319 }
00320
00321 public MethodCall(Method reifiedMethod, Map<TypeVariable,Class> genericTypesMapping, Object[] effectiveArguments) {
00322 this(reifiedMethod, genericTypesMapping, effectiveArguments, null);
00323 }
00324
00332 public MethodCall(MethodCall mc) {
00333 try {
00334 this.componentMetaData = mc.componentMetaData;
00335 this.reifiedMethod = mc.getReifiedMethod();
00336 if (mc.serializedEffectiveArguments == null) {
00337 serializedEffectiveArguments = null;
00338 } else {
00339
00340 byte[] source = mc.serializedEffectiveArguments;
00341 serializedEffectiveArguments = new byte[source.length];
00342 for (int i = 0; i < serializedEffectiveArguments.length; i++) {
00343 serializedEffectiveArguments[i] = source[i];
00344 }
00345 }
00346 if (mc.effectiveArguments == null) {
00347 effectiveArguments = null;
00348 } else {
00349 effectiveArguments = (Object[]) Utils.makeDeepCopy(mc.effectiveArguments);
00350 }
00351 this.genericTypesMapping = mc.getGenericTypesMapping();
00352 this.key = MethodCall.buildKey(mc.getReifiedMethod(), mc.getGenericTypesMapping());
00353 this.exceptioncontext = mc.exceptioncontext;
00354
00355 } catch (java.io.IOException e) {
00356 e.printStackTrace();
00357 }
00358 }
00359
00363 protected MethodCall() {
00364 this.reifiedMethod = null;
00365 this.effectiveArguments = null;
00366 this.serializedEffectiveArguments = null;
00367 this.exceptioncontext = null;
00368 }
00369
00385 public Object execute(Object targetObject)
00386 throws InvocationTargetException, MethodCallExecutionFailedException {
00387
00388 if ((serializedEffectiveArguments != null) &&
00389 (effectiveArguments == null)) {
00390 try {
00391 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(serializedEffectiveArguments);
00392
00393
00394 MarshalInputStream objectInputStream = new MarshalInputStream(byteArrayInputStream);
00395 effectiveArguments = (Object[]) objectInputStream.readObject();
00396 objectInputStream.close();
00397 byteArrayInputStream.close();
00398 } catch (Exception e) {
00399 e.printStackTrace();
00400 }
00401 serializedEffectiveArguments = null;
00402 }
00403 if (logger.isDebugEnabled()) {
00404 logger.debug("MethodCall.execute() name = " + this.getName());
00405 logger.debug("MethodCall.execute() reifiedMethod = " +
00406 reifiedMethod);
00407 logger.debug(
00408 "MethodCall.execute() reifiedMethod.getDeclaringClass() = " +
00409 reifiedMethod.getDeclaringClass());
00410 logger.debug("MethodCall.execute() targetObject " + targetObject);
00411 }
00412 if (reifiedMethod.getParameterTypes().length > 0) {
00413 reifiedMethod.setAccessible(true);
00414 }
00415 try {
00416 targetObject = ProActive.getFutureValue(targetObject);
00417 return reifiedMethod.invoke(targetObject, effectiveArguments);
00418 } catch (IllegalAccessException e) {
00419 throw new MethodCallExecutionFailedException(
00420 "Access rights to the method denied: " + e);
00421 } catch (IllegalArgumentException e) {
00422 e.printStackTrace();
00423 throw new MethodCallExecutionFailedException(
00424 "Arguments for the method " + this.getName() +
00425 " are invalids: " + e);
00426 }
00427
00428
00429
00430 }
00431
00432 protected void finalize() {
00433 MethodCall.setMethodCall(this);
00434 }
00435
00436 public Method getReifiedMethod() {
00437 return reifiedMethod;
00438 }
00439
00444 public String getName() {
00445 return reifiedMethod.getName();
00446 }
00447
00448 public int getNumberOfParameter() {
00449 return this.effectiveArguments.length;
00450 }
00451
00452 public Object getParameter(int index) {
00453 return this.effectiveArguments[index];
00454 }
00455
00456 public Object[] getParameters() {
00457 return this.effectiveArguments;
00458 }
00459
00460 public void setEffectiveArguments(Object[] o) {
00461 effectiveArguments = o;
00462 }
00463
00464 public Object[] getEffectiveArguments() {
00465 return effectiveArguments;
00466 }
00467
00471 public void makeDeepCopyOfArguments() throws java.io.IOException {
00472 effectiveArguments = (Object[]) Utils.makeDeepCopy(effectiveArguments);
00473 }
00474
00475
00476
00477
00478 private Class[] fixBugRead(FixWrapper[] para) {
00479 Class[] tmp = new Class[para.length];
00480 for (int i = 0; i < para.length; i++) {
00481
00482 tmp[i] = para[i].getWrapped();
00483 }
00484 return tmp;
00485 }
00486
00487 private FixWrapper[] fixBugWrite(Class[] para) {
00488 FixWrapper[] tmp = new FixWrapper[para.length];
00489 for (int i = 0; i < para.length; i++) {
00490
00491 tmp[i] = new FixWrapper(para[i]);
00492 }
00493 return tmp;
00494 }
00495
00496
00497 private static String buildKey(Method reifiedMethod, Map<TypeVariable, Class> genericTypesMapping) {
00498 String sb = "";
00499 sb+=(reifiedMethod.getDeclaringClass().getName());
00500
00501 Type returnType = reifiedMethod.getGenericReturnType();
00502 if (genericTypesMapping!=null && genericTypesMapping.containsKey(returnType)) {
00503 sb+=genericTypesMapping.get(returnType);
00504 } else {
00505 sb+=returnType;
00506 }
00507 sb+=(reifiedMethod.getName());
00508
00509 Type[] parameters = reifiedMethod.getGenericParameterTypes();
00510 for (int i = 0; i < parameters.length; i++) {
00511 sb+=((genericTypesMapping!=null && genericTypesMapping.containsKey(parameters[i]))?genericTypesMapping.get(parameters[i]).getName():parameters[i]);
00512 }
00513
00514 return sb.toString();
00515 }
00516
00517
00518
00519
00520 private void writeObject(java.io.ObjectOutputStream out)
00521 throws java.io.IOException {
00522 this.writeTheObject(out);
00523 }
00524
00525 protected void writeTheObject(java.io.ObjectOutputStream out)
00526 throws java.io.IOException {
00527 out.defaultWriteObject();
00528
00529 out.writeObject(reifiedMethod.getDeclaringClass());
00530 out.writeObject(reifiedMethod.getName());
00531 out.writeObject(fixBugWrite(reifiedMethod.getParameterTypes()));
00532 }
00533
00534 private void readObject(java.io.ObjectInputStream in)
00535 throws java.io.IOException, ClassNotFoundException {
00536 this.readTheObject(in);
00537 }
00538
00539 protected void readTheObject(java.io.ObjectInputStream in)
00540 throws java.io.IOException, ClassNotFoundException {
00541 in.defaultReadObject();
00542 reifiedMethod = (Method) reifiedMethodsTable.get(key);
00543 if (reifiedMethod == null) {
00544
00545 Class declaringClass = (Class) in.readObject();
00546 String simpleName = (String) in.readObject();
00547 Class[] parameters = this.fixBugRead((FixWrapper[]) in.readObject());
00548
00549
00550 try {
00551 reifiedMethod = declaringClass.getMethod(simpleName, parameters);
00552 reifiedMethodsTable.put(key, reifiedMethod);
00553 } catch (NoSuchMethodException e) {
00554 throw new InternalException("Lookup for method failed: " + e +
00555 ". This may be caused by having different versions of the same class on different VMs. Check your CLASSPATH settings.");
00556 }
00557 } else {
00558 in.readObject();
00559 in.readObject();
00560 in.readObject();
00561 }
00562 if ((serializedEffectiveArguments != null) &&
00563 (effectiveArguments == null)) {
00564 try {
00565 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(serializedEffectiveArguments);
00566
00567
00568 MarshalInputStream objectInputStream = new MarshalInputStream(byteArrayInputStream);
00569 effectiveArguments = (Object[]) objectInputStream.readObject();
00570 objectInputStream.close();
00571 byteArrayInputStream.close();
00572 } catch (Exception e) {
00573 e.printStackTrace();
00574 }
00575 serializedEffectiveArguments = null;
00576 }
00577 }
00578
00587 public boolean isOneWayCall() {
00588 return this.getReifiedMethod().getReturnType().equals(java.lang.Void.TYPE) &&
00589 (this.getReifiedMethod().getExceptionTypes().length == 0) &&
00590 !this.getExceptionContext().isRuntimeExceptionHandled();
00591 }
00592
00593
00594 static class ReifiableAndExceptions {
00595 boolean reifiable;
00596 boolean exceptions;
00597 String reason;
00598 }
00599
00600 public String getSynchronousReason() {
00601 Method m = this.getReifiedMethod();
00602 ReifiableAndExceptions cached = (ReifiableAndExceptions) REIF_AND_EXCEP.get(key);
00603 if (cached == null) {
00604 cached = new ReifiableAndExceptions();
00605
00606 cached.reifiable = m.getReturnType().equals(java.lang.Void.TYPE);
00607 if (!cached.reifiable) {
00608 try {
00609 if (getGenericTypesMapping()!=null && getGenericTypesMapping().containsKey(m.getGenericReturnType())) {
00610
00611 MOP.checkClassIsReifiable(getGenericTypesMapping().get(m.getGenericReturnType()));
00612 } else {
00613 MOP.checkClassIsReifiable(m.getReturnType());
00614 }
00615 cached.reifiable = true;
00616 } catch (ClassNotReifiableException e) {
00617 cached.reason = e.getMessage();
00618 }
00619 }
00620
00621 cached.exceptions = m.getExceptionTypes().length != 0;
00622 if (cached.exceptions) {
00623 cached.reason = "The method can throw a checked exception";
00624 }
00625 REIF_AND_EXCEP.put(key, cached);
00626 }
00627
00628 if (cached.reifiable && cached.exceptions && getExceptionContext().isExceptionAsynchronously()) {
00629
00630 return null;
00631 }
00632
00633 return cached.reason;
00634 }
00635
00647 public boolean isAsynchronousWayCall() {
00648 return getSynchronousReason() == null;
00649 }
00650
00655 public void setBarrierTags(LinkedList<String> barrierTags) {
00656 this.tagsForBarrier = new LinkedList<String>();
00657 Iterator<String> it = barrierTags.iterator();
00658 while (it.hasNext()) {
00659 this.tagsForBarrier.add(new String(it.next()));
00660 }
00661 }
00662
00667 public LinkedList getBarrierTags() {
00668 return this.tagsForBarrier;
00669 }
00670
00671 public MethodCallExceptionContext getExceptionContext() {
00672 if (exceptioncontext == null) {
00673 return MethodCallExceptionContext.DEFAULT;
00674 }
00675
00676 return exceptioncontext;
00677 }
00678
00679 public ComponentMethodCallMetadata getComponentMetadata() {
00680 return componentMetaData;
00681 }
00682
00683 public Map<TypeVariable, Class> getGenericTypesMapping() {
00684 return genericTypesMapping;
00685 }
00686
00687
00688
00689
00690
00691 public class FixWrapper implements java.io.Serializable {
00692 public boolean isPrimitive;
00693 public Class encapsulated;
00694
00695 public FixWrapper() {
00696 }
00697
00701 public FixWrapper(Class c) {
00702 if (!c.isPrimitive()) {
00703 encapsulated = c;
00704 return;
00705 }
00706 isPrimitive = true;
00707 if (c.equals(Boolean.TYPE)) {
00708 encapsulated = Boolean.class;
00709 } else if (c.equals(Byte.TYPE)) {
00710 encapsulated = Byte.class;
00711 } else if (c.equals(Character.TYPE)) {
00712 encapsulated = Character.class;
00713 } else if (c.equals(Double.TYPE)) {
00714 encapsulated = Double.class;
00715 } else if (c.equals(Float.TYPE)) {
00716 encapsulated = Float.class;
00717 } else if (c.equals(Integer.TYPE)) {
00718 encapsulated = Integer.class;
00719 } else if (c.equals(Long.TYPE)) {
00720 encapsulated = Long.class;
00721 } else if (c.equals(Short.TYPE)) {
00722 encapsulated = Short.class;
00723 }
00724 }
00725
00729 public Class getWrapped() {
00730 if (!isPrimitive) {
00731 return encapsulated;
00732 }
00733 if (encapsulated.equals(Boolean.class)) {
00734 return Boolean.TYPE;
00735 }
00736 if (encapsulated.equals(Byte.class)) {
00737 return Byte.TYPE;
00738 }
00739 if (encapsulated.equals(Character.class)) {
00740 return Character.TYPE;
00741 }
00742 if (encapsulated.equals(Double.class)) {
00743 return Double.TYPE;
00744 }
00745 if (encapsulated.equals(Float.class)) {
00746 return Float.TYPE;
00747 }
00748 if (encapsulated.equals(Integer.class)) {
00749 return Integer.TYPE;
00750 }
00751 if (encapsulated.equals(Long.class)) {
00752 return Long.TYPE;
00753 }
00754 if (encapsulated.equals(Short.class)) {
00755 return Short.TYPE;
00756 }
00757 throw new InternalException("FixWrapper encapsulated class unkown " +
00758 encapsulated);
00759 }
00760
00761 public String toString() {
00762 return "FixWrapper: " + encapsulated.toString();
00763 }
00764 }
00765
00766
00767
00768
00769 }