001    /*
002     *  jDTAUS - DTAUS fileformat.
003     *  Copyright (c) 2005 Christian Schulte <cs@schulte.it>
004     *
005     *  This library is free software; you can redistribute it and/or
006     *  modify it under the terms of the GNU Lesser General Public
007     *  License as published by the Free Software Foundation; either
008     *  version 2.1 of the License, or any later version.
009     *
010     *  This library is distributed in the hope that it will be useful,
011     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
012     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013     *  Lesser General Public License for more details.
014     *
015     *  You should have received a copy of the GNU Lesser General Public
016     *  License along with this library; if not, write to the Free Software
017     *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
018     *
019     */
020    package org.jdtaus.core.container;
021    
022    import java.lang.reflect.Constructor;
023    import java.lang.reflect.InvocationTargetException;
024    import java.lang.reflect.Method;
025    
026    /**
027     * Factory for the {@code Model} singleton.
028     *
029     * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
030     * @version $Id: ModelFactory.java 2756 2007-04-14 02:01:15Z schulte2005 $
031     */
032    public abstract class ModelFactory
033    {
034    
035        //--Constants---------------------------------------------------------------
036    
037        /** Default {@code ModelProvider} implementation. */
038        private static final String DEFAULT_MODEL =
039            "org.jdtaus.core.container.ri.client.DefaultModel";
040    
041        /** Empty array. */
042        private static final Class[] EMPTY = {};
043    
044        //---------------------------------------------------------------Constants--
045        //--ModelFactory------------------------------------------------------------
046    
047        /** Default singleton instance. */
048        private static Model instance;
049    
050        /**
051         * Gets the {@code Model} singleton.
052         * <p>By default this class will instantiate a new instance and hold it in
053         * a static class variable as the singleton to return for other calls. This
054         * behaviour can be changed by setting a system property with key
055         * {@code org.jdtaus.core.container.ModelFactory} to the name of a
056         * class defining a {@code public static Model getModel()} method
057         * returning the singleton instance of the model.</p>
058         *
059         * @return the singleton {@code Model} instance.
060         *
061         * @throws ModelError for unrecoverable model errors.
062         *
063         * @see ModelFactory#newModel()
064         */
065        public static Model getModel()
066        {
067            Object ret = null;
068            final String factory = System.getProperty(ModelFactory.class.getName());
069    
070            try
071            {
072                if(factory != null)
073                {
074                    final Class clazz;
075                    final Method meth;
076    
077                    // Call getModel() on that class.
078                    clazz = ModelFactory.loadClass(factory);
079                    meth = clazz.getDeclaredMethod("getModel",
080                        ModelFactory.EMPTY);
081    
082                    ret = meth.invoke(null, (Object[]) ModelFactory.EMPTY);
083                }
084                else
085                {
086                    if(ModelFactory.instance == null)
087                    {
088                        ModelFactory.instance = ModelFactory.newModel();
089                    }
090    
091                    ret = ModelFactory.instance;
092                }
093    
094                return (Model) ret;
095            }
096            catch (SecurityException e)
097            {
098                throw new ModelError(e);
099            }
100            catch (NoSuchMethodException e)
101            {
102                throw new ModelError(e);
103            }
104            catch (IllegalAccessException e)
105            {
106                throw new ModelError(e);
107            }
108            catch (InvocationTargetException e)
109            {
110                throw new ModelError(e.getTargetException() == null ?
111                    e : e.getTargetException());
112    
113            }
114            catch(ClassCastException e)
115            {
116                throw new ModelError(e);
117            }
118        }
119    
120        /**
121         * Creates a new instance of the configured {@code Model} implementation.
122         * <p>The implementation to be used can be controlled via a system property
123         * with key {@code org.jdtaus.core.container.Model} set to a class
124         * name to be loaded as the {@code Model} implementation.</p>
125         * <p>This method should be used by {@code getModel()} implementors to
126         * retrieve a new {@code Model} instance.</p>
127         *
128         * @return a new instance of the configured {@code Model} implementation.
129         *
130         * @throws ModelError for unrecoverable model errors.
131         */
132        public static Model newModel()
133        {
134            try
135            {
136                final Constructor ctor;
137                final Object instance;
138                final String className = System.getProperty(
139                    Model.class.getName(),
140                    ModelFactory.DEFAULT_MODEL);
141    
142                final Class clazz = ContainerFactory.loadClass(className);
143    
144                ctor = clazz.getDeclaredConstructor(ContainerFactory.EMPTY);
145                ctor.setAccessible(true);
146                instance = ctor.newInstance((Object[]) ContainerFactory.EMPTY);
147    
148                return (Model) instance;
149            }
150            catch (SecurityException e)
151            {
152                throw new ModelError(e);
153            }
154            catch (NoSuchMethodException e)
155            {
156                throw new ModelError(e);
157            }
158            catch (IllegalArgumentException e)
159            {
160                throw new ModelError(e);
161            }
162            catch (IllegalAccessException e)
163            {
164                throw new ModelError(e);
165            }
166            catch (java.lang.InstantiationException e)
167            {
168                throw new ModelError(e);
169            }
170            catch (InvocationTargetException e)
171            {
172                throw new ModelError(e.getTargetException() == null ?
173                    e : e.getTargetException());
174    
175            }
176            catch(ClassCastException e)
177            {
178                throw new ModelError(e);
179            }
180        }
181    
182        static ClassLoader getClassLoader()
183        {
184            ClassLoader classLoader = Thread.currentThread().
185                getContextClassLoader();
186    
187            if(classLoader == null)
188            {
189                classLoader = ClassLoader.getSystemClassLoader();
190            }
191    
192            if(classLoader == null)
193            {
194                throw new ModelError(new NullPointerException("classLoader"));
195            }
196    
197            return classLoader;
198        }
199    
200        static Class loadClass(final String name)
201        {
202            try
203            {
204                return ModelFactory.getClassLoader().loadClass(name);
205            }
206            catch (ClassNotFoundException e)
207            {
208                throw new ModelError(e);
209            }
210        }
211    
212        //------------------------------------------------------------ModelFactory--
213    
214    }