1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package com.ontotext.ordi;
19
20 import java.io.InputStream;
21 import java.lang.reflect.Constructor;
22 import java.lang.reflect.InvocationTargetException;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.Map;
26 import java.util.Properties;
27 import java.util.WeakHashMap;
28 import java.util.Map.Entry;
29
30 import org.apache.log4j.Logger;
31
32 import com.ontotext.ordi.exception.ORDIRuntimeException;
33 import com.ontotext.ordi.tripleset.TSource;
34
35 /**
36 * This class contains methods to instantiate instances of ORDI data model or
37 * domain specific models as WSMO4J layered on top of it.
38 *
39 * Default settings are supported in the optional file "ordi.properties".
40 *
41 * The class cannot be instantiated it has only static method.
42 *
43 * @author vassil
44 *
45 */
46 public final class Factory {
47
48 public static final String ORDI_MODEL_DEAULT_PROPERTIES = "ordi.properties";
49 public static final String ORDI_MODEL_IMPLEMENTATION = TSource.class
50 .getName();
51 private static Properties defaultSettings = null;
52 private static Logger logger = Logger.getLogger(Factory.class);
53
54 /**
55 * Creates a new instance of ORDI data model, based on the default settings.
56 * The class to instantiate is defined by ordi_model_implementation. All
57 * properties described in the file are supplied to the constructor of class
58 * to instantiate.
59 *
60 * @return object to implement ORDI data model
61 */
62 public static TSource createDefaultTSource() {
63 return createTSource(mergeWithDefaultProperties(null));
64 }
65
66 /**
67 * Creates a new instance of ORDI data model, based on the default and
68 * runtime settings. The runtime settings have higher priority than the
69 * default settings. The class to instantiate is defined by
70 * ordi_model_implementation. All properties described in the file are
71 * supplied to the constructor of class to instantiate.
72 *
73 * @param map
74 * runtime settings
75 *
76 * @return object to implement ORDI data model
77 */
78 public static TSource createTSource(Map<Object, Object> map) {
79 map = mergeWithDefaultProperties(map);
80 if (logger.isInfoEnabled()) {
81 Iterator<Map.Entry<Object, Object>> iterator = map.entrySet()
82 .iterator();
83 logger.info("Properties used by factory:");
84 while (iterator.hasNext()) {
85 Entry<Object, Object> entry = iterator.next();
86 logger.info(String.format("%s=%s", entry.getKey(), entry
87 .getValue()));
88 }
89 }
90 if (map.containsKey(ORDI_MODEL_IMPLEMENTATION) == false) {
91 throw new ORDIRuntimeException(String.format(
92 "Default properties do not specify %s key!",
93 ORDI_MODEL_IMPLEMENTATION));
94 }
95 Object result = instantiateObject(map.get(ORDI_MODEL_IMPLEMENTATION)
96 .toString(), map);
97 if (result instanceof TSource == false) {
98 throw new ORDIRuntimeException(
99 String
100 .format(
101 "The provided class %s do not implements TSource interface!",
102 map.get(ORDI_MODEL_IMPLEMENTATION)));
103 }
104 return (TSource) result;
105 }
106
107 /**
108 * Creates a new instance of the supplied class type. This method is useful
109 * for creation of domain specific models layered on top of ORDI data model
110 * like wsmo4rdf. The method reuses also the configuration in the default
111 * settings.
112 *
113 * @param type
114 * is interface or class to be created
115 * @param map
116 * is runtime configuration to be used
117 * @return instance of class type
118 */
119 @SuppressWarnings("unchecked")
120 public static <X> X create(Class<X> type, Map<Object, Object> map) {
121 map = mergeWithDefaultProperties(map);
122 if (logger.isInfoEnabled()) {
123 Iterator<Map.Entry<Object, Object>> iterator = map.entrySet()
124 .iterator();
125 logger.info("Properties used by factory:");
126 while (iterator.hasNext()) {
127 Entry<Object, Object> entry = iterator.next();
128 logger.info(String.format("%s=%s", entry.getKey(), entry
129 .getValue()));
130 }
131 }
132 Object typeName = map.get(type.getName());
133 if (typeName instanceof Class<?>) {
134 typeName = ((Class) typeName).getName();
135 } else if (typeName == null || typeName instanceof String == false) {
136 logger.info(String.format(
137 "No implementation is specified for type %s", type
138 .getName()));
139 typeName = type.getName();
140 }
141 return (X) instantiateObject((String) typeName, map);
142 }
143
144 private static Map<String, WeakHashMap<String, Object>> instances =
145 new HashMap<String, WeakHashMap<String, Object>>();
146
147 /**
148 * This method instantiate type to implements DataSource which has 1)
149 * default constructor OR 2) constructor to get Map.
150 *
151 * @param typeName
152 * is class to be instantiated
153 * @param map
154 * is the parameters to be used
155 * @return
156 */
157 private synchronized static Object instantiateObject(String typeName,
158 Map<Object, Object> map) {
159 Object result = null;
160 Class<?> providerClass = null;
161 Constructor<?> providerConstructor = null;
162 String mapParameters = map.toString();
163
164
165 if (instances.containsKey(typeName)) {
166 WeakHashMap<String, Object> weak = instances.get(typeName);
167 result = weak.get(mapParameters);
168 }
169 if (result instanceof TSource && ((TSource) result).isShutdown() == false) {
170 return result;
171 }
172
173
174 try {
175 providerClass = Class.forName(typeName);
176 } catch (ClassNotFoundException e) {
177 try {
178 providerClass = Class.forName(typeName, true, Thread
179 .currentThread().getContextClassLoader());
180 } catch (ClassNotFoundException ne) {
181 throw new ORDIRuntimeException(String.format(
182 "Provider's class %s is not found in classpath!",
183 typeName), ne);
184 }
185 }
186 Object[] contructorParams = new Object[] {
187 new Class[] { java.util.Map.class }, new Class[0] };
188 try {
189 for (int i = 0; i < contructorParams.length; i++) {
190 providerConstructor = providerClass
191 .getConstructor((Class[]) contructorParams[i]);
192 }
193 } catch (NoSuchMethodException nsme) {
194 }
195 if (providerConstructor == null) {
196 throw new ORDIRuntimeException(
197 String
198 .format(
199 "Provider's class %s has no suitable constructor to invoke!",
200 typeName));
201 }
202 try {
203 result = providerConstructor.newInstance(new Object[] { map });
204 } catch (InvocationTargetException ite) {
205 throw new ORDIRuntimeException(String.format(
206 "Cannot construct object of type %s! ", typeName), ite);
207 } catch (IllegalAccessException ile) {
208 throw new ORDIRuntimeException("Cannot access the constructor!",
209 ile);
210 } catch (InstantiationException inse) {
211 throw new ORDIRuntimeException(String.format(
212 "Cannot instantiate %s!", typeName), inse);
213 }
214
215
216 WeakHashMap<String, Object> weak = instances.get(typeName);
217 if (weak == null) {
218 weak = new WeakHashMap<String, Object>();
219 instances.put(typeName, weak);
220 }
221 weak.put(mapParameters, result);
222
223 return result;
224 }
225
226 private synchronized static void loadDeaultProperties() {
227 if (defaultSettings != null) {
228 return;
229 }
230 defaultSettings = new Properties();
231 InputStream inProps = Thread.currentThread().getContextClassLoader()
232 .getResourceAsStream(ORDI_MODEL_DEAULT_PROPERTIES);
233 if (inProps == null) {
234 inProps = Factory.class.getClassLoader().getResourceAsStream(
235 ORDI_MODEL_DEAULT_PROPERTIES);
236 }
237 if (inProps == null) {
238 defaultSettings = new Properties();
239 return;
240 }
241 try {
242 defaultSettings.load(inProps);
243 } catch (Exception e) {
244 throw new ORDIRuntimeException(String.format(
245 "The file %s could not be read or has invalid format!",
246 ORDI_MODEL_DEAULT_PROPERTIES), e);
247 }
248 }
249
250 private static Map<Object, Object> mergeWithDefaultProperties(
251 Map<Object, Object> map) {
252 loadDeaultProperties();
253 Map<Object, Object> result = new HashMap<Object, Object>();
254 Iterator<Map.Entry<Object, Object>> iteratorProp = defaultSettings
255 .entrySet().iterator();
256 while (iteratorProp.hasNext()) {
257 Map.Entry<Object, Object> entry = iteratorProp.next();
258 result.put(entry.getKey().toString(), entry.getValue());
259 }
260 if (map != null) {
261 Iterator<Map.Entry<Object, Object>> iteratorMap = map.entrySet()
262 .iterator();
263 while (iteratorMap.hasNext()) {
264 Map.Entry<Object, Object> entry = iteratorMap.next();
265 result.put(entry.getKey(), entry.getValue());
266 }
267 }
268 return result;
269 }
270 }