001: package org.apache.velocity.texen.util;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: import java.io.FileInputStream;
023: import java.io.InputStream;
024: import java.util.Properties;
025: import java.util.StringTokenizer;
026:
027: import org.apache.velocity.texen.Generator;
028:
029: /**
030: * A property utility class for the texen text/code generator
031: * Usually this class is only used from a Velocity context.
032: *
033: * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
034: * @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a>
035: * @version $Id: PropertiesUtil.java 463298 2006-10-12 16:10:32Z henning $
036: */
037: public class PropertiesUtil {
038: /**
039: * Load properties from either a file in the templatePath if there
040: * is one or the classPath.
041: *
042: * @param propertiesFile the properties file to load through
043: * either the templatePath or the classpath.
044: * @return a properties instance filled with the properties found
045: * in the file or an empty instance if no file was found.
046: */
047: public Properties load(final String propertiesFile) {
048: Properties properties = null;
049:
050: String templatePath = Generator.getInstance().getTemplatePath();
051: try {
052: if (templatePath != null) {
053: properties = loadFromTemplatePath(propertiesFile);
054: } else {
055: properties = loadFromClassPath(propertiesFile);
056: }
057: } catch (RuntimeException e) {
058: throw e;
059: } catch (Exception e) {
060: throw new RuntimeException("Could not load properties: "
061: + e.getMessage());
062: }
063:
064: return properties;
065: }
066:
067: /**
068: * Load a properties file from the templatePath defined in the
069: * generator. As the templatePath can contains multiple paths,
070: * it will cycle through them to find the file. The first file
071: * that can be successfully loaded is considered. (kind of
072: * like the java classpath), it is done to clone the Velocity
073: * process of loading templates.
074: *
075: * @param propertiesFile the properties file to load. It must be
076: * a relative pathname.
077: * @return a properties instance loaded with the properties from
078: * the file. If no file can be found it returns an empty instance.
079: * @throws Exception
080: */
081: protected Properties loadFromTemplatePath(
082: final String propertiesFile) throws Exception {
083: Properties properties = new Properties();
084: String templatePath = Generator.getInstance().getTemplatePath();
085:
086: // We might have something like the following:
087: //
088: // #set ($dbprops = $properties.load("$generator.templatePath/path/props")
089: //
090: // as we have in Torque but we want people to start using
091: //
092: // #set ($dbprops = $properties.load("path/props")
093: //
094: // so that everything works from the filesystem or from
095: // a JAR. So the actual Generator.getTemplatePath()
096: // is not deprecated but it's use in templates
097: // should be.
098: StringTokenizer st = new StringTokenizer(templatePath, ",");
099: while (st.hasMoreTokens()) {
100: String templateDir = st.nextToken();
101: InputStream stream = null;
102: try {
103: // If the properties file is being pulled from the
104: // file system and someone is using the method whereby
105: // the properties file is assumed to be in the template
106: // path and they are simply using:
107: //
108: // #set ($dbprops = $properties.load("props") (1)
109: //
110: // than we have to tack on the templatePath in order
111: // for the properties file to be found. We want (1)
112: // to work whether the generation is being run from
113: // the file system or from a JAR file.
114: String fullPath = propertiesFile;
115:
116: // FIXME probably not that clever since there could be
117: // a mix of file separators and the test will fail :-(
118: if (!fullPath.startsWith(templateDir)) {
119: fullPath = templateDir + "/" + propertiesFile;
120: }
121:
122: stream = new FileInputStream(fullPath);
123: properties.load(stream);
124: // first pick wins, we don't need to go further since
125: // we found a valid file.
126: break;
127: } finally {
128: if (stream != null) {
129: stream.close();
130: }
131: }
132: }
133: return properties;
134: }
135:
136: /**
137: * Load a properties file from the classpath
138: *
139: * @param propertiesName the properties file to load.
140: * @return a properties instance loaded with the properties from
141: * the file. If no file can be found it returns an empty instance.
142: * @throws Exception
143: */
144: protected Properties loadFromClassPath(final String propertiesName)
145: throws Exception {
146: Properties properties = new Properties();
147: ClassLoader classLoader = this .getClass().getClassLoader();
148:
149: InputStream inputStream = null;
150:
151: try {
152: // This is a hack for now to make sure that properties
153: // files referenced in the filesystem work in
154: // a JAR file. We have to deprecate the use
155: // of $generator.templatePath in templates first
156: // and this hack will allow those same templates
157: // that use $generator.templatePath to work in
158: // JAR files.
159:
160: String propertiesFile = propertiesName
161: .startsWith("$generator") ? propertiesName
162: .substring("$generator.templatePath/".length())
163: : propertiesName;
164:
165: inputStream = classLoader
166: .getResourceAsStream(propertiesFile);
167: properties.load(inputStream);
168: } finally {
169: if (inputStream != null) {
170: inputStream.close();
171: }
172: }
173: return properties;
174: }
175: }
|