/**
   * Look for jars in WEB-INF/lib
   *
   * @param context
   * @return the list of jar resources found within context
   * @throws Exception
   */
  protected List<Resource> findJars(WebAppContext context) throws Exception {
    List<Resource> jarResources = new ArrayList<Resource>();

    Resource web_inf = context.getWebInf();
    if (web_inf == null || !web_inf.exists()) return null;

    Resource web_inf_lib = web_inf.addPath("/lib");

    if (web_inf_lib.exists() && web_inf_lib.isDirectory()) {
      String[] files = web_inf_lib.list();
      for (int f = 0; files != null && f < files.length; f++) {
        try {
          Resource file = web_inf_lib.addPath(files[f]);
          String fnlc = file.getName().toLowerCase(Locale.ENGLISH);
          int dot = fnlc.lastIndexOf('.');
          String extension = (dot < 0 ? null : fnlc.substring(dot));
          if (extension != null && (extension.equals(".jar") || extension.equals(".zip"))) {
            jarResources.add(file);
          }
        } catch (Exception ex) {
          LOG.warn(Log.EXCEPTION, ex);
        }
      }
    }
    return jarResources;
  }
Exemple #2
0
  /* ------------------------------------------------------------ */
  private HttpContent load(String pathInContext, Resource resource) throws IOException {
    Content content = null;

    if (resource == null || !resource.exists()) return null;

    // Will it fit in the cache?
    if (!resource.isDirectory() && isCacheable(resource)) {
      // Create the Content (to increment the cache sizes before adding the content
      content = new Content(pathInContext, resource);

      // reduce the cache to an acceptable size.
      shrinkCache();

      // Add it to the cache.
      Content added = _cache.putIfAbsent(pathInContext, content);
      if (added != null) {
        content.invalidate();
        content = added;
      }

      return content;
    }

    return new HttpContent.ResourceAsHttpContent(
        resource,
        _mimeTypes.getMimeByExtension(resource.toString()),
        getMaxCachedFileSize(),
        _etags);
  }
