1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.services.resources;
18
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.util.Enumeration;
23 import java.util.Hashtable;
24 import java.util.Vector;
25 import javax.servlet.ServletConfig;
26 import javax.servlet.ServletContext;
27
28
29 import org.apache.commons.configuration.Configuration;
30 import org.apache.turbine.services.resources.ResourceService;
31 import org.apache.turbine.services.resources.TurbineResourceService;
32 import org.apache.turbine.services.TurbineServices;
33 import org.apache.turbine.services.InitializationException;
34
35
36 import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
37 import org.apache.jetspeed.services.logging.JetspeedLogger;
38
39 /***
40 * <p>This implementation of the <code>resourcesService</code> relies
41 * on an external properties file for storing the configuration keys
42 * and values</p>
43 *
44 * <P>In order to be compatible with legacy applications, this implementation
45 * kept a static method for initializing the service, so it's still possible
46 * to write the following code:
47 * <p><code>
48 * TurbineResourceService.setPropertiesName("d:/conf/Turbine.properties");
49 * Vector myVar = TurbineResources.getVector("myvar");
50 * </code></p>
51 *
52 * <p>This implementation allows the use of several pre-defined variables within
53 * the configuration file. The variables are identified by the following
54 * sequence of tokens: ${<varname>}. Varname is always folded to lowercase.</p>
55 * <P>The predefined variables are:
56 * <ul>
57 * <li>webapp.dir: base directory for the web application
58 * <li>jvm.dir: JVM startup directory
59 * </ul>
60 * </p>
61 * <p>The init parameters of the servlet are also imported as default variables.
62 * They may override the previously defined default variables
63 * </p>
64 *
65 * @author <a href="mailto:raphael@apache.org">Raphaël Luta</a>
66 * @version $Id: VariableResourcesService.java,v 1.15 2004/02/23 03:29:53 jford Exp $
67 */
68 public class VariableResourcesService extends TurbineResourceService
69 {
70 /***
71 * Static initialization of the logger for this class
72 */
73 private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(VariableResourcesService.class.getName());
74
75 public static final String WEBAPP_DIR="webapp.dir";
76 public static final String WEB_DIR="web.dir";
77 public static final String JVM_DIR="jvm.dir";
78 public static final String START_TOKEN="${";
79 public static final String END_TOKEN="}";
80
81 /*** The container for the generic resources. */
82 private Hashtable variables = null;
83
84 /*** The container for the generic resources. */
85 private Hashtable strings = null;
86 private Hashtable vectors = null;
87 private Hashtable arrays = null;
88
89
90 /***
91 * Late init. Don't return control until early init says we're done.
92 */
93 public void init( )
94 {
95 while( !getInit() ) {
96 try {
97 Thread.sleep(500);
98 } catch (InterruptedException ie ) {
99 logger.info("VariableResources service: Waiting for init()..." );
100 }
101 }
102 }
103
104
105 /***
106 * This method is called when the Service is initialized
107 *
108 * @param config a ServletConfig object
109 */
110 public synchronized void init(ServletConfig config) throws InitializationException
111 {
112 if (getInit()) return;
113 String props = config.getInitParameter(TurbineServices.PROPERTIES_PATH_KEY);
114
115 variables = new Hashtable();
116 strings = new Hashtable();
117 vectors = new Hashtable();
118 arrays = new Hashtable();
119 initVariables(config);
120
121 super.init(config);
122 }
123
124 /***
125 * Initializer method that sets up the generic resources.
126 *
127 * @param confs A Configurations object.
128 */
129 private void initVariables(ServletConfig config)
130 {
131 ServletContext ctxt = config.getServletContext();
132
133 String path = ctxt.getRealPath("/");
134
135
136 if (path != null) {
137 variables.put(WEBAPP_DIR, normalizePath(path) );
138 }
139
140
141
142
143
144
145
146
147
148
149
150 try {
151 path = new File(".").getCanonicalPath();
152 if (path != null) {
153 variables.put(JVM_DIR, normalizePath(path) );
154 }
155 } catch (IOException e) {
156
157
158
159 logger.error( "Exception define JVM app dir", e );
160 }
161
162
163
164
165
166 Enumeration en = config.getInitParameterNames();
167 while( en.hasMoreElements() ) {
168 String paramName = (String)en.nextElement();
169 String paramValue = config.getInitParameter(paramName);
170 variables.put(paramName.toLowerCase(),paramValue);
171 }
172
173 }
174
175 private static String normalizePath(String path) {
176
177
178 if (File.separatorChar != '/') {
179 path = path.replace(File.separatorChar,'/');
180 }
181
182
183 if (path.endsWith("/")) {
184 path = path.substring(0,path.length()-1);
185 }
186
187 return path;
188 }
189
190 protected void setVariables(Hashtable vars)
191 {
192 synchronized (this)
193 {
194 this.variables = vars;
195 this.strings = new Hashtable();
196 this.vectors = new Hashtable();
197 this.arrays = new Hashtable();
198 }
199 }
200
201 protected String substituteString( String base ) {
202 if (base == null) return null;
203
204 int begin = -1;
205 int end = -1;
206 int prec = 0-END_TOKEN.length();
207 String var = null;
208 StringBuffer result = new StringBuffer();
209
210
211 while ( ((begin=base.indexOf(START_TOKEN,prec+END_TOKEN.length()))>-1)
212 && ((end=base.indexOf(END_TOKEN,begin))>-1) ) {
213
214 result.append(base.substring(prec+END_TOKEN.length(),begin));
215 var = base.substring(begin+START_TOKEN.length(),end);
216 if (variables.get(var)!=null) {
217 result.append(variables.get(var));
218 }
219 prec=end;
220 }
221 result.append(base.substring(prec+END_TOKEN.length(),base.length()));
222
223 return result.toString();
224 }
225
226
227 /***
228 * The purpose of this method is to get the configuration resource
229 * with the given name as a string.
230 *
231 * @param name The resource name.
232 * @return The value of the resource as a string.
233 */
234 public String getString(String name)
235 {
236 String std = (String)strings.get(name);
237
238 if (std == null) {
239 std = substituteString(super.getString(name));
240 if (std != null) strings.put(name,std);
241 }
242
243 return std;
244 }
245
246 /***
247 * The purpose of this method is to get the configuration resource
248 * with the given name as a string, or a default value.
249 *
250 * @param name The resource name.
251 * @param def The default value of the resource.
252 * @return The value of the resource as a string.
253 */
254 public String getString(String name,
255 String def)
256 {
257 String std = getString(name);
258
259 if (std == null)
260 std = substituteString(def);
261
262 return std;
263 }
264
265 /***
266 * The purpose of this method is to get the configuration resource
267 * with the given name as a string array.
268 *
269 * @param name The resource name.
270 * @return The value of the resource as a string array.
271 */
272 public String[] getStringArray(String name)
273 {
274 String[] std = (String[])arrays.get(name);
275 if (std==null) {
276 std = super.getStringArray(name);
277 if (std != null) {
278 for(int i=0;i<std.length;i++) {
279 std[i]=substituteString(std[i]);
280 }
281 arrays.put(name,std);
282 }
283 }
284
285 return std;
286 }
287
288 /***
289 * The purpose of this method is to get the configuration resource
290 * with the given name as a vector.
291 *
292 * @param name The resource name.
293 * @return The value of the resource as a vector.
294 */
295 public Vector getVector(String name)
296 {
297 Vector std = (Vector)vectors.get(name);
298
299 if (std==null) {
300 std = super.getVector(name);
301 if (std != null) {
302 Vector newstd = new Vector();
303 Enumeration en = std.elements();
304 while (en.hasMoreElements()) {
305 newstd.addElement(substituteString((String)en.nextElement()));
306 }
307 std = newstd;
308 vectors.put(name,std);
309 }
310 }
311
312 return std;
313 }
314
315 /***
316 * The purpose of this method is to get the configuration resource
317 * with the given name as a vector, or a default value.
318 *
319 * @param name The resource name.
320 * @param def The default value of the resource.
321 * @return The value of the resource as a vector.
322 */
323 public Vector getVector(String name,
324 Vector def)
325 {
326 Vector std = getVector(name);
327 if ( std == null) {
328 if (def != null) {
329 std = new Vector();
330 Enumeration en = def.elements();
331 while (en.hasMoreElements()) {
332 std.addElement(substituteString((String)en.nextElement()));
333 }
334 }
335 }
336
337 return std;
338 }
339
340 /***
341 * The purpose of this method is to extract a subset of configuraton
342 * resources sharing a common name prefix. The prefix is stripped
343 * from the names of the resulting resources.
344 *
345 * @param prefix the common name prefix
346 * @return A ResourceService providing the subset of configuration.
347 */
348 public ResourceService getResources(String prefix)
349 {
350 Configuration config = getConfiguration().subset(prefix);
351
352 if (config == null)
353 {
354 return null;
355 }
356
357 VariableResourcesService res = new VariableResourcesService();
358 try
359 {
360 res.init(config);
361 }
362 catch (Exception e)
363 {
364 logger.error( "Unable to init resources for " + prefix, e );
365 }
366 res.setVariables(this.variables);
367 return (ResourceService)res;
368 }
369
370
371 }