Sorry for the lack of context / explanation; I was getting a little punchy when I sent this out last night...
First, the Forehead.java mod is included here as a diff -u file, to make
it easier to see the modification.
Second, I am re-sending the *source code* (this time, sorry about
that... *sigh*) for the new tags I wrote.
Third, I was thinking that the entry point taglib would help separate a
goal-driven workflow from a script that's more like a shell script, with
simple functions that allow the reuse of sections of a script and
dynamic entry points...for instance, with Ant you can call any target
from the command line. However, the closest thing Jelly seems to have
to equate to this is the goals taglib, which seems semantically
different, and (although I'm largely ignorant of it) seems not to have a
way of entering at an arbitrary goal from command line...this means that
I cannot write a jelly script that has multiple functionality, like
build, jar, clean, etc. -- these would have to be separated into
different scripts, right? I do not intend to step on any toes with this
submission, and if any of my assumptions or conceptions are wrong please
let me know. It just seemed like a potential stumbling block akin to
some of the things I saw on the Ant list last summer...
Finally, the start scripts I mailed out last night were to make Jelly
more usable as a standalone tool...to give it a user-friendly entry
script like Ant has.
I may not be the typical user of Jelly, but I see incredible potential
for Jelly to be able to describe the set of tasks used to deploy our
software in a *very* complex environment, where Ant really wasn't
designed to adapt to.
Sorry for the confusion.
John
On Wed, 2002-07-10 at 00:38, John Casey wrote:
> This is kind of a bulk post, but see what you think...I've done quite a
> bit that I'm reporting here, so please be patient.
>
> 1. Forehead - since there doesn't appear to be a mailing list for this,
> I'm submitting my mod here...I've modified the Forehead class to watch
> out for directories specified in the forehead.conf but not in
> existence. It should ignore these.
>
> 2. I've modified the start scripts for Jelly that I originally
> submitted, and made them use the attached forehead.properties file to
> start. The current version depends on forehead.jar being in
> $JELLY_HOME/lib...I know this is wrong, I'm just not sure what the best
> fix is yet.
>
> 3. I've created a couple of small tag libraries.
>
> The first is called interact. It allows the script to prompt the
> user for input, and stores the results in the JellyContext for later
> use. Initially, values collected are merely stored as Strings.
>
> The second is called entrypoint, and is used to approximate the
> type of process flow seen in Ant. In short, it allows the author to
> define a set of entry points that are either public (default) or not -
> these are like Ant targets. Correspondingly, I've created a tag to
> control the execution of these entry points and their dependencies
> through command line arguments. If an entry point is specified on the
> command line, but is not public, an error is thrown and the entry point
> is skipped. This should help clear up any semantic confusion
> surrounding the usage of goals,etc. that I've read about
> recently...IMHO.
>
> I realize that my tags aren't using the Resource class for
> locale-specific messages yet, but I thought it wise to wait for a
> go-ahead to integrate with the actual project.
>
> Anyway, enjoy, and please give me mucho feedback for making these better
> / scrapping them / etc.
>
> Regards,
> John
>
>
>
>
> ----
>
>
> package com.werken.forehead;
>
> /*
> $Id: Forehead.java,v 1.2 2002/07/04 21:45:30 werken Exp $
>
> Copyright 2001 (C) The Werken Company. All Rights Reserved.
>
> Redistribution and use of this software and associated documentation
> ("Software"), with or without modification, are permitted provided
> that the following conditions are met:
>
> 1. Redistributions of source code must retain copyright
> statements and notices. Redistributions must also contain a
> copy of this document.
>
> 2. Redistributions in binary form must reproduce the
> above copyright notice, this list of conditions and the
> following disclaimer in the documentation and/or other
> materials provided with the distribution.
>
> 3. The name "Forehead" must not be used to endorse or promote
> products derived from this Software without prior written
> permission of The Werken Company. For written permission,
> please contact [EMAIL PROTECTED]
>
> 4. Products derived from this Software may not be called "Forehead"
> nor may "Forehead" appear in their names without prior written
> permission of The Werken Company. Forehead is a registered
> trademark of The Werken Company.
>
> 5. Due credit should be given to the Forehead Project
> (http://drools.org/).
>
> THIS SOFTWARE IS PROVIDED BY THE WERKEN COMPANY AND CONTRIBUTORS
> ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
> NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
> FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
> THE WERKEN COMPANY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
> INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
> SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
> STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
> OF THE POSSIBILITY OF SUCH DAMAGE.
>
> */
>
> import java.io.File;
> import java.io.FilenameFilter;
> import java.io.FileInputStream;
> import java.io.InputStream;
> import java.io.InputStreamReader;
> import java.io.BufferedReader;
> import java.io.Reader;
> import java.io.IOException;
> import java.lang.reflect.Method;
> import java.lang.reflect.Modifier;
> import java.lang.reflect.InvocationTargetException;
> import java.net.URL;
> import java.net.MalformedURLException;
> import java.util.HashMap;
> import java.util.Map;
> import java.util.Properties;
>
> /** ClassLoader configurator and application launcher.
> *
> * <p>
> * This is the main command-line entry-point into the
> * <code>forehead</code> framework. Please see
> * the <code>forehead</code> documentation for usage
> * instructions.
> * </p>
> *
> * @author <a href="mailto:[EMAIL PROTECTED]">bob mcwhirter</a>
> */
> public class Forehead
> {
> // ------------------------------------------------------------
> // Class members
> // ------------------------------------------------------------
>
> /** Singleton. */
> private static final Forehead INSTANCE = new Forehead();
>
> // ------------------------------------------------------------
> // Instance members
> // ------------------------------------------------------------
>
> /** ClassLoaders indexed by name. */
> private Map classLoaders;
>
> /** Root unnamed loader. */
> private ForeheadClassLoader rootLoader;
>
> /** The loader to use for entry-point lookup. */
> private ForeheadClassLoader entryLoader;
>
> /** The entry-point class. */
> private Class entryClass;
>
> /** The entry-point method. */
> private Method entryMethod;
>
> // ------------------------------------------------------------
> // Constructors
> // ------------------------------------------------------------
>
> /** Construct.
> */
> public Forehead()
> {
> this.classLoaders = new HashMap();
> }
>
> // ------------------------------------------------------------
> // Instance methods
> // ------------------------------------------------------------
>
> /** Configure from an <code>InputStream</code>.
> *
> * @param in <code>InputStream</code> carrying configuration information.
> *
> * @throws ForeheadException If there is an error during configuration.
> * @throws IOException If there is an error reading configuration information.
> * @throws ClassNotFoundException If unable to locate entry-point class.
> */
> public void config(InputStream in) throws ForeheadException, IOException,
>ClassNotFoundException
> {
> config( new BufferedReader( new InputStreamReader( in ) ) );
> }
>
> /** Configure from an <code>Reader</code>.
> *
> * @param in <code>Reader</code> carrying configuration information.
> *
> * @throws ForeheadException If there is an error during configuration.
> * @throws IOException If there is an error reading configuration information.
> * @throws ClassNotFoundException If unable to locate entry-point class.
> */
> public void config(Reader in) throws ForeheadException, IOException,
>ClassNotFoundException
> {
> if ( in instanceof BufferedReader )
> {
> config( in );
> }
> else
> {
> config( new BufferedReader( in ) );
> }
> }
>
> /** Configure from an <code>BufferedReader</code>.
> *
> * @param in <code>BufferedReader</code> carrying configuration information.
> *
> * @throws ForeheadException If there is an error during configuration.
> * @throws IOException If there is an error reading configuration information.
> * @throws ClassNotFoundException If unable to locate entry-point class.
> */
> public void config(BufferedReader in) throws ForeheadException, IOException,
>ClassNotFoundException
> {
> this.rootLoader = new ForeheadClassLoader( getClass().getClassLoader(),
> "$forehead-root$");
>
> String line = null;
>
> ForeheadClassLoader currentLoader = this.rootLoader;
>
> Properties props = new Properties();
>
> String entryLine = null;
>
> while ( ( line = in.readLine() ) != null )
> {
> line = line.trim();
>
> if ( "".equals( line ) )
> {
> continue;
> }
>
> if ( line.startsWith( "#" ) )
> {
> continue;
> }
>
> if ( line.startsWith( "+" ) )
> {
> String propName = line.substring( 1 );
> String propValue = System.getProperty( propName );
>
> if ( propValue == null )
> {
> throw new NoSuchPropertyException( propName );
> }
>
> props.setProperty( propName,
> propValue );
>
> continue;
> }
>
> if ( line.startsWith( "=" ) )
> {
> entryLine = line;
> continue;
> }
>
> ForeheadClassLoader parentLoader = null;
>
> if ( line.startsWith( "[" )
> &&
> line.endsWith( "]" ) )
> {
> String loaderName = line.substring( 1,
> line.length() - 1 );
>
> int dotLoc = loaderName.lastIndexOf( "." );
>
> if ( dotLoc > 0 )
> {
> String parentName = loaderName.substring( 0,
> dotLoc );
>
> parentLoader = getClassLoader( parentName );
>
> if ( parentLoader == null )
> {
> throw new NoSuchClassLoaderException( parentName );
> }
> }
> else
> {
> parentLoader = this.rootLoader;
> }
>
> currentLoader = createClassLoader( parentLoader, loaderName );
> }
> else
> {
> String resolvedLine = resolveProperties( line, props );
>
> load( resolvedLine,
> currentLoader );
> }
> }
>
>
> if ( entryLine == null )
> {
> throw new NoEntryDescriptorException();
> }
>
> setupEntry( entryLine );
> }
>
> /** Setup the entry-point.
> *
> * @param line The entry-point configuration line.
> *
> * @throws MalformedEntryDescriptorException If the entry-point descriptor is
>malformed.
> * @throws NoSuchClassLoaderException If the entry-point descriptor references
> * an unknown ClassLoader.
> * @throws ClassNotFoundException If unable to locate the entry-point class.
> */
> protected void setupEntry(String line)
> throws MalformedEntryDescriptorException, NoSuchClassLoaderException,
>ClassNotFoundException
> {
> int leftBrackLoc = line.indexOf( "[" );
>
> if ( leftBrackLoc < 0 )
> {
> throw new MalformedEntryDescriptorException( line );
> }
>
> int rightBrackLoc = line.indexOf( "]",
> leftBrackLoc + 1 );
>
> if ( rightBrackLoc < 0 )
> {
> throw new MalformedEntryDescriptorException( line );
> }
>
> String loaderName = line.substring( leftBrackLoc + 1,
> rightBrackLoc );
>
> String className = line.substring( rightBrackLoc + 1 ).trim();
>
> this.entryLoader = getClassLoader( loaderName );
>
> if ( this.entryLoader == null )
> {
> throw new NoSuchClassLoaderException( loaderName );
> }
>
> this.entryClass = Class.forName( className,
> true,
> this.entryLoader );
>
> }
>
> /** Load a glob, file, or URL into the specified classloader.
> *
> * @param line The path configuration line.
> * @param loader The loader to populate
> *
> * @throws MalformedURLException If the line does not represent
> * a valid path element.
> */
> protected void load(String line,
> ForeheadClassLoader loader) throws MalformedURLException
> {
> if ( line.indexOf( "*" ) >= 0 )
> {
> loadGlob( line,
> loader );
> }
> else
> {
> loadFileOrUrl( line,
> loader );
> }
> }
>
> /** Load a glob into the specified classloader.
> *
> * @param line The path configuration line.
> * @param loader The loader to populate
> *
> * @throws MalformedURLException If the line does not represent
> * a valid path element.
> */
> protected void loadGlob(String line,
> ForeheadClassLoader loader) throws MalformedURLException
> {
> File globFile = new File( line );
>
> File dir = globFile.getParentFile();
>
> String localName = globFile.getName();
>
> int starLoc = localName.indexOf( "*" );
>
> final String prefix = localName.substring( 0,
> starLoc );
>
> final String suffix = localName.substring( starLoc + 1 );
>
> if(dir.exists()){
> File[] matches = dir.listFiles(
> new FilenameFilter() {
> public boolean accept(File dir, String name)
> {
> if ( prefix != null
> &&
> !name.startsWith( prefix ) )
> {
> return false;
> }
>
> if ( suffix != null
> &&
> !name.endsWith( suffix ) )
> {
> return false;
> }
>
> return true;
> }
> }
> );
>
> for ( int i = 0 ; i < matches.length ; ++i )
> {
> loader.addURL( matches[i].toURL() );
> }
> }
> }
>
> /** Load a file or URL into the specified classloader.
> *
> * @param line The path configuration line.
> * @param loader The loader to populate
> *
> * @throws MalformedURLException If the line does not represent
> * a valid path element.
> */
> protected void loadFileOrUrl(String line,
> ForeheadClassLoader loader) throws
>MalformedURLException
> {
> URL url = null;
>
> File file = new File( line );
>
> if ( file.exists() )
> {
> url = file.toURL();
> }
> else
> {
> url = new URL( line );
> }
>
> loader.addURL( url );
> }
>
> /** Create a new ClassLoader given a parent and a name.
> *
> * @param parent The parent of the ClassLoader to create.
> * @param name The name of the ClassLoader to create.
> *
> * @return A newly configured <code>ClassLoader</code>.
> */
> protected ForeheadClassLoader createClassLoader(ForeheadClassLoader parent,
> String name)
> {
> ForeheadClassLoader loader = new ForeheadClassLoader( parent,
> name );
>
> this.classLoaders.put( name,
> loader );
>
> return loader;
> }
>
> /** Retrieve a ClassLoader by name.
> *
> * @param name The name of the ClassLoader to retrieve.
> *
> * @return The associated ClassLoader, or <code>null</code>
> * if none.
> */
> public ForeheadClassLoader getClassLoader(String name)
> {
> return (ForeheadClassLoader) this.classLoaders.get( name );
> }
>
> /** Resolve imported properties.
> *
> * @param input The string input to resolve properties.
> * @param props Properties to resolve against.
> *
> * @return The string with properties resolved.
> */
> public String resolveProperties(String input,
> Properties props)
> {
> String output = "";
>
> int cur = 0;
>
> int prefixLoc = 0;
> int suffixLoc = 0;
>
> while ( cur < input.length() )
> {
> prefixLoc = input.indexOf( "${",
> cur );
>
> if ( prefixLoc < 0 )
> {
> //output = output + input.substring( cur );
> break;
> }
>
> suffixLoc = input.indexOf( "}",
> prefixLoc );
>
> String propName = input.substring( prefixLoc + 2,
> suffixLoc );
>
> output = output + input.substring( cur, prefixLoc );
>
> output = output + props.getProperty( propName );
>
> cur = suffixLoc + 1;
> }
>
> output = output + input.substring( cur );
>
> return output;
> }
>
> /** Launch the wrapped application.
> *
> * @param args Command-line args to pass to wrapped application.
> *
> * @throws NoSuchEntryMethodException If unable to find the entry method on the
>class.
> * @throws IllegalAccessException If an error occurs while attempting to invoke
>the
> * entry-point method.
> * @throws InvocationTargetException If an error occurs while attempting to
>invoke the
> * entry-point method.
> */
> public void run(String[] args) throws NoSuchEntryMethodException,
>IllegalAccessException, InvocationTargetException
> {
> Method[] methods = this.entryClass.getMethods();
>
> for ( int i = 0 ; i < methods.length ; ++i )
> {
> if ( !"main".equals( methods[i].getName() ) )
> {
> continue;
> }
>
> int modifiers = methods[i].getModifiers();
>
> if ( !( Modifier.isStatic( modifiers )
> &&
> Modifier.isPublic( modifiers ) ) )
> {
> continue;
> }
>
> if ( methods[i].getReturnType() != Void.TYPE )
> {
> continue;
> }
>
> Class[] paramTypes = methods[i].getParameterTypes();
>
> if ( paramTypes.length != 1 )
> {
> continue;
> }
>
> if ( paramTypes[0] != String[].class )
> {
> continue;
> }
>
> this.entryMethod = methods[i];
> break;
> }
>
> if ( this.entryMethod == null )
> {
> throw new NoSuchEntryMethodException( this.entryClass,
> "public static void main(String[]
>args)" );
> }
>
> Thread.currentThread().setContextClassLoader( this.entryLoader );
>
> this.entryMethod.invoke( this.entryClass,
> new Object[] { args } );
> }
>
> // ------------------------------------------------------------
> // Class methods
> // ------------------------------------------------------------
>
> public static Forehead getInstance()
> {
> return INSTANCE;
> }
>
> /** Main.
> *
> * @param args Command-line arguments to pass to the wrapped
> * application.
> */
> public static void main(String[] args)
> {
> String confFileName = System.getProperty( "forehead.conf.file" );
>
> File confFile = new File( confFileName );
>
> Forehead forehead = Forehead.getInstance();
>
> try
> {
> forehead.config( new FileInputStream( confFile ) );
>
> forehead.run( args );
> }
> catch (NoSuchEntryMethodException e)
> {
> System.err.println( "No method on class " + e.getEntryClass() + "
>matching: " + e.getEntryMethodDescriptor() );
> e.printStackTrace();
> }
> catch (ForeheadException e)
> {
> System.err.println( "Error during configuration: " +
>e.getLocalizedMessage() );
> e.printStackTrace();
> }
> catch (MalformedURLException e)
> {
> e.printStackTrace();
> }
> catch (IOException e)
> {
> System.err.println( "Error reading configuration: " +
>e.getLocalizedMessage() );
> e.printStackTrace();
> }
> catch (ClassNotFoundException e)
> {
> System.err.println( e.getLocalizedMessage() );
> e.printStackTrace();
> }
> catch (Exception e)
> {
> e.printStackTrace();
> }
> }
> }
> ----
>
>
> +ant.home
> +jelly.home
> +tools.jar
>
> =[root.jelly] org.apache.commons.jelly.Jelly
>
> [root]
>
> [root.jelly]
> ${ant.home}/lib/*.jar
> ${jelly.home}/lib/*.jar
> ${jelly.home}/custom/*.jar
> ${jelly.home}/custom
>
> ----
>
> #!/bin/sh
>
> $JAVA_HOME/bin/java -classpath ${CLASSPATH}:${JELLY_HOME}/lib/forehead.jar \
> -Dforehead.conf.file=${JELLY_HOME}/bin/forehead.conf \
> -Dant.home=${ANT_HOME} -Djelly.home=${JELLY_HOME} \
> -Dtools.jar=${JAVA_HOME}/lib/tools.jar com.werken.forehead.Forehead $*
>
> ----
>
> @echo off
>
> %JAVA_HOME%\bin\java -classpath %CLASSPATH%;%JELLY_HOME\lib\forehead.jar
>-Dforehead.conf.file=%JELLY_HOME%\bin\forehead.conf -Dant.home=%ANT_HOME%
>-Djelly.home=%JELLY_HOME% -Dtools.jar=%JAVA_HOME\lib\tools.jar
>com.werken.forehead.Forehead %@
--- Forehead.java.old Wed Jul 10 09:15:49 2002
+++ Forehead.java Sun Jul 7 23:50:51 2002
@@ -348,6 +348,7 @@
final String suffix = localName.substring( starLoc + 1 );
+ if(dir.exists()){
File[] matches = dir.listFiles(
new FilenameFilter() {
public boolean accept(File dir, String name)
@@ -358,14 +359,14 @@
{
return false;
}
-
+
if ( suffix != null
&&
!name.endsWith( suffix ) )
{
return false;
}
-
+
return true;
}
}
@@ -375,6 +376,7 @@
{
loader.addURL( matches[i].toURL() );
}
+ }
}
/** Load a file or URL into the specified classloader.
+ant.home
+jelly.home
+tools.jar
=[root.jelly] org.apache.commons.jelly.Jelly
[root]
[root.jelly]
${ant.home}/lib/*.jar
${jelly.home}/lib/*.jar
${jelly.home}/custom/*.jar
${jelly.home}/custom
#!/bin/sh
$JAVA_HOME/bin/java -classpath ${CLASSPATH}:${JELLY_HOME}/lib/forehead.jar \
-Dforehead.conf.file=${JELLY_HOME}/bin/forehead.conf \
-Dant.home=${ANT_HOME} -Djelly.home=${JELLY_HOME} \
-Dtools.jar=${JAVA_HOME}/lib/tools.jar com.werken.forehead.Forehead $*
@echo off %JAVA_HOME%\bin\java -classpath %CLASSPATH%;%JELLY_HOME\lib\forehead.jar -Dforehead.conf.file=%JELLY_HOME%\bin\forehead.conf -Dant.home=%ANT_HOME% -Djelly.home=%JELLY_HOME% -Dtools.jar=%JAVA_HOME\lib\tools.jar com.werken.forehead.Forehead %@
jelly-custom-tags.jar
Description: Binary data
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
