⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstractobjectcontainer.java

📁 Java的面向对象数据库系统的源代码
💻 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 + -