📄 abstractobjectcontainer.java
字号:
// You can redistribute this software and/or modify it under the terms of
// the Ozone Core 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: AbstractObjectContainer.java,v 1.15 2003/12/07 18:20:37 per_nyfelt Exp $
package org.ozoneDB.core;
import java.io.*;
import java.util.*;
import java.lang.reflect.*;
import org.ozoneDB.*;
import org.ozoneDB.io.stream.ResolvingObjectInputStream;
import org.ozoneDB.DxLib.*;
import org.ozoneDB.core.*;
import org.ozoneDB.core.helper.ReflectionHelper;
import org.ozoneDB.util.*;
/**
* @author <a href="http://www.softwarebuero.de/">SMB</a>
* @version $Revision: 1.15 $Date: 2003/12/07 18:20:37 $
*/
public abstract class AbstractObjectContainer implements ObjectContainer {
private static transient DxMap methodTable = new DxHashMap( 128 );
private static transient DxMap classTable = new DxHashMap( 128 );
private transient OzoneProxy theProxy;
protected int state;
protected transient boolean shouldCallOnActivate = true;
protected transient boolean shouldCallOnPassivate = true;
public int state() {
return state;
}
public synchronized void raiseState( int newState ) {
state = newState > state ? newState : state;
}
public synchronized void clearState() {
state = STATE_CLEAN;
}
public OzoneInterface database() {
// We should change this to CurrentDatabase.get(), shouldn't we?
return Env.currentEnv().database;
}
public OzoneProxy ozoneProxy() {
try {
if (theProxy == null) {
synchronized (this) {
if (theProxy == null) {
String implName = targetClass().getName();
String proxyName;
if (implName.endsWith( ObjectContainer.IMPLNAME_POSTFIX )) {
proxyName = implName.substring( 0, implName.length() - 5 );
}
else {
proxyName = implName + PROXYNAME_POSTFIX;
}
MethodKey key = new MethodKey( proxyName, "_ctor_", "(default)" );
Constructor ctor = (Constructor)methodTable.elementForKey( key );
if (ctor == null) {
Class cl = Env.currentEnv().classManager.classForName( proxyName );
Class[] argTypes = {ObjectID.class, OzoneInterface.class};
ctor = cl.getConstructor( argTypes );
methodTable.addForKey( ctor, key );
}
//creating proxy: cl.getName()
Object[] args = {id(), database()};
theProxy = (OzoneProxy)ctor.newInstance( args );
Env.currentEnv().logWriter.newEntry (this, "proxy added to cache - " + theProxy, LogWriter.DEBUG2);
}
}
}
return theProxy;
} catch (Exception e) {
Env.currentEnv().logWriter.newEntry( this, "ozoneProxy(): unable to create proper proxy object.", e, LogWriter.WARN );
throw new RuntimeException( e.toString() );
}
}
public OzoneCompatible targetClone() throws Exception {
ByteArrayOutputStream bout = new ByteArrayOutputStream( 2048 );
ObjectOutputStream out = new ObjectOutputStream( bout );
out.writeObject( target() );
out.close();
ObjectInputStream in = new ResolvingObjectInputStream( new ByteArrayInputStream( bout.toByteArray() ) );
Object targetClone = in.readObject();
in.close();
return (OzoneCompatible)targetClone;
}
/**
* Search the method with the specified name and signature. Once
* a method has been invoked it is stored in a global cache that holds
* the method objects of all database classes.
*
*
* @param methodName
* @param sig
* @param args
*/
protected final Method methodFor( Env env, Object obj, String methodName, String sig, Object[] args )
throws Exception {
MethodKey key = new MethodKey( targetClass().getName(), methodName, sig );
Method method = (Method)methodTable.elementForKey( key );
if (method == null) {
Class[] classes;
StringTokenizer st = new StringTokenizer( sig, ReflectionHelper.SIGNATURE_DELIMITER );
classes = new Class[args.length];
for (int i = 0; st.hasMoreTokens(); ++i) {
classes[i] = env.classManager.classForName( st.nextToken() );
}
method = obj.getClass().getMethod( methodName, classes );
methodTable.addForKey( method, key );
env.logWriter.newEntry( this, "method added to cache - " + key, LogWriter.DEBUG );
}
return method;
}
/**
* Search the constructor with the specified signature.
* Once a constructor has been invoked it is stored in a global cache that
* holds the method and constructor objects of all database classes.
*
* @param env
* @param cl
* @param sig
*/
protected Constructor constructorFor( Env env, Class cl, String sig ) throws Exception,NoSuchMethodException {
MethodKey key = new MethodKey( cl.getName(), "_ctor_", sig );
Constructor constructor = (Constructor)methodTable.elementForKey( key );
if (constructor == null) {
Class[] classes;
if (sig == null) {
classes = new Class[0];
} else {
StringTokenizer st = new StringTokenizer( sig, ReflectionHelper.SIGNATURE_DELIMITER );
classes = new Class[st.countTokens()];
for (int i = 0; st.hasMoreTokens(); ++i) {
classes[i] = env.classManager.classForName( st.nextToken() );
}
}
try {
constructor = cl.getConstructor( classes );
} catch (NoSuchMethodException e) {
StringBuffer b = new StringBuffer(200);
b.append("caught NoSuchMethodException for "+cl+" constructor signature \""+sig+"\" (");
for (int i = 0;i<classes.length;i++) {
if (i!=0)
b.append(',');
b.append(classes[i]);
}
b.append(")\n");
b.append("available constructors are:\n");
Constructor[] constructors = cl.getConstructors();
for (int i = 0;i<constructors.length;i++) {
b.append(" "+constructors[i]+"\n");
}
env.logWriter.newEntry( this, b.toString(), LogWriter.ERROR );
throw e;
}
methodTable.addForKey( constructor, key );
env.logWriter.newEntry( this, "constructor added to cache - " + key, LogWriter.DEBUG );
}
return constructor;
}
public static void flushMethodCache() {
methodTable = new DxHashMap( 128 );
}
public Object invokeTarget( Env env, String methodName, String sig, Object[] args ) throws Exception,InvocationTargetException {
Method method = methodFor( env, target(), methodName, sig, args );
if (method == null) {
throw new MethodNotFoundException( methodName );
}
try {
return method.invoke( target(), args );
} catch (InvocationTargetException e) {
throw e;
}
}
public Object invokeTarget( Env env, int methodIndex, Object[] args ) throws Exception,InvocationTargetException {
Class cl = targetClass();
Method[] methods = (Method[])classTable.elementForKey( cl );
if (methods == null) {
methods = ReflectionHelper.methodsOfClass( cl );
classTable.addForKey( methods, cl );
}
Method method = methods[methodIndex];
if (method == null) {
throw new MethodNotFoundException( "Method index: " + methodIndex );
}
if (env.logWriter.hasTarget( LogWriter.DEBUG3 )) {
env.logWriter.newEntry( this, "invoke(): calling method " + method.getName() + " with arguments " + Arrays.asList(args), LogWriter.DEBUG3 );
}
try {
return method.invoke(target(),args);
} catch (InvocationTargetException e) {
throw e;
}
}
public void invokeOnPassivate() {
try {
target().onPassivate();
setShouldCallOnPassivate(false);
setShouldCallOnActivate(true);
} catch (Throwable e) {
Env.currentEnv().logWriter.newEntry( this, "Runtime exception during onPassivate", e, LogWriter.WARN);
// todo: Do something
}
}
public void invokeOnActivate() {
try {
target().onActivate();
// Note that we set this _after_ the method was called. If we set this before,
// the method may fail due to a deadlock TransactionException and might not be re-tried.
setShouldCallOnActivate(false);
setShouldCallOnPassivate(true);
} catch (Throwable e) {
Env.currentEnv().logWriter.newEntry( this, "Runtime exception during onActivate", e, LogWriter.WARN);
// todo: Do something
}
}
public boolean shouldOnActivateBeCalled() {
return shouldCallOnActivate;
}
public boolean shouldOnPassivateBeCalled() {
return shouldCallOnPassivate;
}
public void setShouldCallOnActivate(boolean shouldOnActivateBeCalled) {
shouldCallOnActivate = shouldOnActivateBeCalled;
}
public void setShouldCallOnPassivate(boolean shouldOnPassivateBeCalled) {
shouldCallOnPassivate = shouldOnPassivateBeCalled;
}
public void createTarget( Env env, Class cl, String sig, Object[] args ) throws Exception {
OzoneCompatible result;
if (sig != null) {
Constructor ctor = constructorFor( env, cl, sig );
result = (OzoneCompatible) ctor.newInstance( args );
} else {
result = (OzoneCompatible) cl.newInstance();
}
setTarget( result );
}
public void requireWriteLocking() {
getCurrrentTransaction().requireWriteLockingCallByUser(this);
}
protected Env getEnv() {
return getCurrentDatabase().getEnv();
}
protected static Database getCurrentDatabase() {
return (Database) CurrentDatabase.get();
}
protected Transaction getCurrrentTransaction() {
return getCurrentDatabase().getCurrentTransaction();
}
}
// :indentSize=4:tabSize=4:noTabs=true:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -