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.factories;
018    
019    import java.lang.reflect.InvocationHandler;
020    import java.lang.reflect.Method;
021    import java.lang.reflect.Proxy;
022    
023    public class BasicFactories implements Factories {
024            
025            /* (non-Javadoc)
026             * @see net.ep.db4o.factories.Factories#createFactory(java.lang.Class)
027             */
028            @SuppressWarnings("unchecked")
029            public <T> T createFactory(Class<T> factory) {
030                    Method[] faMethods =factory.getDeclaredMethods();
031                    if (faMethods.length == 0)
032                            throw new InvalidFactoryException("No method found in factory");
033                    Method main = faMethods[0];
034                    Class<?> targetType = main.getReturnType();
035                    if (faMethods.length > targetType.getDeclaredConstructors().length)
036                            throw new InvalidFactoryException(faMethods.length + " found in factory but " + targetType.getDeclaredConstructors().length + " should be declared");
037                    if (targetType == null)
038                            throw new InvalidFactoryException("The return type of '" + main.getName() + "' cannot be void");
039                    Class<?> realType = getRealClass(targetType);
040                    InvocationHandler invHandler = new FactoryInvocationHandler(factory,targetType,realType, this);
041                    return (T) Proxy.newProxyInstance(factory.getClassLoader(), new Class[]{factory},invHandler);
042            }
043    
044            protected Class<?> getRealClass(Class<?> targetType) {
045                    return targetType;
046            }
047    
048            public void onNewInstance(Object inst) {
049                    // do nothing
050                    
051            }
052    
053            @SuppressWarnings("unchecked")
054            public <T> T createInstance(Class<T> clazz) {
055                    T instance;
056                    try {
057                            instance = (T) getRealClass(clazz).newInstance();
058                    } catch (InstantiationException e) {
059                            throw new InvalidFactoryException("No empty constructor found in " + clazz.getName(),e);                                                
060                    } catch (IllegalAccessException e) {
061                            throw new InvalidFactoryException(e);                                           
062                    }
063                    onNewInstance(instance);
064                    return instance;
065            }
066    
067    }