001: /*
002: * @(#)ImportedObject.java 1.5 06/09/06
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.jumpimpl.ixc;
028:
029: import java.lang.reflect.Method;
030: import java.lang.reflect.Constructor;
031: import java.rmi.Remote;
032: import java.rmi.RemoteException;
033: import java.security.AccessController;
034: import java.security.PrivilegedAction;
035: import java.util.Arrays;
036: import java.util.Collection;
037: import java.util.HashMap;
038: import java.util.List;
039: import javax.microedition.xlet.XletContext;
040: import javax.microedition.xlet.ixc.*;
041:
042: /*
043: * An record of an imported Remote objects for this client VM.
044: */
045:
046: public class ImportedObject {
047:
048: static HashMap importedObjects = new HashMap(); // <XletContext, HashMap of RemoteRef, ImportedObj>
049: static HashMap typeByName = new HashMap(); // <Array of interface Names, stub>
050:
051: private StubObject stub;
052:
053: /**
054: * If the list of interface names in the RemoteRef parameter
055: * is something that we've seen in the past, then simply instanciate
056: * the stub class that we generated earlier. Else, generate the stub
057: * and save it for the future use.
058: * TODO: In the future, may need to identify stub based on XletContext
059: * as well (necessary when we have multiple xlets in a single VM).
060: **/
061: private ImportedObject(RemoteRef ref, XletContext context)
062: throws StubException {
063:
064: List interfaceNames = Arrays.asList(ref.interfaceNames);
065: Class stubClass;
066:
067: synchronized (typeByName) {
068:
069: stubClass = (Class) typeByName.get(interfaceNames);
070:
071: if (stubClass == null) {
072: ClassLoader xletLoader = context.getClassLoader();
073:
074: if (xletLoader == null)
075: throw new StubException(
076: "XletContext.getClassLoader() returns null");
077:
078: RemoteObjectType roType;
079: try {
080: roType = new RemoteObjectType(ref.interfaceNames,
081: xletLoader);
082: } catch (RemoteException re) {
083: if (re instanceof StubException)
084: throw (StubException) re;
085: else
086: throw new StubException(
087: "Can't find needed interfaces for stub generation",
088: re.getCause());
089: }
090:
091: checkForTheMethodsMatch(ref.methodIDs,
092: roType.methodsByID.keySet());
093: StubClassGenerator generator = new StubClassGenerator(
094: xletLoader);
095: stubClass = generator.generate(roType);
096:
097: typeByName.put(interfaceNames, stubClass);
098: }
099: }
100:
101: // Stub class to be instanciated.
102: final Class stubClassF = stubClass;
103:
104: //System.out.println("@@ Got remote class " + stubClass);
105: final Class[] types = { Object.class, Object.class };
106: final Object[] args = { ref, context };
107:
108: // Instanciate a stub.
109: Object returnValue = AccessController
110: .doPrivileged(new PrivilegedAction() {
111: public Object run() {
112:
113: Object obj;
114: try {
115: Constructor m = stubClassF
116: .getConstructor(types);
117: obj = m.newInstance(args);
118: } catch (Exception ex) {
119: obj = new StubException(
120: "Cannot create stub object", ex);
121: }
122:
123: return obj;
124: }
125: });
126:
127: if (returnValue instanceof StubException) {
128: throw (StubException) returnValue;
129: }
130:
131: stub = (StubObject) returnValue;
132: //System.out.println("@@ Created object " + stub);
133: }
134:
135: // Return a stub object for the RemoteRef.
136: // If the RemoteRef object has been registered in the past,
137: // then just return the ImportedObject for it.
138: public static Remote registerImportedObject(RemoteRef ref,
139: XletContext context) throws StubException {
140:
141: ImportedObject importedObject = null;
142:
143: synchronized (importedObjects) {
144: //importedObject = (ImportedObject) importedObjects.get(ref);
145: HashMap map = (HashMap) importedObjects.get(context);
146: if (map == null) {
147: map = new HashMap();
148: importedObjects.put(context, map);
149: } else {
150: importedObject = (ImportedObject) map.get(ref);
151: }
152:
153: if (importedObject == null) {
154: importedObject = new ImportedObject(ref, context);
155: map.put(ref, importedObject);
156: }
157: }
158:
159: return (Remote) importedObject.stub;
160: }
161:
162: private void checkForTheMethodsMatch(long[] originalIDs,
163: Collection otherIDs) throws StubException {
164:
165: // Checks whether the array of method hash passed in as a RemoteRef
166: // contains exactly the same set of long values that this importer
167: // computed based on the set of Remote Methods found in this classloader
168: // context.
169:
170: if (originalIDs.length != otherIDs.size())
171: throw new StubException("Mismatching Remote Interface");
172:
173: for (int i = 0; i < originalIDs.length; i++) {
174: if (!otherIDs.contains(new Long(originalIDs[i])))
175: throw new StubException("Mismatching Remote Interface");
176: }
177: }
178: }
|