org/objectweb/proactive/core/exceptions/manager/ExceptionThrower.java

00001 /* 
00002  * ################################################################
00003  * 
00004  * ProActive: The Java(TM) library for Parallel, Distributed, 
00005  *            Concurrent computing with Security and Mobility
00006  * 
00007  * Copyright (C) 1997-2007 INRIA/University of Nice-Sophia Antipolis
00008  * Contact: proactive@objectweb.org
00009  * 
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or any later version.
00014  *  
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  * 
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
00023  * USA
00024  *  
00025  *  Initial developer(s):               The ProActive Team
00026  *                        http://www.inria.fr/oasis/ProActive/contacts.html
00027  *  Contributor(s): 
00028  * 
00029  * ################################################################
00030  */ 
00031 package org.objectweb.proactive.core.exceptions.manager;
00032 
00033 import javassist.ClassPool;
00034 import javassist.CtClass;
00035 import javassist.CtMethod;
00036 import javassist.CtNewConstructor;
00037 import javassist.CtNewMethod;
00038 
00039 
00040 /*
00041  * This is the nasty hack to bypass java checked exceptions
00042  */
00043 /*
00044  * This interface is the entry-point to the thrower, an object implementing this
00045  * interface will be built by reflection. By calling the throwException() method
00046  * on this object, it will be possible to call the ASM generated code.
00047  */
00048 interface Thrower {
00049     public void throwException(Throwable t);
00050 }
00051 
00052 
00053 public class ExceptionThrower {
00054     private static final String THROWER_CLASS_NAME = "TheActualExceptionThrower";
00055     private static final String THROWER_CLASS_PACKAGE = ExceptionThrower.class.getPackage()
00056                                                                               .getName();
00057     private static final String THROWER_CLASS_FULLNAME = THROWER_CLASS_PACKAGE +
00058         "." + THROWER_CLASS_NAME;
00059     private static Thrower thrower = null;
00060 
00061     private static Class loadClassJavassist() {
00062         try {
00063             CtClass throwerClass = ClassPool.getDefault().makeClass(THROWER_CLASS_FULLNAME);
00064             throwerClass.addInterface(ClassPool.getDefault().get(Thrower.class.getName()));
00065             throwerClass.addConstructor(CtNewConstructor.defaultConstructor(throwerClass));
00066             CtMethod throwException = CtNewMethod.make("" +
00067                     "public void throwException(Throwable t) {" +
00068                     "    throw t;}", throwerClass);
00069             throwerClass.addMethod(throwException);
00070             return loadClass(THROWER_CLASS_FULLNAME, throwerClass.toBytecode());
00071         } catch (Exception e) {
00072             e.printStackTrace();
00073         }
00074         return null;
00075     }
00076 
00077     /* We load a class given its name and its binary representation */
00078     private static Class loadClass(String className, byte[] b)
00079         throws Exception {
00080         Class clazz = null;
00081         ClassLoader loader = ClassLoader.getSystemClassLoader();
00082         Class cls = Class.forName("java.lang.ClassLoader");
00083         java.lang.reflect.Method method = cls.getDeclaredMethod("defineClass",
00084                 new Class[] { String.class, byte[].class, int.class, int.class });
00085 
00086         /* protected method invocaton */
00087         method.setAccessible(true);
00088         try {
00089             Object[] args = new Object[] {
00090                     className, b, new Integer(0), new Integer(b.length)
00091                 };
00092             clazz = (Class) method.invoke(loader, args);
00093         } finally {
00094             method.setAccessible(false);
00095         }
00096         return clazz;
00097     }
00098 
00099     /* The first time the mechanism is used, it has to initialize the thrower */
00100     private static void activate() {
00101         try {
00102             Class clazz = loadClassJavassist();
00103             thrower = (Thrower) clazz.newInstance();
00104         } catch (Exception e) {
00105             e.printStackTrace();
00106         }
00107     }
00108 
00109     public synchronized static void throwException(Throwable t) {
00110         if (thrower == null) {
00111             activate();
00112         }
00113 
00114         if (thrower != null) {
00115             thrower.throwException(t);
00116         }
00117     }
00118 }

Generated on Mon Jan 22 15:16:07 2007 for ProActive by  doxygen 1.5.1