Exemple #3
0
  /**
   * Get the resource list as a HTML directory listing.
   *
   * @param base The base URL
   * @param parent True if the parent directory should be included
   * @return String of HTML
   */
  public String getListHTML(String base, boolean parent) throws IOException {
    base = URIUtil.canonicalPath(base);
    if (base == null || !isDirectory()) return null;

    String[] ls = list();
    if (ls == null) return null;
    Arrays.sort(ls);

    String decodedBase = URIUtil.decodePath(base);
    String title = "Directory: " + deTag(decodedBase);

    StringBuilder buf = new StringBuilder(4096);
    buf.append("<HTML><HEAD>");
    buf.append("<LINK HREF=\"")
        .append("jetty-dir.css")
        .append("\" REL=\"stylesheet\" TYPE=\"text/css\"/><TITLE>");
    buf.append(title);
    buf.append("</TITLE></HEAD><BODY>\n<H1>");
    buf.append(title);
    buf.append("</H1>\n<TABLE BORDER=0>\n");

    if (parent) {
      buf.append("<TR><TD><A HREF=\"");
      buf.append(URIUtil.addPaths(base, "../"));
      buf.append("\">Parent Directory</A></TD><TD></TD><TD></TD></TR>\n");
    }

    String encodedBase = hrefEncodeURI(base);

    DateFormat dfmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
    for (int i = 0; i < ls.length; i++) {
      Resource item = addPath(ls[i]);

      buf.append("\n<TR><TD><A HREF=\"");
      String path = URIUtil.addPaths(encodedBase, URIUtil.encodePath(ls[i]));

      buf.append(path);

      if (item.isDirectory() && !path.endsWith("/")) buf.append(URIUtil.SLASH);

      // URIUtil.encodePath(buf,path);
      buf.append("\">");
      buf.append(deTag(ls[i]));
      buf.append("&nbsp;");
      buf.append("</A></TD><TD ALIGN=right>");
      buf.append(item.length());
      buf.append(" bytes&nbsp;</TD><TD>");
      buf.append(dfmt.format(new Date(item.lastModified())));
      buf.append("</TD></TR>");
    }
    buf.append("</TABLE>\n");
    buf.append("</BODY></HTML>\n");

    return buf.toString();
  }
  /** Test a class path resource for existence. */
  @Test
  public void testClassPathResourceClassAbsolute() {
    final String classPathName = "/org/eclipse/jetty/util/resource/Resource.class";

    Resource resource = Resource.newClassPathResource(classPathName);

    assertTrue(resource != null);

    // A class path cannot be a directory
    assertFalse("Class path cannot be a directory.", resource.isDirectory());

    // A class path must exist
    assertTrue("Class path resource does not exist.", resource.exists());
  }
  /** Test a class path resource for existence. */
  @Test
  public void testClassPathResourceClassRelative() {
    final String classPathName = "Resource.class";

    Resource resource = Resource.newClassPathResource(classPathName);

    assertTrue(resource != null);

    // A class path cannot be a directory
    assertFalse("Class path cannot be a directory.", resource.isDirectory());

    // A class path must exist
    assertTrue("Class path resource does not exist.", resource.exists());
  }
  @Override
  public void setWar(String path) {
    super.setWar(path);

    try {
      Resource war = Resource.newResource(path);
      if (war.exists() && war.isDirectory() && getDescriptor() == null) {
        Resource webXml = war.addPath("WEB-INF/web.xml");
        setDescriptor(webXml.toString());
      }
    } catch (IOException e) {
      throw new BuildException(e);
    }
  }
  @Override
  public void configure(WebAppContext context) throws Exception {
    // cannot configure if the context is already started
    if (context.isStarted()) {
      if (LOG.isDebugEnabled())
        LOG.debug("Cannot configure webapp " + context + " after it is started");
      return;
    }

    Resource web_inf = context.getWebInf();

    // Add WEB-INF classes and lib classpaths
    if (web_inf != null
        && web_inf.isDirectory()
        && context.getClassLoader() instanceof WebAppClassLoader) {
      // Look for classes directory
      Resource classes = web_inf.addPath("classes/");
      if (classes.exists()) ((WebAppClassLoader) context.getClassLoader()).addClassPath(classes);

      // Look for jars
      Resource lib = web_inf.addPath("lib/");
      if (lib.exists() || lib.isDirectory())
        ((WebAppClassLoader) context.getClassLoader()).addJars(lib);
    }

    // Look for extra resource
    @SuppressWarnings("unchecked")
    List<Resource> resources = (List<Resource>) context.getAttribute(RESOURCE_URLS);
    if (resources != null) {
      Resource[] collection = new Resource[resources.size() + 1];
      int i = 0;
      collection[i++] = context.getBaseResource();
      for (Resource resource : resources) collection[i++] = resource;
      context.setBaseResource(new ResourceCollection(collection));
    }
  }
  /**
   * Parse all classes in a directory
   *
   * @param dir
   * @param resolver
   * @throws Exception
   */
  public void parseDir(Resource dir, ClassNameResolver resolver) throws Exception {
    // skip dirs whose name start with . (ie hidden)
    if (!dir.isDirectory() || !dir.exists() || dir.getName().startsWith(".")) return;

    if (LOG.isDebugEnabled()) {
      LOG.debug("Scanning dir {}", dir);
    }
    ;

    String[] files = dir.list();
    for (int f = 0; files != null && f < files.length; f++) {
      try {
        Resource res = dir.addPath(files[f]);
        if (res.isDirectory()) parseDir(res, resolver);
        else {
          // we've already verified the directories, so just verify the class file name
          String filename = res.getFile().getName();
          if (isValidClassFileName(filename)) {
            String name = res.getName();
            if ((resolver == null)
                || (!resolver.isExcluded(name)
                    && (!isParsed(name) || resolver.shouldOverride(name)))) {
              Resource r = Resource.newResource(res.getURL());
              if (LOG.isDebugEnabled()) {
                LOG.debug("Scanning class {}", r);
              }
              ;
              scanClass(r.getInputStream());
            }
          }
        }
      } catch (Exception ex) {
        LOG.warn(Log.EXCEPTION, ex);
      }
    }
  }
  /** Test a class path resource for directories. */
  @Test
  public void testClassPathResourceDirectory() throws Exception {
    final String classPathName = "/";

    Resource resource = Resource.newClassPathResource(classPathName);

    assertTrue(resource != null);

    // A class path must be a directory
    assertTrue("Class path must be a directory.", resource.isDirectory());

    assertTrue("Class path returned file must be a directory.", resource.getFile().isDirectory());

    // A class path must exist
    assertTrue("Class path resource does not exist.", resource.exists());
  }
Exemple #10
0
 /* ------------------------------------------------------------ */
 public Collection<Resource> getAllResources() {
   try {
     ArrayList<Resource> deep = new ArrayList<>();
     {
       String[] list = list();
       if (list != null) {
         for (String i : list) {
           Resource r = addPath(i);
           if (r.isDirectory()) deep.addAll(r.getAllResources());
           else deep.add(r);
         }
       }
     }
     return deep;
   } catch (Exception e) {
     throw new IllegalStateException(e);
   }
 }
