You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by mc...@apache.org on 2002/11/11 11:33:49 UTC

cvs commit: jakarta-avalon-excalibur/meta/src/java/org/apache/excalibur/meta/model Parameter.java

mcconnell    2002/11/11 02:33:49

  Added:       meta/src/java/org/apache/excalibur/meta/model Parameter.java
  Log:
  Initial commit of the Parameter class. A parameter represent a single constructor parameter
  and is used within the scope of an Entry as part of the declarative approach
  to context management.
  
  Revision  Changes    Path
  1.1                  jakarta-avalon-excalibur/meta/src/java/org/apache/excalibur/meta/model/Parameter.java
  
  Index: Parameter.java
  ===================================================================
  /* ==================================================================== 
   * The Apache Software License, Version 1.1 
   * 
   * Copyright (c) 2002 The Apache Software Foundation. All rights 
   * reserved. 
   * 
   * Redistribution and use in source and binary forms, with or without 
   * modification, are permitted provided that the following conditions 
   * are met: 
   * 
   * 1. Redistributions of source code must retain the above copyright 
   *    notice, this list of conditions and the following disclaimer.
   *
   * 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 end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *    "This product includes software developed by the
   *    Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software 
   *    itself, if and wherever such third-party acknowledgments  
   *    normally appear.
   *
   * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation" 
   *    must not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``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 APACHE SOFTWARE FOUNDATION 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.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation. For more
   * information on the Apache Software Foundation, please see 
   * <http://www.apache.org/>.
   */ 
  
  package org.apache.excalibur.meta.model;
  
  import java.lang.reflect.Constructor;
  import java.util.Map;
  
  /**
   * A <code>Parameter</code> represents a single constructor typed argument value.  A parameter
   * container a classname (default value of <code>java.lang.String</code>) and possible sub-parameters.
   * A parameter's value is established by creating a new instance using the parameter's classname,
   * together with the values directived from the sub-sidiary parameters as constructor arguments.
   *
   * <p><b>XML</b></p>
   * <p>A parameter is a nested structure containing a string value or contructor parameter arguments.</p>
   * <pre>
   *    <font color="gray">&lt;-- Simple string parameter declaration --&gt;</font>
   *
   *    &lt;parameter&gt;<font color="darkred">London</font>&lt;/parameter&gt;
   *
   *    <font color="gray">&lt;-- Typed parameter declaration --&gt;</font>
   *
   *    &lt;parameter class="<font color="darkred">java.io.File</font>"&gt;<font color="darkred">./home</font>&lt;/parameter&gt;
   *
   *    <font color="gray">&lt;-- Typed parameter declaration referencing a context value --&gt;</font>
   *
   *    &lt;parameter class="<font color="darkred">java.lang.ClassLoader</font>"&gt;<font color="darkred">${my-classloader-import-key}</font>&lt;/parameter&gt;
   *
   *    <font color="gray">&lt;-- Multi-argument parameter declaration --&gt;</font>
   *
   *    &lt;parameter class="<font color="darkred">MyClass</font>"&gt;
   *       &lt;parameter class="<font color="darkred">java.io.File</font>"><font color="darkred">./home</font>&lt;/parameter&gt;
   *       &lt;parameter&gt;<font color="darkred">London</font>&lt;/parameter&gt;
   *    &lt;/parameter&gt;
   * </pre>
   *
   * @see Entry
   * @see Import
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Revision: 1.1 $ $Date: 2002/11/11 10:33:49 $
   */
  public class Parameter
  {
  
      /**
       * The classname to use as the parameter implementation class (defaults to java.lang.String)
       */
      private final String m_classname;
  
      /**
       * The supplied argument.
       */
      private String m_argument;
  
      /**
       * The sub-parameters from which the value for this parameter may be derived.
       */
      private final Parameter[] m_parameters;
  
      /**
       * The derived value.
       */
      private Object m_value;
  
      /**
       * Creation of a new parameter using the default <code>java.lang.String</code>
       * type and a supplied value.
       *
       * @param value the string value
       */
      public Parameter( final String value )
      {
          m_parameters = new Parameter[ 0 ];
          m_classname = "java.lang.String";
          m_argument = value;
      }
  
      /**
       * Creation of a new entry directive using a supplied classname and value.
       * @param classname the classname of the parameter
       * @param value the parameter constructor value
       */
      public Parameter( final String classname, final String value )
      {
          if( null == classname )
          {
              throw new NullPointerException( "classname" );
          }
  
          if( null == value )
          {
              throw new NullPointerException( "value" );
          }
  
          m_parameters = new Parameter[ 0 ];
          m_classname = classname;
          m_argument = value;
      }
  
      /**
       * Creation of a new entry directive.
       * @param classname the classname of the entry implementation
       * @param parameters implementation class constructor parameter directives
       */
      public Parameter( final String classname, final Parameter[] parameters )
      {
          if( null == classname )
          {
              throw new NullPointerException( "classname" );
          }
  
          m_classname = classname;
          m_parameters = parameters;
      }
  
      /**
       * Return the classname of the parameter implementation to use.
       * @return the classname
       */
      public String getClassname()
      {
          return m_classname;
      }
  
      /**
       * Return the classname of the parameter implementation to use.
       * @param loader the classloader to use
       * @return the parameter class
       * @exception ModelException if the parameter class cannot be resolved
       */
      Class getParameterClass( ClassLoader loader ) throws ModelException
      {
          final String classname = getClassname();
          try
          {
              return loader.loadClass( classname );
          }
          catch( final ClassNotFoundException e )
          {
              if( classname.equals( "int" ) )
              {
                  return int.class;
              }
              else if( classname.equals( "short" ) )
              {
                  return short.class;
              }
              else if( classname.equals( "long" ) )
              {
                  return long.class;
              }
              else if( classname.equals( "byte" ) )
              {
                  return byte.class;
              }
              else if( classname.equals( "double" ) )
              {
                  return double.class;
              }
              else if( classname.equals( "byte" ) )
              {
                  return byte.class;
              }
              else if( classname.equals( "float" ) )
              {
                  return float.class;
              }
              else if( classname.equals( "char" ) )
              {
                  return char.class;
              }
              else if( classname.equals( "char" ) )
              {
                  return char.class;
              }
              else if( classname.equals( "boolean" ) )
              {
                  return boolean.class;
              }
              else
              {
                  throw new ModelException(
                      "Could not locate the parameter implemetation for class: '"
                      + m_classname + "'.", e );
              }
          }
      }
  
      /**
       * Return the derived parameter value.
       * @param loader the classloader to use
       * @param map a map of context values from which import directives may be resolved
       * @return the value
       * @exception ModelException if the parameter value cannot be resolved
       */
      public Object getValue( ClassLoader loader, Map map ) throws ModelException
      {
          //
          // if the parameter value has already been established - return it now
          //
  
          if( m_value != null )
          {
              return m_value;
          }
  
          //
          // if the parameter contains a text argument then check if its a reference
          // to a map entry (in the form"${<key>}" ), otherwise its a simple constructor
          // case with a single string paremeter
          //
  
          if( m_argument != null )
          {
              if( m_argument.startsWith( "${" ) )
              {
                  if( m_argument.endsWith( "}" ) )
                  {
                      final String key = m_argument.substring( 2, m_argument.length() - 1 );
                      m_value = map.get( key );
                      if( m_value != null )
                      {
                          return m_value;
                      }
                      else
                      {
                          final String error = "Missing context value: '" + key + "'.";
                          throw new IllegalArgumentException( error );
                      }
                  }
                  else
                  {
                      final String error = "Illegal formal for context refernence: '" + m_argument + "'.";
                      throw new IllegalArgumentException( error );
                  }
              }
              else
              {
                  //
                  // the argument is a single string parameter
                  //
  
                  try
                  {
                      final Class[] params = new Class[]{String.class};
                      Constructor constructor = getParameterClass( loader ).getConstructor( params );
                      final Object[] values = new Object[]{m_argument};
                      m_value = constructor.newInstance( values );
                      return m_value;
                  }
                  catch( InstantiationException e )
                  {
                      final String error = "Unable to instantiate instance of class: " + m_classname
                          + " with the single argument: '" + m_argument + "'";
                      throw new ModelException( error, e );
                  }
                  catch( IllegalAccessException e )
                  {
                      final String error =
                          "Cannot access single string parameter constructor for the class: '"
                          + m_classname + "'.";
                      throw new ModelException( error, e );
                  }
                  catch( Throwable e )
                  {
                      final String error =
                          "Unexpected exception while creating a single string parameter value for the class: '"
                          + m_classname + "'.";
                      throw new ModelException( error, e );
                  }
  
              }
          }
  
          //
          // getting here means we are dealing with 0..n types parameter constructor where the
          // parameters are defined by the nested parameter definitions
          //
  
          if( m_parameters.length == 0 )
          {
              try
              {
                  m_value = getParameterClass( loader ).newInstance();
                  return m_value;
              }
              catch( InstantiationException e )
              {
                  final String error = "Unable to instantiate instance of class: " + m_classname;
                  throw new ModelException( error, e );
              }
              catch( IllegalAccessException e )
              {
                  final String error =
                      "Cannot access null constructor for the class: '"
                      + m_classname + "'.";
                  throw new ModelException( error, e );
              }
          }
          else
          {
              Class[] params = new Class[ m_parameters.length ];
              for( int i = 0; i < m_parameters.length; i++ )
              {
                  try
                  {
                      params[ i ] = m_parameters[ i ].getParameterClass( loader );
                  }
                  catch( Throwable e )
                  {
                      final String error = "Unable to resolve sub-parameter class: "
                          + m_parameters[ i ].getClassname()
                          + " inside the parameter " + m_classname;
                      throw new ModelException( error, e );
                  }
              }
  
              Object[] values = new Object[ m_parameters.length ];
              for( int i = 0; i < m_parameters.length; i++ )
              {
  
                  try
                  {
                      values[ i ] = m_parameters[ i ].getValue( loader, map );
                  }
                  catch( Throwable e )
                  {
                      final String error = "Unable to instantiate sub-parameter for value: "
                          + m_parameters[ i ].getClassname()
                          + " inside the parameter " + m_classname;
                      throw new ModelException( error, e );
                  }
              }
  
              Constructor constructor = null;
              try
              {
                  constructor = getParameterClass( loader ).getConstructor( params );
              }
              catch( NoSuchMethodException e )
              {
                  final String error =
                      "Supplied parameters for " + m_classname
                      + " does not match an available constructor. Cause: " + e.toString()
                      + "\n" + this;
                  throw new ModelException( error );
              }
  
              try
              {
                  m_value = constructor.newInstance( values );
                  return m_value;
              }
              catch( InstantiationException e )
              {
                  final String error =
                      "Unable to instantiate an instance of a multi-parameter constructor for class: '"
                      + m_classname + "'.";
                  throw new ModelException( error, e );
              }
              catch( IllegalAccessException e )
              {
                  final String error =
                      "Cannot access multi-parameter constructor for the class: '"
                      + m_classname + "'.";
                  throw new ModelException( error, e );
              }
              catch( Throwable e )
              {
                  final String error =
                      "Unexpected error while attmpting to instantiate a multi-parameter constructor "
                      + "for the class: '" + m_classname + "'.";
                  throw new ModelException( error, e );
              }
          }
      }
  
      private String getClassesAsString( Class[] classes )
      {
          StringBuffer buffer = new StringBuffer();
          for( int i = 0; i < classes.length; i++ )
          {
              buffer.append( classes[ i ].getName() );
              if( ( i + 1 ) < classes.length )
              {
                  buffer.append( "," );
              }
          }
          return buffer.toString();
      }
  
      /**
       * Returns a string representation of the parameter.
       * @return the parameter as a string
       */
      public String toString()
      {
          StringBuffer buffer = new StringBuffer();
          asString( buffer, "  " );
          return buffer.toString();
      }
  
      /**
       * Utility method to build a string buffer of a composite parameter.
       * @param buffer the string buffer to append information to
       * @param lead string used for formatting content
       */
      protected void asString( StringBuffer buffer, String lead )
      {
          buffer.append(
              lead + "[\n"
              + lead + "   type: " + this.getClass().getName() + "\n"
              + lead + "  class: " + m_classname + "\n"
              + lead + "    arg: " + m_argument + "\n"
              + lead + "  value: " + m_value + "\n"
              + lead + " params: " + m_parameters.length );
  
          if( m_parameters.length > 0 )
          {
              buffer.append( "\n" );
              String str = lead + "  ";
              getParamsAsString( buffer, str );
          }
          buffer.append( "\n" + lead + "]\n" );
      }
  
      private void getParamsAsString( StringBuffer buffer, String lead )
      {
          for( int i = 0; i < m_parameters.length; i++ )
          {
              m_parameters[ i ].asString( buffer, lead + "  " );
          }
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>