public void unpack(WebAppContext context) throws IOException {
    Resource web_app = context.getBaseResource();
    _preUnpackBaseResource = context.getBaseResource();

    if (web_app == null) {
      String war = context.getWar();
      if (war != null && war.length() > 0) web_app = context.newResource(war);
      else web_app = context.getBaseResource();

      // Accept aliases for WAR files
      if (web_app.getAlias() != null) {
        LOG.debug(web_app + " anti-aliased to " + web_app.getAlias());
        web_app = context.newResource(web_app.getAlias());
      }

      if (LOG.isDebugEnabled())
        LOG.debug(
            "Try webapp="
                + web_app
                + ", exists="
                + web_app.exists()
                + ", directory="
                + web_app.isDirectory()
                + " file="
                + (web_app.getFile()));
      // Is the WAR usable directly?
      if (web_app.exists() && !web_app.isDirectory() && !web_app.toString().startsWith("jar:")) {
        // No - then lets see if it can be turned into a jar URL.
        Resource jarWebApp = JarResource.newJarResource(web_app);
        if (jarWebApp.exists() && jarWebApp.isDirectory()) web_app = jarWebApp;
      }

      // If we should extract or the URL is still not usable
      if (web_app.exists()
          && ((context.isCopyWebDir()
                  && web_app.getFile() != null
                  && web_app.getFile().isDirectory())
              || (context.isExtractWAR()
                  && web_app.getFile() != null
                  && !web_app.getFile().isDirectory())
              || (context.isExtractWAR() && web_app.getFile() == null)
              || !web_app.isDirectory())) {
        // Look for sibling directory.
        File extractedWebAppDir = null;

        if (war != null) {
          // look for a sibling like "foo/" to a "foo.war"
          File warfile = Resource.newResource(war).getFile();
          if (warfile != null && warfile.getName().toLowerCase(Locale.ENGLISH).endsWith(".war")) {
            File sibling =
                new File(
                    warfile.getParent(),
                    warfile.getName().substring(0, warfile.getName().length() - 4));
            if (sibling.exists() && sibling.isDirectory() && sibling.canWrite())
              extractedWebAppDir = sibling;
          }
        }

        if (extractedWebAppDir == null)
          // Then extract it if necessary to the temporary location
          extractedWebAppDir = new File(context.getTempDirectory(), "webapp");

        if (web_app.getFile() != null && web_app.getFile().isDirectory()) {
          // Copy directory
          LOG.info("Copy " + web_app + " to " + extractedWebAppDir);
          web_app.copyTo(extractedWebAppDir);
        } else {
          // Use a sentinel file that will exist only whilst the extraction is taking place.
          // This will help us detect interrupted extractions.
          File extractionLock = new File(context.getTempDirectory(), ".extract_lock");

          if (!extractedWebAppDir.exists()) {
            // it hasn't been extracted before so extract it
            extractionLock.createNewFile();
            extractedWebAppDir.mkdir();
            LOG.info("Extract " + web_app + " to " + extractedWebAppDir);
            Resource jar_web_app = JarResource.newJarResource(web_app);
            jar_web_app.copyTo(extractedWebAppDir);
            extractionLock.delete();
          } else {
            // only extract if the war file is newer, or a .extract_lock file is left behind meaning
            // a possible partial extraction
            if (web_app.lastModified() > extractedWebAppDir.lastModified()
                || extractionLock.exists()) {
              extractionLock.createNewFile();
              IO.delete(extractedWebAppDir);
              extractedWebAppDir.mkdir();
              LOG.info("Extract " + web_app + " to " + extractedWebAppDir);
              Resource jar_web_app = JarResource.newJarResource(web_app);
              jar_web_app.copyTo(extractedWebAppDir);
              extractionLock.delete();
            }
          }
        }
        web_app = Resource.newResource(extractedWebAppDir.getCanonicalPath());
      }

      // Now do we have something usable?
      if (!web_app.exists() || !web_app.isDirectory()) {
        LOG.warn("Web application not found " + war);
        throw new java.io.FileNotFoundException(war);
      }

      context.setBaseResource(web_app);

      if (LOG.isDebugEnabled()) LOG.debug("webapp=" + web_app);
    }

    // Do we need to extract WEB-INF/lib?
    if (context.isCopyWebInf() && !context.isCopyWebDir()) {
      Resource web_inf = web_app.addPath("WEB-INF/");

      File extractedWebInfDir = new File(context.getTempDirectory(), "webinf");
      if (extractedWebInfDir.exists()) IO.delete(extractedWebInfDir);
      extractedWebInfDir.mkdir();
      Resource web_inf_lib = web_inf.addPath("lib/");
      File webInfDir = new File(extractedWebInfDir, "WEB-INF");
      webInfDir.mkdir();

      if (web_inf_lib.exists()) {
        File webInfLibDir = new File(webInfDir, "lib");
        if (webInfLibDir.exists()) IO.delete(webInfLibDir);
        webInfLibDir.mkdir();

        LOG.info("Copying WEB-INF/lib " + web_inf_lib + " to " + webInfLibDir);
        web_inf_lib.copyTo(webInfLibDir);
      }

      Resource web_inf_classes = web_inf.addPath("classes/");
      if (web_inf_classes.exists()) {
        File webInfClassesDir = new File(webInfDir, "classes");
        if (webInfClassesDir.exists()) IO.delete(webInfClassesDir);
        webInfClassesDir.mkdir();
        LOG.info(
            "Copying WEB-INF/classes from "
                + web_inf_classes
                + " to "
                + webInfClassesDir.getAbsolutePath());
        web_inf_classes.copyTo(webInfClassesDir);
      }

      web_inf = Resource.newResource(extractedWebInfDir.getCanonicalPath());

      ResourceCollection rc = new ResourceCollection(web_inf, web_app);

      if (LOG.isDebugEnabled()) LOG.debug("context.resourcebase = " + rc);

      context.setBaseResource(rc);
    }
  }
  /* ------------------------------------------------------------ */
  @BeforeClass
  public static void setUp() throws Exception {
    if (data != null) return;

    File file = new File(__userDir);
    file = new File(file.getCanonicalPath());
    URI uri = file.toURI();
    __userURL = uri.toURL();

    __userURL =
        new URL(__userURL.toString() + "src/test/resources/org/eclipse/jetty/util/resource/");
    FilePermission perm = (FilePermission) __userURL.openConnection().getPermission();
    __userDir = new File(perm.getName()).getCanonicalPath() + File.separatorChar;
    __relDir =
        "src/test/resources/org/eclipse/jetty/util/resource/".replace('/', File.separatorChar);

    tmpFile = File.createTempFile("test", null).getCanonicalFile();
    tmpFile.deleteOnExit();

    data = new Data[50];
    int i = 0;

    data[i++] = new Data(tmpFile.toString(), EXISTS, !DIR);

    int rt = i;
    data[i++] = new Data(__userURL, EXISTS, DIR);
    data[i++] = new Data(__userDir, EXISTS, DIR);
    data[i++] = new Data(__relDir, EXISTS, DIR);
    data[i++] = new Data(__userURL + "resource.txt", EXISTS, !DIR);
    data[i++] = new Data(__userDir + "resource.txt", EXISTS, !DIR);
    data[i++] = new Data(__relDir + "resource.txt", EXISTS, !DIR);
    data[i++] = new Data(__userURL + "NoName.txt", !EXISTS, !DIR);
    data[i++] = new Data(__userDir + "NoName.txt", !EXISTS, !DIR);
    data[i++] = new Data(__relDir + "NoName.txt", !EXISTS, !DIR);

    data[i++] = new Data(data[rt], "resource.txt", EXISTS, !DIR);
    data[i++] = new Data(data[rt], "/resource.txt", EXISTS, !DIR);
    data[i++] = new Data(data[rt], "NoName.txt", !EXISTS, !DIR);
    data[i++] = new Data(data[rt], "/NoName.txt", !EXISTS, !DIR);

    int td = i;
    data[i++] = new Data(data[rt], "TestData", EXISTS, DIR);
    data[i++] = new Data(data[rt], "TestData/", EXISTS, DIR);
    data[i++] = new Data(data[td], "alphabet.txt", EXISTS, !DIR, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");

    data[i++] = new Data("jar:file:/somejar.jar!/content/", !EXISTS, DIR);
    data[i++] = new Data("jar:file:/somejar.jar!/", !EXISTS, DIR);

    int tj = i;
    data[i++] = new Data("jar:" + __userURL + "TestData/test.zip!/", EXISTS, DIR);
    data[i++] = new Data(data[tj], "Unkown", !EXISTS, !DIR);
    data[i++] = new Data(data[tj], "/Unkown/", !EXISTS, DIR);

    data[i++] = new Data(data[tj], "subdir", EXISTS, DIR);
    data[i++] = new Data(data[tj], "/subdir/", EXISTS, DIR);
    data[i++] = new Data(data[tj], "alphabet", EXISTS, !DIR, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    data[i++] = new Data(data[tj], "/subdir/alphabet", EXISTS, !DIR, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");

    Resource base = Resource.newResource(__userDir);
    Resource dir0 = base.addPath("TestData");
    assertTrue(dir0.isDirectory());
    assertTrue(dir0.toString().endsWith("/"));
    assertTrue(dir0.getAlias() == null);
    Resource dir1 = base.addPath("TestData/");
    assertTrue(dir1.isDirectory());
    assertTrue(dir1.toString().endsWith("/"));
    assertTrue(dir1.getAlias() == null);
  }