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