1 package org.apache.velocity.texen.util;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.io.FileInputStream;
23 import java.io.InputStream;
24 import java.util.Properties;
25 import java.util.StringTokenizer;
26
27 import org.apache.velocity.texen.Generator;
28
29 /**
30 * A property utility class for the texen text/code generator
31 * Usually this class is only used from a Velocity context.
32 *
33 * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
34 * @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a>
35 * @version $Id: PropertiesUtil.java 510628 2007-02-22 19:07:59Z nbubna $
36 */
37 public class PropertiesUtil
38 {
39 /**
40 * Load properties from either a file in the templatePath if there
41 * is one or the classPath.
42 *
43 * @param propertiesFile the properties file to load through
44 * either the templatePath or the classpath.
45 * @return a properties instance filled with the properties found
46 * in the file or an empty instance if no file was found.
47 */
48 public Properties load(final String propertiesFile)
49 {
50 Properties properties = null;
51
52 String templatePath = Generator.getInstance().getTemplatePath();
53 try
54 {
55 if (templatePath != null)
56 {
57 properties = loadFromTemplatePath(propertiesFile);
58 }
59 else
60 {
61 properties = loadFromClassPath(propertiesFile);
62 }
63 }
64 catch (RuntimeException e)
65 {
66 throw e;
67 }
68 catch (Exception e)
69 {
70 throw new RuntimeException("Could not load properties: " + e.getMessage());
71 }
72
73 return properties;
74 }
75
76 /**
77 * Load a properties file from the templatePath defined in the
78 * generator. As the templatePath can contains multiple paths,
79 * it will cycle through them to find the file. The first file
80 * that can be successfully loaded is considered. (kind of
81 * like the java classpath), it is done to clone the Velocity
82 * process of loading templates.
83 *
84 * @param propertiesFile the properties file to load. It must be
85 * a relative pathname.
86 * @return a properties instance loaded with the properties from
87 * the file. If no file can be found it returns an empty instance.
88 * @throws Exception
89 */
90 protected Properties loadFromTemplatePath(final String propertiesFile)
91 throws Exception
92 {
93 Properties properties = new Properties();
94 String templatePath = Generator.getInstance().getTemplatePath();
95
96 // We might have something like the following:
97 //
98 // #set ($dbprops = $properties.load("$generator.templatePath/path/props")
99 //
100 // as we have in Torque but we want people to start using
101 //
102 // #set ($dbprops = $properties.load("path/props")
103 //
104 // so that everything works from the filesystem or from
105 // a JAR. So the actual Generator.getTemplatePath()
106 // is not deprecated but it's use in templates
107 // should be.
108 StringTokenizer st = new StringTokenizer(templatePath, ",");
109 while (st.hasMoreTokens())
110 {
111 String templateDir = st.nextToken();
112 InputStream stream = null;
113 try
114 {
115 // If the properties file is being pulled from the
116 // file system and someone is using the method whereby
117 // the properties file is assumed to be in the template
118 // path and they are simply using:
119 //
120 // #set ($dbprops = $properties.load("props") (1)
121 //
122 // than we have to tack on the templatePath in order
123 // for the properties file to be found. We want (1)
124 // to work whether the generation is being run from
125 // the file system or from a JAR file.
126 String fullPath = propertiesFile;
127
128 // FIXME probably not that clever since there could be
129 // a mix of file separators and the test will fail :-(
130 if (!fullPath.startsWith(templateDir))
131 {
132 fullPath = templateDir + "/" + propertiesFile;
133 }
134
135 stream = new FileInputStream(fullPath);
136 properties.load(stream);
137 // first pick wins, we don't need to go further since
138 // we found a valid file.
139 break;
140 }
141 finally
142 {
143 if (stream != null)
144 {
145 stream.close();
146 }
147 }
148 }
149 return properties;
150 }
151
152 /**
153 * Load a properties file from the classpath
154 *
155 * @param propertiesName the properties file to load.
156 * @return a properties instance loaded with the properties from
157 * the file. If no file can be found it returns an empty instance.
158 * @throws Exception
159 */
160 protected Properties loadFromClassPath(final String propertiesName)
161 throws Exception
162 {
163 Properties properties = new Properties();
164 ClassLoader classLoader = this.getClass().getClassLoader();
165
166 InputStream inputStream = null;
167
168 try
169 {
170 // This is a hack for now to make sure that properties
171 // files referenced in the filesystem work in
172 // a JAR file. We have to deprecate the use
173 // of $generator.templatePath in templates first
174 // and this hack will allow those same templates
175 // that use $generator.templatePath to work in
176 // JAR files.
177
178 String propertiesFile = propertiesName.startsWith("$generator")
179 ? propertiesName.substring("$generator.templatePath/".length())
180 : propertiesName;
181
182 inputStream = classLoader.getResourceAsStream(propertiesFile);
183 properties.load(inputStream);
184 }
185 finally
186 {
187 if (inputStream != null)
188 {
189 inputStream.close();
190 }
191 }
192 return properties;
193 }
194 }