1/*2 * Copyright 2000-2004 The Apache Software Foundation.3 * 4 * Licensed under the Apache License, Version 2.0 (the "License");5 * you may not use this file except in compliance with the License.6 * You may obtain a copy of the License at7 * 8 * http://www.apache.org/licenses/LICENSE-2.09 * 10 * Unless required by applicable law or agreed to in writing, software11 * distributed under the License is distributed on an "AS IS" BASIS,12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13 * See the License for the specific language governing permissions and14 * limitations under the License.15 */1617packageorg.apache.jetspeed.services.resources;
1819// Java Core Classes20import java.io.File;
21import java.io.IOException;
22import java.util.Enumeration;
23import java.util.Hashtable;
24import java.util.Vector;
25import javax.servlet.ServletConfig;
26import javax.servlet.ServletContext;
2728// Turbine stuff.29import org.apache.commons.configuration.Configuration;
30import org.apache.turbine.services.resources.ResourceService;
31import org.apache.turbine.services.resources.TurbineResourceService;
32import org.apache.turbine.services.TurbineServices;
33import org.apache.turbine.services.InitializationException;
3435// Jetspeed classes36import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
37import org.apache.jetspeed.services.logging.JetspeedLogger;
3839/***40 * <p>This implementation of the <code>resourcesService</code> relies41 * on an external properties file for storing the configuration keys42 * and values</p>43 *44 * <P>In order to be compatible with legacy applications, this implementation45 * kept a static method for initializing the service, so it's still possible46 * 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 within53 * the configuration file. The variables are identified by the following54 * 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 application58 * <li>jvm.dir: JVM startup directory59 * </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 variables63 * </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 */68publicclassVariableResourcesServiceextends TurbineResourceService
69 {
70/***71 * Static initialization of the logger for this class72 */73privatestaticfinalJetspeedLogger logger = JetspeedLogFactoryService.getLogger(VariableResourcesService.class.getName());
7475publicstaticfinal String WEBAPP_DIR="webapp.dir";
76publicstaticfinal String WEB_DIR="web.dir";
77publicstaticfinal String JVM_DIR="jvm.dir";
78publicstaticfinal String START_TOKEN="${";
79publicstaticfinal String END_TOKEN="}";
8081/*** The container for the generic resources. */82private Hashtable variables = null;
8384/*** The container for the generic resources. */85private Hashtable strings = null;
86private Hashtable vectors = null;
87private Hashtable arrays = null;
888990/***91 * Late init. Don't return control until early init says we're done.92 */93publicvoid init( )
94 {
95while( !getInit() ) {
96try {
97 Thread.sleep(500);
98 } catch (InterruptedException ie ) {
99 logger.info("VariableResources service: Waiting for init()..." );
100 }
101 }
102 }
103104105/***106 * This method is called when the Service is initialized107 *108 * @param config a ServletConfig object109 */110publicsynchronizedvoid init(ServletConfig config) throws InitializationException
111 {
112if (getInit()) return;
113 String props = config.getInitParameter(TurbineServices.PROPERTIES_PATH_KEY);
114115 variables = new Hashtable();
116 strings = new Hashtable();
117 vectors = new Hashtable();
118 arrays = new Hashtable();
119 initVariables(config);
120121super.init(config);
122 }
123124/***125 * Initializer method that sets up the generic resources.126 *127 * @param confs A Configurations object.128 */129privatevoid initVariables(ServletConfig config)
130 {
131 ServletContext ctxt = config.getServletContext();
132133 String path = ctxt.getRealPath("/");
134135// define web app dir136if (path != null) {
137 variables.put(WEBAPP_DIR, normalizePath(path) );
138 }
139140// FIXME. the following code blocks on Tomcat 141// when loaded on startup142/*143 path = ctxt.getContext("/").getRealPath("/");144 if (path != null ) {145 variables.put(WEB_DIR, normalizePath(path) );146 }147 */148149// define JVM app dir150try {
151 path = new File(".").getCanonicalPath();
152if (path != null) {
153 variables.put(JVM_DIR, normalizePath(path) );
154 }
155 } catch (IOException e) {
156//very unlikely that the JVM can't 157//resolve its path158//But logging it anyway...159 logger.error( "Exception define JVM app dir", e );
160 }
161162// load servlet init parameters as variables, they may override163// the previously defined variables. All param names are folded164// to lower case165166 Enumeration en = config.getInitParameterNames();
167while( en.hasMoreElements() ) {
168 String paramName = (String)en.nextElement();
169 String paramValue = config.getInitParameter(paramName);
170 variables.put(paramName.toLowerCase(),paramValue);
171 }
172173 }
174175privatestatic String normalizePath(String path) {
176// change all separators to forward177// slashes178if (File.separatorChar != '/') {
179 path = path.replace(File.separatorChar,'/');
180 }
181182// remove any trailing slash183if (path.endsWith("/")) {
184 path = path.substring(0,path.length()-1);
185 }
186187return path;
188 }
189190protectedvoid setVariables(Hashtable vars)
191 {
192synchronized (this)
193 {
194this.variables = vars;
195this.strings = new Hashtable();
196this.vectors = new Hashtable();
197this.arrays = new Hashtable();
198 }
199 }
200201protected String substituteString( String base ) {
202if (base == null) returnnull;
203204int begin = -1;
205int end = -1;
206int prec = 0-END_TOKEN.length();
207 String var = null;
208 StringBuffer result = new StringBuffer();
209210// FIXME: we should probably allow the escaping of the start token211while ( ((begin=base.indexOf(START_TOKEN,prec+END_TOKEN.length()))>-1)
212 && ((end=base.indexOf(END_TOKEN,begin))>-1) ) {
213214 result.append(base.substring(prec+END_TOKEN.length(),begin));
215var = base.substring(begin+START_TOKEN.length(),end);
216if (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()));
222223return result.toString();
224 }
225226227/***228 * The purpose of this method is to get the configuration resource229 * 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 */234public String getString(String name)
235 {
236 String std = (String)strings.get(name);
237238if (std == null) {
239 std = substituteString(super.getString(name));
240if (std != null) strings.put(name,std);
241 }
242243return std;
244 }
245246/***247 * The purpose of this method is to get the configuration resource248 * 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 */254public String getString(String name,
255 String def)
256 {
257 String std = getString(name);
258259if (std == null)
260 std = substituteString(def);
261262return std;
263 }
264265/***266 * The purpose of this method is to get the configuration resource267 * 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 */272public String[] getStringArray(String name)
273 {
274 String[] std = (String[])arrays.get(name);
275if (std==null) {
276 std = super.getStringArray(name);
277if (std != null) {
278for(int i=0;i<std.length;i++) {
279 std[i]=substituteString(std[i]);
280 }
281 arrays.put(name,std);
282 }
283 }
284285return std;
286 }
287288/***289 * The purpose of this method is to get the configuration resource290 * 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 */295public Vector getVector(String name)
296 {
297 Vector std = (Vector)vectors.get(name);
298299if (std==null) {
300 std = super.getVector(name);
301if (std != null) {
302 Vector newstd = new Vector();
303 Enumeration en = std.elements();
304while (en.hasMoreElements()) {
305 newstd.addElement(substituteString((String)en.nextElement()));
306 }
307 std = newstd;
308 vectors.put(name,std);
309 }
310 }
311312return std;
313 }
314315/***316 * The purpose of this method is to get the configuration resource317 * 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 */323public Vector getVector(String name,
324 Vector def)
325 {
326 Vector std = getVector(name);
327if ( std == null) {
328if (def != null) {
329 std = new Vector();
330 Enumeration en = def.elements();
331while (en.hasMoreElements()) {
332 std.addElement(substituteString((String)en.nextElement()));
333 }
334 }
335 }
336337return std;
338 }
339340/***341 * The purpose of this method is to extract a subset of configuraton342 * resources sharing a common name prefix. The prefix is stripped343 * from the names of the resulting resources.344 *345 * @param prefix the common name prefix346 * @return A ResourceService providing the subset of configuration.347 */348public ResourceService getResources(String prefix)
349 {
350 Configuration config = getConfiguration().subset(prefix);
351352if (config == null)
353 {
354returnnull;
355 }
356357VariableResourcesService res = newVariableResourcesService();
358try359 {
360 res.init(config);
361 }
362catch (Exception e)
363 {
364 logger.error( "Unable to init resources for " + prefix, e );
365 }
366 res.setVariables(this.variables);
367return (ResourceService)res;
368 }
369370371 }