You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Ortwin Glück <or...@nose.ch> on 2002/09/23 20:53:19 UTC

Re: [HttpClient] Preferences Architecture Implementation Draft

Here is some code for discussion. It differs slightly from my initial 
sketch but is more flexible that way.


------ Configuration.java

package org.apache.commons.httpclient;

import java.util.*;
import java.io.*;

import org.apache.commons.logging.*;
/**
  * Holds the configuration for the httpclient package. Instances of 
this class
  * are immutable.
  *
  * @author Ortwin Glück
  *
  * @since 2.0
  */

public class Configuration {

     /**
      * The default configuration read from file.
      */
     public static final Configuration DEFAULT = new Configuration();
     public static final String SYSTEM_PROPERTY = 
"org.apache.commons.httpclient.configuration";

     private static final String PROPERTIES_FILE = "httpclient.properties";
     private static final String JAR_PATH = "META-INF/services/";
     private static final Log log = LogFactory.getLog(Configuration.class);
     private Properties props = new Properties();

     /**
      * Creates the default configuration.
      * The default values are read from the 
<tt>httpclient.properties</tt> which is
      * expected in the following locations:
      * 1. $JAVA_HOME/lib/ directory
      * 2. On the classpath
      * 3. In META-INF/services on the classpath
      *
      * For classpath lookups the following class loaders are probed in 
order:
      * 1. the context class loader of the current thread
      * 2. the class loader of this class
      * 3. the system class loader
      *
      * An alternative path and filename may be specified in the
      * <tt>org.apache.commons.httpclient.configuration</tt> System 
Property.
      */
     protected Configuration() {
         String filename = null;
         try {
             filename = System.getProperty(SYSTEM_PROPERTY);
         } catch(SecurityException e) {
         }

         if (filename == null) {
             String javahome = System.getProperty("java.home");
             filename = javahome + File.separator + "lib" + 
File.separator + PROPERTIES_FILE;
         }

         InputStream in = null;
         File file = new File(filename);
         if (file.exists()) {
             try {
                 log.debug("Trying "+filename);
                 in = new FileInputStream(file);
             } catch(Exception e) {
             }
         }

         if (in == null) {
             try {
                 ClassLoader cl = getClassLoader();
                 if (cl == null) {
                     log.debug("Trying last ressort class loader");
                     in = ClassLoader.getSystemResourceAsStream(JAR_PATH 
+ PROPERTIES_FILE);
                 } else {
                     log.debug("Trying class loader "+cl.toString());
                     in = cl.getResourceAsStream(JAR_PATH + 
PROPERTIES_FILE);
                 }
             } catch(Exception e) {
                 log.error("Error while probing class loaders", e);
             }
         }

         if (in != null) {
             try {
                 props.load(in);
             } catch (IOException e) {
                 log.error("Could not load "+ PROPERTIES_FILE, e);
             }
         } else {
             log.warn(PROPERTIES_FILE +" not found. No default values 
available.");
         }
     }

     /**
      * Returns the best class loader.
      * @return
      */
     private ClassLoader getClassLoader() {
         ClassLoader cl = null;
         try {
             cl = Thread.currentThread().getContextClassLoader();
             if (cl != null) return cl;
         } catch(Exception e) {
         }
         try {
             cl = Configuration.class.getClassLoader();
         } catch(Exception e) {
         }
         return cl;
     }

     /**
      * Creates a configuration based on a configuration base that is 
modified
      * by the patch values. The <tt>base</tt> is first copied into the new
      * configuration. Afterwards all values from the <tt>patch</tt> 
Properties are
      * stored in the new configuration overwriting existing ones.
      *
      * @param base The configuration base
      * @param patch Values that are replaced in the base configuration.
      */
     public Configuration(Configuration base, Properties patch) {
         //copy
         props.putAll(base.props);
         //patch
         Enumeration keys = patch.keys();
         while (keys.hasMoreElements()) {
             String key = (String) keys.nextElement();
             String value = patch.getProperty(key, "");
             props.setProperty(key, value);
         }
     }

     /**
      * Convenience method to generate a patched configuration based on 
the current one.
      * @param patch Values that are replaced in the base configuration.
      * @return new Configuration(this, patch)
      */
     public Configuration patch(Properties patch) {
         return new Configuration(this, patch);
     }

     public String getStringValue(String key) {
         return props.getProperty(key, "");
     }

     public long getLongValue(String key) {
         return Long.parseLong(getStringValue(key).trim());
     }

     public long getLongHexValue(String key) {
         return Long.parseLong(getStringValue(key).trim(), 16);
     }

     public int getIntValue(String key) {
         return Integer.parseInt(getStringValue(key).trim());
     }

     public int getIntHexValue(String key) {
         return Integer.parseInt(getStringValue(key).trim(), 16);
     }

     public float getFloatValue(String key) {
         return Float.parseFloat(getStringValue(key).trim());
     }

     public double getDoubleValue(String key) {
         return Double.parseDouble(getStringValue(key).trim());
     }

     /**
      * Returns true if the value is either yes, true, enabled or on. 
The check
      * is not case sensitive.
      * @param key The key to check
      * @return
      */
     public boolean isEnabled(String key) {
         String val = getStringValue(key);
         return (val.equalsIgnoreCase("YES") || val.equalsIgnoreCase("TRUE")
             || val.equalsIgnoreCase("ENABLED") || 
val.equalsIgnoreCase("ON"));
     }

     /**
      * Checks if a key is empty.
      * @param key
      * @return false if a key does not exist, it is the empty string or 
consits
      * solely of whitespace; true otherwise.
      */
     public boolean isEmpty(String key) {
         return getStringValue(key).trim().equals("");
     }
}


------------ ConfigKeys.java

package org.apache.commons.httpclient;

/**
  * Holds the property keys used to configure HttpClient.
  * @see Configuration
  *
  * @author Ortwin Glück
  *
  * @since 2.0
  */

public interface ConfigKeys {

     /** The HTTP version to use.  1.0 means HTTP/1.0, 1.1 means HTTP/1.1 */
     public static final String HTTP_VERSION = "http.version";

     /** Whether to use preemtive authorization or not. Boolean. */
     public static final String PREEMPT_AUTH = "preemtive.authorization";

     /** The maximum number of Location redirects until an Exception is 
thrown. Integer. */
     public static final String MAX_REDIRECT = "redirect.maximum";

     /** The user-agent string used to identify the client against the 
web server. String. */
     public static final String USER_AGENT = "user.agent";
}

--------- httpclient.properties
http.version=1.1
preemtive.authorization=true
redirect.maximum=20
user.agent=Jakarta Commons-HttpClient/2.0M1



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