All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.db4o.YapHandlers Maven / Gradle / Ivy

The newest version!
/* Copyright (C) 2004 - 2005  db4objects Inc.  http://www.db4o.com

This file is part of the db4o open source object database.

db4o is free software; you can redistribute it and/or modify it under
the terms of version 2 of the GNU General Public License as published
by the Free Software Foundation and as clarified by db4objects' GPL 
interpretation policy, available at
http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
Suite 350, San Mateo, CA 94403, USA.

db4o is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */
package com.db4o;

import com.db4o.foundation.*;
import com.db4o.inside.replication.*;
import com.db4o.reflect.*;
import com.db4o.reflect.generic.*;
import com.db4o.types.*;

/**
 */
public final class YapHandlers {
	
	private final YapStream _masterStream;  // this is master YapStream and not valid
	                                   // for YapObjectCarrier

    private static final Db4oTypeImpl[]   i_db4oTypes     = { new BlobImpl()};

    public static final int         ANY_ARRAY_ID      = 12;
    public static final int         ANY_ARRAY_N_ID     = 13;

    // Array Indices in i_YapContainers
    private static final int        CLASSCOUNT      = 11;

    private YapClass                i_anyArray;
    private YapClass                i_anyArrayN;

    public final YapString          i_stringHandler;

    private TypeHandler4[]           i_handlers;

    private int                     i_maxTypeID     = ANY_ARRAY_N_ID + 1;

    private YapTypeAbstract[]       i_platformTypes;
    static private final int        PRIMITIVECOUNT  = 8;

    YapClass[]                      i_yapClasses;

    // need to keep getID Functions in Sync with ArrayIndex
    private static final int        ANY_INDEX          = 10;
    public static final int         ANY_ID        = 11;
    
    final YapFieldVirtual[]         i_virtualFields = new YapFieldVirtual[2]; 

    private final Hashtable4        i_classByClass  = new Hashtable4(32);
    
    Db4oCollections 				i_collections;
    
    YapIndexes              		i_indexes;
    
    ReplicationImpl				    i_replication;
    
    MigrationConnection             i_migration;
    
    Db4oReplicationReferenceProvider _replicationReferenceProvider;
    
    boolean                 i_encrypt;
    byte[]                  i_encryptor;
    int                     i_lastEncryptorByte;
    
    final GenericReflector                _reflector;
    
    ReflectClass ICLASS_COMPARE;
    ReflectClass ICLASS_DB4OTYPE;
    ReflectClass ICLASS_DB4OTYPEIMPL;
	public ReflectClass ICLASS_INTERNAL;
    ReflectClass ICLASS_UNVERSIONED;
    ReflectClass ICLASS_OBJECT;
    ReflectClass ICLASS_OBJECTCONTAINER;
    ReflectClass ICLASS_PBOOTRECORD;
	ReflectClass ICLASS_STATICCLASS;
	ReflectClass ICLASS_STRING;
    ReflectClass ICLASS_TRANSIENTCLASS;

    YapHandlers(final YapStream a_stream, byte stringEncoding, GenericReflector reflector) {
    	
    	_masterStream = a_stream;
    	a_stream.i_handlers = this;
        _reflector = reflector;
    	
    	initClassReflectors(reflector);
        
        i_indexes = new YapIndexes(a_stream);
        
        i_virtualFields[0] = i_indexes.i_fieldVersion;
        i_virtualFields[1] = i_indexes.i_fieldUUID;

        i_stringHandler = new YapString(a_stream, YapStringIO.forEncoding(stringEncoding));

        i_handlers = new TypeHandler4[] { new YInt(a_stream), new YLong(a_stream), new YFloat(a_stream),
            new YBoolean(a_stream), new YDouble(a_stream), new YByte(a_stream), new YChar(a_stream),
            new YShort(a_stream),

            // primitives first
            i_stringHandler, new YDate(a_stream), new YapClassAny(a_stream) // Index = 10, ID = 11
        };
        
        i_platformTypes = Platform4.types(a_stream);

        if (i_platformTypes.length > 0) {
            for (int i = 0; i < i_platformTypes.length; i++) {
                i_platformTypes[i].initialize();
                if (i_platformTypes[i].getID() > i_maxTypeID) {
                    i_maxTypeID = i_platformTypes[i].getID();
                }
            }

            TypeHandler4[] temp = i_handlers;
            i_handlers = new TypeHandler4[i_maxTypeID];
            System.arraycopy(temp, 0, i_handlers, 0, temp.length);
            for (int i = 0; i < i_platformTypes.length; i++) {
                int idx = i_platformTypes[i].getID() - 1;
                i_handlers[idx] = i_platformTypes[i];
            }
        }

        i_yapClasses = new YapClass[i_maxTypeID + 1];

        for (int i = 0; i < CLASSCOUNT; i++) {
            int id = i + 1; // note that we avoid 0 here
            i_yapClasses[i] = new YapClassPrimitive(a_stream, i_handlers[i]);
            i_yapClasses[i].i_id = id; 
            i_classByClass.put(i_handlers[i].classReflector(), i_yapClasses[i]);
            if(i < ANY_INDEX){
            	reflector.registerPrimitiveClass(id, i_handlers[i].classReflector().getName(), null);
            }
            if (!Deploy.csharp) {
                if (i_handlers[i].primitiveClassReflector() != null) {
                	i_classByClass.put(i_handlers[i].primitiveClassReflector(), i_yapClasses[i]);
                }
            }
        }
        for (int i = 0; i < i_platformTypes.length; i++) {
        	int id = i_platformTypes[i].getID();
            int idx = id - 1;
            GenericConverter converter = (i_platformTypes[i] instanceof GenericConverter) ? (GenericConverter)i_platformTypes[i] : null;  
            reflector.registerPrimitiveClass(id, i_platformTypes[i].getName(), converter);
            i_handlers[idx] = i_platformTypes[i];
            i_yapClasses[idx] = new YapClassPrimitive(a_stream, i_platformTypes[i]);
            i_yapClasses[idx].i_id = id;
            if (i_yapClasses[idx].i_id > i_maxTypeID) {
                i_maxTypeID = idx;
            }
            i_classByClass.put(i_platformTypes[i].classReflector(), i_yapClasses[idx]);
            if (!Deploy.csharp) {
                if (i_platformTypes[i].primitiveClassReflector() != null) {
                	i_classByClass.put(i_platformTypes[i].primitiveClassReflector(), i_yapClasses[idx]);
                }
            }
        }

        i_anyArray = new YapClassPrimitive(a_stream, new YapArray(_masterStream,
            i_handlers[ANY_INDEX], false));
        i_anyArray.i_id = ANY_ARRAY_ID;
        i_yapClasses[ANY_ARRAY_ID - 1] = i_anyArray;

        i_anyArrayN = new YapClassPrimitive(a_stream, new YapArrayN(_masterStream,
            i_handlers[ANY_INDEX], false));
        i_anyArrayN.i_id = ANY_ARRAY_N_ID;
        i_yapClasses[ANY_ARRAY_N_ID - 1] = i_anyArrayN;
    }

