KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > remoting > rmi > CodebaseAwareObjectInputStream


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.remoting.rmi;
18
19 import java.io.IOException JavaDoc;
20 import java.io.InputStream JavaDoc;
21 import java.io.ObjectInputStream JavaDoc;
22 import java.io.ObjectStreamClass JavaDoc;
23 import java.lang.reflect.Proxy JavaDoc;
24 import java.rmi.server.RMIClassLoader JavaDoc;
25
26 import org.springframework.util.ClassUtils;
27
28 /**
29  * Special ObjectInputStream subclass that falls back to a specified codebase
30  * to load classes from if not found locally. In contrast to standard RMI
31  * conventions for dynamic class download, it is the client that determines
32  * the codebase URL here, rather than the "java.rmi.server.codebase" system
33  * property on the server.
34  *
35  * <p>Uses the JDK's RMIClassLoader to load classes from the specified codebase.
36  * The codebase can consist of multiple URLs, separated by spaces.
37  * Note that RMIClassLoader requires a SecurityManager to be set, like when
38  * using dynamic class download with standard RMI! (See the RMI documentation
39  * for details.)
40  *
41  * <p>Despite residing in the RMI package, this class is <i>not</i> used for
42  * RmiClientInterceptor, which uses the standard RMI infrastructure instead
43  * and thus is only able to rely on RMI's standard dynamic class download via
44  * "java.rmi.server.codebase". CodebaseAwareObjectInputStream is used by
45  * HttpInvokerClientInterceptor (see the "codebaseUrl" property there).
46  *
47  * <p>Thanks to Lionel Mestre for suggesting the option and providing
48  * a prototype!
49  *
50  * @author Juergen Hoeller
51  * @since 1.1.3
52  * @see java.rmi.server.RMIClassLoader
53  * @see org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor#setCodebaseUrl
54  */

55 public class CodebaseAwareObjectInputStream extends ObjectInputStream JavaDoc {
56
57     private final ClassLoader JavaDoc classLoader;
58
59     private final String JavaDoc codebaseUrl;
60
61
62     /**
63      * Create a new CodebaseAwareObjectInputStream for the given InputStream and codebase.
64      * @param in the InputStream to read from
65      * @param codebaseUrl the codebase URL to load classes from if not found locally
66      * (can consist of multiple URLs, separated by spaces)
67      * @see java.io.ObjectInputStream#ObjectInputStream(java.io.InputStream)
68      */

69     public CodebaseAwareObjectInputStream(InputStream JavaDoc in, String JavaDoc codebaseUrl) throws IOException JavaDoc {
70         this(in, null, codebaseUrl);
71     }
72
73     /**
74      * Create a new CodebaseAwareObjectInputStream for the given InputStream and codebase.
75      * @param in the InputStream to read from
76      * @param classLoader the ClassLoader to use for loading local classes
77      * (may be <code>null</code> to indicate RMI's default ClassLoader)
78      * @param codebaseUrl the codebase URL to load classes from if not found locally
79      * (can consist of multiple URLs, separated by spaces)
80      * @see java.io.ObjectInputStream#ObjectInputStream(java.io.InputStream)
81      */

82     public CodebaseAwareObjectInputStream(
83             InputStream JavaDoc in, ClassLoader JavaDoc classLoader, String JavaDoc codebaseUrl) throws IOException JavaDoc {
84
85         super(in);
86         this.classLoader = classLoader;
87         this.codebaseUrl = codebaseUrl;
88     }
89
90
91     /**
92      * Overridden version delegates to super class first,
93      * falling back to the specified codebase if not found locally.
94      */

95     protected Class JavaDoc resolveClass(ObjectStreamClass JavaDoc classDesc) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
96         try {
97             if (this.classLoader != null) {
98                 // Use the specified ClassLoader to resolve local classes.
99
return Class.forName(classDesc.getName(), false, this.classLoader);
100             }
101             else {
102                 // Let RMI use it's default ClassLoader...
103
return super.resolveClass(classDesc);
104             }
105         }
106         catch (ClassNotFoundException JavaDoc ex) {
107             // Explicitly resolve primitive class name.
108
// This will be done by the standard ObjectInputStream on JDK 1.4+,
109
// but needs to be done explicitly on JDK 1.3.
110
Class JavaDoc clazz = ClassUtils.resolvePrimitiveClassName(classDesc.getName());
111             if (clazz != null) {
112                 return clazz;
113             }
114             // If codebaseUrl is set, try to load the class with the RMIClassLoader.
115
// Else, propagate the ClassNotFoundException.
116
if (this.codebaseUrl == null) {
117                 throw ex;
118             }
119             return RMIClassLoader.loadClass(this.codebaseUrl, classDesc.getName());
120         }
121     }
122
123     /**
124      * Overridden version delegates to super class first,
125      * falling back to the specified codebase if not found locally.
126      */

127     protected Class JavaDoc resolveProxyClass(String JavaDoc[] interfaces) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
128         if (this.classLoader != null) {
129             // Use the specified ClassLoader to resolve local proxy classes.
130
Class JavaDoc[] resolvedInterfaces = new Class JavaDoc[interfaces.length];
131             for (int i = 0; i < interfaces.length; i++) {
132                 try {
133                     resolvedInterfaces[i] = Class.forName(interfaces[i], false, this.classLoader);
134                 }
135                 catch (ClassNotFoundException JavaDoc ex) {
136                     if (this.codebaseUrl == null) {
137                         throw ex;
138                     }
139                     resolvedInterfaces[i] = RMIClassLoader.loadClass(this.codebaseUrl, interfaces[i]);
140                 }
141             }
142             try {
143                 return Proxy.getProxyClass(this.classLoader, resolvedInterfaces);
144             }
145             catch (IllegalArgumentException JavaDoc ex) {
146                 throw new ClassNotFoundException JavaDoc(null, ex);
147             }
148         }
149         else {
150             // Let RMI use it's default ClassLoader...
151
try {
152                 return super.resolveProxyClass(interfaces);
153             }
154             catch (ClassNotFoundException JavaDoc ex) {
155                 if (this.codebaseUrl == null) {
156                     throw ex;
157                 }
158                 ClassLoader JavaDoc loader = RMIClassLoader.getClassLoader(this.codebaseUrl);
159                 Class JavaDoc[] resolvedInterfaces = new Class JavaDoc[interfaces.length];
160                 for (int i = 0; i < interfaces.length; i++) {
161                     resolvedInterfaces[i] = loader.loadClass(interfaces[i]);
162                 }
163                 return Proxy.getProxyClass(loader, resolvedInterfaces);
164             }
165         }
166     }
167
168 }
169
Popular Tags