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