	int arrayType(Object a_object) {
    	ReflectClass claxx = _masterStream.reflector().forObject(a_object);
        if (claxx.isArray()) {
            if (_masterStream.reflector().array().isNDimensional(claxx)) {
                return YapConst.TYPE_NARRAY;
            } else {
                return YapConst.TYPE_ARRAY;
            }
        }
        return 0;
    }
	
    boolean createConstructor(final ReflectClass claxx, boolean skipConstructor){
        
        if (claxx == null) {
            return false;
        }
        
        if (claxx.isAbstract() || claxx.isInterface()) {
            return true;
        }
        
        if(! Platform4.callConstructor()){
            if(claxx.skipConstructor(skipConstructor)){
                return true;
            }
        }
        
        if (! _masterStream.i_config.i_testConstructors) {
            return true;
        }
        
        if (claxx.newInstance() != null) {
            return true;
        }
        
        if (_masterStream.reflector().constructorCallsSupported()) {
            try {
                
                ReflectConstructor[] constructors = claxx.getDeclaredConstructors();
                
                Tree sortedConstructors = null;
                
                // sort constructors by parameter count  
                for (int i = 0; i < constructors.length; i++) {
                    try{
                        constructors[i].setAccessible();
                        int parameterCount =  constructors[i].getParameterTypes().length;
                        sortedConstructors = Tree.add(sortedConstructors, new TreeIntObject(i+constructors.length*parameterCount, constructors[i]));
                    } catch (Throwable t) {
                        if(Debug.atHome){
                            t.printStackTrace();
                        }
                    }
                }
                
                // call zero-arg constructors first
                final boolean[] foundConstructor={false};
                if(sortedConstructors != null){
                    sortedConstructors.traverse(new Visitor4() {
                        public void visit(Object a_object) {
                            if(! foundConstructor[0]) {
	                            ReflectConstructor constructor = (ReflectConstructor)((TreeIntObject)a_object).i_object;
	                            try {
	                                ReflectClass[] pTypes = constructor.getParameterTypes();
	                                Object[] parms = new Object[pTypes.length];
	                                for (int j = 0; j < parms.length; j++) {
	                                    for (int k = 0; k < PRIMITIVECOUNT; k++) {
	                                        if (pTypes[j].equals(i_handlers[k].primitiveClassReflector())) {
	                                            parms[j] = ((YapJavaClass) i_handlers[k])
	                                                .primitiveNull();
	                                            break;
	                                        }
	                                    }
	                                }
	                                Object res = constructor.newInstance(parms);
	                                if (res != null) {
	                                    foundConstructor[0] = true;
                                        claxx.useConstructor(constructor, parms);
	                                }
	                            } catch (Throwable t) {
	                                if(Debug.atHome){
	                                    t.printStackTrace();
	                                }
	                            }
                            }
                        }
                    });
                    
                }
                if(foundConstructor[0]){
                    return true;
                }
                
            } catch (Throwable t1) {
                if(Debug.atHome){
                    t1.printStackTrace();
                }

            }
        }
        return false;
    }
    
