001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: *
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: /**
020: * @author Mikhail A. Markov
021: * @version $Revision: 1.1.2.2 $
022: */package org.apache.harmony.rmi.transport;
023:
024: import java.io.InputStream;
025: import java.io.ObjectInputStream;
026: import java.io.ObjectStreamClass;
027: import java.io.IOException;
028: import java.rmi.server.RMIClassLoader;
029: import java.security.AccessController;
030: import java.security.PrivilegedAction;
031:
032: import org.apache.harmony.rmi.common.GetBooleanPropAction;
033: import org.apache.harmony.rmi.common.RMIProperties;
034: import org.apache.harmony.rmi.internal.nls.Messages;
035:
036: import org.apache.harmony.kernel.vm.VM;
037:
038: /**
039: * The RMIObjectInputStream is a subclass of ObjectInputStream performing
040: * deserialization for RMI calls.
041: *
042: * @author Mikhail A. Markov
043: * @version $Revision: 1.1.2.2 $
044: */
045: public class RMIObjectInputStream extends ObjectInputStream {
046:
047: // Annotations for serialized objects.
048: private ObjectInputStream locStream;
049:
050: // True if this stream was created for handling a RemoteCall
051: private boolean isRCallStream = false;
052:
053: // True if we need DGC ack call.
054: private boolean needDGCAck = false;
055:
056: /*
057: * If true we'll not load classes from places other then local classpath and
058: * location set by java.rmi.server.codebase property.
059: */
060: private static boolean useCodebaseOnly = ((Boolean) AccessController
061: .doPrivileged(new GetBooleanPropAction(
062: RMIProperties.USECODEBASEONLY_PROP)))
063: .booleanValue();
064:
065: /**
066: * Constructs a RMIObjectInputStream that reads from the specified
067: * InputStream. This stream will be a non-RemoteCall stream (i.e.
068: * isRemoteCallStream() method will return false).
069: *
070: * @param in underlying InputStream
071: *
072: * @throws IOException if an I/O error occurred during stream initialization
073: */
074: public RMIObjectInputStream(InputStream in) throws IOException {
075: this (in, false);
076: }
077:
078: /**
079: * Constructs a RMIObjectInputStream that reads from the specified
080: * InputStream.
081: *
082: * @param in underlying InputStream
083: * @param isRCallStream true if this stream was created for handling
084: * a RemoteCall and false otherwise
085: *
086: * @throws IOException if an I/O error occurred during stream initialization
087: */
088: public RMIObjectInputStream(InputStream in, boolean isRCallStream)
089: throws IOException {
090: super (in);
091: this .isRCallStream = isRCallStream;
092: locStream = this ;
093: AccessController.doPrivileged(new PrivilegedAction() {
094: public Object run() {
095: enableResolveObject(true);
096: return null;
097: }
098: });
099: }
100:
101: /**
102: * Resolves annotated class. To resolves class method calls
103: * Class.forName(classname, false, classloader) where classloader is
104: * the first non-null class loader up in the execution stack or null
105: * if no non-null class loaders were found in the stack.
106: *
107: * @param streamCl annotated class
108: *
109: * @throws IOException if an I/O exception occurred
110: * @throws ClassNotFoundException if class of a serialized object
111: * could not be found
112: */
113: protected Class resolveClass(ObjectStreamClass streamCl)
114: throws IOException, ClassNotFoundException {
115: String annot = (locStream == null) ? null : (String) locStream
116: .readObject();
117:
118: if (useCodebaseOnly) {
119: annot = null;
120: }
121: Class cl = RMIClassLoader.loadClass(annot, streamCl.getName(),
122: VM.getNonBootstrapClassLoader());
123: return cl;
124: }
125:
126: /**
127: * Resolves annotated proxy class.
128: *
129: * @param interf array of interfaces which proxy class should implement
130: *
131: * @throws IOException if an I/O exception occurred
132: * @throws ClassNotFoundException if class of a serialized object
133: * could not be found
134: */
135: protected Class resolveProxyClass(String[] interf)
136: throws IOException, ClassNotFoundException {
137: String annot = (locStream == null) ? null : (String) locStream
138: .readObject();
139:
140: if (useCodebaseOnly) {
141: annot = null;
142: }
143: Class cl = RMIClassLoader.loadProxyClass(annot, interf, VM
144: .getNonBootstrapClassLoader());
145: return cl;
146: }
147:
148: /**
149: * Sets annotation's stream to the value specified.
150: * Subclasses should call this method if they want to read annotations from
151: * the stream other then one for objects themselves.
152: *
153: * @param in stream for annotations
154: */
155: protected void setLocStream(ObjectInputStream in) {
156: locStream = in;
157: }
158:
159: /**
160: * Reads object (possibly primitive value) from the stream.
161: *
162: * @param cl expected class to be read from the stream
163: * @param loader ClassLoader for classes resolving (ClassLoader which
164: * will be specified in the calls to RMIClassLoader.)
165: *
166: * @return object read from the stream
167: *
168: * @throws IOException if an I/O error occurred during deserialization
169: * @throws ClassNotFoundException if class of a serialized object
170: * could not be found
171: */
172: public synchronized Object readRMIObject(Class cl)
173: throws IOException, ClassNotFoundException {
174: if (cl.isPrimitive()) {
175: if (cl == Boolean.TYPE) {
176: return new Boolean(readBoolean());
177: } else if (cl == Byte.TYPE) {
178: return new Byte(readByte());
179: } else if (cl == Short.TYPE) {
180: return new Short(readShort());
181: } else if (cl == Integer.TYPE) {
182: return new Integer(readInt());
183: } else if (cl == Long.TYPE) {
184: return new Long(readLong());
185: } else if (cl == Float.TYPE) {
186: return new Float(readFloat());
187: } else if (cl == Double.TYPE) {
188: return new Double(readDouble());
189: } else if (cl == Character.TYPE) {
190: return new Character(readChar());
191: } else if (cl == Void.TYPE) {
192: return null;
193: } else {
194: // rmi.7F=Unknown primitive class: {0}
195: throw new IOException(Messages.getString("rmi.7F", cl)); //$NON-NLS-1$
196: }
197: } else {
198: return readObject();
199: }
200: }
201:
202: /**
203: * Returns true if this stream was created for handling a RemoteCall and
204: * false otherwise.
205: *
206: * @return true if this stream was created for handling a RemoteCall and
207: * false otherwise
208: */
209: public boolean isRemoteCallStream() {
210: return isRCallStream;
211: }
212:
213: /**
214: * Sets the flag of DGC ack call to the given value.
215: *
216: * @param need true if we need DGC ack call and false otherwise
217: */
218: public void needDGCAck(boolean need) {
219: needDGCAck = need;
220: }
221:
222: /**
223: * Returns the value of DGC ack call field.
224: *
225: * @return the value of DGC ack call field
226: */
227: public boolean isDGCAckNeeded() {
228: return needDGCAck;
229: }
230: }
|