Exemple #11
0
    public void addJars(Resource lib) throws IOException {
      if (lib == null || !lib.exists()) throw new IllegalStateException("No such lib: " + lib);

      String[] list = lib.list();
      if (list == null) return;

      for (String path : list) {
        if (".".equals(path) || "..".equals(path)) continue;

        try (Resource item = lib.addPath(path)) {
          if (item.isDirectory()) addJars(item);
          else {
            if (path.toLowerCase().endsWith(".jar") || path.toLowerCase().endsWith(".zip")) {
              URL url = item.getURL();
              _classpath.add(url);
            }
          }
        }
      }
    }
 /**
  * Look for any web-fragment.xml fragments in META-INF of jars in WEB-INF/lib
  *
  * @throws Exception
  */
 public void findWebFragments(final WebAppContext context, final MetaData metaData)
     throws Exception {
   @SuppressWarnings("unchecked")
   List<Resource> frags = (List<Resource>) context.getAttribute(FRAGMENT_RESOURCES);
   if (frags != null) {
     for (Resource frag : frags) {
       if (frag
           .isDirectory()) // tolerate the case where the library is a directory, not a jar. useful
                           // for OSGi for example
       {
         metaData.addFragment(
             frag, Resource.newResource(frag.getURL() + "/META-INF/web-fragment.xml"));
       } else // the standard case: a jar most likely inside WEB-INF/lib
       {
         metaData.addFragment(
             frag, Resource.newResource("jar:" + frag.getURL() + "!/META-INF/web-fragment.xml"));
       }
     }
   }
 }
  /**
   * Parse a resource
   *
   * @param r
   * @param resolver
   * @throws Exception
   */
  public void parse(Resource r, final ClassNameResolver resolver) throws Exception {
    if (r == null) return;

    if (r.exists() && r.isDirectory()) {
      parseDir(r, resolver);
      return;
    }

    String fullname = r.toString();
    if (fullname.endsWith(".jar")) {
      parseJar(r, resolver);
      return;
    }

    if (fullname.endsWith(".class")) {
      scanClass(r.getInputStream());
      return;
    }

    if (LOG.isDebugEnabled()) LOG.warn("Resource not scannable for classes: {}", r);
  }
  /** Test a class path resource for a file. */
  @Test
  public void testClassPathResourceFile() throws Exception {
    final String fileName = "resource.txt";
    final String classPathName = "/" + fileName;

    // Will locate a resource in the class path
    Resource resource = Resource.newClassPathResource(classPathName);

    assertTrue(resource != null);

    // A class path cannot be a directory
    assertFalse("Class path must be a directory.", resource.isDirectory());

    assertTrue(resource != null);

    File file = resource.getFile();

    assertTrue("File returned from class path should not be null.", file != null);
    assertEquals("File name from class path is not equal.", fileName, file.getName());
    assertTrue("File returned from class path should be a file.", file.isFile());

    // A class path must exist
    assertTrue("Class path resource does not exist.", resource.exists());
  }
  /** @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#configureWebApplication() */
  public void configureWebApplication() throws Exception {
    super.configureWebApplication();

    // Set up the location of the webapp.
    // There are 2 parts to this: setWar() and setBaseResource(). On standalone jetty,
    // the former could be the location of a packed war, while the latter is the location
    // after any unpacking. With this mojo, you are running an unpacked, unassembled webapp,
    // so the two locations should be equal.
    Resource webAppSourceDirectoryResource =
        Resource.newResource(webAppSourceDirectory.getCanonicalPath());
    if (webApp.getWar() == null) webApp.setWar(webAppSourceDirectoryResource.toString());

    if (webApp.getBaseResource() == null) webApp.setBaseResource(webAppSourceDirectoryResource);

    if (classesDirectory != null) webApp.setClasses(classesDirectory);
    if (useTestScope && (testClassesDirectory != null)) webApp.setTestClasses(testClassesDirectory);

    webApp.setWebInfLib(getDependencyFiles());

    // get copy of a list of war artifacts
    Set<Artifact> matchedWarArtifacts = new HashSet<Artifact>();

    // make sure each of the war artifacts is added to the scanner
    for (Artifact a : getWarArtifacts()) extraScanTargets.add(a.getFile());

    // process any overlays and the war type artifacts
    List<Overlay> overlays = new ArrayList<Overlay>();
    for (OverlayConfig config : warPluginInfo.getMavenWarOverlayConfigs()) {
      // overlays can be individually skipped
      if (config.isSkip()) continue;

      // an empty overlay refers to the current project - important for ordering
      if (config.isCurrentProject()) {
        Overlay overlay = new Overlay(config, null);
        overlays.add(overlay);
        continue;
      }

      // if a war matches an overlay config
      Artifact a = getArtifactForOverlay(config, getWarArtifacts());
      if (a != null) {
        matchedWarArtifacts.add(a);
        SelectiveJarResource r =
            new SelectiveJarResource(
                new URL("jar:" + Resource.toURL(a.getFile()).toString() + "!/"));
        r.setIncludes(config.getIncludes());
        r.setExcludes(config.getExcludes());
        Overlay overlay = new Overlay(config, r);
        overlays.add(overlay);
      }
    }

    // iterate over the left over war artifacts and unpack them (without include/exclude processing)
    // as necessary
    for (Artifact a : getWarArtifacts()) {
      if (!matchedWarArtifacts.contains(a)) {
        Overlay overlay =
            new Overlay(
                null,
                Resource.newResource(
                    new URL("jar:" + Resource.toURL(a.getFile()).toString() + "!/")));
        overlays.add(overlay);
      }
    }

    webApp.setOverlays(overlays);

    // if we have not already set web.xml location, need to set one up
    if (webApp.getDescriptor() == null) {
      // Has an explicit web.xml file been configured to use?
      if (webXml != null) {
        Resource r = Resource.newResource(webXml);
        if (r.exists() && !r.isDirectory()) {
          webApp.setDescriptor(r.toString());
        }
      }

      // Still don't have a web.xml file: try the resourceBase of the webapp, if it is set
      if (webApp.getDescriptor() == null && webApp.getBaseResource() != null) {
        Resource r = webApp.getBaseResource().addPath("WEB-INF/web.xml");
        if (r.exists() && !r.isDirectory()) {
          webApp.setDescriptor(r.toString());
        }
      }

      // Still don't have a web.xml file: finally try the configured static resource directory if
      // there is one
      if (webApp.getDescriptor() == null && (webAppSourceDirectory != null)) {
        File f = new File(new File(webAppSourceDirectory, "WEB-INF"), "web.xml");
        if (f.exists() && f.isFile()) {
          webApp.setDescriptor(f.getCanonicalPath());
        }
      }
    }
    getLog().info("web.xml file = " + webApp.getDescriptor());
    getLog().info("Webapp directory = " + webAppSourceDirectory.getCanonicalPath());
  }
