// You can redistribute this software and/or modify it under the terms of
// the Ozone Library License version 1 published by ozone-db.org.
//
// The original code and portions created by SMB are
// Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
//
// $Id: OzoneProxy.java,v 1.3 2002/06/08 00:49:38 mediumnet Exp $
package org.ozoneDB;
import java.io.*;
import org.ozoneDB.DxLib.DxHashMap;
import org.ozoneDB.DxLib.DxMap;
import org.ozoneDB.core.Env;
import org.ozoneDB.core.ObjectID;
import org.ozoneDB.core.GarbageCollector;
import org.ozoneDB.core.xml.Consts;
import org.xml.sax.helpers.AttributesImpl;
/**
* Proxy of an OzoneRemote object.
*
*
* @author <a href="http://www.softwarebuero.de/">SMB</a>
* @author <a href="http://www.medium.net/">Medium.net</a>
* @version $Revision: 1.3 $Date: 2002/06/08 00:49:38 $
*/
public class OzoneProxy implements OzoneRemote, Externalizable {
private final static long serialVersionUID = 3L;
/**
* Table of stream to OzoneInterface pairs. readExternal() checks this
* table to find corresponding database link.
*/
public static DxMap linkTable = new DxHashMap();
public transient OzoneInterface link = null;
public ObjectID remoteID;
/**
* This constructor will only be called, when the object is constructed
* from a stream.
*/
public OzoneProxy() {
//we assume that we are inside the kernel
Env env = Env.currentEnv();
if (env != null) {
link = env.database;
}
}
/**
* This constructor is only be called, when this object is constructed
* inside the database. However, it may be the result of a RMI call.
*/
public OzoneProxy(ObjectID id, OzoneInterface link) {
this.link = link;
remoteID = (ObjectID) id.clone();
}
public OzoneProxy(OzoneProxy rhs) {
link = rhs.link;
remoteID = (ObjectID) rhs.remoteID.clone();
}
public boolean isSame(OzoneProxy proxy) {
return remoteID.equals(proxy.remoteID);
}
/**
* Base implementation of equals(). May be overwritten by an implementation
* of the actual database object. In that case the method is handled, as all
* remote methods, on the server side.
*/
public boolean equals(Object obj) {
if (obj instanceof OzoneProxy && obj != null) {
return isSame((OzoneProxy) obj);
} else {
return false;
}
}
/**
* Base implementation of hashCode(). May be overwritten by an implementation
* of the actual database object. In that case the method is handled, as all
* remote methods, on the server side.
*/
public int hashCode() {
return remoteID.hashCode();
}
/**
* Base implementation of toString(). May be overwritten by an implementation
* of the actual database object. In that case the method is handled, as all
* remote methods, on the server side.
*/
public String toString() {
return getClass().toString() + " remoteID:" + remoteID.toString();
}
public ObjectID remoteID() {
return remoteID;
}
/**
Returns the ObjectID of the represented ozone object. ObjectIDs are equal for equal
ozone objects and different for different ozone objects. They are comparable, so that
ozone objects may use {@link ObjectID#compareTo) in comparison functions.
<P>
Currently, ObjectID exposes other methods than {@link ObjectID#equals) and
{@link ObjectID#compareTo). However, they should not be used, as ObjectIDs should
be, apart from this methods, opaque.
</P>
*/
public ObjectID getObjectID() {
return remoteID();
}
/**
* Retrieves a handle to a specific instance of an OzoneObject. <br>
* A handle is
* the externalizeable equivalent of OzoneProxy. The purpose of handles is to enable
* detached systems (such as web interfaces) that are not able to use OzoneProxy
* objects directly a means to access specific objects where object naming is not
* practical or convenient. A handle is valid for the lifetime of
* the OzoneObject it references. Unlike OzoneProxy, retrieving a handle on an
* object does nothing to guarantee its existence. While the handle is valid
* for the lifetime of the object it refers to, that object's lifetime may
* be shorter than the handle's.
* <br><br>
* The resultant string representation will be composed
* entirely of alphanumeric characters [A-Z], [a-z], and [0-9]; as such,
* it can safely and reliably be used in URLs without need for escaping.
*
*/
public String handle() {
return remoteID.toString();
}
/**
* <p>Adds the required attributes for a simple XLink which points to this
* proxy to an attribute list.</p>
*
* @param atts The SAX attribute list to which the attributes will be added.
*/
public void createProxyLinkAttributes(AttributesImpl atts) {
atts.addAttribute(Consts.ATTR_XLINK_NAMESPACE,
Consts.ATTR_XLINK_TYPE_LOCAL, Consts.ATTR_XLINK_TYPE_RAW,
"PCDATA", "simple");
atts.addAttribute(Consts.ATTR_XLINK_NAMESPACE,
Consts.ATTR_XLINK_HREF_LOCAL, Consts.ATTR_XLINK_HREF_RAW,
"PCDATA", String.valueOf(remoteID));
}
/**
* Method to use the proxy without a generated stub. The method signature
* will be generated from the actual argument types. This may be in
* some cases!
*/
public Object invoke(String methodName, int lockLevel) throws Exception {
Object[] args = {};
return link.invoke(this, methodName, null, args, lockLevel);
}
/**
* Method to use the proxy without a generated stub.
*/
public Object invoke(String methodName, Object arg1, int lockLevel) throws Exception {
Object[] args = {arg1};
return link.invoke(this, methodName, null, args, lockLevel);
}
/**
* Method to use the proxy without a generated stub.
*/
public Object invoke(String methodName, Object arg1, Object arg2, int lockLevel) throws Exception {
Object[] args = {arg1, arg2};
return link.invoke(this, methodName, null, args, lockLevel);
}
/**
* Method to use the proxy without a generated stub.
*/
public Object invoke(String methodName, Object arg1, Object arg2, Object arg3, int lockLevel) throws Exception {
Object[] args = {arg1, arg2, arg3};
return link.invoke(this, methodName, null, args, lockLevel);
}
/**
Notify the database link that this reference dies.
*/
public void finalize() {
if (link!=null) {
try {
link.notifyProxyDeath(this);
} finally {
link = null; // We notify the proxy death only once.
}
}
}
public void writeExternal(ObjectOutput out) throws IOException {
if (out instanceof GarbageCollector.GarbageCollectorProxyObjectIdentificationObjectOutputStream) {
((GarbageCollector.GarbageCollectorProxyObjectIdentificationObjectOutputStream) out).notifyOzoneProxyEncountered(this);
}
out.writeLong(remoteID.value());
// out.writeObject (remoteID);
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
remoteID = new ObjectID(in.readLong());
// remoteID = (ObjectID)in.readObject();
ExternalDatabase db = (ExternalDatabase) linkTable.elementForKey(in);
if (db != null) {
link = db.linkForProxy(this);
// System.out.println ("*** Proxy link updated.");
// new Exception().fillInStackTrace().printStackTrace();
}
}
}