	final void decrypt(YapReader reader) {
	    if(i_encrypt){
			int encryptorOffSet = i_lastEncryptorByte;
			byte[] bytes = reader._buffer;
			for (int i = reader.getLength() - 1; i >= 0; i--) {
				bytes[i] += i_encryptor[encryptorOffSet];
				if (encryptorOffSet == 0) {
					encryptorOffSet = i_lastEncryptorByte;
				} else {
					encryptorOffSet--;
				}
			}
	    }
	}
	
    final void encrypt(YapReader reader) {
        if(i_encrypt){
	        byte[] bytes = reader._buffer;
	        int encryptorOffSet = i_lastEncryptorByte;
	        for (int i = reader.getLength() - 1; i >= 0; i--) {
	            bytes[i] -= i_encryptor[encryptorOffSet];
	            if (encryptorOffSet == 0) {
	                encryptorOffSet = i_lastEncryptorByte;
	            } else {
	                encryptorOffSet--;
	            }
	        }
        }
    }
    
    final TypeHandler4 getHandler(int a_index) {
        return i_handlers[a_index - 1];
    }

    final TypeHandler4 handlerForClass(ReflectClass a_class, ReflectClass[] a_Supported) {
        for (int i = 0; i < a_Supported.length; i++) {
            if (a_Supported[i].equals(a_class)) {
                return i_handlers[i];
            }
        }
        return null;
    }

    /**
     * Can't return ANY class for interfaces, since that would kill the
     * translators built into the architecture.
     */
    final TypeHandler4 handlerForClass(YapStream a_stream, ReflectClass a_class) {
        if(a_class == null){
            return null;
        }
        if (a_class.isArray()) {
            return handlerForClass(a_stream, a_class.getComponentType());
        }
        YapClass yc = getYapClassStatic(a_class);
        if (yc != null) {
            return ((YapClassPrimitive) yc).i_handler;
        }
        return a_stream.getYapClass(a_class, true);
    }
    
    private void initClassReflectors(GenericReflector reflector){
		ICLASS_COMPARE = reflector.forClass(YapConst.CLASS_COMPARE);
		ICLASS_DB4OTYPE = reflector.forClass(YapConst.CLASS_DB4OTYPE);
		ICLASS_DB4OTYPEIMPL = reflector.forClass(YapConst.CLASS_DB4OTYPEIMPL);
        ICLASS_INTERNAL = reflector.forClass(YapConst.CLASS_INTERNAL);
        ICLASS_UNVERSIONED = reflector.forClass(YapConst.CLASS_UNVERSIONED);
		ICLASS_OBJECT = reflector.forClass(YapConst.CLASS_OBJECT);
		ICLASS_OBJECTCONTAINER = reflector
				.forClass(YapConst.CLASS_OBJECTCONTAINER);
		ICLASS_PBOOTRECORD = reflector.forClass(YapConst.CLASS_PBOOTRECORD);
		ICLASS_STATICCLASS = reflector.forClass(YapConst.CLASS_STATICCLASS);
		ICLASS_STRING = reflector.forClass(String.class);
		ICLASS_TRANSIENTCLASS = reflector
				.forClass(YapConst.CLASS_TRANSIENTCLASS);
		
		Platform4.registerCollections(reflector);
    }
    
    void initEncryption(Config4Impl a_config){
        if (a_config.i_encrypt && a_config.i_password != null
            && a_config.i_password.length() > 0) {
            i_encrypt = true;
            i_encryptor = new byte[a_config.i_password.length()];
            for (int i = 0; i < i_encryptor.length; i++) {
                i_encryptor[i] = (byte) (a_config.i_password.charAt(i) & 0xff);
            }
            i_lastEncryptorByte = a_config.i_password.length() - 1;
        } else {
            i_encrypt = false;
            i_encryptor = null;
            i_lastEncryptorByte = 0;
        }
    }
    
    static Db4oTypeImpl getDb4oType(ReflectClass clazz) {
        for (int i = 0; i < i_db4oTypes.length; i++) {
            if (clazz.isInstance(i_db4oTypes[i])) {
                return i_db4oTypes[i];
            }
        }
        return null;
    }

    public YapClass getYapClassStatic(int a_id) {
        if (a_id > 0 && a_id <= i_maxTypeID) {
            return i_yapClasses[a_id - 1];
        }
        return null;
    }

    YapClass getYapClassStatic(ReflectClass a_class) {
        if (a_class == null) {
            return null;
        }
        if (a_class.isArray()) {
            if (_masterStream.reflector().array().isNDimensional(a_class)) {
                return i_anyArrayN;
            }
            return i_anyArray;
        }
        return (YapClass) i_classByClass.get(a_class);
    }
    
    public boolean isSecondClass(Object a_object){
    	if(a_object != null){
    		ReflectClass claxx = _masterStream.reflector().forObject(a_object);
    		if(i_classByClass.get(claxx) != null){
    			return true;
    		}
            if(Deploy.csharp){
                return Platform4.isValueType(claxx);
            }
    	}
    	return false;
    }

    int maxTypeID() {
        return i_maxTypeID;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy