001: // You can redistribute this software and/or modify it under the terms of
002: // the Ozone Library License version 1 published by ozone-db.org.
003: //
004: // The original code and portions created by SMB are
005: // Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
006: //
007: // $Id: OzoneProxy.java,v 1.3 2002/06/08 00:49:38 mediumnet Exp $
008:
009: package org.ozoneDB;
010:
011: import java.io.*;
012:
013: import org.ozoneDB.DxLib.DxHashMap;
014: import org.ozoneDB.DxLib.DxMap;
015: import org.ozoneDB.core.Env;
016: import org.ozoneDB.core.ObjectID;
017: import org.ozoneDB.core.GarbageCollector;
018: import org.ozoneDB.core.xml.Consts;
019: import org.xml.sax.helpers.AttributesImpl;
020:
021: /**
022: * Proxy of an OzoneRemote object.
023: *
024: *
025: * @author <a href="http://www.softwarebuero.de/">SMB</a>
026: * @author <a href="http://www.medium.net/">Medium.net</a>
027: * @version $Revision: 1.3 $Date: 2002/06/08 00:49:38 $
028: */
029: public class OzoneProxy implements OzoneRemote, Externalizable {
030:
031: private final static long serialVersionUID = 3L;
032:
033: /**
034: * Table of stream to OzoneInterface pairs. readExternal() checks this
035: * table to find corresponding database link.
036: */
037: public static DxMap linkTable = new DxHashMap();
038:
039: public transient OzoneInterface link = null;
040:
041: public ObjectID remoteID;
042:
043: /**
044: * This constructor will only be called, when the object is constructed
045: * from a stream.
046: */
047: public OzoneProxy() {
048: //we assume that we are inside the kernel
049: Env env = Env.currentEnv();
050: if (env != null) {
051: link = env.database;
052: }
053: }
054:
055: /**
056: * This constructor is only be called, when this object is constructed
057: * inside the database. However, it may be the result of a RMI call.
058: */
059: public OzoneProxy(ObjectID id, OzoneInterface link) {
060: this .link = link;
061: remoteID = (ObjectID) id.clone();
062: }
063:
064: public OzoneProxy(OzoneProxy rhs) {
065: link = rhs.link;
066: remoteID = (ObjectID) rhs.remoteID.clone();
067: }
068:
069: public boolean isSame(OzoneProxy proxy) {
070: return remoteID.equals(proxy.remoteID);
071: }
072:
073: /**
074: * Base implementation of equals(). May be overwritten by an implementation
075: * of the actual database object. In that case the method is handled, as all
076: * remote methods, on the server side.
077: */
078: public boolean equals(Object obj) {
079: if (obj instanceof OzoneProxy && obj != null) {
080: return isSame((OzoneProxy) obj);
081: } else {
082: return false;
083: }
084: }
085:
086: /**
087: * Base implementation of hashCode(). May be overwritten by an implementation
088: * of the actual database object. In that case the method is handled, as all
089: * remote methods, on the server side.
090: */
091: public int hashCode() {
092: return remoteID.hashCode();
093: }
094:
095: /**
096: * Base implementation of toString(). May be overwritten by an implementation
097: * of the actual database object. In that case the method is handled, as all
098: * remote methods, on the server side.
099: */
100: public String toString() {
101: return getClass().toString() + " remoteID:"
102: + remoteID.toString();
103: }
104:
105: public ObjectID remoteID() {
106: return remoteID;
107: }
108:
109: /**
110: Returns the ObjectID of the represented ozone object. ObjectIDs are equal for equal
111: ozone objects and different for different ozone objects. They are comparable, so that
112: ozone objects may use {@link ObjectID#compareTo) in comparison functions.
113: <P>
114: Currently, ObjectID exposes other methods than {@link ObjectID#equals) and
115: {@link ObjectID#compareTo). However, they should not be used, as ObjectIDs should
116: be, apart from this methods, opaque.
117: </P>
118: */
119: public ObjectID getObjectID() {
120: return remoteID();
121: }
122:
123: /**
124: * Retrieves a handle to a specific instance of an OzoneObject. <br>
125: * A handle is
126: * the externalizeable equivalent of OzoneProxy. The purpose of handles is to enable
127: * detached systems (such as web interfaces) that are not able to use OzoneProxy
128: * objects directly a means to access specific objects where object naming is not
129: * practical or convenient. A handle is valid for the lifetime of
130: * the OzoneObject it references. Unlike OzoneProxy, retrieving a handle on an
131: * object does nothing to guarantee its existence. While the handle is valid
132: * for the lifetime of the object it refers to, that object's lifetime may
133: * be shorter than the handle's.
134: * <br><br>
135: * The resultant string representation will be composed
136: * entirely of alphanumeric characters [A-Z], [a-z], and [0-9]; as such,
137: * it can safely and reliably be used in URLs without need for escaping.
138: *
139: */
140: public String handle() {
141: return remoteID.toString();
142: }
143:
144: /**
145: * <p>Adds the required attributes for a simple XLink which points to this
146: * proxy to an attribute list.</p>
147: *
148: * @param atts The SAX attribute list to which the attributes will be added.
149: */
150: public void createProxyLinkAttributes(AttributesImpl atts) {
151: atts.addAttribute(Consts.ATTR_XLINK_NAMESPACE,
152: Consts.ATTR_XLINK_TYPE_LOCAL,
153: Consts.ATTR_XLINK_TYPE_RAW, "PCDATA", "simple");
154: atts.addAttribute(Consts.ATTR_XLINK_NAMESPACE,
155: Consts.ATTR_XLINK_HREF_LOCAL,
156: Consts.ATTR_XLINK_HREF_RAW, "PCDATA", String
157: .valueOf(remoteID));
158: }
159:
160: /**
161: * Method to use the proxy without a generated stub. The method signature
162: * will be generated from the actual argument types. This may be in
163: * some cases!
164: */
165: public Object invoke(String methodName, int lockLevel)
166: throws Exception {
167: Object[] args = {};
168: return link.invoke(this , methodName, null, args, lockLevel);
169: }
170:
171: /**
172: * Method to use the proxy without a generated stub.
173: */
174: public Object invoke(String methodName, Object arg1, int lockLevel)
175: throws Exception {
176: Object[] args = { arg1 };
177: return link.invoke(this , methodName, null, args, lockLevel);
178: }
179:
180: /**
181: * Method to use the proxy without a generated stub.
182: */
183: public Object invoke(String methodName, Object arg1, Object arg2,
184: int lockLevel) throws Exception {
185: Object[] args = { arg1, arg2 };
186: return link.invoke(this , methodName, null, args, lockLevel);
187: }
188:
189: /**
190: * Method to use the proxy without a generated stub.
191: */
192: public Object invoke(String methodName, Object arg1, Object arg2,
193: Object arg3, int lockLevel) throws Exception {
194: Object[] args = { arg1, arg2, arg3 };
195: return link.invoke(this , methodName, null, args, lockLevel);
196: }
197:
198: /**
199: Notify the database link that this reference dies.
200: */
201: public void finalize() {
202: if (link != null) {
203: try {
204: link.notifyProxyDeath(this );
205: } finally {
206: link = null; // We notify the proxy death only once.
207: }
208: }
209: }
210:
211: public void writeExternal(ObjectOutput out) throws IOException {
212: if (out instanceof GarbageCollector.GarbageCollectorProxyObjectIdentificationObjectOutputStream) {
213: ((GarbageCollector.GarbageCollectorProxyObjectIdentificationObjectOutputStream) out)
214: .notifyOzoneProxyEncountered(this );
215: }
216:
217: out.writeLong(remoteID.value());
218: // out.writeObject (remoteID);
219: }
220:
221: public void readExternal(ObjectInput in) throws IOException,
222: ClassNotFoundException {
223: remoteID = new ObjectID(in.readLong());
224: // remoteID = (ObjectID)in.readObject();
225:
226: ExternalDatabase db = (ExternalDatabase) linkTable
227: .elementForKey(in);
228: if (db != null) {
229: link = db.linkForProxy(this );
230: // System.out.println ("*** Proxy link updated.");
231: // new Exception().fillInStackTrace().printStackTrace();
232: }
233: }
234:
235: }
|