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