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