/* This file is part of the db4o object database http://www.db4o.com Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com db4o is free software; you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation. 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, see http://www.gnu.org/licenses/. */ package com.db4o.internal; import com.db4o.foundation.*; import com.db4o.internal.diagnostic.*; import com.db4o.internal.encoding.*; import com.db4o.internal.handlers.*; import com.db4o.internal.handlers.array.*; import com.db4o.internal.handlers.versions.*; import com.db4o.internal.marshall.*; import com.db4o.internal.replication.*; import com.db4o.reflect.*; import com.db4o.reflect.generic.*; import com.db4o.typehandlers.*; /** * @exclude * * TODO: This class was written to make ObjectContainerBase * leaner, so TransportObjectContainer has less members. * * All functionality of this class should become part of * ObjectContainerBase and the functionality in * ObjectContainerBase should delegate to independent * modules without circular references. * */ public final class HandlerRegistry { public static final byte HANDLER_VERSION = (byte) 10; private final ObjectContainerBase _container; // this is the master container and not valid // for TransportObjectContainer private static final Db4oTypeImpl[] _db4oTypes = { new BlobImpl() }; private TypeHandler4 _openArrayHandler; private TypeHandler4 _openMultiDimensionalArrayHandler; private TypeHandler4 _openTypeHandler; public StringHandler _stringHandler; private Hashtable4 _mapIdToTypeInfo = newHashtable(); private Hashtable4 _mapReflectorToClassMetadata = newHashtable(); private int _highestBuiltinTypeID = Handlers4.ANY_ARRAY_N_ID + 1; private final VirtualFieldMetadata[] _virtualFields = new VirtualFieldMetadata[3]; private final Hashtable4 _mapReflectorToTypeHandler = newHashtable(); private SharedIndexedFields _indexes; Db4oReplicationReferenceProvider _replicationReferenceProvider; private final DiagnosticProcessor _diagnosticProcessor; public boolean i_encrypt; byte[] i_encryptor; int i_lastEncryptorByte; final GenericReflector _reflector; private final HandlerVersionRegistry _handlerVersions; private LatinStringIO _stringIO; public ReflectClass ICLASS_COMPARE; ReflectClass ICLASS_DB4OTYPE; ReflectClass ICLASS_DB4OTYPEIMPL; public ReflectClass ICLASS_INTERNAL; ReflectClass ICLASS_UNVERSIONED; public ReflectClass ICLASS_OBJECT; ReflectClass ICLASS_OBJECTCONTAINER; public ReflectClass ICLASS_STATICCLASS; public ReflectClass ICLASS_STRING; ReflectClass ICLASS_TRANSIENTCLASS; private PrimitiveTypeMetadata _untypedArrayMetadata; private PrimitiveTypeMetadata _untypedMultiDimensionalMetadata; HandlerRegistry(final ObjectContainerBase container, byte stringEncoding, GenericReflector reflector) { _handlerVersions = new HandlerVersionRegistry(this); _stringIO = BuiltInStringEncoding.stringIoForEncoding(stringEncoding, container.configImpl().stringEncoding()); _container = container; container._handlers = this; _reflector = reflector; _diagnosticProcessor = container.configImpl().diagnosticProcessor(); initClassReflectors(reflector); _indexes = new SharedIndexedFields(); _virtualFields[0] = _indexes._version; _virtualFields[1] = _indexes._uUID; _virtualFields[2] = _indexes._commitTimestamp; registerBuiltinHandlers(); registerPlatformTypes(); initArrayHandlers(); Platform4.registerPlatformHandlers(container); } private void initArrayHandlers() { TypeHandler4 elementHandler = openTypeHandler(); _untypedArrayMetadata = new PrimitiveTypeMetadata( container(), new ArrayHandler(elementHandler, false), Handlers4.ANY_ARRAY_ID, ICLASS_OBJECT); _openArrayHandler = _untypedArrayMetadata.typeHandler(); mapTypeInfo( Handlers4.ANY_ARRAY_ID, _untypedArrayMetadata, null ); _untypedMultiDimensionalMetadata = new PrimitiveTypeMetadata( container(), new MultidimensionalArrayHandler(elementHandler, false), Handlers4.ANY_ARRAY_N_ID, ICLASS_OBJECT); _openMultiDimensionalArrayHandler = _untypedMultiDimensionalMetadata.typeHandler(); mapTypeInfo( Handlers4.ANY_ARRAY_N_ID, _untypedMultiDimensionalMetadata, null ); } private void registerPlatformTypes() { NetTypeHandler[] handlers = Platform4.types(_container.reflector()); for (int i = 0; i < handlers.length; i++) { registerNetTypeHandler(handlers[i]); } } public void registerNetTypeHandler(NetTypeHandler handler) { handler.registerReflector(_reflector); GenericConverter converter = (handler instanceof GenericConverter) ? (GenericConverter)handler : null; registerBuiltinHandler(handler.getID(), handler, true, handler.getName(), converter); } private void registerBuiltinHandlers(){ IntHandler intHandler = new IntHandler(); registerBuiltinHandler(Handlers4.INT_ID, intHandler); registerHandlerVersion(intHandler, 0, new IntHandler0()); LongHandler longHandler = new LongHandler(); registerBuiltinHandler(Handlers4.LONG_ID, longHandler); registerHandlerVersion(longHandler, 0, new LongHandler0()); FloatHandler floatHandler = new FloatHandler(); registerBuiltinHandler(Handlers4.FLOAT_ID, floatHandler); registerHandlerVersion(floatHandler, 0, new FloatHandler0()); BooleanHandler booleanHandler = new BooleanHandler(); registerBuiltinHandler(Handlers4.BOOLEAN_ID, booleanHandler); // TODO: Are we missing a boolean handler version? DoubleHandler doubleHandler = new DoubleHandler(); registerBuiltinHandler(Handlers4.DOUBLE_ID, doubleHandler); registerHandlerVersion(doubleHandler, 0, new DoubleHandler0()); ByteHandler byteHandler = new ByteHandler(); registerBuiltinHandler(Handlers4.BYTE_ID, byteHandler); // TODO: Are we missing a byte handler version? CharHandler charHandler = new CharHandler(); registerBuiltinHandler(Handlers4.CHAR_ID, charHandler); // TODO: Are we missing a char handler version? ShortHandler shortHandler = new ShortHandler(); registerBuiltinHandler(Handlers4.SHORT_ID, shortHandler); registerHandlerVersion(shortHandler, 0, new ShortHandler0()); _stringHandler = new StringHandler(); registerBuiltinHandler(Handlers4.STRING_ID, _stringHandler); registerHandlerVersion(_stringHandler, 0, new StringHandler0()); DateHandler dateHandler = new DateHandler(); registerBuiltinHandler(Handlers4.DATE_ID, dateHandler); registerHandlerVersion(dateHandler, 0, new DateHandler0()); registerUntypedHandlers(); registerCompositeHandlerVersions(); } private void registerUntypedHandlers() { _openTypeHandler = new OpenTypeHandler(container()); PrimitiveTypeMetadata classMetadata = new ObjectTypeMetadata(container(), _openTypeHandler, Handlers4.UNTYPED_ID, ICLASS_OBJECT); map(Handlers4.UNTYPED_ID, classMetadata, ICLASS_OBJECT); registerHandlerVersion(_openTypeHandler, 0, new OpenTypeHandler0(container())); registerHandlerVersion(_openTypeHandler, 2, new OpenTypeHandler2(container())); registerHandlerVersion(_openTypeHandler, 7, new OpenTypeHandler7(container())); } private void registerCompositeHandlerVersions(){ registerHandlerVersion(new StandardReferenceTypeHandler(), 0, new StandardReferenceTypeHandler0()); ArrayHandler arrayHandler = new ArrayHandler(); registerHandlerVersion(arrayHandler, 0, new ArrayHandler0()); registerHandlerVersion(arrayHandler, 1, new ArrayHandler1()); registerHandlerVersion(arrayHandler, 3, new ArrayHandler3()); registerHandlerVersion(arrayHandler, 5, new ArrayHandler5()); MultidimensionalArrayHandler multidimensionalArrayHandler = new MultidimensionalArrayHandler(); registerHandlerVersion(multidimensionalArrayHandler, 0, new MultidimensionalArrayHandler0()); registerHandlerVersion(multidimensionalArrayHandler, 3, new MultidimensionalArrayHandler3()); } private void registerBuiltinHandler(int id, BuiltinTypeHandler handler) { registerBuiltinHandler(id, handler, true, null, null); } private void registerBuiltinHandler(int id, BuiltinTypeHandler typeHandler, boolean registerPrimitiveClass, String primitiveName, GenericConverter converter) { typeHandler.registerReflector(_reflector); if(primitiveName == null) { primitiveName = typeHandler.classReflector().getName(); } if(registerPrimitiveClass){ _reflector.registerPrimitiveClass(id, primitiveName, converter); } ReflectClass classReflector = typeHandler.classReflector(); PrimitiveTypeMetadata classMetadata = new PrimitiveTypeMetadata(container(), typeHandler, id, classReflector); map(id, classMetadata, classReflector); if(typeHandler instanceof PrimitiveHandler){ ReflectClass primitiveClassReflector = ((PrimitiveHandler) typeHandler).primitiveClassReflector(); if(primitiveClassReflector != null){ mapPrimitive(0, classMetadata, primitiveClassReflector); } } } private void map( int id, PrimitiveTypeMetadata classMetadata, // TODO: remove when _mapIdToClassMetadata is gone ReflectClass classReflector) { mapTypeInfo(id, classMetadata, classReflector); mapPrimitive(id, classMetadata, classReflector); if (id > _highestBuiltinTypeID) { _highestBuiltinTypeID = id; } } private void mapTypeInfo( int id, ClassMetadata classMetadata, ReflectClass classReflector) { _mapIdToTypeInfo.put(id, new TypeInfo(classMetadata, classReflector)); } private void mapPrimitive(int id, ClassMetadata classMetadata, ReflectClass classReflector) { mapClassToTypeHandler(classReflector, classMetadata.typeHandler()); if(classReflector != null){ _mapReflectorToClassMetadata.put(classReflector, classMetadata); } } private void mapClassToTypeHandler(ReflectClass classReflector, TypeHandler4 typeHandler) { _mapReflectorToTypeHandler.put(classReflector, typeHandler); } public void registerHandlerVersion(TypeHandler4 handler, int version, TypeHandler4 replacement) { if(replacement instanceof BuiltinTypeHandler) { ((BuiltinTypeHandler)replacement).registerReflector(_reflector); } _handlerVersions.put(handler, version, replacement); } public TypeHandler4 correctHandlerVersion(TypeHandler4 handler, int version){ return _handlerVersions.correctHandlerVersion(handler, version); } public static TypeHandler4 correctHandlerVersion(HandlerVersionContext context, TypeHandler4 typeHandler, ClassMetadata classMetadata) { TypeHandler4 correctHandlerVersion = correctHandlerVersion(context, typeHandler); if (typeHandler != correctHandlerVersion) { correctClassMetadataOn(correctHandlerVersion, classMetadata); if (correctHandlerVersion instanceof ArrayHandler) { ArrayHandler arrayHandler = (ArrayHandler) correctHandlerVersion; correctClassMetadataOn(arrayHandler.delegateTypeHandler(), classMetadata); } } return correctHandlerVersion; } private static void correctClassMetadataOn(TypeHandler4 typeHandler, ClassMetadata classMetadata) { if (typeHandler instanceof StandardReferenceTypeHandler) { StandardReferenceTypeHandler handler = (StandardReferenceTypeHandler) typeHandler; handler.classMetadata(classMetadata); } } ArrayType arrayType(Object obj) { ReflectClass claxx = reflector().forObject(obj); if (! claxx.isArray()) { return ArrayType.NONE; } if (isNDimensional(claxx)) { return ArrayType.MULTIDIMENSIONAL_ARRAY; } return ArrayType.PLAIN_ARRAY; } public final void decrypt(ByteArrayBuffer reader) { if(i_encrypt){ int encryptorOffSet = i_lastEncryptorByte; byte[] bytes = reader._buffer; for (int i = reader.length() - 1; i >= 0; i--) { bytes[i] += i_encryptor[encryptorOffSet]; if (encryptorOffSet == 0) { encryptorOffSet = i_lastEncryptorByte; } else { encryptorOffSet--; } } } } public final void encrypt(ByteArrayBuffer reader) { if(i_encrypt){ byte[] bytes = reader._buffer; int encryptorOffSet = i_lastEncryptorByte; for (int i = reader.length() - 1; i >= 0; i--) { bytes[i] -= i_encryptor[encryptorOffSet]; if (encryptorOffSet == 0) { encryptorOffSet = i_lastEncryptorByte; } else { encryptorOffSet--; } } } } public void oldEncryptionOff() { i_encrypt = false; i_encryptor = null; i_lastEncryptorByte = 0; container().configImpl().oldEncryptionOff(); } public final ReflectClass classForID(int id) { TypeInfo typeInfo = typeInfoForID(id); if(typeInfo == null){ return null; } return typeInfo.classReflector; } private TypeInfo typeInfoForID(int id){ return (TypeInfo)_mapIdToTypeInfo.get(id); } private void initClassReflectors(GenericReflector reflector){ ICLASS_COMPARE = reflector.forClass(Const4.CLASS_COMPARE); ICLASS_DB4OTYPE = reflector.forClass(Const4.CLASS_DB4OTYPE); ICLASS_DB4OTYPEIMPL = reflector.forClass(Const4.CLASS_DB4OTYPEIMPL); ICLASS_INTERNAL = reflector.forClass(Const4.CLASS_INTERNAL); ICLASS_UNVERSIONED = reflector.forClass(Const4.CLASS_UNVERSIONED); ICLASS_OBJECT = reflector.forClass(Const4.CLASS_OBJECT); ICLASS_OBJECTCONTAINER = reflector .forClass(Const4.CLASS_OBJECTCONTAINER); ICLASS_STATICCLASS = reflector.forClass(Const4.CLASS_STATICCLASS); ICLASS_STRING = reflector.forClass(String.class); ICLASS_TRANSIENTCLASS = reflector .forClass(Const4.CLASS_TRANSIENTCLASS); Platform4.registerCollections(reflector); } void initEncryption(Config4Impl a_config){ if (a_config.encrypt() && a_config.password() != null && a_config.password().length() > 0) { i_encrypt = true; i_encryptor = new byte[a_config.password().length()]; for (int i = 0; i < i_encryptor.length; i++) { i_encryptor[i] = (byte) (a_config.password().charAt(i) & 0xff); } i_lastEncryptorByte = a_config.password().length() - 1; return; } oldEncryptionOff(); } static Db4oTypeImpl getDb4oType(ReflectClass clazz) { for (int i = 0; i < _db4oTypes.length; i++) { if (clazz.isInstance(_db4oTypes[i])) { return _db4oTypes[i]; } } return null; } public ClassMetadata classMetadataForId(int id) { TypeInfo typeInfo = typeInfoForID(id); if(typeInfo == null){ return null; } return typeInfo.classMetadata; } ClassMetadata classMetadataForClass(ReflectClass clazz) { if (clazz == null) { return null; } if (clazz.isArray()) { return isNDimensional(clazz) ? _untypedMultiDimensionalMetadata : _untypedArrayMetadata; } return (ClassMetadata) _mapReflectorToClassMetadata.get(clazz); } public TypeHandler4 openTypeHandler(){ return _openTypeHandler; } public TypeHandler4 openArrayHandler(ReflectClass clazz){ if (clazz.isArray()) { if (isNDimensional(clazz)) { return _openMultiDimensionalArrayHandler; } return _openArrayHandler; } return null; } private boolean isNDimensional(ReflectClass clazz) { return reflector().array().isNDimensional(clazz); } public TypeHandler4 typeHandlerForClass(ReflectClass clazz){ if (clazz == null) { return null; } if (clazz.isArray()) { if (isNDimensional(clazz)) { return _openMultiDimensionalArrayHandler; } return _openArrayHandler; } TypeHandler4 cachedTypeHandler = (TypeHandler4) _mapReflectorToTypeHandler.get(clazz); if(cachedTypeHandler != null){ return cachedTypeHandler; } TypeHandler4 configuredTypeHandler = configuredTypeHandler(clazz); if(Handlers4.isValueType(configuredTypeHandler)){ return configuredTypeHandler; } return null; } public boolean isSystemHandler(int id) { return id > 0 && id <= _highestBuiltinTypeID; } public int lowestValidId(){ return _highestBuiltinTypeID + 1; } public VirtualFieldMetadata virtualFieldByName(String name) { for (int i = 0; i < _virtualFields.length; i++) { if (name.equals(_virtualFields[i].getName())) { return _virtualFields[i]; } } return null; } public SharedIndexedFields indexes(){ return _indexes; } public LatinStringIO stringIO(){ return _stringIO; } public void stringIO(LatinStringIO io) { _stringIO = io; } private GenericReflector reflector() { return container().reflector(); } private ObjectContainerBase container() { return _container; } private static final Hashtable4 newHashtable(){ return new Hashtable4(32); } public TypeHandler4 configuredTypeHandler(ReflectClass claxx) { final Object cachedHandler = _mapReflectorToTypeHandler.get(claxx); if (null != cachedHandler) { return (TypeHandler4) cachedHandler; } TypeHandler4 typeHandler = container().configImpl().typeHandlerForClass(claxx, HANDLER_VERSION); if(typeHandler instanceof BuiltinTypeHandler) { ((BuiltinTypeHandler) typeHandler).registerReflector(reflector()); } if(Handlers4.isValueType(typeHandler)){ mapClassToTypeHandler(claxx, typeHandler); } return typeHandler; } public static TypeHandler4 correctHandlerVersion(HandlerVersionContext context, TypeHandler4 handler){ int version = context.handlerVersion(); if(version >= HANDLER_VERSION){ return handler; } return context.transaction().container().handlers().correctHandlerVersion(handler, version); } public boolean isTransient(ReflectClass claxx) { return ICLASS_TRANSIENTCLASS.isAssignableFrom(claxx) || Platform4.isTransient(claxx); } public void treatAsOpenType(Class<?> clazz) { mapClassToTypeHandler(reflectClassFor(clazz), openTypeHandler()); } private ReflectClass reflectClassFor(Class<?> clazz) { return container().reflector().forClass(clazz); } public DiagnosticProcessor diagnosticProcessor() { return _diagnosticProcessor; } private static class TypeInfo { // TODO: remove when no longer needed in HandlerRegistry public ClassMetadata classMetadata; public ReflectClass classReflector; public TypeInfo( ClassMetadata classMetadata_, ReflectClass classReflector_) { classMetadata = classMetadata_; classReflector = classReflector_; } } }