Exemple #16
0
  /**
   * Configure a jetty instance and deploy the webapps presented as args
   *
   * @param args the command line arguments
   * @throws Exception if unable to configure
   */
  public void configure(String[] args) throws Exception {
    // handle classpath bits first so we can initialize the log mechanism.
    for (int i = 0; i < args.length; i++) {
      if ("--lib".equals(args[i])) {
        try (Resource lib = Resource.newResource(args[++i])) {
          if (!lib.exists() || !lib.isDirectory()) usage("No such lib directory " + lib);
          _classpath.addJars(lib);
        }
      } else if ("--jar".equals(args[i])) {
        try (Resource jar = Resource.newResource(args[++i])) {
          if (!jar.exists() || jar.isDirectory()) usage("No such jar " + jar);
          _classpath.addPath(jar);
        }
      } else if ("--classes".equals(args[i])) {
        try (Resource classes = Resource.newResource(args[++i])) {
          if (!classes.exists() || !classes.isDirectory())
            usage("No such classes directory " + classes);
          _classpath.addPath(classes);
        }
      } else if (args[i].startsWith("--")) i++;
    }

    initClassLoader();

    LOG.info("Runner");
    LOG.debug("Runner classpath {}", _classpath);

    String contextPath = __defaultContextPath;
    boolean contextPathSet = false;
    int port = __defaultPort;
    String host = null;
    int stopPort = 0;
    String stopKey = null;

    boolean runnerServerInitialized = false;

    for (int i = 0; i < args.length; i++) {
      switch (args[i]) {
        case "--port":
          port = Integer.parseInt(args[++i]);
          break;
        case "--host":
          host = args[++i];
          break;
        case "--stop-port":
          stopPort = Integer.parseInt(args[++i]);
          break;
        case "--stop-key":
          stopKey = args[++i];
          break;
        case "--log":
          _logFile = args[++i];
          break;
        case "--out":
          String outFile = args[++i];
          PrintStream out = new PrintStream(new RolloverFileOutputStream(outFile, true, -1));
          LOG.info("Redirecting stderr/stdout to " + outFile);
          System.setErr(out);
          System.setOut(out);
          break;
        case "--path":
          contextPath = args[++i];
          contextPathSet = true;
          break;
        case "--config":
          if (_configFiles == null) _configFiles = new ArrayList<>();
          _configFiles.add(args[++i]);
          break;
        case "--lib":
          ++i; // skip

          break;
        case "--jar":
          ++i; // skip

          break;
        case "--classes":
          ++i; // skip

          break;
        case "--stats":
          _enableStats = true;
          _statsPropFile = args[++i];
          _statsPropFile = ("unsecure".equalsIgnoreCase(_statsPropFile) ? null : _statsPropFile);
          break;
        default:
          // process contexts

          if (!runnerServerInitialized) // log handlers not registered, server maybe not created,
                                        // etc
          {
            if (_server == null) // server not initialized yet
            {
              // build the server
              _server = new Server();
            }

            // apply jetty config files if there are any
            if (_configFiles != null) {
              for (String cfg : _configFiles) {
                try (Resource resource = Resource.newResource(cfg)) {
                  XmlConfiguration xmlConfiguration = new XmlConfiguration(resource.getURL());
                  xmlConfiguration.configure(_server);
                }
              }
            }

            // check that everything got configured, and if not, make the handlers
            HandlerCollection handlers =
                (HandlerCollection) _server.getChildHandlerByClass(HandlerCollection.class);
            if (handlers == null) {
              handlers = new HandlerCollection();
              _server.setHandler(handlers);
            }

            // check if contexts already configured
            _contexts =
                (ContextHandlerCollection)
                    handlers.getChildHandlerByClass(ContextHandlerCollection.class);
            if (_contexts == null) {
              _contexts = new ContextHandlerCollection();
              prependHandler(_contexts, handlers);
            }

            if (_enableStats) {
              // if no stats handler already configured
              if (handlers.getChildHandlerByClass(StatisticsHandler.class) == null) {
                StatisticsHandler statsHandler = new StatisticsHandler();

                Handler oldHandler = _server.getHandler();
                statsHandler.setHandler(oldHandler);
                _server.setHandler(statsHandler);

                ServletContextHandler statsContext = new ServletContextHandler(_contexts, "/stats");
                statsContext.addServlet(new ServletHolder(new StatisticsServlet()), "/");
                statsContext.setSessionHandler(new SessionHandler());
                if (_statsPropFile != null) {
                  HashLoginService loginService =
                      new HashLoginService("StatsRealm", _statsPropFile);
                  Constraint constraint = new Constraint();
                  constraint.setName("Admin Only");
                  constraint.setRoles(new String[] {"admin"});
                  constraint.setAuthenticate(true);

                  ConstraintMapping cm = new ConstraintMapping();
                  cm.setConstraint(constraint);
                  cm.setPathSpec("/*");

                  ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
                  securityHandler.setLoginService(loginService);
                  securityHandler.setConstraintMappings(Collections.singletonList(cm));
                  securityHandler.setAuthenticator(new BasicAuthenticator());
                  statsContext.setSecurityHandler(securityHandler);
                }
              }
            }

            // ensure a DefaultHandler is present
            if (handlers.getChildHandlerByClass(DefaultHandler.class) == null) {
              handlers.addHandler(new DefaultHandler());
            }

            // ensure a log handler is present
            _logHandler =
                (RequestLogHandler) handlers.getChildHandlerByClass(RequestLogHandler.class);
            if (_logHandler == null) {
              _logHandler = new RequestLogHandler();
              handlers.addHandler(_logHandler);
            }

            // check a connector is configured to listen on
            Connector[] connectors = _server.getConnectors();
            if (connectors == null || connectors.length == 0) {
              ServerConnector connector = new ServerConnector(_server);
              connector.setPort(port);
              if (host != null) connector.setHost(host);
              _server.addConnector(connector);
              if (_enableStats) connector.addBean(new ConnectorStatistics());
            } else {
              if (_enableStats) {
                for (Connector connector : connectors) {
                  ((AbstractConnector) connector).addBean(new ConnectorStatistics());
                }
              }
            }

            runnerServerInitialized = true;
          }

          // Create a context
          try (Resource ctx = Resource.newResource(args[i])) {
            if (!ctx.exists()) usage("Context '" + ctx + "' does not exist");

            if (contextPathSet && !(contextPath.startsWith("/"))) contextPath = "/" + contextPath;

            // Configure the context
            if (!ctx.isDirectory() && ctx.toString().toLowerCase().endsWith(".xml")) {
              // It is a context config file
              XmlConfiguration xmlConfiguration = new XmlConfiguration(ctx.getURL());
              xmlConfiguration.getIdMap().put("Server", _server);
              ContextHandler handler = (ContextHandler) xmlConfiguration.configure();
              if (contextPathSet) handler.setContextPath(contextPath);
              _contexts.addHandler(handler);
              handler.setAttribute(
                  "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
                  __containerIncludeJarPattern);
            } else {
              // assume it is a WAR file
              WebAppContext webapp = new WebAppContext(_contexts, ctx.toString(), contextPath);
              webapp.setConfigurationClasses(__plusConfigurationClasses);
              webapp.setAttribute(
                  "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
                  __containerIncludeJarPattern);
            }
          }
          // reset
          contextPathSet = false;
          contextPath = __defaultContextPath;
          break;
      }
    }

    if (_server == null) usage("No Contexts defined");
    _server.setStopAtShutdown(true);

    switch ((stopPort > 0 ? 1 : 0) + (stopKey != null ? 2 : 0)) {
      case 1:
        usage("Must specify --stop-key when --stop-port is specified");
        break;

      case 2:
        usage("Must specify --stop-port when --stop-key is specified");
        break;

      case 3:
        ShutdownMonitor monitor = ShutdownMonitor.getInstance();
        monitor.setPort(stopPort);
        monitor.setKey(stopKey);
        monitor.setExitVm(true);
        break;
    }

    if (_logFile != null) {
      NCSARequestLog requestLog = new NCSARequestLog(_logFile);
      requestLog.setExtended(false);
      _logHandler.setRequestLog(requestLog);
    }
  }
  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);
  }
  /* ------------------------------------------------------------ */
  private HttpContent load(String pathInContext, Resource resource, int maxBufferSize)
      throws IOException {
    if (resource == null || !resource.exists()) return null;

    if (resource.isDirectory())
      return new ResourceHttpContent(
          resource, _mimeTypes.getMimeByExtension(resource.toString()), getMaxCachedFileSize());

    // Will it fit in the cache?
    if (isCacheable(resource)) {
      CachedHttpContent content = null;

      // Look for a gzip resource
      if (_gzip) {
        String pathInContextGz = pathInContext + ".gz";
        CachedHttpContent contentGz = _cache.get(pathInContextGz);
        if (contentGz == null || !contentGz.isValid()) {
          contentGz = null;
          Resource resourceGz = _factory.getResource(pathInContextGz);
          if (resourceGz.exists()
              && resourceGz.lastModified() >= resource.lastModified()
              && resourceGz.length() < resource.length()) {
            contentGz = new CachedHttpContent(pathInContextGz, resourceGz, null);
            CachedHttpContent added = _cache.putIfAbsent(pathInContextGz, contentGz);
            if (added != null) {
              contentGz.invalidate();
              contentGz = added;
            }
          }
        }
        content = new CachedHttpContent(pathInContext, resource, contentGz);
      } else content = new CachedHttpContent(pathInContext, resource, null);

      // Add it to the cache.
      CachedHttpContent added = _cache.putIfAbsent(pathInContext, content);
      if (added != null) {
        content.invalidate();
        content = added;
      }

      return content;
    }

    // Look for non Cacheable gzip resource or content
    String mt = _mimeTypes.getMimeByExtension(pathInContext);
    if (_gzip) {
      // Is the gzip content cached?
      String pathInContextGz = pathInContext + ".gz";
      CachedHttpContent contentGz = _cache.get(pathInContextGz);
      if (contentGz != null
          && contentGz.isValid()
          && contentGz.getResource().lastModified() >= resource.lastModified())
        return new ResourceHttpContent(resource, mt, maxBufferSize, contentGz);

      // Is there a gzip resource?
      Resource resourceGz = _factory.getResource(pathInContextGz);
      if (resourceGz.exists()
          && resourceGz.lastModified() >= resource.lastModified()
          && resourceGz.length() < resource.length())
        return new ResourceHttpContent(
            resource,
            mt,
            maxBufferSize,
            new ResourceHttpContent(
                resourceGz, _mimeTypes.getMimeByExtension(pathInContextGz), maxBufferSize));
    }

    return new ResourceHttpContent(resource, mt, maxBufferSize);
  }
    public void configureContextHandler() throws Exception {
      if (_configured) return;

      _configured = true;

      // Override for bundle root may have been set
      String bundleOverrideLocation =
          (String) _properties.get(OSGiWebappConstants.JETTY_BUNDLE_INSTALL_LOCATION_OVERRIDE);
      if (bundleOverrideLocation == null)
        bundleOverrideLocation =
            (String)
                _properties.get(OSGiWebappConstants.SERVICE_PROP_BUNDLE_INSTALL_LOCATION_OVERRIDE);

      // Location on filesystem of bundle or the bundle override location
      File bundleLocation =
          BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(_bundle);
      File root =
          (bundleOverrideLocation == null ? bundleLocation : new File(bundleOverrideLocation));
      Resource rootResource =
          Resource.newResource(
              BundleFileLocatorHelperFactory.getFactory()
                  .getHelper()
                  .getLocalURL(root.toURI().toURL()));

      // try and make sure the rootResource is useable - if its a jar then make it a jar file url
      if (rootResource.exists()
          && !rootResource.isDirectory()
          && !rootResource.toString().startsWith("jar:")) {
        Resource jarResource = JarResource.newJarResource(rootResource);
        if (jarResource.exists() && jarResource.isDirectory()) rootResource = jarResource;
      }

      // Set the base resource of the ContextHandler, if not already set, can also be overridden by
      // the context xml file
      if (_contextHandler != null && _contextHandler.getBaseResource() == null) {
        _contextHandler.setBaseResource(rootResource);
      }

      // Use a classloader that knows about the common jetty parent loader, and also the bundle
      OSGiClassLoader classLoader =
          new OSGiClassLoader(getServerInstanceWrapper().getParentClassLoaderForWebapps(), _bundle);

      // if there is a context file, find it and apply it
      if (_contextFile == null && _contextHandler == null)
        throw new IllegalStateException("No context file or ContextHandler");

      if (_contextFile != null) {
        // apply the contextFile, creating the ContextHandler, the DeploymentManager will register
        // it in the ContextHandlerCollection
        Resource res = null;

        // try to find the context file in the filesystem
        if (_contextFile.startsWith("/")) res = getFileAsResource(_contextFile);

        // try to find it relative to jetty home
        if (res == null) {
          // See if the specific server we are related to has jetty.home set
          String jettyHome =
              (String)
                  getServerInstanceWrapper()
                      .getServer()
                      .getAttribute(OSGiServerConstants.JETTY_HOME);
          if (jettyHome != null) res = getFileAsResource(jettyHome, _contextFile);

          // try to see if a SystemProperty for jetty.home is set
          if (res == null) {
            jettyHome = System.getProperty(OSGiServerConstants.JETTY_HOME);

            if (jettyHome != null) {
              if (jettyHome.startsWith("\"") || jettyHome.startsWith("'"))
                jettyHome = jettyHome.substring(1);
              if (jettyHome.endsWith("\"") || (jettyHome.endsWith("'")))
                jettyHome = jettyHome.substring(0, jettyHome.length() - 1);

              res = getFileAsResource(jettyHome, _contextFile);
              if (LOG.isDebugEnabled()) LOG.debug("jetty home context file:" + res);
            }
          }
        }

        // try to find it relative to an override location that has been specified
        if (res == null) {
          if (bundleOverrideLocation != null) {
            res =
                getFileAsResource(
                    Resource.newResource(bundleOverrideLocation).getFile(), _contextFile);
            if (LOG.isDebugEnabled()) LOG.debug("Bundle override location context file:" + res);
          }
        }

        // try to find it relative to the bundle in which it is being deployed
        if (res == null) {
          if (_contextFile.startsWith("./")) _contextFile = _contextFile.substring(1);

          if (!_contextFile.startsWith("/")) _contextFile = "/" + _contextFile;

          URL contextURL = _bundle.getEntry(_contextFile);
          if (contextURL != null) res = Resource.newResource(contextURL);
        }

        // apply the context xml file, either to an existing ContextHandler, or letting the
        // it create the ContextHandler as necessary
        if (res != null) {
          ClassLoader cl = Thread.currentThread().getContextClassLoader();

          LOG.debug("Context classloader = " + cl);
          try {
            Thread.currentThread().setContextClassLoader(classLoader);

            XmlConfiguration xmlConfiguration = new XmlConfiguration(res.getInputStream());
            HashMap properties = new HashMap();
            // put the server instance in
            properties.put("Server", getServerInstanceWrapper().getServer());
            // put in the location of the bundle root
            properties.put("bundle.root", rootResource.toString());

            // insert the bundle's location as a property.
            xmlConfiguration.getProperties().putAll(properties);

            if (_contextHandler == null)
              _contextHandler = (ContextHandler) xmlConfiguration.configure();
            else xmlConfiguration.configure(_contextHandler);
          } finally {
            Thread.currentThread().setContextClassLoader(cl);
          }
        }
      }

      // Set up the class loader we created
      _contextHandler.setClassLoader(classLoader);

      // If a bundle/service property specifies context path, let it override the context xml
      String contextPath = (String) _properties.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
      if (contextPath == null)
        contextPath = (String) _properties.get(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH);
      if (contextPath != null) _contextHandler.setContextPath(contextPath);

      // osgi Enterprise Spec r4 p.427
      _contextHandler.setAttribute(
          OSGiWebappConstants.OSGI_BUNDLECONTEXT, _bundle.getBundleContext());

      // make sure we protect also the osgi dirs specified by OSGi Enterprise spec
      String[] targets = _contextHandler.getProtectedTargets();
      int length = (targets == null ? 0 : targets.length);

      String[] updatedTargets = null;
      if (targets != null) {
        updatedTargets =
            new String[length + OSGiWebappConstants.DEFAULT_PROTECTED_OSGI_TARGETS.length];
        System.arraycopy(targets, 0, updatedTargets, 0, length);

      } else updatedTargets = new String[OSGiWebappConstants.DEFAULT_PROTECTED_OSGI_TARGETS.length];
      System.arraycopy(
          OSGiWebappConstants.DEFAULT_PROTECTED_OSGI_TARGETS,
          0,
          updatedTargets,
          length,
          OSGiWebappConstants.DEFAULT_PROTECTED_OSGI_TARGETS.length);
      _contextHandler.setProtectedTargets(updatedTargets);
    }
  public JettyWebAppContext configureWebApplication(MavenProject project, Log log)
      throws Exception {
    JettyWebAppContext webAppConfig = new JettyWebAppContext();

    Plugin plugin = project.getPlugin("com.polopoly.jetty:jetty-maven-plugin");
    Xpp3Dom config = (Xpp3Dom) plugin.getConfiguration();
    applyPOMWebAppConfig(config, webAppConfig);

    if (webAppConfig.getContextPath() == null || webAppConfig.getContextPath().length() < 1) {
      webAppConfig.setContextPath("/" + project.getArtifactId());
    }

    final File baseDir = project.getBasedir();
    final File webAppSourceDirectory = new File(baseDir, "src/main/webapp");
    final File classesDirectory = new File(baseDir, "target/classes");

    Resource webAppSourceDirectoryResource =
        Resource.newResource(webAppSourceDirectory.getCanonicalPath());
    if (webAppConfig.getWar() == null) {
      webAppConfig.setWar(webAppSourceDirectoryResource.toString());
    }

    if (webAppConfig.getBaseResource() == null) {
      webAppConfig.setBaseResource(webAppSourceDirectoryResource);
    }

    webAppConfig.setWebInfClasses(
        new ArrayList<File>() {
          {
            add(classesDirectory);
          }
        });
    addDependencies(project, webAppConfig);

    // if we have not already set web.xml location, need to set one up
    if (webAppConfig.getDescriptor() == null) {
      // Still don't have a web.xml file: try the resourceBase of the webapp, if it is set
      if (webAppConfig.getDescriptor() == null && webAppConfig.getBaseResource() != null) {
        Resource r = webAppConfig.getBaseResource().addPath("WEB-INF/web.xml");
        if (r.exists() && !r.isDirectory()) {
          webAppConfig.setDescriptor(r.toString());
        }
      }

      // Still don't have a web.xml file: finally try the configured static resource directory if
      // there is one
      if (webAppConfig.getDescriptor() == null && (webAppSourceDirectory != null)) {
        File f = new File(new File(webAppSourceDirectory, "WEB-INF"), "web.xml");
        if (f.exists() && f.isFile()) {
          webAppConfig.setDescriptor(f.getCanonicalPath());
        }
      }
    }

    // Turn off some default settings in jetty
    URL overrideWebXMLUrl = this.getClass().getResource("/com/polopoly/web_override.xml");
    if (overrideWebXMLUrl != null) {
      webAppConfig.addOverrideDescriptor(overrideWebXMLUrl.toExternalForm());
    }

    return webAppConfig;
  }
    public void configureWebApp() throws Exception {
      // TODO turn this around and let any context.xml file get applied first, and have the
      // properties override
      _webApp.setContextPath(_contextPath);

      // osgi Enterprise Spec r4 p.427
      _webApp.setAttribute(OSGiWebappConstants.OSGI_BUNDLECONTEXT, _bundle.getBundleContext());

      String overrideBundleInstallLocation =
          (String) _properties.get(OSGiWebappConstants.JETTY_BUNDLE_INSTALL_LOCATION_OVERRIDE);
      File bundleInstallLocation =
          (overrideBundleInstallLocation == null
              ? BundleFileLocatorHelperFactory.getFactory()
                  .getHelper()
                  .getBundleInstallLocation(_bundle)
              : new File(overrideBundleInstallLocation));
      URL url = null;
      Resource rootResource =
          Resource.newResource(
              BundleFileLocatorHelperFactory.getFactory()
                  .getHelper()
                  .getLocalURL(bundleInstallLocation.toURI().toURL()));
      // try and make sure the rootResource is useable - if its a jar then make it a jar file url
      if (rootResource.exists()
          && !rootResource.isDirectory()
          && !rootResource.toString().startsWith("jar:")) {
        Resource jarResource = JarResource.newJarResource(rootResource);
        if (jarResource.exists() && jarResource.isDirectory()) rootResource = jarResource;
      }

      // if the path wasn't set or it was ., then it is the root of the bundle's installed location
      if (_webAppPath == null || _webAppPath.length() == 0 || ".".equals(_webAppPath)) {
        url = bundleInstallLocation.toURI().toURL();
      } else {
        // Get the location of the root of the webapp inside the installed bundle
        if (_webAppPath.startsWith("/") || _webAppPath.startsWith("file:")) {
          url = new File(_webAppPath).toURI().toURL();
        } else if (bundleInstallLocation != null && bundleInstallLocation.isDirectory()) {
          url = new File(bundleInstallLocation, _webAppPath).toURI().toURL();
        } else if (bundleInstallLocation != null) {
          Enumeration<URL> urls =
              BundleFileLocatorHelperFactory.getFactory()
                  .getHelper()
                  .findEntries(_bundle, _webAppPath);
          if (urls != null && urls.hasMoreElements()) url = urls.nextElement();
        }
      }

      if (url == null) {
        throw new IllegalArgumentException(
            "Unable to locate "
                + _webAppPath
                + " in "
                + (bundleInstallLocation != null
                    ? bundleInstallLocation.getAbsolutePath()
                    : "unlocated bundle '" + _bundle.getSymbolicName() + "'"));
      }

      // Sets the location of the war file
      // converts bundleentry: protocol if necessary
      _webApp.setWar(
          BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(url).toString());

      // Set up what has been configured on the provider
      _webApp.setParentLoaderPriority(isParentLoaderPriority());
      _webApp.setExtractWAR(isExtract());
      if (getConfigurationClasses() != null)
        _webApp.setConfigurationClasses(getConfigurationClasses());
      else _webApp.setConfigurationClasses(__defaultConfigurations);

      if (getDefaultsDescriptor() != null) _webApp.setDefaultsDescriptor(getDefaultsDescriptor());

      // Set up configuration from manifest headers
      // extra classpath
      String tmp = (String) _properties.get(OSGiWebappConstants.JETTY_EXTRA_CLASSPATH);
      if (tmp != null) _webApp.setExtraClasspath(tmp);

      // web.xml
      tmp = (String) _properties.get(OSGiWebappConstants.JETTY_WEB_XML_PATH);
      if (tmp != null && tmp.trim().length() != 0) {
        File webXml = getFile(tmp, bundleInstallLocation);
        if (webXml != null && webXml.exists()) _webApp.setDescriptor(webXml.getAbsolutePath());
      }

      // webdefault.xml
      tmp = (String) _properties.get(OSGiWebappConstants.JETTY_DEFAULT_WEB_XML_PATH);
      if (tmp != null) {
        File defaultWebXml = getFile(tmp, bundleInstallLocation);
        if (defaultWebXml != null) {
          if (defaultWebXml.exists())
            _webApp.setDefaultsDescriptor(defaultWebXml.getAbsolutePath());
          else LOG.warn(defaultWebXml.getAbsolutePath() + " does not exist");
        }
      }

      // Handle Require-TldBundle
      // This is a comma separated list of names of bundles that contain tlds that this webapp uses.
      // We add them to the webapp classloader.
      String requireTldBundles = (String) _properties.get(OSGiWebappConstants.REQUIRE_TLD_BUNDLE);
      String pathsToTldBundles = getPathsToRequiredBundles(requireTldBundles);

      // make sure we provide access to all the jetty bundles by going
      // through this bundle.
      OSGiWebappClassLoader webAppLoader =
          new OSGiWebappClassLoader(
              _serverWrapper.getParentClassLoaderForWebapps(), _webApp, _bundle);

      if (pathsToTldBundles != null) webAppLoader.addClassPath(pathsToTldBundles);
      _webApp.setClassLoader(webAppLoader);

      // apply any META-INF/context.xml file that is found to configure
      // the webapp first
      applyMetaInfContextXml(rootResource);

      // pass the value of the require tld bundle so that the TagLibOSGiConfiguration
      // can pick it up.
      _webApp.setAttribute(OSGiWebappConstants.REQUIRE_TLD_BUNDLE, requireTldBundles);

      // Set up some attributes
      // rfc66
      _webApp.setAttribute(
          OSGiWebappConstants.RFC66_OSGI_BUNDLE_CONTEXT, _bundle.getBundleContext());

      // spring-dm-1.2.1 looks for the BundleContext as a different attribute.
      // not a spec... but if we want to support
      // org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext
      // then we need to do this to:
      _webApp.setAttribute(
          "org.springframework.osgi.web." + BundleContext.class.getName(),
          _bundle.getBundleContext());

      // also pass the bundle directly. sometimes a bundle does not have a
      // bundlecontext.
      // it is still useful to have access to the Bundle from the servlet
      // context.
      _webApp.setAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE, _bundle);
    }