1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.jxpath;
17
18 import java.io.BufferedReader;
19 import java.io.File;
20 import java.io.FileInputStream;
21 import java.io.InputStream;
22 import java.io.InputStreamReader;
23 import java.util.Properties;
24
25 /***
26 * Defines a factory API that enables applications to obtain a
27 * JXPathContext instance. To acquire a JXPathContext, first call the
28 * static <code>newInstance()</code> method of JXPathContextFactory.
29 * This method returns a concrete JXPathContextFactory.
30 * Then call <code>newContext()</code> on that instance. You will rarely
31 * need to perform these steps explicitly: usually you can call one of the
32 * <code>JXPathContex.newContext</code> methods, which will perform these steps
33 * for you.
34 *
35 * @see JXPathContext#newContext(Object)
36 * @see JXPathContext#newContext(JXPathContext,Object)
37 *
38 * @author Dmitri Plotnikov
39 * @version $Revision: 1.8 $ $Date: 2004/02/29 14:17:42 $
40 */
41 public abstract class JXPathContextFactory {
42
43 /*** The default property */
44 public static final String FACTORY_NAME_PROPERTY =
45 "org.apache.commons.jxpath.JXPathContextFactory";
46
47 /*** The default factory class */
48 private static final String DEFAULT_FACTORY_CLASS =
49 "org.apache.commons.jxpath.ri.JXPathContextFactoryReferenceImpl";
50
51 /*** Avoid reading all the files when the findFactory
52 method is called the second time ( cache the result of
53 finding the default impl )
54 */
55 private static String factoryImplName = null;
56
57 protected JXPathContextFactory () {
58
59 }
60
61 /***
62 * Obtain a new instance of a <code>JXPathContextFactory</code>.
63 * This static method creates a new factory instance.
64 * This method uses the following ordered lookup procedure to determine
65 * the <code>JXPathContextFactory</code> implementation class to load:
66 * <ul>
67 * <li>
68 * Use the <code>org.apache.commons.jxpath.JXPathContextFactory</code>
69 * system property.
70 * </li>
71 * <li>
72 * Alternatively, use the JAVA_HOME (the parent directory where jdk is
73 * installed)/lib/jxpath.properties for a property file that contains the
74 * name of the implementation class keyed on
75 * <code>org.apache.commons.jxpath.JXPathContextFactory</code>.
76 * </li>
77 * <li>
78 * Use the Services API (as detailed in the JAR specification), if
79 * available, to determine the classname. The Services API will look
80 * for a classname in the file
81 * <code>META- INF/services/<i>org.apache.commons.jxpath.
82 * JXPathContextFactory</i></code> in jars available to the runtime.
83 * </li>
84 * <li>
85 * Platform default <code>JXPathContextFactory</code> instance.
86 * </li>
87 * </ul>
88 *
89 * Once an application has obtained a reference to a
90 * <code>JXPathContextFactory</code> it can use the factory to
91 * obtain JXPathContext instances.
92 *
93 * @exception JXPathFactoryConfigurationError if the implementation is not
94 * available or cannot be instantiated.
95 */
96 public static JXPathContextFactory newInstance() {
97 if (factoryImplName == null) {
98 factoryImplName =
99 findFactory(FACTORY_NAME_PROPERTY, DEFAULT_FACTORY_CLASS);
100 }
101
102 JXPathContextFactory factoryImpl;
103 try {
104 Class clazz = Class.forName(factoryImplName);
105 factoryImpl = (JXPathContextFactory) clazz.newInstance();
106 }
107 catch (ClassNotFoundException cnfe) {
108 throw new JXPathContextFactoryConfigurationError(cnfe);
109 }
110 catch (IllegalAccessException iae) {
111 throw new JXPathContextFactoryConfigurationError(iae);
112 }
113 catch (InstantiationException ie) {
114 throw new JXPathContextFactoryConfigurationError(ie);
115 }
116 return factoryImpl;
117 }
118
119 /***
120 * Creates a new instance of a JXPathContext using the
121 * currently configured parameters.
122 *
123 * @exception JXPathContextFactoryConfigurationError if a JXPathContext
124 * cannot be created which satisfies the configuration requested
125 */
126
127 public abstract JXPathContext newContext(
128 JXPathContext parentContext,
129 Object contextBean)
130 throws JXPathContextFactoryConfigurationError;
131
132
133
134
135
136
137 /*** Temp debug code - this will be removed after we test everything
138 */
139 private static boolean debug = false;
140 static {
141 try {
142 debug = System.getProperty("jxpath.debug") != null;
143 }
144 catch (SecurityException se) {
145
146 }
147 }
148
149 /*** Private implementation method - will find the implementation
150 class in the specified order.
151 @param property Property name
152 @param defaultFactory Default implementation, if nothing else is found
153
154 @return class name of the JXPathContextFactory
155 */
156 private static String findFactory(String property, String defaultFactory) {
157
158 try {
159 String systemProp = System.getProperty(property);
160 if (systemProp != null) {
161 if (debug) {
162 System.err.println(
163 "JXPath: found system property" + systemProp);
164 }
165 return systemProp;
166 }
167
168 }
169 catch (SecurityException se) {
170
171 }
172
173
174 try {
175 String javah = System.getProperty("java.home");
176 String configFile =
177 javah
178 + File.separator
179 + "lib"
180 + File.separator
181 + "jxpath.properties";
182 File f = new File(configFile);
183 if (f.exists()) {
184 Properties props = new Properties();
185 props.load(new FileInputStream(f));
186 String factory = props.getProperty(property);
187 if (factory != null) {
188 if (debug) {
189 System.err.println(
190 "JXPath: found java.home property " + factory);
191 }
192 return factory;
193 }
194 }
195 }
196 catch (Exception ex) {
197 if (debug) {
198 ex.printStackTrace();
199 }
200 }
201
202 String serviceId = "META-INF/services/" + property;
203
204 try {
205 ClassLoader cl = JXPathContextFactory.class.getClassLoader();
206 InputStream is = null;
207 if (cl == null) {
208 is = ClassLoader.getSystemResourceAsStream(serviceId);
209 }
210 else {
211 is = cl.getResourceAsStream(serviceId);
212 }
213
214 if (is != null) {
215 if (debug) {
216 System.err.println("JXPath: found " + serviceId);
217 }
218 BufferedReader rd =
219 new BufferedReader(new InputStreamReader(is));
220
221 String factory = rd.readLine();
222 rd.close();
223
224 if (factory != null && !"".equals(factory)) {
225 if (debug) {
226 System.err.println(
227 "JXPath: loaded from services: " + factory);
228 }
229 return factory;
230 }
231 }
232 }
233 catch (Exception ex) {
234 if (debug) {
235 ex.printStackTrace();
236 }
237 }
238
239 return defaultFactory;
240 }
241 }