diff options
Diffstat (limited to 'libjava/classpath/gnu/CORBA/ObjectCreator.java')
-rw-r--r-- | libjava/classpath/gnu/CORBA/ObjectCreator.java | 397 |
1 files changed, 270 insertions, 127 deletions
diff --git a/libjava/classpath/gnu/CORBA/ObjectCreator.java b/libjava/classpath/gnu/CORBA/ObjectCreator.java index 81c1d06e775..5937e76b31e 100644 --- a/libjava/classpath/gnu/CORBA/ObjectCreator.java +++ b/libjava/classpath/gnu/CORBA/ObjectCreator.java @@ -38,27 +38,37 @@ exception statement from your version. */ package gnu.CORBA; -import gnu.CORBA.CDR.cdrBufOutput; +import gnu.CORBA.CDR.UnknownExceptionCtxHandler; +import gnu.CORBA.CDR.BufferredCdrInput; +import gnu.CORBA.CDR.BufferedCdrOutput; +import gnu.CORBA.CDR.AbstractCdrInput; +import gnu.CORBA.GIOP.ServiceContext; +import gnu.CORBA.typecodes.RecordTypeCode; +import gnu.classpath.VMStackWalker; import org.omg.CORBA.Any; import org.omg.CORBA.CompletionStatus; import org.omg.CORBA.CompletionStatusHelper; import org.omg.CORBA.MARSHAL; -import org.omg.CORBA.StructMember; import org.omg.CORBA.SystemException; import org.omg.CORBA.TCKind; import org.omg.CORBA.UNKNOWN; import org.omg.CORBA.UserException; +import org.omg.CORBA.portable.IDLEntity; import org.omg.CORBA.portable.InputStream; import org.omg.CORBA.portable.OutputStream; +import org.omg.CORBA.portable.ValueBase; -import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.util.Map; +import java.util.WeakHashMap; + +import javax.rmi.CORBA.Util; /** * Creates java objects from the agreed IDL names for the simple case when the * CORBA object is directly mapped into the locally defined java class. - * + * * @author Audrius Meskauskas (AudriusA@Bioinformatics.org) */ public class ObjectCreator @@ -79,91 +89,137 @@ public class ObjectCreator public static final String CLASSPATH_PREFIX = "gnu.CORBA."; /** + * Maps classes to they IDL or RMI names. Computing RMI name is an expensive + * operations, so frequently used RMI keys are reused. The map must be weak to + * ensure that the class can be unloaded, when applicable. + */ + public static Map m_names = new WeakHashMap(); + + /** + * Maps IDL strings into known classes. The map must be weak to ensure that + * the class can be unloaded, when applicable. + */ + public static Map m_classes = new WeakHashMap(); + + /** + * Maps IDL types to they helpers. + */ + public static Map m_helpers = new WeakHashMap(); + + /** * Try to instantiate an object with the given IDL name. The object must be * mapped to the local java class. The omg.org domain must be mapped into the * object in either org/omg or gnu/CORBA namespace. - * + * * @param IDL name * @return instantiated object instance or null if no such available. */ public static java.lang.Object createObject(String idl, String suffix) { - try - { - return Class.forName(toClassName(JAVA_PREFIX, idl) + suffix) - .newInstance(); - } - catch (Exception ex) + synchronized (m_classes) { - try + Class known = (Class) (suffix == null ? m_classes.get(idl) + : m_classes.get(idl + 0xff + suffix)); + Object object; + + if (known != null) { - return Class.forName(toClassName(CLASSPATH_PREFIX, idl) + suffix) - .newInstance(); + try + { + return known.newInstance(); + } + catch (Exception ex) + { + RuntimeException rex = new RuntimeException(idl + " suffix " + + suffix, ex); + throw rex; + } } - catch (Exception exex) + else { - return null; + if (suffix == null) + suffix = ""; + try + { + known = forName(toClassName(JAVA_PREFIX, idl) + suffix); + object = known.newInstance(); + } + catch (Exception ex) + { + try + { + known = forName(toClassName(CLASSPATH_PREFIX, idl) + + suffix); + object = known.newInstance(); + } + catch (Exception exex) + { + return null; + } + } + m_classes.put(idl + 0xff + suffix, known); + return object; } } } /** - * Create the system exception with the given idl name. - * - * @param idl the exception IDL name, must match the syntax "IDL:<class/name>:1.0". - * @param minor the exception minor code. - * @param completed the exception completion status. - * - * @return the created exception. + * Read the system exception from the given stream. + * + * @param input the CDR stream to read from. + * @param contexts the service contexts in request/reply header/ + * + * @return the exception that has been stored in the stream (IDL name, minor + * code and completion status). */ - public static SystemException createSystemException(String idl, int minor, - CompletionStatus completed - ) + public static SystemException readSystemException(InputStream input, + ServiceContext[] contexts) { + SystemException exception; + + String idl = input.read_string(); + int minor = input.read_ulong(); + CompletionStatus completed = CompletionStatusHelper.read(input); + try { - String cl = toClassName(JAVA_PREFIX, idl); - Class exClass = Class.forName(cl); - - Constructor constructor = - exClass.getConstructor(new Class[] - { - String.class, int.class, CompletionStatus.class - } - ); - - Object exception = - constructor.newInstance(new Object[] - { - " Remote exception " + idl + ", minor " + minor + ", " + - completed + ".", new Integer(minor), completed - } - ); - - return (SystemException) exception; + exception = (SystemException) createObject(idl, null); + exception.minor = minor; + exception.completed = completed; } catch (Exception ex) { - ex.printStackTrace(); - return new UNKNOWN("Unsupported system exception", minor, completed); + UNKNOWN u = new UNKNOWN("Unsupported system exception " + idl, minor, + completed); + u.initCause(ex); + throw u; } - } - /** - * Read the system exception from the given stream. - * - * @param input the CDR stream to read from. - * @return the exception that has been stored in the stream (IDL name, minor - * code and completion status). - */ - public static SystemException readSystemException(InputStream input) - { - String idl = input.read_string(); - int minor = input.read_ulong(); - CompletionStatus status = CompletionStatusHelper.read(input); + try + { + // If UnknownExceptionInfo is present in the contexts, read it and + // set as a cause of this exception. + ServiceContext uEx = ServiceContext.find( + ServiceContext.UnknownExceptionInfo, contexts); - SystemException exception = - ObjectCreator.createSystemException(idl, minor, status); + if (uEx != null) + { + BufferredCdrInput in = new BufferredCdrInput(uEx.context_data); + in.setOrb(in.orb()); + if (input instanceof AbstractCdrInput) + { + ((AbstractCdrInput) input).cloneSettings(in); + } + + Throwable t = UnknownExceptionCtxHandler.read(in, contexts); + exception.initCause(t); + } + } + catch (Exception ex) + { + // Unsupported context format. Do not terminate as the user program may + // not need it. + } return exception; } @@ -172,10 +228,10 @@ public class ObjectCreator * Reads the user exception, having the given Id, from the input stream. The * id is expected to be in the form like * 'IDL:test/org/omg/CORBA/ORB/communication/ourUserException:1.0' - * + * * @param idl the exception idl name. * @param input the stream to read from. - * + * * @return the loaded exception. * @return null if the helper class cannot be found. */ @@ -183,13 +239,10 @@ public class ObjectCreator { try { - String helper = toHelperName(idl); - Class helperClass = Class.forName(helper); + Class helperClass = findHelper(idl); - Method read = - helperClass.getMethod("read", - new Class[] { org.omg.CORBA.portable.InputStream.class } - ); + Method read = helperClass.getMethod("read", + new Class[] { org.omg.CORBA.portable.InputStream.class }); return (UserException) read.invoke(null, new Object[] { input }); } @@ -208,7 +261,7 @@ public class ObjectCreator /** * Gets the helper class name from the string like * 'IDL:test/org/omg/CORBA/ORB/communication/ourUserException:1.0' - * + * * @param IDL the idl name. */ public static String toHelperName(String IDL) @@ -227,15 +280,14 @@ public class ObjectCreator /** * Writes the system exception data to CDR output stream. - * + * * @param output a stream to write data to. * @param ex an exception to write. */ public static void writeSystemException(OutputStream output, - SystemException ex - ) + SystemException ex) { - String exIDL = toIDL(ex.getClass().getName()); + String exIDL = getRepositoryId(ex.getClass()); output.write_string(exIDL); output.write_ulong(ex.minor); CompletionStatusHelper.write(output, ex.completed); @@ -243,9 +295,9 @@ public class ObjectCreator /** * Converts the given IDL name to class name. - * + * * @param IDL the idl name. - * + * */ protected static String toClassName(String prefix, String IDL) { @@ -265,34 +317,43 @@ public class ObjectCreator * Converts the given IDL name to class name and tries to load the matching * class. The OMG prefix (omg.org) is replaced by the java prefix org.omg. No * other prefixes are added. - * + * * @param IDL the idl name. - * - * TODO Cache the returned classes, avoiding these string manipulations each - * time the conversion is required. - * + * * @return the matching class or null if no such is available. */ public static Class Idl2class(String IDL) { - String s = IDL; - int a = s.indexOf(':') + 1; - int b = s.lastIndexOf(':'); - - s = IDL.substring(a, b); - - if (s.startsWith(OMG_PREFIX)) - s = JAVA_PREFIX + s.substring(OMG_PREFIX.length()); - - String cn = s.replace('/', '.'); - - try + synchronized (m_classes) { - return Class.forName(cn); - } - catch (ClassNotFoundException ex) - { - return null; + Class c = (Class) m_classes.get(IDL); + + if (c != null) + return c; + else + { + String s = IDL; + int a = s.indexOf(':') + 1; + int b = s.lastIndexOf(':'); + + s = IDL.substring(a, b); + + if (s.startsWith(OMG_PREFIX)) + s = JAVA_PREFIX + s.substring(OMG_PREFIX.length()); + + String cn = s.replace('/', '.'); + + try + { + c = forName(cn); + m_classes.put(IDL, c); + return c; + } + catch (ClassNotFoundException ex) + { + return null; + } + } } } @@ -301,9 +362,9 @@ public class ObjectCreator * and create an object instance with parameterless constructor. The OMG * prefix (omg.org) is replaced by the java prefix org.omg. No other prefixes * are added. - * + * * @param IDL the idl name. - * + * * @return instantiated object instance or null if such attempt was not * successful. */ @@ -325,34 +386,53 @@ public class ObjectCreator } /** - * Convert the class name to IDL name. - * - * @param cn the class name. - * - * @return the idl name. + * Convert the class name to IDL or RMI name (repository id). If the class + * inherits from IDLEntity, ValueBase or SystemException, returns repository + * Id in the IDL:(..) form. If it does not, returns repository Id in the + * RMI:(..) form. + * + * @param cx the class for that the name must be computed. + * + * @return the idl or rmi name. */ - public static String toIDL(String cn) + public static synchronized String getRepositoryId(Class cx) { - if (cn.startsWith(JAVA_PREFIX)) - cn = OMG_PREFIX + cn.substring(JAVA_PREFIX.length()).replace('.', '/'); - else if (cn.startsWith(CLASSPATH_PREFIX)) - cn = - OMG_PREFIX + - cn.substring(CLASSPATH_PREFIX.length()).replace('.', '/'); - - return "IDL:" + cn + ":1.0"; + String name = (String) m_names.get(cx); + if (name != null) + return name; + + String cn = cx.getName(); + if (!(IDLEntity.class.isAssignableFrom(cx) + || ValueBase.class.isAssignableFrom(cx) || SystemException.class.isAssignableFrom(cx))) + { + // Not an IDL entity. + name = Util.createValueHandler().getRMIRepositoryID(cx); + } + else + { + if (cn.startsWith(JAVA_PREFIX)) + cn = OMG_PREFIX + + cn.substring(JAVA_PREFIX.length()).replace('.', '/'); + else if (cn.startsWith(CLASSPATH_PREFIX)) + cn = OMG_PREFIX + + cn.substring(CLASSPATH_PREFIX.length()).replace('.', '/'); + + name = "IDL:" + cn + ":1.0"; + } + m_names.put(cx, name); + return name; } /** * Insert the passed parameter into the given Any, assuming that the helper * class is available. The helper class must have the "Helper" suffix and be * in the same package as the class of the object being inserted. - * + * * @param into the target to insert. - * + * * @param object the object to insert. It can be any object as far as the * corresponding helper is provided. - * + * * @return true on success, false otherwise. */ public static boolean insertWithHelper(Any into, Object object) @@ -360,12 +440,10 @@ public class ObjectCreator try { String helperClassName = object.getClass().getName() + "Helper"; - Class helperClass = Class.forName(helperClassName); + Class helperClass = forName(helperClassName); - Method insert = - helperClass.getMethod("insert", - new Class[] { Any.class, object.getClass() } - ); + Method insert = helperClass.getMethod("insert", new Class[] { + Any.class, object.getClass() }); insert.invoke(null, new Object[] { into, object }); @@ -385,20 +463,20 @@ public class ObjectCreator { try { - cdrBufOutput output = new cdrBufOutput(); + BufferedCdrOutput output = new BufferedCdrOutput(); - String m_exception_id = toIDL(exception.getClass().getName()); + String m_exception_id = getRepositoryId(exception.getClass()); output.write_string(m_exception_id); output.write_ulong(exception.minor); CompletionStatusHelper.write(output, exception.completed); String name = getDefaultName(m_exception_id); - universalHolder h = new universalHolder(output); + GeneralHolder h = new GeneralHolder(output); into.insert_Streamable(h); - recordTypeCode r = new recordTypeCode(TCKind.tk_except); + RecordTypeCode r = new RecordTypeCode(TCKind.tk_except); r.setId(m_exception_id); r.setName(name); into.type(r); @@ -444,4 +522,69 @@ public class ObjectCreator if (!ok) throw new InternalError("Exception wrapping broken"); } + + /** + * Find helper for the class with the given name. + */ + public static Class findHelper(String idl) + { + synchronized (m_helpers) + { + Class c = (Class) m_helpers.get(idl); + if (c != null) + return c; + try + { + String helper = toHelperName(idl); + c = forName(helper); + + m_helpers.put(idl, c); + return c; + } + catch (Exception ex) + { + return null; + } + } + } + + /** + * Load the class with the given name. This method tries to use the context + * class loader first. If this fails, it searches for the suitable class + * loader in the caller stack trace. This method is a central point where all + * requests to find a class by name are delegated. + */ + public static Class forName(String className) throws ClassNotFoundException + { + try + { + return Class.forName(className, true, + Thread.currentThread().getContextClassLoader()); + } + catch (ClassNotFoundException nex) + { + /** + * Returns the first user defined class loader on the call stack, or + * null when no non-null class loader was found. + */ + Class[] ctx = VMStackWalker.getClassContext(); + for (int i = 0; i < ctx.length; i++) + { + // Since we live in a class loaded by the bootstrap + // class loader, getClassLoader is safe to call without + // needing to be wrapped in a privileged action. + ClassLoader cl = ctx[i].getClassLoader(); + try + { + if (cl != null) + return Class.forName(className, true, cl); + } + catch (ClassNotFoundException nex2) + { + // Try next. + } + } + } + throw new ClassNotFoundException(className); + } }
\ No newline at end of file |