/**
   * @param o
   * @param a
   * @return
   */
  protected boolean overlayMatchesArtifact(OverlayConfig o, Artifact a) {
    if (((o.getGroupId() == null && a.getGroupId() == null)
            || (o.getGroupId() != null && o.getGroupId().equals(a.getGroupId())))
        && ((o.getArtifactId() == null && a.getArtifactId() == null)
            || (o.getArtifactId() != null && o.getArtifactId().equals(a.getArtifactId())))
        && ((o.getClassifier() == null) || (o.getClassifier().equals(a.getClassifier()))))
      return true;

    return false;
  }
  /** @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());
  }
  /**
   * @return
   * @throws MojoExecutionException
   */
  public File prepareConfiguration() throws MojoExecutionException {
    try {
      // work out the configuration based on what is configured in the pom
      File propsFile = new File(target, "fork.props");
      if (propsFile.exists()) propsFile.delete();

      propsFile.createNewFile();
      // propsFile.deleteOnExit();

      Properties props = new Properties();

      // web.xml
      if (webXml != null) props.put("web.xml", webXml);

      // sort out the context path
      if (contextPath != null) props.put("context.path", contextPath);

      // sort out the tmp directory (make it if it doesn't exist)
      if (tmpDirectory != null) {
        if (!tmpDirectory.exists()) tmpDirectory.mkdirs();
        props.put("tmp.dir", tmpDirectory.getAbsolutePath());
      }

      // sort out base dir of webapp
      if (webAppSourceDirectory != null)
        props.put("base.dir", webAppSourceDirectory.getAbsolutePath());

      // sort out the resource base directories of the webapp
      StringBuilder builder = new StringBuilder();
      props.put("base.first", Boolean.toString(baseAppFirst));

      // web-inf classes
      List<File> classDirs = getClassesDirs();
      StringBuffer strbuff = new StringBuffer();
      for (int i = 0; i < classDirs.size(); i++) {
        File f = classDirs.get(i);
        strbuff.append(f.getAbsolutePath());
        if (i < classDirs.size() - 1) strbuff.append(",");
      }

      if (classesDirectory != null) {
        props.put("classes.dir", classesDirectory.getAbsolutePath());
      }

      if (useTestScope && testClassesDirectory != null) {
        props.put("testClasses.dir", testClassesDirectory.getAbsolutePath());
      }

      // web-inf lib
      List<File> deps = getDependencyFiles();
      strbuff.setLength(0);
      for (int i = 0; i < deps.size(); i++) {
        File d = deps.get(i);
        strbuff.append(d.getAbsolutePath());
        if (i < deps.size() - 1) strbuff.append(",");
      }
      props.put("lib.jars", strbuff.toString());

      // any war files
      List<Artifact> warArtifacts = getWarArtifacts();
      for (int i = 0; i < warArtifacts.size(); i++) {
        strbuff.setLength(0);
        Artifact a = warArtifacts.get(i);
        strbuff.append(a.getGroupId() + ",");
        strbuff.append(a.getArtifactId() + ",");
        strbuff.append(a.getFile().getAbsolutePath());
        props.put("maven.war.artifact." + i, strbuff.toString());
      }

      // any overlay configuration
      WarPluginInfo warPlugin = new WarPluginInfo(project);

      // add in the war plugins default includes and excludes
      props.put("maven.war.includes", toCSV(warPlugin.getDependentMavenWarIncludes()));
      props.put("maven.war.excludes", toCSV(warPlugin.getDependentMavenWarExcludes()));

      List<OverlayConfig> configs = warPlugin.getMavenWarOverlayConfigs();
      int i = 0;
      for (OverlayConfig c : configs) {
        props.put("maven.war.overlay." + (i++), c.toString());
      }

      props.store(
          new BufferedOutputStream(new FileOutputStream(propsFile)),
          "properties for forked webapp");
      return propsFile;
    } catch (Exception e) {
      throw new MojoExecutionException("Prepare webapp configuration", e);
    }
  }