001    /**
002     * Copyright (C) 2009 Erik Putrycz <erik.putrycz@gmail.com>
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     *         http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package net.ep.db4o.javassist;
018    
019    import java.lang.reflect.Field;
020    
021    import net.ep.db4o.factories.InvalidFactoryException;
022    import net.ep.db4o.factories.ObjectContainerProvider;
023    
024    import com.db4o.ObjectContainer;
025    import com.db4o.reflect.generic.GenericReflector;
026    import com.db4o.reflect.jdk.JavaReflectClass;
027    
028    public class Enhancer {
029    
030            @SuppressWarnings("unchecked")
031            public static <T> Class<T> enhancedClass(Class<T> targetType,
032                            ObjectContainerProvider _provider) {
033                    ObjectContainer db = _provider.db();
034                    if (db == null)
035                            throw new NullPointerException(ObjectContainerProvider.class.getName() + " returned a null result");
036                    GenericReflector refl = db.ext().reflector();
037                    if (refl.getDelegate() instanceof JVSTReflector) {
038                            JVSTReflector reflector = (JVSTReflector) _provider.db().ext().reflector()
039                                            .getDelegate();
040                            // Class enhancedClass =
041                            if (JVSTReflector.canBeEnhanced(targetType)) {
042                                    JVSTClass enhClazz1 = reflector.enhanceClass(targetType);
043                                    return enhClazz1.getEnhancedClass();
044                            } else
045                                    throw new InvalidFactoryException(targetType + " cannot be enhanced: "
046                                                    + JVSTReflector.explainWhyNotEnhanced(targetType));
047                    }
048                    return targetType;
049            }
050    
051            @SuppressWarnings("unchecked")
052            public static <T> T newInstance(Class<T> clazz, ObjectContainer container) {
053                    GenericReflector refl = container.ext().reflector();
054                    if (refl.getDelegate() instanceof JVSTReflector) {
055                            JVSTReflector reflector = (JVSTReflector) container.ext().reflector()
056                                            .getDelegate();
057                            // Class enhancedClass =
058                            JavaReflectClass enhClazz1 = (JavaReflectClass) reflector.forClass(clazz);
059                            T copy = (T) enhClazz1.newInstance();
060                            container.store(copy);
061                            return copy;
062                    }
063                    try {
064                            return clazz.newInstance();
065                    } catch (Exception e) {
066                            e.printStackTrace();
067                            return null;
068                    }
069            }
070    
071            @SuppressWarnings("unchecked")
072            public static <T> T enhance(T input, ObjectContainer container) {
073                    Class clazz = input.getClass();
074                    T output = (T) newInstance(clazz, container);
075                    if (output == null)
076                            return null;
077                    try {
078                            cloneFrom(clazz, input, output);
079                    } catch (Exception e) {
080                            e.printStackTrace();
081                            return null;
082                    }
083                    return output;
084            }
085    
086            public static <T> void cloneFrom(T input, T output)
087                            throws IllegalArgumentException, IllegalAccessException {
088                    cloneFrom(input.getClass(), input, output);
089            }
090    
091            @SuppressWarnings("unchecked")
092            private static <T> void cloneFrom(Class cl, T input, T output)
093                            throws IllegalArgumentException, IllegalAccessException {
094                    for (Field field : cl.getDeclaredFields()) {
095                            boolean acc = field.isAccessible();
096                            field.setAccessible(true);
097                            field.set(output, field.get(input));
098                            field.setAccessible(acc);
099                    }
100                    if (cl.getSuperclass() != null)
101                            cloneFrom(cl.getSuperclass(), input, output);
102            }
103    
104    }