You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by jb...@apache.org on 2003/08/12 06:16:47 UTC

cvs commit: incubator-geronimo/modules/core/src/test/org/apache/geronimo/deployment/repository DownloadTest.java

jboynes     2003/08/11 21:16:47

  Added:       modules/core/src/java/org/apache/geronimo/deployment/repository
                        ComponentDescription.java ComponentRepository.java
                        ComponentRepositoryMBean.java
               modules/core/src/test/org/apache/geronimo/deployment/repository
                        DownloadTest.java
  Log:
  Add repository concept for components downloaded on demand
  
  Revision  Changes    Path
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/repository/ComponentDescription.java
  
  Index: ComponentDescription.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 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 "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" 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",
   *    "Apache Geronimo", 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.geronimo.deployment.repository;
  
  import java.net.URL;
  import java.io.Serializable;
  
  /**
   * Description of a component stored in a repository.
   * Information used to describe a component that may be deployed into a server.
   * Attributes are:
   * <table>
   * <tr><td>Group</td><td>Optional</td><td>A project or product name</td></tr>
   * <tr><td>Name</td><td>Required</td><td>Component name</td></tr>
   * <tr><td>Version</td><td>Required</td><td>Component version</td></tr>
   * <tr><td>Description</td><td>Optional</td><td>Wordy description</td></tr>
   * <tr><td>Homepage</td><td>Optional</td><td>Product home page</td></tr>
   * <tr><td>Location</td><td>Required</td><td>Specific location to download from</td></tr>
   * </table>
   * @version $Revision: 1.1 $ $Date: 2003/08/12 04:16:47 $
   */
  public class ComponentDescription implements Serializable {
      private String group;
      private String name;
      private String version;
      private String description;
      private URL homepage;
      private String location;
  
      public ComponentDescription() {
      }
  
      public ComponentDescription(String name, String version, String location) {
          this.name = name;
          this.version = version;
          this.location = location;
      }
  
      /**
       * Return the description of this component
       * @return the description
       */
      public String getDescription() {
          return description;
      }
  
      /**
       * Set the description for this component
       * @param description a description of this component
       */
      public void setDescription(String description) {
          this.description = description;
      }
  
      /**
       * Return the group for this component
       * @return the group
       */
      public String getGroup() {
          return group;
      }
  
      /**
       * Set the group to which this component belongs.
       * @param group the group for this project
       */
      public void setGroup(String group) {
          this.group = group;
      }
  
      /**
       * Return the homepage for this component
       * @return the homepage for this component
       */
      public URL getHomepage() {
          return homepage;
      }
  
      /**
       * Set the homepage for this component
       * @param homepage the homepage
       */
      public void setHomepage(URL homepage) {
          this.homepage = homepage;
      }
  
      /**
       * Return the location of this component in the repository
       * @return the path to the component
       */
      public String getLocation() {
          return location;
      }
  
      /**
       * Set the location of this component in the repository
       * @param location the path to this component relative to the root of the repository
       */
      public void setLocation(String location) {
          this.location = location;
      }
  
      /**
       * Return the name of this component
       * @return the name
       */
      public String getName() {
          return name;
      }
  
      /**
       * Set the name of this component
       * @param name the name
       */
      public void setName(String name) {
          this.name = name;
      }
  
      /**
       * Get the version id for this component. No meaning should be attached
       * to the syntax of the version
       * @return the version id
       */
      public String getVersion() {
          return version;
      }
  
      /**
       * Set the version for this component
       * @param version the version
       */
      public void setVersion(String version) {
          this.version = version;
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/repository/ComponentRepository.java
  
  Index: ComponentRepository.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 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 "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" 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",
   *    "Apache Geronimo", 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.geronimo.deployment.repository;
  
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.net.URLConnection;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.Set;
  import java.util.List;
  import java.util.Collections;
  
  import javax.management.MBeanServer;
  import javax.management.ObjectName;
  import javax.management.InstanceNotFoundException;
  import javax.management.MBeanException;
  import javax.management.ReflectionException;
  import javax.management.MBeanServerFactory;
  import javax.management.MBeanRegistration;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.apache.geronimo.deployment.DeploymentException;
  import org.apache.geronimo.jmx.JMXUtil;
  
  /**
   * A proxy for a repository of components that can accessed remotely and
   * downloaded to the local machine.
   *
   * @version $Revision: 1.1 $ $Date: 2003/08/12 04:16:47 $
   */
  public class ComponentRepository implements ComponentRepositoryMBean,MBeanRegistration {
      private final Log log = LogFactory.getLog(getClass().getName());
      private final File localRoot;
      private MBeanServer server;
      private Set remoteRoots = new HashSet();
  
      /**
       * Construct a repository using the specified local directory as root.
       * It will be created if it does not exists
       * @param localRoot the local root directory
       */
      public ComponentRepository(File localRoot) {
          if (!localRoot.exists()) {
              localRoot.mkdirs();
          } else if (!localRoot.isDirectory()) {
              throw new IllegalArgumentException("Local root is not a directory: " + localRoot);
          }
          this.localRoot = localRoot;
      }
  
      public ObjectName preRegister(MBeanServer mBeanServer, ObjectName objectName) throws Exception {
          this.server = mBeanServer;
          return objectName;
      }
  
      public void postRegister(Boolean aBoolean) {
      }
  
      public void preDeregister() throws Exception {
      }
  
      public void postDeregister() {
      }
  
      public File getLocalRoot() {
          return localRoot;
      }
  
      public Set getRemoteRoots() {
          return Collections.unmodifiableSet(remoteRoots);
      }
  
      public void addRemoteRoot(URL root) {
          remoteRoots.add(root);
      }
  
      public void removeRemoteRoot(URL root) {
          remoteRoots.remove(root);
      }
  
      public void ensureLocal(String name, String version, String location) {
          // @todo get rid of this and use a property editor
          ComponentDescription desc = new ComponentDescription(name, version, location);
          ensureLocal(desc);
      }
  
      public boolean ensureLocal(ComponentDescription desc) {
          String location = desc.getLocation();
          File localFile = new File(localRoot, location);
          if (localFile.exists()) {
              // is exists - we do not check for SNAPSHOT updates
              log.debug("Local copy exists for "+location);
              return true;
          }
  
          for (Iterator i = remoteRoots.iterator(); i.hasNext();) {
              URL root = (URL) i.next();
              URL remoteURL = null;
              try {
                  remoteURL = new URL(root, location);
              } catch (MalformedURLException e) {
                  continue;
              }
              log.debug("Checking for archive at "+remoteURL);
  
              InputStream is = null;
              FileOutputStream os = null;
              try {
                  URLConnection con = remoteURL.openConnection();
                  con.connect();
  
                  is = con.getInputStream();
  
                  log.debug("Downloading archive "+remoteURL);
                  localFile.getParentFile().mkdirs();
                  localFile.createNewFile();
                  os = new FileOutputStream(localFile);
                  byte[] buffer = new byte[4096];
                  int count;
                  while ((count = is.read(buffer)) > 0) {
                      os.write(buffer, 0, count);
                  }
                  os.close();
                  is.close();
                  log.debug("Downloaded archive "+remoteURL);
                  return true;
              } catch (IOException e) {
                  // remove a potentially partially copied file
                  localFile.delete();
                  continue;
              } finally {
                  if (os != null) {
                      try {
                          os.close();
                      } catch (IOException e) {
                          // ignore
                      }
                  }
                  if (is != null) {
                      try {
                          is.close();
                      } catch (IOException e) {
                          // ignore
                      }
                  }
              }
          }
          return false;
      }
  
      public void removeLocal(String name, String version, String location) {
          // @todo get rid of this and use a property editor
          ComponentDescription desc = new ComponentDescription(name, version, location);
          removeLocal(desc);
      }
  
      public void removeLocal(ComponentDescription desc) {
          String location = desc.getLocation();
          File localFile = new File(localRoot, location);
          if (localFile.exists()) {
              localFile.delete();
          }
      }
  
      public void deploy(String name, String version, String location) throws DeploymentException {
          // @todo get rid of this and use a property editor
          ComponentDescription desc = new ComponentDescription(name, version, location);
          deploy(desc);
      }
  
      public void deploy(ComponentDescription desc) throws DeploymentException {
          if (!ensureLocal(desc)) {
              throw new DeploymentException("Could not obtain local copy of "+desc.getName()+" "+desc.getVersion());
          }
          URL url = null;
          try {
              url = new File(localRoot, desc.getLocation()).toURL();
          } catch (MalformedURLException e) {
              throw new DeploymentException(e);
          }
  
          // @todo replace with relation-based proxy
          ObjectName controller = JMXUtil.getObjectName("geronimo.deployment:role=DeploymentController");
          try {
              server.invoke(controller, "deploy", new Object[] { url }, new String[] { "java.net.URL"});
          } catch (InstanceNotFoundException e) {
              throw new DeploymentException(e);
          } catch (MBeanException e) {
              if (e.getCause() instanceof DeploymentException) {
                  throw (DeploymentException) e.getCause();
              } else {
                  throw new DeploymentException(e);
              }
          } catch (ReflectionException e) {
              throw new DeploymentException(e);
          }
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/deployment/repository/ComponentRepositoryMBean.java
  
  Index: ComponentRepositoryMBean.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 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 "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" 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",
   *    "Apache Geronimo", 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.geronimo.deployment.repository;
  
  import java.io.File;
  import java.net.URL;
  import java.util.Set;
  
  import org.apache.geronimo.deployment.DeploymentException;
  
  /**
   * 
   * 
   * @version $Revision: 1.1 $ $Date: 2003/08/12 04:16:47 $
   */
  public interface ComponentRepositoryMBean {
      /**
       * Return the local root directory
       * @return the local root directory
       */
      File getLocalRoot();
  
      /**
       * Add a remote repository
       * @param root the location of the remote repository
       */
      void addRemoteRoot(URL root);
  
      /**
       * Remove a remote repository
       * @param root the location to remove
       */
      void removeRemoteRoot(URL root);
  
      /**
       * Ensure a component is available in the local repository
       * @param desc the component to add
       * @return true if the component is present; false if it could not be found or downloaded
       */
      boolean ensureLocal(ComponentDescription desc);
  
      /**
       * Remove a local copy
       * @param desc the component to remove from the local repository
       */
      void removeLocal(ComponentDescription desc);
  
      void ensureLocal(String name, String version, String location);
  
      void deploy(String name, String version, String location) throws DeploymentException;
  
      void deploy(ComponentDescription desc) throws DeploymentException;
  
      Set getRemoteRoots();
  
      void removeLocal(String name, String version, String location);
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/test/org/apache/geronimo/deployment/repository/DownloadTest.java
  
  Index: DownloadTest.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 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 "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" 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",
   *    "Apache Geronimo", 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.geronimo.deployment.repository;
  
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.PrintWriter;
  import java.net.URL;
  
  import junit.framework.TestCase;
  
  /**
   * 
   * 
   * @version $Revision: 1.1 $ $Date: 2003/08/12 04:16:47 $
   */
  public class DownloadTest extends TestCase {
      private File localRoot;
      private File fakeRemoteRoot;
      private ComponentRepository repo;
      private ComponentDescription desc;
      private ComponentDescription desc2;
      private ComponentDescription desc3;
      private File testArchive;
  
      public void testLocalCopy() throws Exception {
          assertTrue(repo.ensureLocal(desc));
  
          File localFile = new File(localRoot, desc.getLocation());
          assertTrue(localFile.exists());
  
          long ts = localFile.lastModified();
          sleep(50);
  
          assertTrue(repo.ensureLocal(desc));
          assertTrue(ts == localFile.lastModified());
  
          repo.removeLocal(desc);
          assertFalse(localFile.exists());
      }
  
      public void testRemoteCopy() throws Exception {
          assertTrue(repo.ensureLocal(desc2));
  
          File localFile = new File(localRoot, desc2.getLocation());
          assertTrue(localFile.exists());
  
          long ts = localFile.lastModified();
          sleep(50);
  
          assertTrue(repo.ensureLocal(desc));
          assertTrue(ts == localFile.lastModified());
  
          repo.removeLocal(desc2);
          assertFalse(localFile.exists());
      }
  
      public void testNotFound() throws Exception {
          assertFalse(repo.ensureLocal(desc3));
          File localFile = new File(localRoot, desc3.getLocation());
          assertFalse(localFile.exists());
      }
  
      private void sleep(long naptime) {
          try {
              Thread.sleep(naptime);
          } catch (InterruptedException e) {
              // ignore
          }
      }
      protected void setUp() throws Exception {
          super.setUp();
          File temp = new File(System.getProperty("java.io.tmpdir"));
          localRoot = new File(temp, "localRepo");
  
          desc = new ComponentDescription("product", "1.1.1", "myproduct/product-1.1.1.txt");
          fakeRemoteRoot = new File(temp, "remoteRepo");
          testArchive = new File(fakeRemoteRoot, desc.getLocation());
          testArchive.getParentFile().mkdirs();
          testArchive.createNewFile();
          FileOutputStream fos = new FileOutputStream(testArchive);
          PrintWriter writer = new PrintWriter(fos);
          writer.println("Hello World");
          writer.flush();
          writer.close();
  
          desc2 = new ComponentDescription("commons-logging", "1.0.1", "commons-logging/jars/commons-logging-1.0.1.jar");
          desc3 = new ComponentDescription("nosuchfile", "noversion", "nolocation");
  
          repo = new ComponentRepository(localRoot);
          repo.addRemoteRoot(fakeRemoteRoot.toURL());
          repo.addRemoteRoot(new URL("http://www.ibiblio.org/maven/"));
      }
  
      protected void tearDown() throws Exception {
          super.tearDown();
          recursiveDelete(localRoot);
          recursiveDelete(fakeRemoteRoot);
      }
  
      private void recursiveDelete(File root) throws Exception {
          File[] files = root.listFiles();
          for (int i = 0; i < files.length; i++) {
              File file = files[i];
              if (file.isDirectory()) {
                  recursiveDelete(file);
              } else {
                  file.delete();
              }
          }
          root.delete();
      }
  }