1 /*
2 * jDTAUS Core API
3 * Copyright (C) 2005 Christian Schulte
4 * <cs@schulte.it>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21 package org.jdtaus.core.container;
22
23 import java.lang.reflect.Constructor;
24 import java.lang.reflect.InvocationTargetException;
25 import java.lang.reflect.Method;
26
27 /**
28 * Factory for the {@code Context} singleton.
29 *
30 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
31 * @version $JDTAUS: ContextFactory.java 8743 2012-10-07 03:06:20Z schulte $
32 */
33 public abstract class ContextFactory
34 {
35 //--Constants---------------------------------------------------------------
36
37 /** Default {@code Context} implementation. */
38 private static final String DEFAULT_CONTEXT =
39 "org.jdtaus.core.container.ri.client.DefaultContext";
40
41 /** Empty array. */
42 private static final Class[] EMPTY =
43 {
44 };
45
46 //---------------------------------------------------------------Constants--
47 //--ContextFactory----------------------------------------------------------
48
49 /** Default singleton instance. */
50 private static Context instance;
51
52 /**
53 * Gets the {@code Context} singleton.
54 * <p>By default this class will instantiate a new context and hold it in a
55 * static class variable as the singleton to return for other calls. This
56 * behaviour can be changed by setting a system property with key
57 * {@code org.jdtaus.core.container.ContextFactory} to the name of a
58 * class defining a {@code public static Context getContext()} method
59 * returning the singleton instance of {@code Context}.</p>
60 *
61 * @return the singleton {@code Context} instance.
62 *
63 * @throws ContextError for unrecoverable context errors.
64 *
65 * @see ContextFactory#newContext()
66 */
67 public static Context getContext()
68 {
69 Object ret = null;
70 final String factory = System.getProperty(
71 ContextFactory.class.getName() );
72
73 try
74 {
75 if ( factory != null )
76 {
77 // Call getContext() on that class.
78 final Class clazz = ClassLoaderFactory.loadClass(
79 ContextFactory.class, factory );
80
81 final Method meth = clazz.getDeclaredMethod( "getContext",
82 EMPTY );
83
84 ret = meth.invoke( null, EMPTY );
85 }
86 else
87 {
88 if ( instance == null )
89 {
90 instance = newContext();
91 }
92
93 ret = instance;
94 }
95
96 return (Context) ret;
97 }
98 catch ( final SecurityException e )
99 {
100 throw new ContextError( e );
101 }
102 catch ( final NoSuchMethodException e )
103 {
104 throw new ContextError( e );
105 }
106 catch ( final IllegalAccessException e )
107 {
108 throw new ContextError( e );
109 }
110 catch ( final InvocationTargetException e )
111 {
112 final Throwable targetException = e.getTargetException();
113
114 if ( targetException instanceof Error )
115 {
116 throw (Error) targetException;
117 }
118 else if ( targetException instanceof RuntimeException )
119 {
120 throw (RuntimeException) targetException;
121 }
122 else
123 {
124 throw new ContextError( targetException == null
125 ? e
126 : targetException );
127
128 }
129 }
130 catch ( final ClassCastException e )
131 {
132 throw new ContextError( e );
133 }
134 catch ( final ClassNotFoundException e )
135 {
136 throw new ContextError( e );
137 }
138 }
139
140 /**
141 * Creates a new instance of the configured {@code Context} implementation.
142 * <p>The context implementation to be used can be controlled via a system
143 * property with key {@code org.jdtaus.core.container.Context} set
144 * to a class name to be loaded as the context implementation.</p>
145 * <p>This method should be used by {@code getContext()} implementors to
146 * retrieve a new {@code Context} instance.</p>
147 *
148 * @return a new instance of the configured {@code Context}
149 * implementation.
150 *
151 * @throws ContextError for unrecoverable context errors.
152 */
153 public static Context newContext()
154 {
155 final String impl = System.getProperty( Context.class.getName(),
156 DEFAULT_CONTEXT );
157
158 Constructor ctor = null;
159
160 try
161 {
162 final Class clazz = ClassLoaderFactory.loadClass(
163 ContextFactory.class, impl );
164
165 ctor = clazz.getDeclaredConstructor( EMPTY );
166 ctor.setAccessible( true );
167 return (Context) ctor.newInstance( EMPTY );
168 }
169 catch ( final SecurityException e )
170 {
171 throw new ContextError( e );
172 }
173 catch ( final NoSuchMethodException e )
174 {
175 throw new ContextError( e );
176 }
177 catch ( final IllegalAccessException e )
178 {
179 throw new ContextError( e );
180 }
181 catch ( final java.lang.InstantiationException e )
182 {
183 throw new ContextError( e );
184 }
185 catch ( final InvocationTargetException e )
186 {
187 final Throwable targetException = e.getTargetException();
188
189 if ( targetException instanceof Error )
190 {
191 throw (Error) targetException;
192 }
193 else if ( targetException instanceof RuntimeException )
194 {
195 throw (RuntimeException) targetException;
196 }
197 else
198 {
199 throw new ContextError( targetException == null
200 ? e
201 : targetException );
202
203 }
204 }
205 catch ( final ClassCastException e )
206 {
207 throw new ContextError( e );
208 }
209 catch ( final ClassNotFoundException e )
210 {
211 throw new ContextError( e );
212 }
213 finally
214 {
215 if ( ctor != null )
216 {
217 ctor.setAccessible( false );
218 }
219 }
220 }
221
222 //----------------------------------------------------------ContextFactory--
223 }