%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
org.apache.commons.jelly.Jelly |
|
|
1 | /* |
|
2 | * Copyright 2002,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 at |
|
7 | * |
|
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
9 | * |
|
10 | * Unless required by applicable law or agreed to in writing, software |
|
11 | * 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 and |
|
14 | * limitations under the License. |
|
15 | */ |
|
16 | ||
17 | package org.apache.commons.jelly; |
|
18 | ||
19 | import java.io.File; |
|
20 | import java.io.InputStream; |
|
21 | import java.io.FileInputStream; |
|
22 | import java.io.IOException; |
|
23 | import java.net.MalformedURLException; |
|
24 | import java.net.URL; |
|
25 | import java.util.Enumeration; |
|
26 | import java.util.Properties; |
|
27 | ||
28 | import org.apache.commons.jelly.parser.XMLParser; |
|
29 | import org.apache.commons.jelly.util.ClassLoaderUtils; |
|
30 | import org.apache.commons.jelly.util.CommandLineParser; |
|
31 | import org.apache.commons.logging.Log; |
|
32 | import org.apache.commons.logging.LogFactory; |
|
33 | ||
34 | import org.xml.sax.SAXException; |
|
35 | ||
36 | /** |
|
37 | * <p><code>Jelly</code> is a helper class which is capable of |
|
38 | * running a Jelly script. This class can be used from the command line |
|
39 | * or can be used as the basis of an Ant task.</p> Command line usage is as follows: |
|
40 | * |
|
41 | * <pre> |
|
42 | * jelly [scriptFile] [-script scriptFile -o outputFile -Dsysprop=syspropval] |
|
43 | * </pre> |
|
44 | * |
|
45 | * @author <a href="mailto:jstrachan@apache.org">James Strachan</a> |
|
46 | * @version $Revision: 155420 $ |
|
47 | */ |
|
48 | public class Jelly { |
|
49 | ||
50 | /** The Log to which logging calls will be made. */ |
|
51 | 520 | private static final Log log = LogFactory.getLog(Jelly.class); |
52 | ||
53 | /** The JellyContext to use */ |
|
54 | private JellyContext context; |
|
55 | ||
56 | /** The URL of the script to execute */ |
|
57 | private URL url; |
|
58 | ||
59 | /** The URL of the root context for other scripts */ |
|
60 | private URL rootContext; |
|
61 | ||
62 | /** Whether we have loaded the properties yet */ |
|
63 | 1066 | private boolean loadedProperties = false; |
64 | ||
65 | /** |
|
66 | * whether to override the default namespace |
|
67 | */ |
|
68 | 1066 | private String defaultNamespaceURI = null; |
69 | ||
70 | /** |
|
71 | * whether or not to validate the Jelly script |
|
72 | */ |
|
73 | 1066 | private boolean validateXML = false; |
74 | ||
75 | 1066 | public Jelly() { |
76 | 1066 | } |
77 | ||
78 | /** |
|
79 | * Usage: jelly [scriptFile] [-script scriptFile -o outputFile -Dsysprop=syspropval] |
|
80 | */ |
|
81 | public static void main(String[] args) throws Exception { |
|
82 | ||
83 | try { |
|
84 | 0 | if (args.length <= 0) { |
85 | 0 | System.out.println("Usage: jelly [scriptFile] [-script scriptFile -o outputFile -Dsysprop=syspropval]"); |
86 | 0 | return; |
87 | } |
|
88 | ||
89 | // parse the command line options using CLI |
|
90 | // using a separate class to avoid unnecessary |
|
91 | // dependencies |
|
92 | 0 | CommandLineParser.getInstance().invokeCommandLineJelly(args); |
93 | } |
|
94 | 0 | catch (JellyException e) { |
95 | 0 | Throwable cause = e.getCause(); |
96 | ||
97 | 0 | if (cause == null) { |
98 | 0 | e.printStackTrace(); |
99 | 0 | } else { |
100 | 0 | cause.printStackTrace(); |
101 | } |
|
102 | 0 | } |
103 | 0 | } |
104 | ||
105 | ||
106 | public static String getJellyVersion() { |
|
107 | 0 | return readBuildTimestampResource("jelly-version.txt"); |
108 | } |
|
109 | ||
110 | public static String getJellyBuildDate() { |
|
111 | 0 | return readBuildTimestampResource("jelly-build-date.txt"); |
112 | } |
|
113 | ||
114 | private static String readBuildTimestampResource(String name) { |
|
115 | 0 | java.io.Reader in = null; |
116 | try { |
|
117 | 0 | java.io.StringWriter w = new java.io.StringWriter(); |
118 | 0 | in = new java.io.InputStreamReader(Jelly.class.getResourceAsStream(name),"utf-8"); |
119 | int r; |
|
120 | 0 | while ( (r=in.read()) >= 0 ) { |
121 | 0 | w.write((char) r); |
122 | 0 | } |
123 | 0 | return w.toString(); |
124 | 0 | } catch(Exception ex) { |
125 | 0 | ex.printStackTrace(); |
126 | 0 | try { in.close(); } catch(Exception e) {} |
127 | 0 | throw new IllegalStateException("Resource \"" + name + "\" not found."); |
128 | } |
|
129 | } |
|
130 | ||
131 | ||
132 | ||
133 | /** |
|
134 | * Compiles the script |
|
135 | */ |
|
136 | public Script compileScript() throws JellyException { |
|
137 | 845 | if (! loadedProperties) { |
138 | 819 | loadedProperties = true; |
139 | 819 | loadJellyProperties(); |
140 | } |
|
141 | ||
142 | 845 | XMLParser parser = new XMLParser(); |
143 | try { |
|
144 | 845 | parser.setContext(getJellyContext()); |
145 | 0 | } catch (MalformedURLException e) { |
146 | 0 | throw new JellyException(e.toString()); |
147 | 845 | } |
148 | ||
149 | 845 | Script script = null; |
150 | try { |
|
151 | 845 | parser.setDefaultNamespaceURI(this.defaultNamespaceURI); |
152 | 845 | parser.setValidating(this.validateXML); |
153 | 845 | script = parser.parse(getUrl()); |
154 | 806 | script = script.compile(); |
155 | 806 | if (log.isDebugEnabled()) { |
156 | 0 | log.debug("Compiled script: " + getUrl()); |
157 | } |
|
158 | 0 | } catch (IOException e) { |
159 | 0 | throw new JellyException("could not parse Jelly script",e); |
160 | 39 | } catch (SAXException e) { |
161 | 39 | throw new JellyException("could not parse Jelly script",e); |
162 | 806 | } |
163 | ||
164 | 806 | return script; |
165 | } |
|
166 | ||
167 | ||
168 | // Properties |
|
169 | //------------------------------------------------------------------------- |
|
170 | ||
171 | /** |
|
172 | * Sets the script URL to use as an absolute URL or a relative filename |
|
173 | */ |
|
174 | public void setScript(String script) throws MalformedURLException { |
|
175 | 13 | setUrl(resolveURL(script)); |
176 | 13 | } |
177 | ||
178 | public URL getUrl() { |
|
179 | 1664 | return url; |
180 | } |
|
181 | ||
182 | /** |
|
183 | * Sets the script URL to use |
|
184 | */ |
|
185 | public void setUrl(URL url) { |
|
186 | 819 | this.url = url; |
187 | 819 | } |
188 | ||
189 | /** |
|
190 | * Gets the root context |
|
191 | */ |
|
192 | public URL getRootContext() throws MalformedURLException { |
|
193 | 819 | if (rootContext == null) { |
194 | 819 | rootContext = new File(System.getProperty("user.dir")).toURL(); |
195 | } |
|
196 | 819 | return rootContext; |
197 | } |
|
198 | ||
199 | /** |
|
200 | * Sets the root context |
|
201 | */ |
|
202 | public void setRootContext(URL rootContext) { |
|
203 | 0 | this.rootContext = rootContext; |
204 | 0 | } |
205 | ||
206 | /** |
|
207 | * The context to use |
|
208 | */ |
|
209 | public JellyContext getJellyContext() throws MalformedURLException { |
|
210 | 845 | if (context == null) { |
211 | // take off the name off the URL |
|
212 | 819 | String text = getUrl().toString(); |
213 | 819 | int idx = text.lastIndexOf('/'); |
214 | 819 | text = text.substring(0, idx + 1); |
215 | 819 | context = new JellyContext(getRootContext(), class="keyword">new URL(text)); |
216 | } |
|
217 | 845 | return context; |
218 | } |
|
219 | ||
220 | ||
221 | /** |
|
222 | * Set the jelly namespace to use for unprefixed elements. |
|
223 | * Will be overridden by an explicit namespace in the |
|
224 | * XML document. |
|
225 | * |
|
226 | * @param namespace jelly namespace to use (e.g. 'jelly:core') |
|
227 | */ |
|
228 | public void setDefaultNamespaceURI(String namespace) { |
|
229 | 26 | this.defaultNamespaceURI = namespace; |
230 | 26 | } |
231 | ||
232 | /** |
|
233 | * When set to true, the XML parser will attempt to validate |
|
234 | * the Jelly XML before converting it into a Script. |
|
235 | * |
|
236 | * @param validate whether or not to validate |
|
237 | */ |
|
238 | public void setValidateXML(boolean validate) { |
|
239 | 65 | this.validateXML = validate; |
240 | 65 | } |
241 | ||
242 | // Implementation methods |
|
243 | //------------------------------------------------------------------------- |
|
244 | /** |
|
245 | * @return the URL for the relative file name or absolute URL |
|
246 | */ |
|
247 | protected URL resolveURL(String name) throws MalformedURLException { |
|
248 | ||
249 | 13 | URL resourceUrl = ClassLoaderUtils.getClassLoader(getClass()).getResource(name); |
250 | 13 | if (resourceUrl == null) |
251 | { |
|
252 | 13 | File file = new File(name); |
253 | 13 | if (file.exists()) { |
254 | 0 | return file.toURL(); |
255 | } |
|
256 | 13 | return new URL(name); |
257 | } else { |
|
258 | 0 | return resourceUrl; |
259 | } |
|
260 | } |
|
261 | ||
262 | /** |
|
263 | * Attempts to load jelly.properties from the current directory, |
|
264 | * the users home directory or from the classpath |
|
265 | */ |
|
266 | protected void loadJellyProperties() { |
|
267 | 819 | InputStream is = null; |
268 | ||
269 | 819 | String userDir = System.getProperty("user.home"); |
270 | 819 | File f = new File(userDir + File.separator + "jelly.properties"); |
271 | 819 | loadProperties(f); |
272 | ||
273 | 819 | f = new File("jelly.properties"); |
274 | 819 | loadProperties(f); |
275 | ||
276 | ||
277 | 819 | is = ClassLoaderUtils.getClassLoader(getClass()).getResourceAsStream("jelly.properties"); |
278 | 819 | if (is != null) { |
279 | try { |
|
280 | 0 | loadProperties(is); |
281 | } |
|
282 | 0 | catch (Exception e) { |
283 | 0 | log.error( "Caught exception while loading jelly.properties from the classpath. Reason: " + e, e ); |
284 | 0 | } |
285 | } |
|
286 | 819 | } |
287 | ||
288 | /** |
|
289 | * Load properties from a file into the context |
|
290 | * @param f |
|
291 | */ |
|
292 | private void loadProperties(File f) { |
|
293 | 1638 | InputStream is = null; |
294 | try { |
|
295 | 1638 | if (f.exists()) { |
296 | 0 | is = new FileInputStream(f); |
297 | 0 | loadProperties(is); |
298 | } |
|
299 | 0 | } catch (Exception e) { |
300 | 0 | log.error( "Caught exception while loading: " + f.getName() + ". Reason: " + e, e ); |
301 | } finally { |
|
302 | 1638 | if (is != null) { |
303 | try { |
|
304 | 0 | is.close(); |
305 | 0 | } catch (IOException e) { |
306 | 0 | if (log.isDebugEnabled()) log.debug("error closing property input stream", e); |
307 | 0 | } |
308 | 0 | } |
309 | 0 | } |
310 | 1638 | } |
311 | ||
312 | /** |
|
313 | * Loads the properties from the given input stream |
|
314 | */ |
|
315 | protected void loadProperties(InputStream is) throws IOException { |
|
316 | 0 | JellyContext theContext = getJellyContext(); |
317 | 0 | Properties props = new Properties(); |
318 | 0 | props.load(is); |
319 | 0 | Enumeration propsEnum = props.propertyNames(); |
320 | 0 | while (propsEnum.hasMoreElements()) { |
321 | 0 | String key = (String) propsEnum.nextElement(); |
322 | 0 | String value = props.getProperty(key); |
323 | ||
324 | // @todo we should parse the value in case its an Expression |
|
325 | 0 | theContext.setVariable(key, value); |
326 | 0 | } |
327 | 0 | } |
328 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |