You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by da...@apache.org on 2004/02/27 01:43:45 UTC

cvs commit: incubator-geronimo/modules/system/src/test-data/org/apache/geronimo/system/url/resource resource.properties

dain        2004/02/26 16:43:45

  Modified:    modules/system project.xml
               modules/system/src/java/org/apache/geronimo/system/main
                        CommandLine.java Daemon.java
  Added:       modules/system/src/java/org/apache/geronimo/system/url
                        DelegatingURLConnection.java
                        GeronimoURLFactory.java
               modules/system/src/java/org/apache/geronimo/system/url/file
                        FileURLConnection.java Handler.java
               modules/system/src/java/org/apache/geronimo/system/url/resource
                        Handler.java ResourceURLConnection.java
               modules/system/src/test/org/apache/geronimo/system/url
                        GeronimoURLFactoryTest.java
               modules/system/src/test/org/apache/geronimo/system/url/file
                        FileProtocolTest.java
               modules/system/src/test/org/apache/geronimo/system/url/resource
                        ResourceProtocolTest.java
               modules/system/src/test-data resource.properties
               modules/system/src/test-data/org/apache/geronimo/system/url/resource
                        resource.properties
  Log:
  Added a URL protocol handler serverice, based on the net package in
  the commons module.  This handler is designed to be installed into
  URL.setURLStreamHandlerFactory, and allows us complete control over URLs.
  
  Revision  Changes    Path
  1.7       +1 -17     incubator-geronimo/modules/system/project.xml
  
  Index: project.xml
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/system/project.xml,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- project.xml	24 Feb 2004 12:20:46 -0000	1.6
  +++ project.xml	27 Feb 2004 00:43:44 -0000	1.7
  @@ -65,20 +65,4 @@
           </dependency>
   
       </dependencies>
  -
  -
  -    <!-- =================== -->
  -    <!-- Build Specification -->
  -    <!-- =================== -->
  -
  -    <build>
  -        <unitTest>
  -            <includes>
  -                <include>**/*Test.java</include>
  -            </includes>
  -            <excludes>
  -                <exclude>**/Abstract*.java</exclude>
  -            </excludes>
  -        </unitTest>
  -    </build>
   </project>
  
  
  
  1.4       +5 -1      incubator-geronimo/modules/system/src/java/org/apache/geronimo/system/main/CommandLine.java
  
  Index: CommandLine.java
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/system/src/java/org/apache/geronimo/system/main/CommandLine.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- CommandLine.java	25 Feb 2004 09:58:14 -0000	1.3
  +++ CommandLine.java	27 Feb 2004 00:43:44 -0000	1.4
  @@ -37,6 +37,7 @@
   import org.apache.geronimo.kernel.config.Configuration;
   import org.apache.geronimo.kernel.config.ConfigurationManager;
   import org.apache.geronimo.kernel.log.GeronimoLogging;
  +import org.apache.geronimo.system.url.GeronimoURLFactory;
   
   
   /**
  @@ -46,6 +47,9 @@
       static {
           // This MUST be done before the first log is acquired
           GeronimoLogging.initialize(GeronimoLogging.ERROR);
  +
  +        // Install our url factory
  +        GeronimoURLFactory.install();
       }
   
       private CommandLine() {
  
  
  
  1.3       +5 -1      incubator-geronimo/modules/system/src/java/org/apache/geronimo/system/main/Daemon.java
  
  Index: Daemon.java
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/system/src/java/org/apache/geronimo/system/main/Daemon.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Daemon.java	25 Feb 2004 09:58:14 -0000	1.2
  +++ Daemon.java	27 Feb 2004 00:43:44 -0000	1.3
  @@ -30,6 +30,7 @@
   import org.apache.geronimo.kernel.config.Configuration;
   import org.apache.geronimo.kernel.config.ConfigurationManager;
   import org.apache.geronimo.kernel.log.GeronimoLogging;
  +import org.apache.geronimo.system.url.GeronimoURLFactory;
   
   /**
    *
  @@ -40,6 +41,9 @@
       static {
           // This MUST be done before the first log is acquired
           GeronimoLogging.initialize(GeronimoLogging.INFO);
  +
  +        // Install our url factory
  +        GeronimoURLFactory.install();
       }
   
       private Daemon() {
  
  
  
  1.1                  incubator-geronimo/modules/system/src/java/org/apache/geronimo/system/url/DelegatingURLConnection.java
  
  Index: DelegatingURLConnection.java
  ===================================================================
  /**
   *
   * Copyright 2003-2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  
  package org.apache.geronimo.system.url;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.net.URLConnection;
  import java.security.Permission;
  import java.util.Map;
  
  /**
   * An delegating URLConnection support class.
   *
   * @version $Revision: 1.1 $ $Date: 2004/02/27 00:43:44 $
   */
  public class DelegatingURLConnection extends URLConnection {
      private URL delegateUrl;
      private URLConnection delegateConnection;
  
      public DelegatingURLConnection(final URL url) throws MalformedURLException, IOException {
          super(url);
  
          delegateUrl = makeDelegateUrl(url);
          assert delegateUrl != null;
  
          delegateConnection = makeDelegateUrlConnection(delegateUrl);
          assert delegateConnection != null;
      }
  
      protected URL makeDelegateUrl(final URL url) throws MalformedURLException, IOException {
          assert url != null;
  
          return url;
      }
  
      private URLConnection makeDelegateUrlConnection(final URL url) throws IOException {
          assert url != null;
  
          return url.openConnection();
      }
  
      public void connect() throws IOException {
          delegateConnection.connect();
      }
  
      public URL getURL() {
          return delegateConnection.getURL();
      }
  
      public int getContentLength() {
          return delegateConnection.getContentLength();
      }
  
      public String getContentType() {
          return delegateConnection.getContentType();
      }
  
      public String getContentEncoding() {
          return delegateConnection.getContentEncoding();
      }
  
      public long getExpiration() {
          return delegateConnection.getExpiration();
      }
  
      public long getDate() {
          return delegateConnection.getDate();
      }
  
      public long getLastModified() {
          return delegateConnection.getLastModified();
      }
  
      public String getHeaderField(String name) {
          return delegateConnection.getHeaderField(name);
      }
  
      public Map getHeaderFields() {
          return delegateConnection.getHeaderFields();
      }
  
      public int getHeaderFieldInt(String name, int _default) {
          return delegateConnection.getHeaderFieldInt(name, _default);
      }
  
      public long getHeaderFieldDate(String name, long _default) {
          return delegateConnection.getHeaderFieldDate(name, _default);
      }
  
      public String getHeaderFieldKey(int n) {
          return delegateConnection.getHeaderFieldKey(n);
      }
  
      public String getHeaderField(int n) {
          return delegateConnection.getHeaderField(n);
      }
  
      public Object getContent() throws IOException {
          return delegateConnection.getContent();
      }
  
      public Object getContent(Class[] classes) throws IOException {
          return delegateConnection.getContent(classes);
      }
  
      public Permission getPermission() throws IOException {
          return delegateConnection.getPermission();
      }
  
      public InputStream getInputStream() throws IOException {
          return delegateConnection.getInputStream();
      }
  
      public OutputStream getOutputStream() throws IOException {
          return delegateConnection.getOutputStream();
      }
  
      public String toString() {
          return super.toString() + "{ " + delegateConnection + " }";
      }
  
      public void setDoInput(boolean doinput) {
          delegateConnection.setDoInput(doinput);
      }
  
      public boolean getDoInput() {
          return delegateConnection.getDoInput();
      }
  
      public void setDoOutput(boolean dooutput) {
          delegateConnection.setDoOutput(dooutput);
      }
  
      public boolean getDoOutput() {
          return delegateConnection.getDoOutput();
      }
  
      public void setAllowUserInteraction(boolean allowuserinteraction) {
          delegateConnection.setAllowUserInteraction(allowuserinteraction);
      }
  
      public boolean getAllowUserInteraction() {
          return delegateConnection.getAllowUserInteraction();
      }
  
      public void setUseCaches(boolean usecaches) {
          delegateConnection.setUseCaches(usecaches);
      }
  
      public boolean getUseCaches() {
          return delegateConnection.getUseCaches();
      }
  
      public void setIfModifiedSince(long ifmodifiedsince) {
          delegateConnection.setIfModifiedSince(ifmodifiedsince);
      }
  
      public long getIfModifiedSince() {
          return delegateConnection.getIfModifiedSince();
      }
  
      public boolean getDefaultUseCaches() {
          return delegateConnection.getDefaultUseCaches();
      }
  
      public void setDefaultUseCaches(boolean defaultusecaches) {
          delegateConnection.setDefaultUseCaches(defaultusecaches);
      }
  
      public void setRequestProperty(String key, String value) {
          delegateConnection.setRequestProperty(key, value);
      }
  
      public void addRequestProperty(String key, String value) {
          delegateConnection.addRequestProperty(key, value);
      }
  
      public String getRequestProperty(String key) {
          return delegateConnection.getRequestProperty(key);
      }
  
      public Map getRequestProperties() {
          return delegateConnection.getRequestProperties();
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/system/src/java/org/apache/geronimo/system/url/GeronimoURLFactory.java
  
  Index: GeronimoURLFactory.java
  ===================================================================
  /**
   *
   * Copyright 2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  package org.apache.geronimo.system.url;
  
  import java.lang.reflect.Field;
  import java.net.URL;
  import java.net.URLStreamHandler;
  import java.security.AccessController;
  import java.security.PrivilegedAction;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Map;
  import java.util.StringTokenizer;
  
  import org.apache.geronimo.gbean.GBean;
  import org.apache.geronimo.gbean.GBeanContext;
  import org.apache.geronimo.gbean.GBeanInfo;
  import org.apache.geronimo.gbean.GBeanInfoFactory;
  import org.apache.geronimo.gbean.WaitingException;
  
  /**
   * This service replaces the URLStreamHandlerFactory used in URL, which gives Geronimo
   * complete control over the URLs creted in the server.  This allows us to replace the
   * broken implementation of the "file" protocol.
   *
   * @version $Revision: 1.1 $ $Date: 2004/02/27 00:43:44 $
   */
  public class GeronimoURLFactory implements GBean {
      private static final URLStreamHandlerFactory factory = new URLStreamHandlerFactory();
      private static boolean installed = false;
  
      public void setGBeanContext(GBeanContext context) {
      }
  
      public void doStart() throws WaitingException, Exception {
          // verify that our factory is installed... if our factory can not be
          // installed the gbean will fail
          install();
      }
  
      public void doStop() throws WaitingException, Exception {
      }
  
      public void doFail() {
      }
  
      /**
       * Assigns the handler to the specified protocol.
       * @param protocol the prototcol name
       * @param handler the url handler for the protocol
       * @throws IllegalStateException if a handler is alreayd assigned to the protocol
       */
      public void registerHandler(String protocol, URLStreamHandler handler) {
          factory.registerHandler(protocol, handler);
      }
  
      /**
       * Gets the handler registered for the specified protocol
       * @param protocol the protocol name
       * @return the registered handler or null if no handler is registerd for the protocol
       */
      public URLStreamHandler getRegisteredHandler(String protocol) {
          return factory.getRegisteredHandler(protocol);
      }
  
      /**
       * Gets a map of all registered handlers keyed by protocol name.
       * @return a map from protocol name to handler
       */
      public Map getRegisteredHandlers() {
          return factory.getRegisteredHandlers();
      }
  
      /**
       * Is our factory installed?
       * @return true if our factory is installed; false otherwise
       */
      public static boolean isInstalled() {
          return installed;
      }
  
      /**
       * Installs the factory into URL using the setURLStreamHandlerFactory method.
       * This will fail is some other code already installed a factory.
       *
       * This should be called from your main method to assure the factory is installed
       * before another code has a chance to take the slot.
       *
       * @throws Error if the application has already set a factory
       * @throws SecurityException if a security manager exists and its checkSetFactory method doesn't allow the operation
       */
      public static void install() throws Error, SecurityException {
          if (!installed) {
              URL.setURLStreamHandlerFactory(factory);
              installed = true;
          }
      }
  
      /**
       * Installs the factory into directly URL's private and package protected fields using
       * Field.setAccessable(true).  This is the "naughty" way of installing a factory but works
       * on most platforms.  If the platform is not using Sun's implementation of URL, this code is
       * likely to not work, but all known platforms use Sun's URL code.
       *
       * You should not use this method unless you absolutely have to.
       *
       * @throws Error if the application has already set a factory
       * @throws SecurityException if a security manager exists and its checkSetFactory method doesn't allow the operation
       */
      public static void forceInstall() throws Error, SecurityException {
          if (!installed) {
              // This way is "naughty" but works great
              Throwable t = (Throwable) AccessController.doPrivileged(new PrivilegedAction() {
                  public Object run() {
                      try {
                          // get a reference to the URL stream handler lock... we need to
                          // synchronize on this field to be safe
                          Field streamHandlerLockField = URL.class.getDeclaredField("streamHandlerLock");
                          streamHandlerLockField.setAccessible(true);
                          Object streamHandlerLock = streamHandlerLockField.get(null);
  
                          synchronized (streamHandlerLock) {
                              // get a reference to the factory field and change the permissions
                              // to make it accessable (factory is a package protected field)
                              Field factoryField = URL.class.getDeclaredField("factory");
                              factoryField.setAccessible(true);
  
                              // get a reference to the handlers field and change the permissions
                              // to make it accessable (handlers is a package protected field)
                              Field handlersField = URL.class.getDeclaredField("handlers");
                              handlersField.setAccessible(true);
  
                              // the the handlers map first
                              Map handlers = (Map) handlersField.get(null);
  
                              // set the factory field to our factory
                              factoryField.set(null, factory);
  
                              // clear the handlers
                              handlers.clear();
                          }
                      } catch (Throwable e) {
                          return e;
                      }
                      return null;
                  }
              });
  
              if (t != null) {
                  if (t instanceof SecurityException) {
                      throw (SecurityException) t;
                  } else if (t instanceof Error) {
                      throw (Error) t;
                  }
                  throw new Error("Unknown error while force installing URL factory", t);
              }
              installed = true;
          }
      }
  
      private static class URLStreamHandlerFactory implements java.net.URLStreamHandlerFactory {
          private final Map handlers = new HashMap();
          private final List handlerPackages = new LinkedList();
  
          private URLStreamHandlerFactory() {
              // add the packages listed in the standard system property
              String systemPackages = System.getProperty("java.protocol.handler.pkgs");
              if (systemPackages != null) {
                  StringTokenizer stok = new StringTokenizer(systemPackages, "|");
                  while (stok.hasMoreTokens()) {
                      handlerPackages.add(stok.nextToken().trim());
                  }
              }
              // always add the sun handlers
              handlerPackages.add("sun.net.www.protocol");
  
              // register our well known protocol handlers
              // URL permanently caches our handlers so we may want to register a wrapper
              // around the true handler to enable changing the implementation at runtime
              handlers.put("file", new org.apache.geronimo.system.url.file.Handler());
              handlers.put("resource", new org.apache.geronimo.system.url.resource.Handler());
          }
  
          public URLStreamHandler createURLStreamHandler(String protocol) {
              if (protocol == null) {
                  throw new IllegalArgumentException("protocol is null");
              }
              protocol = protocol.trim();
  
              URLStreamHandler handler;
  
              // first check the registered handlers
              synchronized (this) {
                  handler = (URLStreamHandler) handlers.get(protocol);
              }
              if (handler != null) {
                  return handler;
              }
  
              // try to get the stream handler from the registered package list
              Class type = findProtocolHandler(protocol);
              if (type == null) {
                  throw new IllegalArgumentException("unknown protocol: " + protocol);
              }
  
              try {
                  return (URLStreamHandler) type.newInstance();
              } catch (Exception e) {
                  throw new IllegalArgumentException("Error constructing protocol handler:" +
                          "protocol " + protocol +
                          " messgae=" + e.getMessage());
              }
          }
  
          private synchronized void registerHandler(String protocol, URLStreamHandler handler) {
              assert protocol != null: "protocol is null";
              assert handler != null: "handler is null";
              if (handlers.containsKey(protocol)) {
                  throw new IllegalStateException("Protocol already has a registered handler: " + protocol);
              }
              handlers.put(protocol, handler);
          }
  
          private synchronized URLStreamHandler getRegisteredHandler(String protocol) {
              return (URLStreamHandler) handlers.get(protocol);
          }
  
          private synchronized Map getRegisteredHandlers() {
              return new HashMap(handlers);
          }
  
          /**
           * Searches each registered package for specified protocol handler. The class name
           * is packageName + "." + protocolName + ".Handler"
           *
           * @param protocol the desired protocol handler
           * @return the protocol handler or null if none is found
           */
          private Class findProtocolHandler(final String protocol) {
              ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
              if (classLoader == null) {
                  classLoader = ClassLoader.getSystemClassLoader();
              }
              for (Iterator iterator = handlerPackages.iterator(); iterator.hasNext();) {
                  String pkg = (String) iterator.next();
                  String classname = pkg + "." + protocol + ".Handler";
  
                  try {
                      return classLoader.loadClass(classname);
                  } catch (Throwable e) {
                      // ignore
                  }
              }
              return null;
          }
      }
  
      public static final GBeanInfo GBEAN_INFO;
  
      static {
          GBeanInfoFactory infoFactory = new GBeanInfoFactory(GeronimoURLFactory.class.getName());
          infoFactory.addOperation("registerHandler", new Class[]{String.class, URLStreamHandler.class});
          infoFactory.addOperation("getRegisteredHandler", new Class[]{String.class});
          infoFactory.addOperation("getRegisteredHandlers", new Class[]{});
          GBEAN_INFO = infoFactory.getBeanInfo();
      }
  
      public static GBeanInfo getGBeanInfo() {
          return GBEAN_INFO;
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/system/src/java/org/apache/geronimo/system/url/file/FileURLConnection.java
  
  Index: FileURLConnection.java
  ===================================================================
  /**
   *
   * Copyright 2003-2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  
  package org.apache.geronimo.system.url.file;
  
  import java.io.BufferedInputStream;
  import java.io.BufferedOutputStream;
  import java.io.File;
  import java.io.FileDescriptor;
  import java.io.FileInputStream;
  import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.io.FilePermission;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.io.SyncFailedException;
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.net.URLConnection;
  import java.security.Permission;
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  import sun.net.www.ParseUtil;
  
  /**
   * A URLConnection for the 'file' protocol.
   *
   * <p>Correctly returns headers.
   *
   * @version $Revision: 1.1 $ $Date: 2004/02/27 00:43:44 $
   */
  public class FileURLConnection extends URLConnection {
      private static final boolean IS_OS_WINDOWS = System.getProperty("os.name").startsWith("Windows");
      private File file;
      private FileDescriptor fd;
  
      public FileURLConnection(final URL url, final File file) throws MalformedURLException, IOException {
          super(url);
  
          if (file == null) {
              throw new IllegalArgumentException("file is null");
          }
  
          this.file = file;
      }
  
      public File getFile() {
          return file;
      }
  
      public void connect() throws IOException {
          if (connected) {
              return;
          }
  
          if (!file.exists()) {
              throw new FileNotFoundException(file.toString());
          }
  
          connected = true;
      }
  
      /**
       * Return the input stream for the file.
       *
       * <p>Sun's URL connections use buffered streams, so we do too.
       *
       * <p>This impl will return a new stream for each call.
       */
      public InputStream getInputStream() throws IOException {
          if (!connected) {
              connect();
          }
  
          FileInputStream fis = new FileInputStream(file);
          fd = fis.getFD();
  
          return new BufferedInputStream(fis);
      }
  
      /**
       * Return the output stream for the file.
       *
       * <p>Sun's URL connections use buffered streams, so we do too.
       *
       * <p>This impl will return a new stream for each call.
       */
      public OutputStream getOutputStream() throws IOException {
          if (!connected) {
              connect();
          }
  
          FileOutputStream fos = new FileOutputStream(file);
          fd = fos.getFD();
  
          return new BufferedOutputStream(fos);
      }
  
      /**
       * Return the permission for the file.
       *
       * <p>Sun's impl always returns "read", but no reason why we can
       *    not also write to a file URL, so we do.
       */
      public Permission getPermission() throws IOException {
          // Detect if we have read/write perms
          String perms = null;
  
          if (file.canRead()) {
              perms = "read";
          }
          if (file.canWrite()) {
              if (perms != null) {
                  perms += ",write";
              } else {
                  perms = "write";
              }
          }
  
          // File perms need filename to be in system format
          String filename = ParseUtil.decode(url.getPath());
          if (File.separatorChar != '/') {
              filename.replace('/', File.separatorChar);
          }
  
          return new FilePermission(filename, perms);
      }
  
      /**
       * Conditionaly sync the underlying file descriptor if we are running
       * on windows, so that the file details update.
       */
      private void maybeSync() {
          if (fd != null && fd.valid()) {
              if (IS_OS_WINDOWS) {
                  try {
                      fd.sync();
                  } catch (SyncFailedException e) {
                      // ignore... data may be a bit out of sync but who cares?
                  }
              }
          }
      }
  
      /**
       * Always return the last-modified from the file.
       *
       * <p>NOTE: Sun's impl caches this value, so it will appear to never change
       *          even if the underlying file's last-modified has changed.
       */
      public long getLastModified() {
          maybeSync();
          return file.lastModified();
      }
  
      /**
       * Returns the last modified time of the file.
       */
      public long getDate() {
          return getLastModified();
      }
  
      /**
       * Returns the length of the file.
       *
       */
      public int getContentLength() {
          maybeSync();
  
          final long value = file.length();
          if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) {
              throw new IllegalStateException("Can not safly convert to int: " + value);
          }
  
          return (int) value;
      }
  
      /**
       * Returns the content type of the file as mapped by the filename map.
       */
      public String getContentType() {
          return getFileNameMap().getContentTypeFor(file.getName());
      }
  
  
      /////////////////////////////////////////////////////////////////////////
      //                                Headers                              //
      /////////////////////////////////////////////////////////////////////////
  
      /**
       * Get a header field by name.
       *
       * <p>Supported headers:
       * <ul>
       * <li>last-modified
       * <li>content-length
       * <li>content-type
       * <li>date
       * </ul>
       *
       * <p>Hook into our local methods to get headers.  URLConnection
       *    normally goes the other way around.  ie. URLConnection.getDate()
       *    calls getHeaderField('date'), but for file usage this is wasteful
       *    string creation as normally the getHeaderField() will not be called.
       */
      public String getHeaderField(final String name) {
          if (name == null) {
              throw new IllegalArgumentException("name is null");
          }
  
          String headerName = name.toLowerCase();
  
          if (headerName.equals("last-modified")) {
              return String.valueOf(getLastModified());
          } else if (headerName.equals("content-length")) {
              return String.valueOf(getContentLength());
          } else if (headerName.equals("content-type")) {
              return getContentType();
          } else if (headerName.equals("date")) {
              return String.valueOf(getDate());
          }
  
          return super.getHeaderField(name);
      }
  
      /**
       * Returns supported headers.
       *
       * @see #getHeaderField(java.lang.String)
       */
      public Map getHeaderFields() {
          Map headers = new HashMap();
          String[] headerNames = {
              "last-modified",
              "content-length",
              "content-type",
              "date"
          };
  
          for (int i = 0; i < headerNames.length; i++) {
              List list = new ArrayList(1);
              list.add(getHeaderField(headerNames[i]));
              headers.put(headerNames[i], Collections.unmodifiableList(list));
          }
  
          return Collections.unmodifiableMap(headers);
      }
  
      //
      // TODO: implement these... no one uses these so who cares?
      //
  
      public String getHeaderFieldKey(final int n) {
          return getHeaderFieldKey(n);
      }
  
      public String getHeaderField(final int n) {
          return getHeaderField(n);
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/system/src/java/org/apache/geronimo/system/url/file/Handler.java
  
  Index: Handler.java
  ===================================================================
  /**
   *
   * Copyright 2003-2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  
  package org.apache.geronimo.system.url.file;
  
  import java.io.File;
  import java.io.FileNotFoundException;
  import java.io.IOException;
  import java.net.URL;
  import java.net.URLConnection;
  import java.net.URLStreamHandler;
  
  import sun.net.www.ParseUtil;
  
  /**
   * A protocol handler for the 'file' protocol.
   *
   * @version $Revision: 1.1 $ $Date: 2004/02/27 00:43:44 $
   */
  public class Handler extends URLStreamHandler {
      protected void parseURL(final URL url, final String s, final int i, final int j) {
          super.parseURL(url, s.replace(File.separatorChar, '/'), i, j);
      }
  
      /**
       * Open a connection to the file.
       *
       * <p>NOTE: Sun's impl attempts to translate into a 'ftp' URL which is dumb
       *          so fix that by removing it ;-)
       */
      public URLConnection openConnection(final URL url) throws IOException {
          String path = ParseUtil.decode(url.getPath());
          path = path.replace('/', File.separatorChar).replace('|', ':');
          File file = new File(path);
  
          // Handle the hostname of the URL if given, puke if not valid
          String hostname = url.getHost();
          if (hostname == null ||
                  hostname.equals("") ||
                  hostname.equals("~") ||
                  hostname.equals("localhost") ||
                  file.exists()) {
              return new FileURLConnection(url, file);
          }
  
          throw new FileNotFoundException("Invalid host specification: " + url);
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/system/src/java/org/apache/geronimo/system/url/resource/Handler.java
  
  Index: Handler.java
  ===================================================================
  /**
   *
   * Copyright 2003-2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  
  package org.apache.geronimo.system.url.resource;
  
  import java.io.IOException;
  import java.net.URL;
  import java.net.URLConnection;
  import java.net.URLStreamHandler;
  
  /**
   * A protocol handler for the 'resource' protocol.  Provides
   * access to system resources.
   *
   * @version $Revision: 1.1 $ $Date: 2004/02/27 00:43:44 $
   */
  public class Handler extends URLStreamHandler {
      public URLConnection openConnection(final URL url) throws IOException {
          return new ResourceURLConnection(url);
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/system/src/java/org/apache/geronimo/system/url/resource/ResourceURLConnection.java
  
  Index: ResourceURLConnection.java
  ===================================================================
  /**
   *
   * Copyright 2003-2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  
  package org.apache.geronimo.system.url.resource;
  
  import java.io.FileNotFoundException;
  import java.io.IOException;
  import java.net.MalformedURLException;
  import java.net.URL;
  
  import org.apache.geronimo.system.url.DelegatingURLConnection;
  
  /**
   * Provides access to system resources as a URLConnection.
   *
   * @version $Revision: 1.1 $ $Date: 2004/02/27 00:43:44 $
   */
  public class ResourceURLConnection extends DelegatingURLConnection {
      public ResourceURLConnection(final URL url) throws MalformedURLException, IOException {
          super(url);
      }
  
      protected URL makeDelegateUrl(final URL url) throws MalformedURLException, IOException {
          ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
          String name = url.getPath();
          URL target = null;
  
          // If there is a ref, load from the ref class
          String ref = url.getRef();
          if (ref != null) {
              try {
                  Class type = classLoader.loadClass(ref);
                  target = type.getResource(name);
              } catch (ClassNotFoundException ignore) {
                  // ignore... somewhat expected, and we are handling this below
              }
          }
  
          if (target == null) {
              // Then try TCL and then SCL
              target = classLoader.getResource(name);
  
              if (target == null) {
                  target = ClassLoader.getSystemClassLoader().getResource(name);
              }
          }
  
          if (target == null) {
              throw new FileNotFoundException("Could not locate resource: " + name);
          }
  
          return target;
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/system/src/test/org/apache/geronimo/system/url/GeronimoURLFactoryTest.java
  
  Index: GeronimoURLFactoryTest.java
  ===================================================================
  /**
   *
   * Copyright 2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  package org.apache.geronimo.system.url;
  
  import java.net.URL;
  import java.net.URLStreamHandlerFactory;
  import java.net.URLStreamHandler;
  
  import junit.framework.TestCase;
  
  /**
   * 
   * 
   * @version $Revision: 1.1 $ $Date: 2004/02/27 00:43:45 $
   */
  public class GeronimoURLFactoryTest extends TestCase {
      public void testForceInstall() throws Exception{
          URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory() {
              public URLStreamHandler createURLStreamHandler(String protocol) {
                  throw new RuntimeException("Bogus handler still installed");
              }
          });
          GeronimoURLFactory.forceInstall();
          new URL("ftp://www.apache.org/");
      }
  
      public void testSunURLHandlerAccess() throws Exception {
          new URL("ftp://www.apache.org/");
          new URL("http://www.apache.org/index.html");
          new URL("https://www.apache.org/index.html");
          new URL(" http://www.apache.org/index.html");
      }
  }
  
  
  
  
  1.1                  incubator-geronimo/modules/system/src/test/org/apache/geronimo/system/url/file/FileProtocolTest.java
  
  Index: FileProtocolTest.java
  ===================================================================
  /**
   *
   * Copyright 2003-2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  
  package org.apache.geronimo.system.url.file;
  
  import java.io.BufferedOutputStream;
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.net.URL;
  import java.net.URLConnection;
  
  import org.apache.geronimo.system.url.GeronimoURLFactory;
  
  import junit.framework.TestCase;
  
  /**
   * Unit test for the 'file' protocol.
   *
   * @version $Revision: 1.1 $ $Date: 2004/02/27 00:43:45 $
   */
  public class FileProtocolTest extends TestCase {
      static {
          //
          // Have to install factory to make sure that our file handler is used
          // and not Sun's
          //
          GeronimoURLFactory.install();
      }
  
      private File file;
      private URL fileURL;
  
      protected void setUp() throws Exception {
          file = File.createTempFile("FileProtocolTest", ".tmp");
          fileURL = file.toURI().toURL();
      }
  
      protected void tearDown() throws Exception {
          file.delete();
      }
  
      public void testCreateURL() throws Exception {
          new URL("file:/some/file");
      }
  
      public void testURLConnectionType() throws Exception {
          URL url = new URL("file:/some/file");
          URLConnection c = url.openConnection();
          assertEquals(FileURLConnection.class, c.getClass());
      }
  
      public void testFileToURL() throws Exception {
          URL url = file.toURL();
          URLConnection c = url.openConnection();
          assertEquals(FileURLConnection.class, c.getClass());
      }
  
      public void testGetLastModified() throws Exception {
          URLConnection c = fileURL.openConnection();
          assertEquals(file.lastModified(), c.getLastModified());
          file.setLastModified(System.currentTimeMillis());
          assertEquals(file.lastModified(), c.getLastModified());
      }
  
      public void testGetDate() throws Exception {
          URLConnection c = fileURL.openConnection();
          assertEquals(file.lastModified(), c.getDate());
          file.setLastModified(System.currentTimeMillis());
          assertEquals(file.lastModified(), c.getDate());
      }
  
      private void writeSomeBytes(final File file, final int count) throws IOException {
          OutputStream output = new FileOutputStream(file);
          try {
              writeSomeBytes(output, count);
          } finally {
              output.close();
          }
      }
  
      private void writeSomeBytes(final OutputStream output, final int count) throws IOException {
          output.write(new byte[count]);
          output.flush();
      }
  
      public void testGetContentLength() throws Exception {
          int length = 0;
          URLConnection c = fileURL.openConnection();
          assertEquals(file.length(), c.getContentLength());
  
          length += 8;
          writeSomeBytes(file, length);
          assertEquals(length, file.length());
          assertEquals(file.length(), c.getContentLength());
  
          length += 1;
          writeSomeBytes(file, length);
          assertEquals(length, file.length());
          assertEquals(file.length(), c.getContentLength());
  
          length += 10;
          writeSomeBytes(file, length);
          assertEquals(length, file.length());
          assertEquals(file.length(), c.getContentLength());
  
          length *= 2;
          writeSomeBytes(file, length);
          assertEquals(length, file.length());
          assertEquals(file.length(), c.getContentLength());
      }
  
      public void testGetContentType() throws Exception {
          File file = File.createTempFile("FileProtocolTest", ".xml");
          try {
              URLConnection c = file.toURI().toURL().openConnection();
              assertEquals("application/xml", c.getContentType());
          } finally {
              file.delete();
          }
      }
  
      public void testGetInputStream() throws Exception {
          URLConnection c = fileURL.openConnection();
          InputStream input = c.getInputStream();
  
          int length = 8;
          writeSomeBytes(file, length);
          assertEquals(length, input.available());
  
          length *= 8;
          writeSomeBytes(file, length);
          assertEquals(length, input.available());
  
          try {
              input.close();
              input.read();
              fail("Expected IOException");
          } catch (IOException e) {
              // OK
          }
      }
  
      public void testSyncFDUpdatesFileLength() throws Exception {
          File foo = File.createTempFile("TestFileLength", ".tmp");
          FileOutputStream fos = new FileOutputStream(foo);
          OutputStream out = new BufferedOutputStream(fos);
          try {
              out.write(new byte[10]);
              out.flush();
              // out.close();
              fos.getFD().sync(); // this is required on Windows for foo.length to be updated
              assertEquals(10, foo.length());
          } finally {
              foo.delete();
          }
      }
  
      public void testGetOutputStream() throws Exception {
          URLConnection c = fileURL.openConnection();
          OutputStream output = c.getOutputStream();
  
          int length = 8;
          writeSomeBytes(output, length);
  
          // Do not check file length, may fail on windows
          // assertEquals(length, file.length());
  
          // This should work, as the connection should sync the fd
          assertEquals(length, c.getContentLength());
  
          writeSomeBytes(output, length);
  
          // Do not check file length, may fail on windows
          // assertEquals(length * 2, file.length());
  
          // This should work, as the connection should sync the fd
          assertEquals(length * 2, c.getContentLength());
  
          try {
              output.close();
              writeSomeBytes(output, 1);
              fail("Expected IOException");
          } catch (IOException e) {
              // OK
          }
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/system/src/test/org/apache/geronimo/system/url/resource/ResourceProtocolTest.java
  
  Index: ResourceProtocolTest.java
  ===================================================================
  /**
   *
   * Copyright 2003-2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  
  package org.apache.geronimo.system.url.resource;
  
  import java.io.InputStream;
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.util.Properties;
  
  import org.apache.geronimo.system.url.GeronimoURLFactory;
  
  import junit.framework.TestCase;
  
  /**
   * Unit test for the 'resource' protocol.
   *
   * @version $Revision: 1.1 $ $Date: 2004/02/27 00:43:45 $
   */
  public class ResourceProtocolTest extends TestCase {
      static {
          //
          // Have to install factory to make sure that our file handler is used
          // and not Sun's
          //
          GeronimoURLFactory.install();
      }
  
      public void testCreateURL() throws MalformedURLException {
          new URL("resource:resource.properties");
      }
  
      public void testRead() throws Exception {
          URL url = new URL("resource:resource.properties");
          Properties props = new Properties();
          InputStream input = url.openConnection().getInputStream();
          try {
              props.load(input);
              assertEquals("whatever", props.getProperty("some.property"));
          } finally {
              input.close();
          }
      }
  
      public void testRead_FromClass() throws Exception {
          URL url = new URL("resource:resource.properties#" + getClass().getName());
          Properties props = new Properties();
          InputStream input = url.openConnection().getInputStream();
          try {
              props.load(input);
              assertEquals("fromclass", props.getProperty("some.property"));
          } finally {
              input.close();
          }
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/system/src/test-data/resource.properties
  
  Index: resource.properties
  ===================================================================
  ##
  ## A test resource file.
  ##
  ## $Revision: 1.1 $ $Date: 2004/02/27 00:43:45 $
  ##
  
  some.property=whatever
  
  
  
  
  1.1                  incubator-geronimo/modules/system/src/test-data/org/apache/geronimo/system/url/resource/resource.properties
  
  Index: resource.properties
  ===================================================================
  ##
  ## A test resource file.
  ##
  ## $Revision: 1.1 $ $Date: 2004/02/27 00:43:45 $
  ##
  
  some.property=fromclass