donaldp 01/04/03 16:35:24 Added: proposal/4.0/src/java/org/apache/avalon/aut Enum.java StringUtil.java ValuedEnum.java Version.java proposal/4.0/src/java/org/apache/avalon/aut/collections ArrayEnumeration.java ArrayStack.java IteratorEnumeration.java ListUtils.java proposal/4.0/src/java/org/apache/avalon/aut/i18n ResourceGroup.java XMLResourceBundle.java XMLResourceBundleFactory.java XPathAPI.java proposal/4.0/src/java/org/apache/avalon/aut/io DirectoryFileFilter.java ExtensionFileFilter.java FileUtil.java IOUtil.java proposal/4.0/src/java/org/apache/avalon/aut/log AvalonLogFormatter.java proposal/4.0/src/java/org/apache/avalon/aut/security AbstractPolicy.java PolicyClassLoader.java proposal/4.0/src/java/org/apache/avalon/cli AbstractParserControl.java CLArgsParser.java CLOption.java CLOptionDescriptor.java CLUtil.java ParserControl.java Removed: proposal/4.0/src/java/org/apache/aut Enum.java StringUtil.java ValuedEnum.java Version.java proposal/4.0/src/java/org/apache/aut/cli AbstractParserControl.java CLArgsParser.java CLOption.java CLOptionDescriptor.java CLUtil.java ParserControl.java proposal/4.0/src/java/org/apache/aut/collections ArrayEnumeration.java ArrayStack.java IteratorEnumeration.java ListUtils.java proposal/4.0/src/java/org/apache/aut/i18n ResourceGroup.java XMLResourceBundle.java XMLResourceBundleFactory.java XPathAPI.java proposal/4.0/src/java/org/apache/aut/io DirectoryFileFilter.java ExtensionFileFilter.java FileUtil.java IOUtil.java proposal/4.0/src/java/org/apache/aut/security AbstractPolicy.java PolicyClassLoader.java proposal/4.0/src/java/org/apache/log/format AvalonLogFormatter.java Log: Moved org.apache.aut to org.apache.avalon.aut Revision Changes Path 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/Enum.java Index: Enum.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut; import java.util.Map; /** * Basic enum class for type-safe enums. Should be used as an abstract base. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public abstract class Enum { protected final String m_name; public Enum( final String name ) { this( name, null ); } public Enum( final String name, final Map map ) { m_name = name; if( null != map ) { map.put( name, this ); } } public final String getName() { return m_name; } public String toString() { return getClass().getName() + "[" + m_name + "]"; } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/StringUtil.java Index: StringUtil.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut; /** * This class provides basic facilities for manipulating strings. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public final class StringUtil { /** * Private constructor to prevent instantiation. */ private StringUtil() { } /** * Replace substrings of one string with another string and return altered string. * * @param original input string * @param oldString the substring section to replace * @param newString the new substring replacing old substring section * @return converted string */ public static String replaceSubString( final String original, final String oldString, final String newString ) { final StringBuffer sb = new StringBuffer(); int end = original.indexOf( oldString ); int start = 0; final int stringSize = oldString.length(); while( end != -1 ) { sb.append( original.substring( start, end ) ); sb.append( newString ); start = end + stringSize; end = original.indexOf( oldString, start ); } end = original.length(); sb.append( original.substring( start, end ) ); return sb.toString(); } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/ValuedEnum.java Index: ValuedEnum.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut; /** * Basic enum class for type-safe enums with values. Should be used as an abstract base. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public abstract class ValuedEnum extends Enum { protected final int m_value; public ValuedEnum( final String name, final int value ) { super( name ); m_value = value; } public final int getValue() { return m_value; } public final boolean isEqualTo( final ValuedEnum enum ) { return m_value == enum.m_value; } public final boolean isGreaterThan( final ValuedEnum enum ) { return m_value > enum.m_value; } public final boolean isGreaterThanOrEqual( final ValuedEnum enum ) { return m_value >= enum.m_value; } public final boolean isLessThan( final ValuedEnum enum ) { return m_value < enum.m_value; } public final boolean isLessThanOrEqual( final ValuedEnum enum ) { return m_value <= enum.m_value; } public String toString() { return getClass().getName() + "[" + m_name + "=" + m_value + "]"; } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/Version.java Index: Version.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut; /** * This document is NOT RIGHT. * <p /> * * The version number of a <code>Block</code> is made up of three * dot-separated fields: * <p /> * "<b>major.minor.patchlevel</b>" * <p /> * and (optionally) by a fourth field (always <b>"-dev"</b>) * specifying that this version is under development. * <p /> * The <b>major</b>, <b>minor</b> and <b>patchlevel</b> fields are * <i>integer</i> numbers represented in decimal notation and have the * following meaning: * <ul> * <p /><li><b>major</b> - When the major version changes (in ex. from * "1.5.12" to "2.0.0"), then backward compatibility * with previous releases is not granted (this usually happens this * <code>Block</code> is implementing a new major version of an interface * specified in <b>org.apache.avalon.blocks</b> package). * </li><p /> * <p /><li><b>minor</b> - When the minor version changes (in ex. from * "1.5.12" to "1.6.0"), then backward compatibility * with previous releases is granted, but something changed in the * implementation (in ex. new features were added, the configuration * syntax may be different, or the <code>Block</code> is implementing a * new minor version of an interface specified in * <b>org.apache.avalon.blocks</b> package). * </li><p /> * <p /><li><b>patchlevel</b> - When the patchlevel version changes (in ex. * from "1.5.12" to "1.5.13"), then the only changed * things are fixes in the code implementation, but no new features or * changes were made to the behaviour of the code. * </li> * </ul> * <p /> * The fourth field, optional and always "<b>-dev</b>" (in ex. * "1.5.12-dev") specifies that current <code>Block</code> * implementation is under development, and so may contain not-working * code or not all features were implemented. * <p /> * <p /> * <b>NOTE: The absence of the "-dev" tag does not endorse * any warranty of particular stability, safety or compliancy. * The only source for such informations is the (usually provided) license * file accompaining the block itself.</b> * * The class defining versioning pattern. * <p /> * <p /> * Any interface in <b>org.apache.avalon.blocks</b> package <b>MUST</b> provides * a Version instance containing versioning informations on this interface.<p /> * Any BlockInfo returned by a Block implementation <b>MUST</b> provides a * Version instances containing versioning informations on this implementation. * <p /><p /> * Version numbers are:<p /> * "<b>major.minor.revision.dev</b>" * <p /> * The <b>major</b> , <b>minor</b> and <b>revision</b>fields are <i>integer</i> * numbers represented in decimal notation and have the following meaning: * <ul><b> - Refering to an interface</b> * <ul> * <li><b>major</b> - When the major version changes (in ex. from * "1.5" to "2.0"), then backward compatibility with * previous releases is not granted. * </li><p /> * <p /><li><b>minor</b> - When the minor version changes (in ex. from * "1.5" to "1.6"), then backward compatibility * with previous releases is granted, but something changed in the * interface (in ex. new methods were added). * </li><p /> * <li><b>revision</b> - When refering to an interface may represent a change * in documentation or other minor changes. If some methods are modified a minor * version changes is needed.<p /> * - When refering to a Block implementation this represent minor changes in * implementation like bugs fix. * </li><p /> * <li><b>dev</b> - The boolean dev field specify if this Block or interface * is under development and not yet approved by the Java Apache org.apache.avalon.interfaces; * developers group (mailing-list). * </li><p /> * </ul> * </ul> * <ul><b> - Refering to a Block</b> * <ul> * <li><b>major</b> - When the major version changes (in ex. from * "1.5" to "2.0"), then backward compatibility with * previous releases is not granted. * </li><p /> * <p /><li><b>minor</b> - When the minor version changes (in ex. from * "1.5" to "1.6"), then backward compatibility * with previous releases is granted, but something changed in the * interface (in ex. new methods were added). * </li><p /> * <li><b>revision</b> - When refering to an interface may represent a change * in documentation or other minor changes. If some methods are modified a minor * version changes is needed.<p /> * - When refering to a Block implementation this represent minor changes in * implementation like bugs fix. * </li><p /> * <li><b>dev</b> - The boolean dev field specify if this Block or interface * is under development and not yet approved by the Java Apache org.apache.avalon.interfaces; * developers group (mailing-list). * </li><p /> * </ul> * </ul> * The third field, optional and always "<b>-dev</b>" (in ex. * "1.5-dev") specifies that the interface is currently under * development, or it was not yet approved by the Java Apache org.apache.avalon.interfaces; * developers group (mailing-list) and so, not yet integrated with the * org.apache.avalon.interfaces; distributions. * * @author <a href="mailto:[EMAIL PROTECTED]">Federico Barbieri</a> * @author <a href="mailto:[EMAIL PROTECTED]">Pierpaolo Fumagalli</a> * @author <a href="mailto:[EMAIL PROTECTED]">Stefano Mazzocchi</a> * @author <a href="mailto:[EMAIL PROTECTED]">Roberto Lo Giacco</a> * @author <a href="http://java.apache.org/">Java Apache Project</a> */ public final class Version { protected int m_major; protected int m_minor; protected int m_revision; /** * Create a new instance of a <code>Version</code> object with the * specified version numbers. * * @param major This <code>Version</code> major number. * @param minor This <code>Version</code> minor number. * @param rev This <code>Version</code> revision number. */ public Version( final int major, final int minor, final int revision ) { m_major = major; m_minor = minor; m_revision = revision; } /** * Check this <code>Version</code> against another for equality. * <p /> * If this <code>Version</code> is compatible with the specified one, then * <b>true</b> is returned, otherwise <b>false</b>. * * @param other The other <code>Version</code> object to be compared with this * for equality. */ public boolean equals( final Version other ) { if( m_major != other.m_major) return false; else if( m_minor != other.m_minor) return false; else if( m_revision != other.m_revision ) return false; else return true; } /** * Check this <code>Version</code> against another for compliancy * (compatibility). * <p /> * If this <code>Version</code> is compatible with the specified one, then * <b>true</b> is returned, otherwise <b>false</b>. Be careful when using * this method since, in example, version 1.3.7 is compliant to version * 1.3.6, while the opposite is not. * * @param v The other <code>Version</code> object to be compared with this * for compliancy (compatibility). */ public boolean complies( final Version other ) { if( m_major != other.m_major) return false; else if( m_minor < other.m_minor) return false; else return true; } /** * Overload toString to report version correctly. * * @return the dot seperated version string */ public String toString() { return m_major + "." + m_minor + "." + m_revision; } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/collections/ArrayEnumeration.java Index: ArrayEnumeration.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut.collections; import java.util.Enumeration; import java.util.List; import java.util.NoSuchElementException; /** * Enumeration wrapper for array. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public final class ArrayEnumeration implements Enumeration { protected Object[] m_elements; protected int m_index; public ArrayEnumeration( final List elements ) { m_elements = elements.toArray(); } public ArrayEnumeration( final Object[] elements ) { m_elements = elements; } public boolean hasMoreElements() { return ( m_index < m_elements.length ); } public Object nextElement() { if( !hasMoreElements() ) { throw new NoSuchElementException("No more elements exist"); } return m_elements[ m_index++ ]; } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/collections/ArrayStack.java Index: ArrayStack.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut.collections; import java.util.ArrayList; import java.util.EmptyStackException; /** * Unsynchronized stakc. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class ArrayStack extends ArrayList { public void setSize( final int size ) { if( 0 == size ) clear(); else { removeRange( size, size() - 1 ); } } /** * Adds the object to the top of the stack. * * @param element object to add to stack * @return the object */ public Object push( final Object element ) { add( element ); return element; } /** * Remove element from top of stack and return it * * @return the element from stack * @exception EmptyStackException if no elements left on stack */ public Object pop() throws EmptyStackException { final int size = size(); if( 0 == size ) throw new EmptyStackException(); return remove( size - 1 ); } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/collections/IteratorEnumeration.java Index: IteratorEnumeration.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut.collections; import java.util.Enumeration; import java.util.Iterator; import java.util.NoSuchElementException; /** * Enumeration wrapper for iterator. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public final class IteratorEnumeration implements Enumeration { protected Iterator m_iterator; public IteratorEnumeration( final Iterator iterator ) { m_iterator = iterator; } public boolean hasMoreElements() { return m_iterator.hasNext(); } public Object nextElement() { return m_iterator.next(); } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/collections/ListUtils.java Index: ListUtils.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut.collections; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Miscelaneous utilities to manipulate Lists. * * @author <a href="mailto:[EMAIL PROTECTED]">Federico Barbieri</a> * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class ListUtils { public static List intersection( final List list1, final List list2 ) { final ArrayList result = new ArrayList(); final Iterator iterator = list2.iterator(); while( iterator.hasNext() ) { final Object o = iterator.next(); if ( list1.contains( o ) ) { result.add( o ); } } return result; } public static List subtract( final List list1, final List list2 ) { final ArrayList result = new ArrayList( list1 ); final Iterator iterator = list2.iterator(); while( iterator.hasNext() ) { result.remove( iterator.next() ); } return result; } public static List sum( final List list1, final List list2 ) { return subtract( union( list1, list2 ), intersection( list1, list2 ) ); } public static List union( final List list1, final List list2 ) { final ArrayList result = new ArrayList( list1 ); result.addAll( list2 ); return result; } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/i18n/ResourceGroup.java Index: ResourceGroup.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut.i18n; import java.text.MessageFormat; import java.util.HashMap; import java.util.Locale; import java.util.MissingResourceException; import java.util.Random; import java.util.ResourceBundle; /** * A class used to manage resource bundles. */ public class ResourceGroup { protected final static Random RANDOM = new Random(); protected final HashMap m_bundles = new HashMap(); protected final Locale m_locale; /** * Create a ResourceGroup to manage resource bundles for a particular locale. * * @param locale the locale */ public ResourceGroup( final Locale locale ) { m_locale = locale; } public Locale getLocale() { return m_locale; } public String format( final String base, final String key, final Object[] args ) { final String pattern = getPattern( base, key ); final MessageFormat messageFormat = new MessageFormat( pattern ); messageFormat.setLocale( m_locale ); return messageFormat.format( args ); } public ResourceBundle getBundle( final String base ) throws MissingResourceException { ResourceBundle result = (ResourceBundle) m_bundles.get( base ); if( null != result ) return result; // bundle wasn't cached, so load it, cache it, and return it. final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); result = ResourceBundle.getBundle( base, m_locale, classLoader ); m_bundles.put( base, result ); return result; } public String getPattern( final String base, final String key ) throws MissingResourceException { final ResourceBundle bundle = getBundle( base ); final Object object = bundle.getObject( key ); // is the resource a single string if( object instanceof String ) { return (String)object; } else if( object instanceof String[] ) { //if string array then randomly pick one final String[] strings = (String[])object; return strings[ RANDOM.nextInt( strings.length ) ]; } else { throw new MissingResourceException( "Unable to find resource of appropriate type.", "java.lang.String", key ); } } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/i18n/XMLResourceBundle.java Index: XMLResourceBundle.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut.i18n; import java.io.IOException; import java.lang.ref.SoftReference; import java.util.Hashtable; import java.util.Locale; import java.util.MissingResourceException; import org.apache.xalan.xpath.XObject; import org.apache.xalan.xpath.XPath; import org.apache.xalan.xpath.XPathProcessorImpl; import org.apache.xalan.xpath.XPathSupport; import org.apache.xalan.xpath.xml.PrefixResolverDefault; import org.apache.xalan.xpath.xml.XMLParserLiaisonDefault; import org.apache.xerces.dom.DocumentImpl; import org.apache.xerces.dom.TextImpl; import org.apache.xerces.parsers.DOMParser; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * @author <a href="mailto:[EMAIL PROTECTED]">Mike Engelhart</a> * @author <a href="mailto:[EMAIL PROTECTED]">Neeme Praks</a> * @author <a href="mailto:[EMAIL PROTECTED]">Oleg Podolsky</a> * @version $Id: XMLResourceBundle.java,v 1.1 2001/04/03 23:35:22 donaldp Exp $ */ public class XMLResourceBundle { // Cache for storing string values for existing XPaths private Hashtable cacheIS = new Hashtable(); // Cache for storing non-existing XPaths private Hashtable cacheNO = new Hashtable(); private Document resource; public String bundleName = ""; //used by getLocale() protected XMLResourceBundle parent = null; public XMLResourceBundle( Document doc, String name, XMLResourceBundle p ) { System.out.print( "Constructing XMLResourceBundle: " + name ); if ( p != null ) System.out.println( " --> parent: " + p.bundleName ); else System.out.println( " --> parent: " + p ); this.resource = doc; this.bundleName = name; this.parent = p; } public void addToCache( String key, String value ) { cacheIS.put( key, value ); } public Document getResource() { return this.resource; } // gets string without throwing an exception, returns empty string instead public String getStringSimple( String xPathKey ) { String result = ""; try { result = getString( xPathKey ); } catch ( MissingResourceException e ) { // do nothing } return result; } public String getString( String xPathKey ) throws MissingResourceException { if ( cacheIS.containsKey( xPathKey ) ) return ( String ) cacheIS.get( xPathKey ); if ( cacheNO.containsKey( xPathKey ) ) new MissingResourceException( "Unable to locate resource: " + xPathKey, "XMLResourceBundle", xPathKey ); Node root = this.resource.getDocumentElement(); try { Node node = XPathAPI.selectSingleNode( root, xPathKey ); if ( node != null ) { String temp = getTextNodeAsString( node ); addToCache( xPathKey, temp ); return temp; } else { if ( this.parent != null ) return this.parent.getString( xPathKey ); else throw new Exception(); } } catch ( Exception e ) { // no nodes returned?? cacheNO.put( xPathKey, "" ); throw new MissingResourceException( "Unable to locate resource: " + xPathKey, "XMLResourceBundle", xPathKey ); } } public String getString( Node role, String key ) throws MissingResourceException { try { Node node = XPathAPI.selectSingleNode( role, key ); if ( node != null ) return getTextNodeAsString( node ); else throw new Exception(); } catch ( Exception e ) { // no nodes returned?? throw new MissingResourceException( "Unable to locate resource: " + key, "XMLResourceBundle", key ); } } private String getTextNodeAsString( Node node ) throws MissingResourceException { node = node.getFirstChild(); if ( node.getNodeType() == Node.TEXT_NODE ) return ( ( TextImpl ) node ).getData(); else throw new MissingResourceException( "Unable to locate XMLResourceBundle", "XMLResourceBundleFactory", "" ); } public Node getRole( String xPath ) { Node root = resource.getDocumentElement(); try { Node node = XPathAPI.selectSingleNode( root, xPath ); if ( node != null ) return node; else throw new Exception(); } catch ( Exception e ) { // no nodes returned?? throw new MissingResourceException( "Unable to locate resource: " + xPath, "XMLResourceBundle", xPath ); } } public Node getRole( Node role, String xPath ) { try { Node node = XPathAPI.selectSingleNode( role, xPath ); if ( node != null ) return node; else throw new Exception(); } catch ( Exception e ) { // no nodes returned?? throw new MissingResourceException( "Unable to locate resource: " + xPath, "XMLResourceBundle", xPath ); } } public XPath createXPath( String str, Node namespaceNode ) throws SAXException { XPathSupport xpathSupport = new XMLParserLiaisonDefault(); if ( null == namespaceNode ) throw new SAXException( "A namespace node is required to resolve prefixes!" ); PrefixResolverDefault prefixResolver = new PrefixResolverDefault( ( namespaceNode.getNodeType() == Node.DOCUMENT_NODE ) ? ( ( Document ) namespaceNode ).getDocumentElement() : namespaceNode ); // Create the XPath object. XPath xpath = new XPath(); // Create a XPath parser. XPathProcessorImpl parser = new XPathProcessorImpl( xpathSupport ); parser.initXPath( xpath, str, prefixResolver ); return xpath; } public Locale getLocale() { String bundle = bundleName.substring( 0, bundleName.indexOf( ".xml" ) ); int localeStart = bundle.indexOf( "_" ); if ( localeStart == -1 ) return new Locale( "", "", "" ); bundle = bundle.substring( localeStart + 1 ); localeStart = bundle.indexOf( "_" ); if ( localeStart == -1 ) return new Locale( bundle, "", "" ); String lang = bundle.substring( 0, localeStart ); bundle = bundle.substring( localeStart + 1 ); localeStart = bundle.indexOf( "_" ); if ( localeStart == -1 ) return new Locale( lang, bundle, "" ); String country = bundle.substring( 0, localeStart ); bundle = bundle.substring( localeStart + 1 ); return new Locale( lang, country, bundle ); } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/i18n/XMLResourceBundleFactory.java Index: XMLResourceBundleFactory.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut.i18n; import java.io.IOException; import java.util.Hashtable; import java.util.Locale; import java.util.MissingResourceException; import java.util.Vector; import org.apache.xerces.dom.DocumentImpl; import org.apache.xerces.dom.TextImpl; import org.apache.xerces.parsers.DOMParser; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * @author <a href="mailto:[EMAIL PROTECTED]">Mike Engelhart</a> * @author <a href="mailto:[EMAIL PROTECTED]">Neeme Praks</a> * @author <a href="mailto:[EMAIL PROTECTED]">Oleg Podolsky</a> * @version $Id: XMLResourceBundleFactory.java,v 1.1 2001/04/03 23:35:22 donaldp Exp $ */ public class XMLResourceBundleFactory { protected static Hashtable cache = new Hashtable(); protected static String directory; protected XMLResourceBundleFactory() {} public static XMLResourceBundle getBundle( String name ) throws MissingResourceException { return getBundle( name, Locale.getDefault() ); } public static XMLResourceBundle getBundle( String name, Locale loc ) throws MissingResourceException { return getBundle( name, loc, false ); } public static XMLResourceBundle getBundle( String name, Locale loc, boolean cacheAtStartup ) throws MissingResourceException { XMLResourceBundle parent = null; String bundleName = getBundleName( name, loc ); // first look in the cache - if there grab it XMLResourceBundle bundle = getCachedBundle( bundleName ); if ( bundle != null ) return bundle; // if bundle is not in cache try loading the bundle using the given name and locale bundleName Document doc = null; doc = loadResourceBundle( bundleName ); if ( doc != null ) { if ( ! loc.getLanguage().equals( "" ) ) parent = getParentBundle( name, loc, cacheAtStartup ); bundle = new XMLResourceBundle( doc, bundleName, parent ); if ( cacheAtStartup ) storeTextElements( bundle, bundle.getResource(), "" ); updateCache( bundleName, bundle ); return bundle; } // if the locale's language is "" then we've already tried to load the default resource and it's not available while ( ! loc.getLanguage().equals( "" ) ) { // if the given bundle name is not found, then try loading using a shortened Locale loc = getParentLocale( loc ); bundleName = getBundleName( name, loc ); // first look in the cache - if there grab it and return bundle = getCachedBundle( bundleName ); if ( bundle != null ) return bundle; // try loading the bundle using the given name and locale bundleName doc = loadResourceBundle( bundleName ); if ( doc != null ) { if ( ! loc.getLanguage().equals( "" ) ) parent = getParentBundle( name, loc, cacheAtStartup ); bundle = new XMLResourceBundle( doc, bundleName, parent ); if ( cacheAtStartup ) storeTextElements( bundle, bundle.getResource(), "" ); updateCache( bundleName, bundle ); return bundle; } } throw new MissingResourceException( "Unable to locate resource: " + bundleName, "XMLResourceBundleFactory", "" ); } protected synchronized static XMLResourceBundle getParentBundle( String name, Locale loc ) { return getParentBundle( name, loc, false ); } protected synchronized static XMLResourceBundle getParentBundle( String name, Locale loc, boolean cacheAtStartup ) { loc = getParentLocale( loc ); String bundleName = getBundleName( name, loc ); Document doc = loadResourceBundle( bundleName ); XMLResourceBundle bundle = null; if ( doc != null ) { if ( ! loc.getLanguage().equals( "" ) ) bundle = getParentBundle( name, loc ); bundle = new XMLResourceBundle( doc, bundleName, bundle ); if ( cacheAtStartup ) storeTextElements( bundle, bundle.getResource(), "" ); updateCache( bundleName, bundle ); } return bundle; } // this method returns the next locale up the parent hierarchy // e.g.; the parent of new Locale("en","us","mac") // would be new Locale("en", "us", ""); protected static Locale getParentLocale( Locale loc ) { if ( loc.getVariant().equals( "" ) ) { if ( loc.getCountry().equals( "" ) ) loc = new Locale( "", "", "" ); else loc = new Locale( loc.getLanguage(), "", "" ); } else loc = new Locale( loc.getLanguage(), loc.getCountry(), "" ); return loc; } protected synchronized static XMLResourceBundle getCachedBundle( String bundleName ) { /* SoftReference ref = (SoftReference)(cache.get(bundleName)); if (ref != null) return (XMLResourceBundle) ref.get(); else return null; */ return ( XMLResourceBundle ) ( cache.get( bundleName ) ); } protected synchronized static void updateCache( String bundleName, XMLResourceBundle bundle ) { cache.put( bundleName, bundle ); } /* protected static String getBundleName(String name, Locale loc) { StringBuffer sb = new StringBuffer(name); if (! loc.getLanguage().equals("")) { sb.append("_"); sb.append(loc.getLanguage()); } if (! loc.getCountry().equals("")) { sb.append("_"); sb.append(loc.getCountry()); } if (! loc.getVariant().equals("")) { sb.append("_"); sb.append(loc.getVariant()); } // should all the files have an extension of .xml? Seems reasonable sb.append(".xml"); return sb.toString(); } */ protected static String getBundleName( String name, Locale loc ) { String lang = loc.getLanguage(); StringBuffer sb = new StringBuffer( getDirectory() ); if ( lang.length() > 0 ) sb.append( "/" ).append( lang ); sb.append( "/" ).append( name ).append( ".xml" ); return sb.toString(); } public static XMLResourceBundle getBundle( String fileName, String localeName ) throws MissingResourceException { return getBundle( fileName, new Locale( localeName, localeName ) ); } public static XMLResourceBundle getBundleFromFilename( String bundleName ) throws MissingResourceException { return getBundleFromFilename( bundleName, true ); } public static XMLResourceBundle getBundleFromFilename( String bundleName, boolean cacheAtStartup ) throws MissingResourceException { Document doc = null; doc = loadResourceBundle( getDirectory() + "/" + bundleName ); XMLResourceBundle bundle = getCachedBundle( bundleName ); if ( bundle != null ) return bundle; if ( doc != null ) { bundle = new XMLResourceBundle( doc, bundleName, null ); if ( cacheAtStartup ) storeTextElements( bundle, bundle.getResource(), "" ); updateCache( bundleName, bundle ); return bundle; } throw new MissingResourceException( "Unable to locate resource: " + bundleName, "XMLResourceBundleFactory", "" ); } // Load the XML document based on bundleName protected static Document loadResourceBundle( String bundleName ) { try { DOMParser parser = new DOMParser(); parser.parse( bundleName ); return parser.getDocument(); } catch ( IOException e ) { return null; } catch ( SAXException e ) { return null; } } public static void setDirectory( String dir ) { directory = dir; } public static String getDirectory() { return ( directory != null ? directory : "" ); } // Steps through the bundle tree and stores all text element values // in bundle's cache, and also stores attributes for all element nodes. // Parent must be am element-type node. private static void storeTextElements( XMLResourceBundle bundle, Node parent, String pathToParent ) { NodeList children = parent.getChildNodes(); int childnum = children.getLength(); for ( int i = 0; i < childnum; i++ ) { Node child = children.item( i ); if ( child.getNodeType() == Node.ELEMENT_NODE ) { String pathToChild = pathToParent + '/' + child.getNodeName(); NamedNodeMap attrs = child.getAttributes(); if ( attrs != null ) { Node temp = null; String pathToAttr = null; int attrnum = attrs.getLength(); for ( int j = 0; j < attrnum; j++ ) { temp = attrs.item( j ); pathToAttr = "/@" + temp.getNodeName(); bundle.addToCache( pathToChild + pathToAttr, temp.getNodeValue() ); } } String childValue = getTextValue( child ); if ( childValue != null ) bundle.addToCache( pathToChild, childValue ); else storeTextElements( bundle, child, pathToChild ); } } } private static String getTextValue( Node element ) { NodeList list = element.getChildNodes(); int listsize = list.getLength(); Node item = null; String itemValue = null; for ( int i = 0; i < listsize; i++ ) { item = list.item( i ); if ( item.getNodeType() != Node.TEXT_NODE ) return null; itemValue = item.getNodeValue(); if ( itemValue == null ) return null; itemValue = itemValue.trim(); if ( itemValue.length() == 0 ) return null; return itemValue; } return null; } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/i18n/XPathAPI.java Index: XPathAPI.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut.i18n; import org.apache.xalan.xpath.XObject; import org.apache.xalan.xpath.XPath; import org.apache.xalan.xpath.XPathProcessorImpl; import org.apache.xalan.xpath.XPathSupport; import org.apache.xalan.xpath.xml.PrefixResolverDefault; import org.apache.xalan.xpath.xml.XMLParserLiaisonDefault; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * The methods in this class are convenience methods into the * low-level XPath API. We would like to eventually move these * methods into the XPath core, but would like to do some peer * review first to make sure we have it right. * Please note that these methods execute pure XPaths. They do not * implement those parts of XPath extended by XSLT, such as the * document() function). If you want to install XSLT functions, you * have to use the low-level API. * These functions tend to be a little slow, since a number of objects must be * created for each evaluation. A faster way is to precompile the * XPaths using the low-level API, and then just use the XPaths * over and over. * * @author <a href="mailto:[EMAIL PROTECTED]">Mike Engelhart</a> * @see http://www.w3.org/TR/xpath * @version $Id: XPathAPI.java,v 1.1 2001/04/03 23:35:22 donaldp Exp $ */ public class XPathAPI { /** * Use an XPath string to select a single node. XPath namespace * prefixes are resolved from the context node, which may not * be what you want (see the next method). * * @param contextNode The node to start searching from. * @param str A valid XPath string. * @return The first node found that matches the XPath, or null. */ public static Node selectSingleNode( Node contextNode, String str ) throws SAXException { return selectSingleNode( contextNode, str, contextNode ); } /** * Use an XPath string to select a single node. * XPath namespace prefixes are resolved from the namespaceNode. * * @param contextNode The node to start searching from. * @param str A valid XPath string. * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces. * @return The first node found that matches the XPath, or null. */ public static Node selectSingleNode( Node contextNode, String str, Node namespaceNode ) throws SAXException { // Have the XObject return its result as a NodeSet. NodeList nl = selectNodeList( contextNode, str, namespaceNode ); // Return the first node, or null return ( nl.getLength() > 0 ) ? nl.item( 0 ) : null; } /** * Use an XPath string to select a nodelist. * XPath namespace prefixes are resolved from the contextNode. * * @param contextNode The node to start searching from. * @param str A valid XPath string. * @return A nodelist, should never be null. */ public static NodeList selectNodeList( Node contextNode, String str ) throws SAXException { return selectNodeList( contextNode, str, contextNode ); } /** * Use an XPath string to select a nodelist. * XPath namespace prefixes are resolved from the namespaceNode. * * @param contextNode The node to start searching from. * @param str A valid XPath string. * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces. * @return A nodelist, should never be null. */ public static NodeList selectNodeList( Node contextNode, String str, Node namespaceNode ) throws SAXException { // Execute the XPath, and have it return the result XObject list = eval( contextNode, str, namespaceNode ); // Have the XObject return its result as a NodeSet. return list.nodeset(); } /** * Evaluate XPath string to an XObject. Using this method, * XPath namespace prefixes will be resolved from the namespaceNode. * @param contextNode The node to start searching from. * @param str A valid XPath string. * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces. * @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null. * @see org.apache.xalan.xpath.XObject * @see org.apache.xalan.xpath.XNull * @see org.apache.xalan.xpath.XBoolean * @see org.apache.xalan.xpath.XNumber * @see org.apache.xalan.xpath.XString * @see org.apache.xalan.xpath.XRTreeFrag */ public static XObject eval( Node contextNode, String str ) throws SAXException { return eval( contextNode, str, contextNode ); } /** * Evaluate XPath string to an XObject. * XPath namespace prefixes are resolved from the namespaceNode. * The implementation of this is a little slow, since it creates * a number of objects each time it is called. This could be optimized * to keep the same objects around, but then thread-safety issues would arise. * * @param contextNode The node to start searching from. * @param str A valid XPath string. * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces. * @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null. * @see org.apache.xalan.xpath.XObject * @see org.apache.xalan.xpath.XNull * @see org.apache.xalan.xpath.XBoolean * @see org.apache.xalan.xpath.XNumber * @see org.apache.xalan.xpath.XString * @see org.apache.xalan.xpath.XRTreeFrag */ public static XObject eval( Node contextNode, String str, Node namespaceNode ) throws SAXException { // Since we don't have a XML Parser involved here, install some default support // for things like namespaces, etc. // (Changed from: XPathSupportDefault xpathSupport = new XPathSupportDefault(); // because XPathSupportDefault is weak in a number of areas... perhaps // XPathSupportDefault should be done away with.) XPathSupport xpathSupport = new XMLParserLiaisonDefault(); if ( null == namespaceNode ) namespaceNode = contextNode; // Create an object to resolve namespace prefixes. // XPath namespaces are resolved from the input context node's document element // if it is a root node, or else the current context node (for lack of a better // resolution space, given the simplicity of this sample code). PrefixResolverDefault prefixResolver = new PrefixResolverDefault( ( namespaceNode.getNodeType() == Node.DOCUMENT_NODE ) ? ( ( Document ) namespaceNode ).getDocumentElement() : namespaceNode ); // Create the XPath object. XPath xpath = new XPath(); // Create a XPath parser. XPathProcessorImpl parser = new XPathProcessorImpl( xpathSupport ); parser.initXPath( xpath, str, prefixResolver ); // Execute the XPath, and have it return the result return xpath.execute( xpathSupport, contextNode, prefixResolver ); } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/io/DirectoryFileFilter.java Index: DirectoryFileFilter.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut.io; import java.io.File; import java.io.FilenameFilter; /** * This filters files based if not a directory. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class DirectoryFileFilter implements FilenameFilter { public boolean accept( final File file, final String name ) { return file.isDirectory(); } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/io/ExtensionFileFilter.java Index: ExtensionFileFilter.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut.io; import java.io.File; import java.io.FilenameFilter; /** * This filters files based on the extension (what the filename * ends with). This is used in retrieving all the files of a * particular type. * * @author Federico Barbieri <[EMAIL PROTECTED]> * @author Serge Knystautas <[EMAIL PROTECTED]> * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class ExtensionFileFilter implements FilenameFilter { private String[] m_extensions; public ExtensionFileFilter( final String[] extensions ) { m_extensions = extensions; } public ExtensionFileFilter( final String extension ) { m_extensions = new String[] { extension }; } public boolean accept( final File file, final String name ) { for( int i = 0; i < m_extensions.length; i++ ) { if( name.endsWith( m_extensions[ i ] ) ) return true; } return false; } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/io/FileUtil.java Index: FileUtil.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut.io; import java.io.*; import java.net.URL; import org.apache.aut.StringUtil; /** * This class provides basic facilities for manipulating files. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public final class FileUtil { /** * Private constructor to prevent instantiation. * */ private FileUtil() { } public static File toFile( final URL url ) { if( !url.getProtocol().equals( "file" ) ) { return null; } else { final String filename = url.getFile().replace( '/', File.separatorChar ); return new File( filename ); } } /** * Remove extention from filename. * ie * fo.txt --> foo * a\b\c.jpg --> a\b\c * a\b\c --> a\b\c * * @param filename the filename * @return the filename minus extention */ public static String removeExtention( final String filename ) { final int index = filename.lastIndexOf( '.' ); if( -1 == index ) { return filename; } else { return filename.substring( 0, index ); } } /** * remove path from filename. * ie. * a/b/c.txt --> c.txt * a.txt --> a.txt * * @param filepath the filepath * @return the filename minus path */ public static String removePath( final String filepath ) { final int index = filepath.lastIndexOf( File.separator ); if( -1 == index ) { return filepath; } else { return filepath.substring( index + 1 ); } } /** * Copy file from source to destination. */ public static void copyFileToDirectory( final String source, final String destinationDirectory ) throws IOException { copyFileToDirectory( new File( source ), new File( destinationDirectory ) ); } /** * Copy file from source to destination. */ public static void copyFileToDirectory( final File source, final File destinationDirectory ) throws IOException { if( destinationDirectory.exists() && !destinationDirectory.isDirectory() ) { throw new IllegalArgumentException( "Destination is not a directory" ); } copyFile( source, new File( destinationDirectory, source.getName() ) ); } /** * Copy file from source to destination. */ public static void copyFile( final File source, final File destination ) throws IOException { //check source exists if( !source.exists() ) { throw new IOException( "File " + source + " does not exist" ); } //does destinations directory exist ? if( !destination.getParentFile().exists() ) { destination.mkdirs(); } //make sure we can write to destination if( destination.exists() && !destination.canWrite() ) { throw new IOException( "Unable to open file " + destination + " for writing." ); } IOUtil.copy( new FileInputStream( source ), new FileOutputStream( destination ) ); if( source.length() != destination.length() ) { throw new IOException( "Failed to copy full contents from " + source + " to " + destination ); } } public static void copyURLToFile( final URL source, final File destination ) throws IOException { //does destinations directory exist ? if( !destination.getParentFile().exists() ) { destination.mkdirs(); } //make sure we can write to destination if( destination.exists() && !destination.canWrite() ) { throw new IOException( "Unable to open file " + destination + " for writing." ); } IOUtil.copy( source.openStream(), new FileOutputStream( destination ) ); } public static String normalize( String location ) { location = StringUtil.replaceSubString( location, "/./", "/" ); final StringBuffer sb = new StringBuffer(); int trail = 0; int end = location.indexOf( "/../" ); int start = 0; while( end != -1 ) { //TODO: fix when starts with /../ trail = location.lastIndexOf( "/", end - 1 ); sb.append( location.substring( start, trail ) ); sb.append( '/' ); start = end + 4; end = location.indexOf( "/../", start ); } end = location.length(); sb.append( location.substring( start, end ) ); return sb.toString(); } /** Will concatenate 2 paths, dealing with .. * ( /a/b/c + d = /a/b/d, /a/b/c + ../d = /a/d ) * * Thieved from Tomcat sources... * * @return null if error occurs */ public static String catPath( String lookupPath, String path ) { // Cut off the last slash and everything beyond int index = lookupPath.lastIndexOf( "/" ); lookupPath = lookupPath.substring( 0, index ); // Deal with .. by chopping dirs off the lookup path while( path.startsWith( "../" ) ) { if( lookupPath.length() > 0 ) { index = lookupPath.lastIndexOf( "/" ); lookupPath = lookupPath.substring( 0, index ); } else { // More ..'s than dirs, return null return null; } index = path.indexOf( "../" ) + 3; path = path.substring( index ); } return lookupPath + "/" + path; } public static File resolveFile( final File baseFile, String filename ) { if( '/' != File.separatorChar ) { filename = filename.replace( '/', File.separatorChar ); } if( '\\' != File.separatorChar ) { filename = filename.replace( '\\', File.separatorChar ); } // deal with absolute files if( filename.startsWith( File.separator ) ) { File file = new File( filename ); try { file = file.getCanonicalFile(); } catch( final IOException ioe ) {} return file; } final char[] chars = filename.toCharArray(); final StringBuffer sb = new StringBuffer(); //remove duplicate file seperators in succession - except //on win32 as UNC filenames can be \\AComputer\AShare\myfile.txt int start = 0; if( '\\' == File.separatorChar ) { sb.append( filename.charAt( 0 ) ); start++; } for( int i = start; i < chars.length; i++ ) { final boolean doubleSeperator = File.separatorChar == chars[ i ] && File.separatorChar == chars[ i - 1 ]; if( !doubleSeperator ) sb.append( chars[ i ] ); } filename = sb.toString(); //must be relative File file = (new File( baseFile, filename )).getAbsoluteFile(); try { file = file.getCanonicalFile(); } catch( final IOException ioe ) {} return file; } /** * Delete a file. If file is directory delete it and all sub-directories. */ public static void forceDelete( final String file ) throws IOException { forceDelete( new File( file ) ); } /** * Delete a file. If file is directory delete it and all sub-directories. */ public static void forceDelete( final File file ) throws IOException { if( file.isDirectory() ) deleteDirectory( file ); else { if( false == file.delete() ) { throw new IOException( "File " + file + " unable to be deleted." ); } } } /** * Recursively delete a directory. */ public static void deleteDirectory( final String directory ) throws IOException { deleteDirectory( new File( directory ) ); } /** * Recursively delete a directory. */ public static void deleteDirectory( final File directory ) throws IOException { if( !directory.exists() ) return; cleanDirectory( directory ); if( false == directory.delete() ) { throw new IOException( "Directory " + directory + " unable to be deleted." ); } } /** * Clean a directory without deleting it. */ public static void cleanDirectory( final String directory ) throws IOException { cleanDirectory( new File( directory ) ); } /** * Clean a directory without deleting it. */ public static void cleanDirectory( final File directory ) throws IOException { if( !directory.exists() ) { throw new IllegalArgumentException( directory + " does not exist" ); } if( !directory.isDirectory() ) { throw new IllegalArgumentException( directory + " is not a directory" ); } final File[] files = directory.listFiles(); for( int i = 0; i < files.length; i++ ) { final File file = files[ i ]; if( file.isFile() ) file.delete(); else if( file.isDirectory() ) { cleanDirectory( file ); if( false == file.delete() ) { throw new IOException( "Directory " + file + " unable to be deleted." ); } } } } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/io/IOUtil.java Index: IOUtil.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut.io; import java.io.*; /** * This class provides basic facilities for manipulating io streams. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public final class IOUtil { /** * Private constructor to prevent instantiation. */ private IOUtil() { } public static void shutdownStream( final OutputStream output ) { if( null == output ) return; try { output.close(); } catch( final IOException ioe ) {} } public static void shutdownStream( final InputStream input ) { if( null == input ) return; try { input.close(); } catch( final IOException ioe ) {} } /** * Copy stream-data from source to destination. */ public static void copy( final InputStream source, final OutputStream destination ) throws IOException { try { final BufferedInputStream input = new BufferedInputStream( source ); final BufferedOutputStream output = new BufferedOutputStream( destination ); final int BUFFER_SIZE = 1024 * 4; final byte[] buffer = new byte[ BUFFER_SIZE ]; while( true ) { final int count = input.read( buffer, 0, BUFFER_SIZE ); if( -1 == count ) break; // write out those same bytes output.write( buffer, 0, count ); } //needed to flush cache output.flush(); } finally { shutdownStream( source ); shutdownStream( destination ); } } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/log/AvalonLogFormatter.java Index: AvalonLogFormatter.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut.log; import java.util.Date; import org.apache.framework.ExceptionUtil; import org.apache.log.format.PatternFormatter; /** * Specialized formatter that knows about CascadingThrowables. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class AvalonLogFormatter extends PatternFormatter { protected String getStackTrace( final Throwable throwable, final String format ) { if( null == throwable ) return ""; return ExceptionUtil.printStackTrace( throwable, 8, true ); } /** * Utility method to format time. * * @param time the time * @param format ancilliary format parameter - allowed to be null * @return the formatted string */ protected String getTime( final long time, final String format ) { return new Date().toString(); } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/security/AbstractPolicy.java Index: AbstractPolicy.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut.security; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.security.AccessController; import java.security.CodeSource; import java.security.Permission; import java.security.PermissionCollection; import java.security.Permissions; import java.security.Policy; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.security.cert.Certificate; import java.util.ArrayList; import java.util.Enumeration; import java.util.PropertyPermission; import org.apache.aut.io.FileUtil; import org.apache.framework.component.Component; import org.apache.framework.logger.Loggable; import org.apache.log.Logger; /** * Abstract policy extended in avalon. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public abstract class AbstractPolicy extends Policy implements Component, Loggable { protected final static boolean DEBUG = true; protected final ArrayList m_entries = new ArrayList(); protected Logger m_logger; /** * Internal Policy Entry holder class. */ protected final static class PolicyEntry { CodeSource m_codeSource; Permissions m_permissions; } public void setLogger( final Logger logger ) { m_logger = logger; } /** * Overide so we can have a per-application security policy with * no side-effects to other applications. * * @param codeSource the codeSource to get permissions for * @return the PermissionCollection */ public PermissionCollection getPermissions( CodeSource codeSource ) { codeSource = normalize( codeSource ); getLogger().debug( "getPermissions(" + codeSource.getLocation() + ");" ); final Permissions permissions = new Permissions(); final int size = m_entries.size(); for( int i = 0; i < size; i++ ) { final PolicyEntry entry = (PolicyEntry)m_entries.get( i ); if( entry.m_codeSource.implies( codeSource ) ) { if( DEBUG ) { getLogger().debug( entry.m_codeSource.getLocation() + " implies " + codeSource.getLocation() ); } copyPermissions( permissions, entry.m_permissions ); } } if( DEBUG ) { getLogger().debug( codeSource.getLocation() + " permissions = " + permissions ); } return permissions; } /** * Refresh policy. Ignored in this implementation. */ public void refresh() { } /** * Normalizing CodeSource involves removing relative addressing * (like .. and .) for file urls. * * @param codeSource the codeSource to be normalized * @return the normalized codeSource */ protected CodeSource normalize( final CodeSource codeSource ) { final URL initialLocation = codeSource.getLocation(); // This is a bit of a hack. I don't know why CodeSource should behave like this // Fear not, this only seems to be a problem for home grown classloaders. // - Paul Hammant, Nov 2000 if( null == initialLocation ) return codeSource; String location = null; if( !initialLocation.getProtocol().equalsIgnoreCase( "file" ) ) { location = initialLocation.getFile(); location = FileUtil.normalize( location ); } else { final File file = new File( initialLocation.getFile() ); location = file.getAbsoluteFile().toString().replace( File.separatorChar, '/' ); location = FileUtil.normalize( location ); } URL finalLocation = null; try { finalLocation = new URL( initialLocation.getProtocol(), initialLocation.getHost(), initialLocation.getPort(), location ); } catch( final MalformedURLException mue ) { getLogger().warn( "Error building codeBase", mue ); } return new CodeSource( finalLocation, codeSource.getCertificates() ); } protected void copyPermissions( final Permissions destination, final Permissions src ) { final Enumeration enum = src.elements(); while( enum.hasMoreElements() ) { destination.add( (Permission)enum.nextElement() ); } } /** * Create a permission set for a codeBase. * These are read-write permissions and can be written till until the * time in which they are applied to code. * * @param location the location of codes to apply permission set to. * @param signers a comma seperated string of thos who signed codebase * @return the new permission set * @exception MalformedURLException if location string is malformed */ protected Permissions createPermissionSetFor( final String location, final Certificate[] signers ) throws MalformedURLException { final PolicyEntry entry = new PolicyEntry(); entry.m_codeSource = new CodeSource( new URL( location ), signers ); entry.m_codeSource = normalize( entry.m_codeSource ); getLogger().debug( "createPermissionSetFor(" + entry.m_codeSource.getLocation() + ");" ); entry.m_permissions = new Permissions(); m_entries.add( entry ); return entry.m_permissions; } protected final Logger getLogger() { return m_logger; } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/aut/security/PolicyClassLoader.java Index: PolicyClassLoader.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.aut.security; import java.net.URL; import java.net.URLClassLoader; import java.security.CodeSource; import java.security.PermissionCollection; import java.security.Permissions; import java.security.Policy; /** * Classloader that applies correct policy information. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class PolicyClassLoader extends URLClassLoader { protected Policy m_policy; public PolicyClassLoader( final URL[] urls, final ClassLoader classLoader, final Policy policy ) { super( urls, classLoader ); m_policy = policy; } /** * Overide so we can have a per-application security policy with * no side-effects to other applications. * * @param codeSource the codeSource to get permissions for * @return the PermissionCollection */ protected PermissionCollection getPermissions( final CodeSource codeSource ) { if( null == m_policy ) { final Permissions permissions = new Permissions(); permissions.add( new java.security.AllPermission() ); return permissions; } else { return m_policy.getPermissions( codeSource ); } } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/cli/AbstractParserControl.java Index: AbstractParserControl.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cli; /** * Class to inherit from so when in future when new controls are added * clients will no have to implement them. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class AbstractParserControl implements ParserControl { public boolean isFinished( int lastOptionCode ) { return false; } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/cli/CLArgsParser.java Index: CLArgsParser.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cli; import java.text.ParseException; import java.util.Arrays; import java.util.Vector; /** * Parser for command line arguments. * * This parses command lines according to the standard (?) of * gnu utilities. * * Note: This is still used in 1.1 libraries so do not add 1.2+ dependancies. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public final class CLArgsParser { protected class Token { protected final int m_type; protected final String m_value; public Token( final int type, final String value ) { m_type = type; m_value = value; } public String getValue() { return m_value; } public int getType() { return m_type; } public String toString() { return "" + m_type + ":" + m_value; } } private final static int STATE_NORMAL = 0; private final static int STATE_REQUIRE_2ARGS = 1; private final static int STATE_REQUIRE_ARG = 2; private final static int STATE_OPTIONAL_ARG = 3; private final static int STATE_NO_OPTIONS = 4; private final static int STATE_OPTION_MODE = 5; protected final static int TOKEN_SEPERATOR = 0; protected final static int TOKEN_STRING = 1; protected final static char[] ARG2_SEPERATORS = new char[] { (char)0, '=', '-' }; protected final static char[] ARG_SEPERATORS = new char[] { (char)0, '=' }; protected final static char[] NULL_SEPERATORS = new char[] { (char)0 }; protected final CLOptionDescriptor[] m_optionDescriptors; protected final Vector m_options; protected final ParserControl m_control; protected String m_errorMessage; protected String[] m_unparsedArgs = new String[] {}; //variables used while parsing options. protected char ch; protected String[] args; protected boolean isLong; protected int argIndex; protected int stringIndex; protected int stringLength; //cached character == Integer.MAX_VALUE when invalid protected final static int INVALID = Integer.MAX_VALUE; protected int m_lastChar = INVALID; protected int m_lastOptionId; protected CLOption m_option; protected int m_state = STATE_NORMAL; public String[] getUnparsedArgs() { return m_unparsedArgs; } /** * Retrieve a list of options that were parsed from command list. * * @return the list of options */ public Vector getArguments() { //System.out.println( "Arguments: " + m_options ); return m_options; } /** * Get Descriptor for option id. * * @param id the id * @return the descriptor */ private CLOptionDescriptor getDescriptorFor( final int id ) { for( int i = 0; i < m_optionDescriptors.length; i++ ) { if( m_optionDescriptors[i].getId() == id ) { return m_optionDescriptors[i]; } } return null; } /** * Retrieve a descriptor by name. * * @param name the name * @return the descriptor */ private CLOptionDescriptor getDescriptorFor( final String name ) { for( int i = 0; i < m_optionDescriptors.length; i++ ) { if( m_optionDescriptors[i].getName().equals( name ) ) { return m_optionDescriptors[i]; } } return null; } /** * Retrieve an error message that occured during parsing if one existed. * * @return the error string */ public String getErrorString() { //System.out.println( "ErrorString: " + m_errorMessage ); return m_errorMessage; } /** * Requier state to be placed in for option. * * @param descriptor the Option Descriptor * @return the state */ private int getStateFor( final CLOptionDescriptor descriptor ) { int flags = descriptor.getFlags(); if( ( flags & CLOptionDescriptor.ARGUMENTS_REQUIRED_2 ) == CLOptionDescriptor.ARGUMENTS_REQUIRED_2 ) { return STATE_REQUIRE_2ARGS; } else if( ( flags & CLOptionDescriptor.ARGUMENT_REQUIRED ) == CLOptionDescriptor.ARGUMENT_REQUIRED ) { return STATE_REQUIRE_ARG; } else if( ( flags & CLOptionDescriptor.ARGUMENT_OPTIONAL ) == CLOptionDescriptor.ARGUMENT_OPTIONAL ) { return STATE_OPTIONAL_ARG; } else { return STATE_NORMAL; } } /** * Create a parser that can deals with options and parses certain args. * * @param args[] the args * @param optionDescriptors[] the option descriptors */ public CLArgsParser( final String[] args, final CLOptionDescriptor[] optionDescriptors, final ParserControl control ) { m_optionDescriptors = optionDescriptors; m_control = control; m_options = new Vector(); this.args = args; try { parse(); checkIncompatabilities( m_options ); } catch( final ParseException pe ) { m_errorMessage = pe.getMessage(); } //System.out.println( "Built : " + m_options ); //System.out.println( "From : " + Arrays.asList( args ) ); } /** * Check for duplicates of an option. * It is an error to have duplicates unless appropriate flags is set in descriptor. * * @param arguments the arguments */ protected void checkIncompatabilities( final Vector arguments ) throws ParseException { final int size = arguments.size(); for( int i = 0; i < size; i++ ) { final CLOption option = (CLOption)arguments.elementAt( i ); final int id = option.getId(); final CLOptionDescriptor descriptor = getDescriptorFor( id ); //this occurs when id == 0 and user has not supplied a descriptor //for arguments if( null == descriptor ) continue; final int[] incompatable = descriptor.getIncompatble(); checkIncompatable( arguments, incompatable, i ); } } protected void checkIncompatable( final Vector arguments, final int[] incompatable, final int original ) throws ParseException { final int size = arguments.size(); for( int i = 0; i < size; i++ ) { if( original == i ) continue; final CLOption option = (CLOption)arguments.elementAt( i ); final int id = option.getId(); final CLOptionDescriptor descriptor = getDescriptorFor( id ); for( int j = 0; j < incompatable.length; j++ ) { if( id == incompatable[ j ] ) { final CLOption originalOption = (CLOption)arguments.elementAt( original ); final int originalId = originalOption.getId(); String message = null; if( id == originalId ) { message = "Duplicate options for " + describeDualOption( originalId ) + " found."; } else { message = "Incompatable options -" + describeDualOption( id ) + " and " + describeDualOption( originalId ) + " found."; } throw new ParseException( message, 0 ); } } } } protected String describeDualOption( final int id ) { final CLOptionDescriptor descriptor = getDescriptorFor( id ); if( null == descriptor ) return "<parameter>"; else { final StringBuffer sb = new StringBuffer(); boolean hasCharOption = false; if( Character.isLetter( (char)id ) ) { sb.append( '-' ); sb.append( (char)id ); hasCharOption = true; } final String longOption = descriptor.getName(); if( null != longOption ) { if( hasCharOption ) sb.append( '/' ); sb.append( "--" ); sb.append( longOption ); } return sb.toString(); } } /** * Create a parser that can deals with options and parses certain args. * * @param args[] the args * @param optionDescriptors[] the option descriptors */ public CLArgsParser( final String[] args, final CLOptionDescriptor[] optionDescriptors ) { this( args, optionDescriptors, null ); } /** * Create a string array that is subset of input array. * The sub-array should start at array entry indicated by index. That array element * should only include characters from charIndex onwards. * * @param array[] the original array * @param index the cut-point in array * @param charIndex the cut-point in element of array * @return the result array */ protected String[] subArray( final String[] array, final int index, final int charIndex ) { final int remaining = array.length - index; final String[] result = new String[ remaining ]; if( remaining > 1 ) { System.arraycopy( array, index + 1, result, 1, remaining - 1 ); } result[0] = array[ index ].substring( charIndex - 1 ); return result; } /** * Actually parse arguments * * @param args[] arguments */ protected void parse() throws ParseException { if( 0 == args.length ) return; stringLength = args[ argIndex ].length(); //ch = peekAtChar(); while( true ) { ch = peekAtChar(); if( argIndex >= args.length ) break; if( null != m_control && m_control.isFinished( m_lastOptionId ) ) { //this may need mangling due to peeks m_unparsedArgs = subArray( args, argIndex, stringIndex ); return; } //System.out.println( "State=" + m_state ); //System.out.println( "Char=" + (char)ch ); if( STATE_OPTION_MODE == m_state ) { //if get to an arg barrier then return to normal mode //else continue accumulating options if( 0 == ch ) { getChar(); //strip the null m_state = STATE_NORMAL; } else parseShortOption(); } else if( STATE_NORMAL == m_state ) { parseNormal(); } else if( STATE_NO_OPTIONS == m_state ) { //should never get to here when stringIndex != 0 addOption( new CLOption( args[ argIndex++ ] ) ); } else if( STATE_OPTIONAL_ARG == m_state && '-' == ch ) { m_state = STATE_NORMAL; addOption( m_option ); } else { parseArguments(); } } if( m_option != null ) { if( STATE_OPTIONAL_ARG == m_state ) { m_options.addElement( m_option ); } else if( STATE_REQUIRE_ARG == m_state ) { final CLOptionDescriptor descriptor = getDescriptorFor( m_option.getId() ); final String message = "Missing argument to option " + getOptionDescription( descriptor ); throw new ParseException( message, 0 ); } else if( STATE_REQUIRE_2ARGS == m_state ) { if( 1 == m_option.getArgumentCount() ) { m_option.addArgument( "" ); m_options.addElement( m_option ); } else { final CLOptionDescriptor descriptor = getDescriptorFor( m_option.getId() ); final String message = "Missing argument to option " + getOptionDescription( descriptor ); throw new ParseException( message, 0 ); } } else { throw new ParseException( "IllegalState " + m_state + ": " + m_option, 0 ); } } } protected final String getOptionDescription( final CLOptionDescriptor descriptor ) { if( isLong ) return "--" + descriptor.getName(); else return "-" + (char)descriptor.getId(); } protected final char peekAtChar() { if( INVALID == m_lastChar ) m_lastChar = readChar(); return (char)m_lastChar; } protected final char getChar() { if( INVALID != m_lastChar ) { final char result = (char)m_lastChar; m_lastChar = INVALID; return result; } else return readChar(); } private final char readChar() { if( stringIndex >= stringLength ) { argIndex++; stringIndex = 0; if( argIndex < args.length ) stringLength = args[ argIndex ].length(); else stringLength = 0; return 0; } if( argIndex >= args.length ) return 0; return args[ argIndex ].charAt( stringIndex++ ); } protected final Token nextToken( final char[] seperators ) { ch = getChar(); if( isSeperator( ch, seperators ) ) { ch = getChar(); return new Token( TOKEN_SEPERATOR, null ); } final StringBuffer sb = new StringBuffer(); do { sb.append( ch ); ch = getChar(); } while( !isSeperator( ch, seperators ) ); return new Token( TOKEN_STRING, sb.toString() ); } private final boolean isSeperator( final char ch, final char[] seperators ) { for( int i = 0; i < seperators.length; i++ ) { if( ch == seperators[ i ] ) return true; } return false; } protected void addOption( final CLOption option ) { m_options.addElement( option ); m_lastOptionId = option.getId(); m_option = null; } protected void parseOption( final CLOptionDescriptor descriptor, final String optionString ) throws ParseException { if( null == descriptor ) { throw new ParseException( "Unknown option " + optionString, 0 ); } m_state = getStateFor( descriptor ); m_option = new CLOption( descriptor.getId() ); if( STATE_NORMAL == m_state ) addOption( m_option ); } protected void parseShortOption() throws ParseException { ch = getChar(); final CLOptionDescriptor descriptor = getDescriptorFor( (int)ch ); isLong = false; parseOption( descriptor, "-" + ch ); if( STATE_NORMAL == m_state ) m_state = STATE_OPTION_MODE; } protected boolean parseArguments() throws ParseException { if( STATE_REQUIRE_ARG == m_state ) { if( '=' == ch || 0 == ch ) getChar(); final Token token = nextToken( NULL_SEPERATORS ); m_option.addArgument( token.getValue() ); addOption( m_option ); m_state = STATE_NORMAL; } else if( STATE_REQUIRE_2ARGS == m_state ) { if( 0 == m_option.getArgumentCount() ) { final Token token = nextToken( ARG_SEPERATORS ); if( TOKEN_SEPERATOR == token.getType() ) { final CLOptionDescriptor descriptor = getDescriptorFor( m_option.getId() ); final String message = "Unable to parse first argument for option " + getOptionDescription( descriptor ); throw new ParseException( message, 0 ); } else { m_option.addArgument( token.getValue() ); } } else //2nd argument { final StringBuffer sb = new StringBuffer(); ch = getChar(); if( '-' == ch ) m_lastChar = ch; while( !isSeperator( ch, ARG2_SEPERATORS ) ) { sb.append( ch ); ch = getChar(); } final String argument = sb.toString(); //System.out.println( "Arguement:" + argument ); m_option.addArgument( argument ); addOption( m_option ); m_option = null; m_state = STATE_NORMAL; } } return true; } /** * Parse Options from Normal mode. */ protected void parseNormal() throws ParseException { if( '-' != ch ) { //Parse the arguments that are not options final String argument = nextToken( NULL_SEPERATORS ).getValue(); addOption( new CLOption( argument ) ); m_state = STATE_NORMAL; } else { getChar(); // strip the - if( 0 == peekAtChar() ) { throw new ParseException( "Malformed option -", 0 ); } else { ch = peekAtChar(); //if it is a short option then parse it else ... if( '-' != ch ) parseShortOption(); else { getChar(); // strip the - //-- sequence .. it can either mean a change of state //to STATE_NO_OPTIONS or else a long option if( 0 == peekAtChar() ) { getChar(); m_state = STATE_NO_OPTIONS; } else { //its a long option final String optionName = nextToken( ARG_SEPERATORS ).getValue(); final CLOptionDescriptor descriptor = getDescriptorFor( optionName ); isLong = true; parseOption( descriptor, "--" + optionName ); } } } } } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/cli/CLOption.java Index: CLOption.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cli; import java.util.Arrays; /** * Basic class describing an instance of option. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class CLOption { protected final int m_id; protected String[] m_arguments; /** * Retrieve argument to option if it takes arguments. * * @return the argument */ public final String getArgument() { return getArgument( 0 ); } /** * Retrieve argument to option if it takes arguments. * * @return the argument */ public final String getArgument( final int index ) { if( null == m_arguments || index < 0 || index >= m_arguments.length ) { return null; } else return m_arguments[ index ]; } /** * Retrieve id of option. * * The id is eqivelent to character code if it can be a single letter option. * * @return the id */ public final int getId() { return m_id; } /** * Constructor taking an id (that must be a proper character code) * * @param id the new id */ public CLOption( final int id ) { m_id = id; } /** * Constructor taking argument for option. * * @param argument the argument */ public CLOption( final String argument ) { this( 0 ); addArgument( argument ); } /** * Mutator fo Argument property. * * @param argument the argument */ public final void addArgument( final String argument ) { if( null == m_arguments ) m_arguments = new String[] { argument }; else { final String[] arguments = new String[ m_arguments.length + 1 ]; System.arraycopy( m_arguments, 0, arguments, 0, m_arguments.length ); arguments[ m_arguments.length ] = argument; m_arguments = arguments; } } public int getArgumentCount() { if( null == m_arguments ) return 0; else return m_arguments.length; } /** * Convert to String. * * @return the string value */ public String toString() { final StringBuffer sb = new StringBuffer(); sb.append( "[Option " ); sb.append( (char)m_id ); if( null != m_arguments ) { sb.append( ", " ); sb.append( Arrays.asList( m_arguments ) ); } sb.append( " ]" ); return sb.toString(); } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/cli/CLOptionDescriptor.java Index: CLOptionDescriptor.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cli; /** * Basic class describing an type of option. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class CLOptionDescriptor { public final static int ARGUMENT_REQUIRED = 1 << 1; public final static int ARGUMENT_OPTIONAL = 1 << 2; public final static int ARGUMENT_DISALLOWED = 1 << 3; public final static int ARGUMENTS_REQUIRED_2 = 1 << 4; protected final int m_id; protected final int m_flags; protected final String m_name; protected final String m_description; protected final int[] m_incompatable; /** * Constructor. * * @param name the name/long option * @param flags the flags * @param id the id/character option * @param description description of option usage */ public CLOptionDescriptor( final String name, final int flags, final int id, final String description ) { this( name, flags, id, description, new int[] { id } ); } /** * Constructor. * * @param name the name/long option * @param flags the flags * @param id the id/character option * @param description description of option usage */ public CLOptionDescriptor( final String name, final int flags, final int id, final String description, final int[] incompatable ) { m_id = id; m_name = name; m_flags = flags; m_description = description; m_incompatable = incompatable; } protected int[] getIncompatble() { return m_incompatable; } /** * Retrieve textual description. * * @return the description */ public final String getDescription() { return m_description; } /** * Retrieve flags about option. * Flags include details such as whether it allows parameters etc. * * @return the flags */ public final int getFlags() { return m_flags; } /** * Retrieve the id for option. * The id is also the character if using single character options. * * @return the id */ public final int getId() { return m_id; } /** * Retrieve name of option which is also text for long option. * * @return name/long option */ public final String getName() { return m_name; } /** * Convert to String. * * @return the converted value to string. */ public String toString() { return "[OptionDescriptor " + m_name + ", " + m_id + ", " + m_flags + ", " + m_description + " ]"; } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/cli/CLUtil.java Index: CLUtil.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cli; /** * CLUtil offers basic utility operations for use both internal and external to package. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public final class CLUtil { protected static int MAX_DESCRIPTION_COLUMN_LENGTH = 60; /** * Format options into StringBuffer and return. * * @param options[] the option descriptors * @return the formatted description/help for options */ public static StringBuffer describeOptions( final CLOptionDescriptor[] options ) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < options.length; i++) { final char ch = (char) options[i].getId(); final String name = options[i].getName(); String description = options[i].getDescription(); boolean needComma = false; sb.append('\t'); if( Character.isLetter(ch) ) { sb.append("-"); sb.append(ch); needComma = true; } if (null != name) { if( needComma ) sb.append(", "); sb.append("--"); sb.append(name); sb.append('\n'); } if( null != description ) { while( description.length() > MAX_DESCRIPTION_COLUMN_LENGTH ) { final String descriptionPart = description.substring( 0, MAX_DESCRIPTION_COLUMN_LENGTH ); description = description.substring( MAX_DESCRIPTION_COLUMN_LENGTH ); sb.append( "\t\t" ); sb.append( descriptionPart ); sb.append( '\n' ); } sb.append( "\t\t" ); sb.append( description ); sb.append( '\n' ); } } return sb; } /** * Private Constructor so that no instance can ever be created. * */ private CLUtil() { } } 1.1 jakarta-avalon/proposal/4.0/src/java/org/apache/avalon/cli/ParserControl.java Index: ParserControl.java =================================================================== /* * Copyright (C) The Apache Software Foundation. All rights reserved. * * This software is published under the terms of the Apache Software License * version 1.1, a copy of which has been included with this distribution in * the LICENSE file. */ package org.apache.avalon.cli; /** * ParserControl is used to control particular behaviour of the parser. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public interface ParserControl { boolean isFinished( int lastOptionCode ); } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]