001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026: package org.cougaar.mts.rmi;
027:
028: import java.io.ObjectInput;
029: import java.lang.reflect.Constructor;
030: import java.net.URI;
031: import java.rmi.server.RemoteRef;
032:
033: import org.cougaar.mts.base.SocketFactory;
034:
035: import sun.rmi.server.UnicastRef;
036: import sun.rmi.transport.LiveRef;
037:
038: /**
039: * Decode an RMI RemoteObject from a URI.
040: *
041: * @see RMIRemoteObjectEncoder
042: */
043: public final class RMIRemoteObjectDecoder {
044:
045: private RMIRemoteObjectDecoder() {
046: }
047:
048: /**
049: * @param uri the URI representation
050: * @return a RemoteObject
051: * @see RMIRemoteObjectEncoder#encode(Object) decode is the reverse of encode
052: */
053: public static Object decode(URI uri) throws Exception {
054: MyObjectInput lrIn = new MyObjectInput(uri);
055: LiveRef lr = LiveRef.read(lrIn, lrIn.has_csf);
056: final RemoteRef rr = new UnicastRef(lr);
057: Class cl = Class.forName(lrIn.clname);
058: Constructor cons = cl
059: .getConstructor(new Class[] { RemoteRef.class });
060: Object ret = cons.newInstance(new Object[] { rr });
061: return ret;
062: }
063:
064: /** custom object input, exactly matching UnicastRef */
065: private static class MyObjectInput implements ObjectInput {
066:
067: public final String tcp_host;
068: public final int tcp_port;
069: public final String clname;
070: public final boolean ref_remote;
071: public final int uid_unique;
072: public final long uid_time;
073: public final short uid_count;
074: public final long oid_num;
075: public boolean has_csf;
076: public boolean use_ssl;
077: public boolean use_aspects;
078:
079: private int state = 0;
080:
081: public MyObjectInput(URI uri) {
082: try {
083: if (!("rmi".equals(uri.getScheme()))) {
084: throw new RuntimeException(
085: "Expecting scheme to be \"rmi\", not "
086: + uri.getScheme());
087: }
088: this .tcp_host = uri.getHost();
089: this .tcp_port = uri.getPort();
090: String s = uri.getPath();
091: int i = 0;
092: if (s.charAt(0) != '/') {
093: throw new RuntimeException("Invalid path");
094: }
095: i++;
096: int j = s.indexOf('/', i);
097: this .clname = s.substring(i, j);
098: i = j + 1;
099: j = s.indexOf('_', i);
100: this .ref_remote = "1".equals(s.substring(i, j));
101: i = j + 1;
102: j = s.indexOf('_', i);
103: this .uid_unique = Integer.parseInt(s.substring(i, j),
104: 16);
105: i = j + 1;
106: j = s.indexOf('_', i);
107: this .uid_time = Long.parseLong(s.substring(i, j), 16);
108: i = j + 1;
109: j = s.indexOf('_', i);
110: this .uid_count = Short
111: .parseShort(s.substring(i, j), 16);
112: i = j + 1;
113: j = s.indexOf('/', i);
114: this .oid_num = Long.parseLong(s.substring(i, j));
115: i = j + 1;
116: if (i < s.length()) {
117: // the ref has a socket factory
118: has_csf = true;
119: char ssl_flag = s.charAt(i);
120: char aspect_flag = s.charAt(i + 1);
121: use_ssl = ssl_flag == '1';
122: use_aspects = aspect_flag == '1';
123: } else {
124: has_csf = false;
125: }
126: } catch (Exception e) {
127: throw new RuntimeException("Invalid URI: " + uri, e);
128: }
129: }
130:
131: public int readInt() {
132: ++state;
133: if (state == 2)
134: return tcp_port;
135: if (state == 4)
136: return uid_unique;
137: die();
138: return -1;
139: }
140:
141: public long readLong() {
142: ++state;
143: if (state == 3)
144: return oid_num;
145: if (state == 5)
146: return uid_time;
147: die();
148: return -1;
149: }
150:
151: public short readShort() {
152: ++state;
153: if (state == 6)
154: return uid_count;
155: die();
156: return -1;
157: }
158:
159: public String readUTF() {
160: ++state;
161: if (state == 1)
162: return tcp_host;
163: die();
164: return null;
165: }
166:
167: public boolean readBoolean() {
168: ++state;
169: if (state == 7)
170: return ref_remote;
171: die();
172: return false;
173: }
174:
175: // Handle socket factories
176:
177: public byte readByte() {
178: // Should only be called if has_csf is true and is only used
179: // in this object to return a flag indicating that fact. So
180: // always return 1 (or die if no csf).
181: if (!has_csf)
182: die();
183: return 1;
184: }
185:
186: public Object readObject() {
187: // Should only be called if has_csf is true. This is used to
188: // get the csf itself. For simpler backward compatibility,
189: // don't increment the state.
190: if (has_csf && state == 2) {
191: // HACK: hardwire the creation of a SocketFactory!
192: // Later we might want to share the factory rather than
193: // creating a new one for each remote ref.
194: return new SocketFactory(use_ssl, use_aspects);
195: } else {
196: die();
197: return null;
198: }
199: }
200:
201: // die:
202: private void die() {
203: throw new RuntimeException(
204: "LiveRef reader has changed (state=" + state + ")");
205: }
206:
207: // DataInput:
208: public void readFully(byte b[]) {
209: die();
210: }
211:
212: public void readFully(byte b[], int off, int len) {
213: die();
214: }
215:
216: public int skipBytes(int n) {
217: die();
218: return -1;
219: }
220:
221: public int readUnsignedByte() {
222: die();
223: return -1;
224: }
225:
226: public int readUnsignedShort() {
227: die();
228: return -1;
229: }
230:
231: public char readChar() {
232: die();
233: return (char) -1;
234: }
235:
236: public float readFloat() {
237: die();
238: return -1;
239: }
240:
241: public double readDouble() {
242: die();
243: return -1;
244: }
245:
246: public String readLine() {
247: die();
248: return null;
249: }
250:
251: // ObjectInput:
252: public int read() {
253: die();
254: return -1;
255: }
256:
257: public int read(byte b[]) {
258: die();
259: return -1;
260: }
261:
262: public int read(byte b[], int off, int len) {
263: die();
264: return -1;
265: }
266:
267: public long skip(long n) {
268: die();
269: return -1;
270: }
271:
272: public int available() {
273: die();
274: return -1;
275: }
276:
277: public void close() {
278: die();
279: }
280: };
281: }
|