Java tutorial
/* * Copyright 2002,2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.jelly; import java.io.File; import java.io.InputStream; import java.io.FileInputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.Enumeration; import java.util.Properties; import org.apache.commons.jelly.parser.XMLParser; import org.apache.commons.jelly.util.ClassLoaderUtils; import org.apache.commons.jelly.util.CommandLineParser; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.xml.sax.SAXException; /** * <p><code>Jelly</code> is a helper class which is capable of * running a Jelly script. This class can be used from the command line * or can be used as the basis of an Ant task.</p> Command line usage is as follows: * * <pre> * jelly [scriptFile] [-script scriptFile -o outputFile -Dsysprop=syspropval] * </pre> * * @author <a href="mailto:jstrachan@apache.org">James Strachan</a> * @version $Revision: 1.35 $ */ public class Jelly { /** The Log to which logging calls will be made. */ private static final Log log = LogFactory.getLog(Jelly.class); /** The JellyContext to use */ private JellyContext context; /** The URL of the script to execute */ private URL url; /** The URL of the root context for other scripts */ private URL rootContext; /** Whether we have loaded the properties yet */ private boolean loadedProperties = false; /** * whether to override the default namespace */ private String defaultNamespaceURI = null; /** * whether or not to validate the Jelly script */ private boolean validateXML = false; public Jelly() { } /** * Usage: jelly [scriptFile] [-script scriptFile -o outputFile -Dsysprop=syspropval] */ public static void main(String[] args) throws Exception { try { if (args.length <= 0) { System.out.println( "Usage: jelly [scriptFile] [-script scriptFile -o outputFile -Dsysprop=syspropval]"); return; } // parse the command line options using CLI // using a separate class to avoid unnecessary // dependencies CommandLineParser.getInstance().invokeCommandLineJelly(args); } catch (JellyException e) { Throwable cause = e.getCause(); if (cause == null) { e.printStackTrace(); } else { cause.printStackTrace(); } } } public static String getJellyVersion() { return readBuildTimestampResource("jelly-version.txt"); } public static String getJellyBuildDate() { return readBuildTimestampResource("jelly-build-date.txt"); } private static String readBuildTimestampResource(String name) { java.io.Reader in = null; try { java.io.StringWriter w = new java.io.StringWriter(); in = new java.io.InputStreamReader(Jelly.class.getResourceAsStream(name), "utf-8"); int r; while ((r = in.read()) >= 0) { w.write((char) r); } return w.toString(); } catch (Exception ex) { ex.printStackTrace(); try { in.close(); } catch (Exception e) { } throw new IllegalStateException("Resource \"" + name + "\" not found."); } } /** * Compiles the script */ public Script compileScript() throws JellyException { if (!loadedProperties) { loadedProperties = true; loadJellyProperties(); } XMLParser parser = new XMLParser(); try { parser.setContext(getJellyContext()); } catch (MalformedURLException e) { throw new JellyException(e.toString()); } Script script = null; try { parser.setDefaultNamespaceURI(this.defaultNamespaceURI); parser.setValidating(this.validateXML); script = parser.parse(getUrl()); script = script.compile(); if (log.isDebugEnabled()) { log.debug("Compiled script: " + getUrl()); } } catch (IOException e) { throw new JellyException("could not parse Jelly script", e); } catch (SAXException e) { throw new JellyException("could not parse Jelly script", e); } return script; } // Properties //------------------------------------------------------------------------- /** * Sets the script URL to use as an absolute URL or a relative filename */ public void setScript(String script) throws MalformedURLException { setUrl(resolveURL(script)); } public URL getUrl() { return url; } /** * Sets the script URL to use */ public void setUrl(URL url) { this.url = url; } /** * Gets the root context */ public URL getRootContext() throws MalformedURLException { if (rootContext == null) { rootContext = new File(System.getProperty("user.dir")).toURL(); } return rootContext; } /** * Sets the root context */ public void setRootContext(URL rootContext) { this.rootContext = rootContext; } /** * The context to use */ public JellyContext getJellyContext() throws MalformedURLException { if (context == null) { // take off the name off the URL String text = getUrl().toString(); int idx = text.lastIndexOf('/'); text = text.substring(0, idx + 1); context = new JellyContext(getRootContext(), new URL(text)); } return context; } /** * Set the jelly namespace to use for unprefixed elements. * Will be overridden by an explicit namespace in the * XML document. * * @param namespace jelly namespace to use (e.g. 'jelly:core') */ public void setDefaultNamespaceURI(String namespace) { this.defaultNamespaceURI = namespace; } /** * When set to true, the XML parser will attempt to validate * the Jelly XML before converting it into a Script. * * @param validate whether or not to validate */ public void setValidateXML(boolean validate) { this.validateXML = validate; } // Implementation methods //------------------------------------------------------------------------- /** * @return the URL for the relative file name or absolute URL */ protected URL resolveURL(String name) throws MalformedURLException { URL resourceUrl = ClassLoaderUtils.getClassLoader(getClass()).getResource(name); if (resourceUrl == null) { File file = new File(name); if (file.exists()) { return file.toURL(); } return new URL(name); } else { return resourceUrl; } } /** * Attempts to load jelly.properties from the current directory, * the users home directory or from the classpath */ protected void loadJellyProperties() { InputStream is = null; String userDir = System.getProperty("user.home"); File f = new File(userDir + File.separator + "jelly.properties"); loadProperties(f); f = new File("jelly.properties"); loadProperties(f); is = ClassLoaderUtils.getClassLoader(getClass()).getResourceAsStream("jelly.properties"); if (is != null) { try { loadProperties(is); } catch (Exception e) { log.error("Caught exception while loading jelly.properties from the classpath. Reason: " + e, e); } } } /** * Load properties from a file into the context * @param f */ private void loadProperties(File f) { InputStream is = null; try { if (f.exists()) { is = new FileInputStream(f); loadProperties(is); } } catch (Exception e) { log.error("Caught exception while loading: " + f.getName() + ". Reason: " + e, e); } finally { if (is != null) { try { is.close(); } catch (IOException e) { if (log.isDebugEnabled()) log.debug("error closing property input stream", e); } } } } /** * Loads the properties from the given input stream */ protected void loadProperties(InputStream is) throws IOException { JellyContext theContext = getJellyContext(); Properties props = new Properties(); props.load(is); Enumeration propsEnum = props.propertyNames(); while (propsEnum.hasMoreElements()) { String key = (String) propsEnum.nextElement(); String value = props.getProperty(key); // @todo we should parse the value in case its an Expression theContext.setVariable(key, value); } } }