/* 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 java.io.*; import java.lang.reflect.*; import com.db4o.foundation.*; import com.db4o.reflect.*; import com.db4o.reflect.core.*; /** * @sharpen.ignore */ @decaf.Remove(unlessCompatible=decaf.Platform.JDK15) class DalvikVM extends JDK_5 { @decaf.Remove(unlessCompatible=decaf.Platform.JDK15) public final static class Factory implements JDKFactory { public JDK tryToCreate() { if (!"Dalvik".equals(System.getProperty("java.vm.name"))) { return null; } return new DalvikVM(); } }; @Override public ReflectConstructor serializableConstructor(Reflector reflector, final Class clazz) { return new ReflectConstructor() { private final ObjectFactory factory = factory().newFactory(clazz); public Object newInstance(Object[] parameters) { return factory.newInstance(clazz); } public ReflectClass[] getParameterTypes() { return new ReflectClass[0]; } }; } public static class SkipConstructorCheck { public SkipConstructorCheck() throws UnsupportedOperationException { throw new UnsupportedOperationException(); } } private TernaryBool supportSkipConstructorCall = TernaryBool.UNSPECIFIED; private ObjectFactoryFactory _factory; @Override boolean supportSkipConstructorCall() { factory(); return supportSkipConstructorCall.definiteYes(); } private ObjectFactoryFactory factory(){ if(supportSkipConstructorCall.definiteNo()){ return null; } if(_factory != null){ return _factory; } try { _factory = new Dalvik2ObjectFactoryFactory(); _factory.newFactory(SkipConstructorCheck.class).newInstance(SkipConstructorCheck.class); supportSkipConstructorCall = TernaryBool.YES; return _factory; } catch (UnsupportedOperationException e){ // didn't work, let's try Dalvik 3 } try { _factory = new Dalvik3ObjectFactoryFactory(); _factory.newFactory(SkipConstructorCheck.class).newInstance(SkipConstructorCheck.class); supportSkipConstructorCall = TernaryBool.YES; return _factory; } catch (UnsupportedOperationException e){ e.printStackTrace(); // didn't work, maybe log that we need to find a new way? } supportSkipConstructorCall = TernaryBool.NO; return null; } @Override public String generateSignature() { return DalvikSignatureGenerator.generateSignature(); } private static interface ObjectFactory { public Object newInstance(Class clazz); } private static interface ObjectFactoryFactory { public ObjectFactory newFactory(Class clazz); } private static class Dalvik2ObjectFactoryFactory implements ObjectFactoryFactory{ private final Dalvik2ObjectFactory factory = new Dalvik2ObjectFactory(); public ObjectFactory newFactory(Class clazz) { return factory; } } private static class Dalvik3ObjectFactoryFactory implements ObjectFactoryFactory{ private int _methodId; public Dalvik3ObjectFactoryFactory() { try { Method constructorIdMethod = ObjectStreamClass.class.getDeclaredMethod("getConstructorId", Class.class); constructorIdMethod.setAccessible(true); _methodId = (Integer) constructorIdMethod.invoke(null, Object.class); } catch (Exception e) { throw new UnsupportedOperationException(e); } } public ObjectFactory newFactory(Class clazz) { return new Dalvik3ObjectFactory(clazz, _methodId); } } private static class Dalvik2ObjectFactory implements ObjectFactory { private Method _method; public Dalvik2ObjectFactory(){ try { _method = ObjectInputStream.class.getDeclaredMethod("newInstance", Class.class, Class.class); _method.setAccessible(true); } catch (Exception e) { throw new UnsupportedOperationException(e); } } public Object newInstance(Class clazz) { try { return _method.invoke(null, clazz, Object.class); } catch (Exception e) { throw new UnsupportedOperationException(e); } } } private static class Dalvik3ObjectFactory implements ObjectFactory { private Method _method; private final Class _clazz; private int _methodId; public Dalvik3ObjectFactory(Class clazz, int methodId) { _clazz = clazz; _methodId = methodId; try { _method = ObjectStreamClass.class.getDeclaredMethod("newInstance", Class.class, Integer.TYPE); _method.setAccessible(true); } catch (Exception e) { throw new UnsupportedOperationException(e); } } public Object newInstance(Class clazz) { if(clazz != _clazz){ throw new IllegalArgumentException(); } try { return _method.invoke(null, _clazz, _methodId); } catch (Exception e) { throw new UnsupportedOperationException(e); } } } }