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
jelly-custom-tags.jar
Description: Binary data
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 %@
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
