Issue 2081: Specifying code downloading (java2idl-rtf) Source: (, ) Nature: Uncategorized Issue Severity: Summary: Summary: The spec should mandate codebase annotation when marshalling in Java, and should specify how the annotation is selected. The spec should mandate code downloading using the codebase annotation when demarshalling in Java, and should specify the classloader semantics. Resolution: Closed, accepted Revised Text: Requirements The spec should allow codebase annotation when marshalling in Java, and should specify how the annotation is selected for RMI-IIOP values and object references. The spec should mandate code downloading using the codebase annotation for Java demarshalling of RMI-IIOP values, stubs and ties, and should specify the classloader semantics. Original Proposal This proposal is defined in terms of JDK 1.2 APIs. When sending from Java, for any given java.lang.Class instance C, the codebase annotation used must be equivalent to the codebase returned by: java.rmi.server.RMIClassLoader.getClassAnnotation(C); (with the string parsed into space-separated URL strings). When receiving in Java, for any given class name N, if there is no codebase annotation, or if the system property java.rmi.server.useCodebaseOnly is equal to "true" ignoring case, then the Java class that this name resolves to must be the same as that returned by: java.rmi.server.RMIClassLoader.loadClass(N); Otherwise, if the codebase annotation is CA, then the Java class that this name resolves to must be the same as that returned by: java.rmi.server.RMIClassLoader.loadClass(CA, N); (with CA turned into a single string with space as separator). Ammended Proposal Class downloading is supported for stubs, ties, values, and value helpers. The implementation is based on the original proposal, with enhancements to enable implementation on JDK 1.1.6 APIs, to enable transmission of codebase information on the wire for stubs and ties, and to enable usage of pre-existing ClassLoaders when relevant. Definitions "codebase" - A java.lang.String containing a space-separated array of URLs (e.g. "http://acme.com/classes" or "http://abc.net/classes http://abc.net/ext/classes"). [Note: the space-separated representation is preferred over a String[] representation in order to avoid conversion when calling the 1.2 JDK RMI APIs.] "localCodebase" - The System Property "java.rmi.server.codebase" whose value is a codebase or null. Defaults to null. "remoteCodebase" - The codebase transmitted from a remote system. May be null. "useCodebaseOnly" - The System Property "java.rmi.server.useCodebaseOnly" whose value is either "true" or "false". Defaults to "false". If "true" (ignoring case), any remote codebase is ignored and only the local codebase used. "loadingContext" - A class that specifies a context within which class loading is initiated. May be null. Codebase Selection The following method is added to the javax.rmi.CORBA.Util class: public static String getCodebase(java.lang.Class clz) { ... } On JDK 1.2, this method returns the same string as: java.rmi.server.RMIClassLoader.getClassAnnotation(clz) On JDK 1.1, this method works as follows: 1. If the name of clz starts with "java.", then return null, else... 2. If clz has a ClassLoader with a URL security context, then return this URL, else... 3. If there is a security manager with a URL security context, then return this URL, else... 4 Return localCodebase. When sending RMI/IDL values from Java, the codebase transmitted over GIOP must be the codebase that this method would return for the value's class. When sending RMI/IDL object references from Java, the codebase transmitted over GIOP is selected by calling the org.omg.CORBA_2_3.portable.ObjectImpl._get_codebase method (see below) on the stub object. Codebase Transmission For values and value helpers, the OBV specification defines the wire format for codebase transmission. For stubs and ties, the codebase is transmitted as a TaggedComponent in the IOR profile, where the component_data is a CDR encapsulation of the codebase written as an IDL string. The codebase is a blank-separated list of one or more URLs. [NOTE: component_id needs to be assigned by the Interoperability RTF.] In all cases, the SendingContext.RunTime object may provide a default codebase that is used if not overridden by a more specific codebase encoded in a valuetype or IOR. For object references created using InputStream.read_Object or InputStream.read_Abstract, the transmitted codebase is stored in the object reference (stub) and can be retrieved subsequently using the org.omg.CORBA_2_3.portable.ObjectImpl._get_codebase method, described below. If no codebase was transmitted, localCodebase is stored in the object reference (stub). Codebase Access In the event that PortableRemoteObject.narrow() must load a stub, a new API is required to extract codebase information from the original stub. This API is also used by the OutputStream methods write_Object and write_Abstract to obtain the codebase to be transmitted in the new TaggedComponent. The following method is added to org.omg.CORBA_2_3.portable.ObjectImpl, which is a newly created subclass of org.omg.CORBA.portable.ObjectImpl: /** Returns the codebase for this object reference. * @return the codebase as a space delimited list of url strings or * null if none. */ public java.lang.String _get_codebase() { return ((org.omg.CORBA_2_3.portable.Delegate)_get_delegate()).get_codebase(this); } and a corresponding method is added to org.omg.CORBA_2_3.portable.Delegate, which is a newly created subclass of org.omg.CORBA.portable.Delegate: /** Returns the codebase for the object reference provided. * @param self the object reference whose codebase needs to be returned. * @return the codebase as a space delimited list of url strings or * null if none. */ public java.lang.String get_codebase(org.omg.CORBA.Object self) { return null; } The javax.rmi.CORBA.Stub class is changed to extend org.omg.CORBA_2_3.portable.ObjectImpl instead of org.omg.CORBA.portable.ObjectImpl. Codebase Usage The following method is added to the javax.rmi.CORBA.Util class: public static Class loadClass(String className, String remoteCodebase, Class loadingContext) throws ClassNotFoundException { ... } On JDK 1.2, this method works as follows: 1. Find the first non-null ClassLoader on the call stack, and attempt to load the class using this ClassLoader. If this fails... 2. If remoteCodebase is non-null and useCodebaseOnly is false, then call java.rmi.server.RMIClassLoader.loadClass(remoteCodebase, className). 3. If remoteCodebase is null or useCodebaseOnly is true, then call java.rmi.server.RMIClassLoader.loadClass(className). 4. If a class was not successfully loaded by step 1, 2, or 3, and loadingContext and loadingContext.getClassLoader() are both non-null, then call loadingContext.getClassLoader().loadClass(className). 5. If a class was successfully loaded by step 1, 2, 3, or 4, then return the loaded class. On JDK 1.1, this method works as follows: 1. If className is an array type, extract the array element type. If this is a primitive type, then call Class.forName(className), else proceed using the array element class name as className. 2. Search the call stack for the first non-null ClassLoader. If a ClassLoader is found, then attempt to load the class using this ClassLoader, else attempt to load the class using Class.ForName(className). If this fails... 3. If remoteCodebase is non-null and useCodebaseOnly is false, then call java.rmi.server.RMIClassLoader.loadClass(codebaseURL, className) for each remote codebase URL in the remoteCodebase string until the class is found. 4. If remoteCodebase is null or useCodebaseOnly is true, then call java.rmi.server.RMIClassLoader.loadClass(className). 5. If a class was not successfully loaded by step 1, 2, 3, or 4, and loadingContext and loadingContext.getClassLoader() are both non-null, then call loadingContext.getClassLoader().loadClass(className). 6. If a class was successfully loaded by step 1, 2, 3, 4, or 5, then return the loaded class, unless the className parameter was a non-primitive array type, in which case return a suitably dimensioned array class for the element class that was loaded. When loading classes for RMI/IDL values, stubs, and ties, the class loaded must be be the same as that returned by this method except where stated below. For values and their helper classes, remoteCodebase is the codebase that was transmitted in the GIOP valuetype encoding (if any), or else the codebase obtained from the SendingContext.RunTime object associated with the IIOP connection. loadingContext is null or the expected value class, if known. For ties created by PortableRemoteObject.exportObject, remoteCodebase is obtained by calling Util.getCodebase on the class of the implementation object. loadingContext is null. For stubs created by InputStream.read_Object(), remoteCodebase is the codebase transmitted in the new IOR TaggedComponent (if any), or else the codebase obtained from the SendingContext.RunTime object associated with the IIOP connection. This method may either create a generic stub for subsequent narrowing or may attempt to create a stub by loading a stub class that matches the RepositoryId in the IOR. loadingContext is null. For stubs created by InputStream.read_Object(clz), remoteCodebase is the same as for InputStream.read_Object(). The implementation of read_Object(clz) may either use the actual parameter clz to create a stub or may attempt to create a stub by loading a stub class that matches the RepositoryId in the IOR. loadingContext is clz. For stubs created by PortableRemoteObject.narrow, remoteCodebase is obtained from the narrowFrom object by calling the ObjectImpl._get_codebase method. For stubs created by PortableRemoteObject.toStub, Util.writeRemoteObject or Util.writeAbstractObject, remoteCodebase is obtained by calling Util.getCodebase on the class of the implementation object. loadingContext is narrowFrom. For all stubs, remoteCodebase is stored by the Delegate and can be retrieved subsequently using the org.omg.CORBA_2_3.portable.ObjectImpl._get_codebase method. Other Changes In section 28.3.5.11, change the definition of javax.rmi.CORBA.ClassDesc to: // Java package javax.rmi.CORBA; public class ClassDesc implements java.io.Serializable { private String repid; private String codebase; // blank-separated list of URLs } Actions taken: October 14, 1998: received issue June 4, 1999: closed issue Discussion: End of Annotations:===== Return-Path: Date: Wed, 14 Oct 1998 17:57:54 +0100 From: Simon Nash Organization: IBM To: issues@omg.org CC: java2idl-rtf@omg.org Subject: Specifying code downloading The following Java to IDL issue was raised by Bob Scheifler. It needs to be added to the issues database. The spec should mandate codebase annotation when marshalling in Java, and should specify how the annotation is selected. The spec should mandate code downloading using the codebase annotation when demarshalling in Java, and should specify the classloader semantics. Simon -- Simon C Nash, IBM Java Technology Centre, Hursley, UK MailPoint 146, x245156 Tel. 01962 815156 or +44-1962-815156 Internet: nash@hursley.ibm.com Notes mail: Simon Nash@ibmgb