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 Context} singleton.
031     *
032     * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a>
033     * @version $Id: ContextFactory.java 8044 2009-07-02 01:29:05Z schulte2005 $
034     */
035    public abstract class ContextFactory
036    {
037        //--Constants---------------------------------------------------------------
038    
039        /** Default {@code Context} implementation. */
040        private static final String DEFAULT_CONTEXT =
041            "org.jdtaus.core.container.ri.client.DefaultContext";
042    
043        /** Empty array. */
044        private static final Class[] EMPTY =
045        {
046        };
047    
048        //---------------------------------------------------------------Constants--
049        //--ContextFactory----------------------------------------------------------
050    
051        /** Default singleton instance. */
052        private static Context instance;
053    
054        /**
055         * Gets the {@code Context} singleton.
056         * <p>By default this class will instantiate a new context and hold it in a
057         * 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.ContextFactory} to the name of a
060         * class defining a {@code public static Context getContext()} method
061         * returning the singleton instance of {@code Context}.</p>
062         *
063         * @return the singleton {@code Context} instance.
064         *
065         * @throws ContextError for unrecoverable context errors.
066         *
067         * @see ContextFactory#newContext()
068         */
069        public static Context getContext()
070        {
071            Object ret = null;
072            final String factory = System.getProperty(
073                ContextFactory.class.getName() );
074    
075            try
076            {
077                if ( factory != null )
078                {
079                    // Call getContext() on that class.
080                    final Class clazz = ClassLoaderFactory.loadClass(
081                        ContextFactory.class, factory );
082    
083                    final Method meth = clazz.getDeclaredMethod( "getContext",
084                                                                 EMPTY );
085    
086                    ret = meth.invoke( null, EMPTY );
087                }
088                else
089                {
090                    if ( instance == null )
091                    {
092                        instance = newContext();
093                    }
094    
095                    ret = instance;
096                }
097    
098                return (Context) ret;
099            }
100            catch ( SecurityException e )
101            {
102                throw new ContextError( e );
103            }
104            catch ( NoSuchMethodException e )
105            {
106                throw new ContextError( e );
107            }
108            catch ( IllegalAccessException e )
109            {
110                throw new ContextError( 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 ContextError( targetException == null
127                                            ? e
128                                            : targetException );
129    
130                }
131            }
132            catch ( ClassCastException e )
133            {
134                throw new ContextError( e );
135            }
136            catch ( ClassNotFoundException e )
137            {
138                throw new ContextError( e );
139            }
140        }
141    
142        /**
143         * Creates a new instance of the configured {@code Context} implementation.
144         * <p>The context implementation to be used can be controlled via a system
145         * property with key {@code org.jdtaus.core.container.Context} set
146         * to a class name to be loaded as the context implementation.</p>
147         * <p>This method should be used by {@code getContext()} implementors to
148         * retrieve a new {@code Context} instance.</p>
149         *
150         * @return a new instance of the configured {@code Context}
151         * implementation.
152         *
153         * @throws ContextError for unrecoverable context errors.
154         */
155        public static Context newContext()
156        {
157            final String impl = System.getProperty( Context.class.getName(),
158                                                    DEFAULT_CONTEXT );
159    
160            Constructor ctor = null;
161    
162            try
163            {
164                final Class clazz = ClassLoaderFactory.loadClass(
165                    ContextFactory.class, impl );
166    
167                ctor = clazz.getDeclaredConstructor( EMPTY );
168                ctor.setAccessible( true );
169                return (Context) ctor.newInstance( EMPTY );
170            }
171            catch ( SecurityException e )
172            {
173                throw new ContextError( e );
174            }
175            catch ( NoSuchMethodException e )
176            {
177                throw new ContextError( e );
178            }
179            catch ( IllegalAccessException e )
180            {
181                throw new ContextError( e );
182            }
183            catch ( java.lang.InstantiationException e )
184            {
185                throw new ContextError( e );
186            }
187            catch ( InvocationTargetException e )
188            {
189                final Throwable targetException = e.getTargetException();
190    
191                if ( targetException instanceof Error )
192                {
193                    throw (Error) targetException;
194                }
195                else if ( targetException instanceof RuntimeException )
196                {
197                    throw (RuntimeException) targetException;
198                }
199                else
200                {
201                    throw new ContextError( targetException == null
202                                            ? e
203                                            : targetException );
204    
205                }
206            }
207            catch ( ClassCastException e )
208            {
209                throw new ContextError( e );
210            }
211            catch ( ClassNotFoundException e )
212            {
213                throw new ContextError( e );
214            }
215            finally
216            {
217                if ( ctor != null )
218                {
219                    ctor.setAccessible( false );
220                }
221            }
222        }
223    
224        //----------------------------------------------------------ContextFactory--
225    }