/**
     * Initialisation routine called after handler creation with the element name and attributes.
     * The attributes which this handler can deal with are: <code>"name"</code>, <code>"depends"
     * </code>, <code>"if"</code>, <code>"unless"</code>, <code>"id"</code> and <code>"description"
     * </code>.
     *
     * @param uri The namespace URI for this element.
     * @param tag Name of the element which caused this handler to be created. Should not be <code>
     *     null</code>. Ignored in this implementation.
     * @param qname The qualified name for this element.
     * @param attrs Attributes of the element which caused this handler to be created. Must not be
     *     <code>null</code>.
     * @param context The current context.
     * @exception SAXParseException if an unexpected attribute is encountered or if the <code>"name"
     *     </code> attribute is missing.
     */
    public void onStartElement(
        String uri, String tag, String qname, Attributes attrs, AntXMLContext context)
        throws SAXParseException {
      String name = null;
      String depends = "";
      String extensionPoint = null;
      OnMissingExtensionPoint extensionPointMissing = null;

      Project project = context.getProject();
      Target target = "target".equals(tag) ? new Target() : new ExtensionPoint();
      target.setProject(project);
      target.setLocation(new Location(context.getLocator()));
      context.addTarget(target);

      for (int i = 0; i < attrs.getLength(); i++) {
        String attrUri = attrs.getURI(i);
        if (attrUri != null && !attrUri.equals("") && !attrUri.equals(uri)) {
          continue; // Ignore attributes from unknown uris
        }
        String key = attrs.getLocalName(i);
        String value = attrs.getValue(i);

        if (key.equals("name")) {
          name = value;
          if ("".equals(name)) {
            throw new BuildException("name attribute must " + "not be empty");
          }
        } else if (key.equals("depends")) {
          depends = value;
        } else if (key.equals("if")) {
          target.setIf(value);
        } else if (key.equals("unless")) {
          target.setUnless(value);
        } else if (key.equals("id")) {
          if (value != null && !value.equals("")) {
            context.getProject().addReference(value, target);
          }
        } else if (key.equals("description")) {
          target.setDescription(value);
        } else if (key.equals("extensionOf")) {
          extensionPoint = value;
        } else if (key.equals("onMissingExtensionPoint")) {
          try {
            extensionPointMissing = OnMissingExtensionPoint.valueOf(value);
          } catch (IllegalArgumentException e) {
            throw new BuildException("Invalid onMissingExtensionPoint " + value);
          }
        } else {
          throw new SAXParseException("Unexpected attribute \"" + key + "\"", context.getLocator());
        }
      }

      if (name == null) {
        throw new SAXParseException(
            "target element appears without a name attribute", context.getLocator());
      }

      String prefix = null;
      boolean isInIncludeMode = context.isIgnoringProjectTag() && isInIncludeMode();
      String sep = getCurrentPrefixSeparator();

      if (isInIncludeMode) {
        prefix = getTargetPrefix(context);
        if (prefix == null) {
          throw new BuildException(
              "can't include build file "
                  + context.getBuildFileURL()
                  + ", no as attribute has been given"
                  + " and the project tag doesn't"
                  + " specify a name attribute");
        }
        name = prefix + sep + name;
      }

      // Check if this target is in the current build file
      if (context.getCurrentTargets().get(name) != null) {
        throw new BuildException("Duplicate target '" + name + "'", target.getLocation());
      }
      Hashtable projectTargets = project.getTargets();
      boolean usedTarget = false;
      // If the name has not already been defined define it
      if (projectTargets.containsKey(name)) {
        project.log(
            "Already defined in main or a previous import, ignore " + name, Project.MSG_VERBOSE);
      } else {
        target.setName(name);
        context.getCurrentTargets().put(name, target);
        project.addOrReplaceTarget(name, target);
        usedTarget = true;
      }

      if (depends.length() > 0) {
        if (!isInIncludeMode) {
          target.setDepends(depends);
        } else {
          for (Iterator iter = Target.parseDepends(depends, name, "depends").iterator();
              iter.hasNext(); ) {
            target.addDependency(prefix + sep + iter.next());
          }
        }
      }
      if (!isInIncludeMode
          && context.isIgnoringProjectTag()
          && (prefix = getTargetPrefix(context)) != null) {
        // In an imported file (and not completely
        // ignoring the project tag or having a preconfigured prefix)
        String newName = prefix + sep + name;
        Target newTarget = usedTarget ? new Target(target) : target;
        newTarget.setName(newName);
        context.getCurrentTargets().put(newName, newTarget);
        project.addOrReplaceTarget(newName, newTarget);
      }
      if (extensionPointMissing != null && extensionPoint == null) {
        throw new BuildException(
            "onMissingExtensionPoint attribute cannot "
                + "be specified unless extensionOf is specified",
            target.getLocation());
      }
      if (extensionPoint != null) {
        ProjectHelper helper =
            (ProjectHelper)
                context.getProject().getReference(ProjectHelper.PROJECTHELPER_REFERENCE);
        for (Iterator iter = Target.parseDepends(extensionPoint, name, "extensionOf").iterator();
            iter.hasNext(); ) {
          String tgName = (String) iter.next();
          if (isInIncludeMode()) {
            tgName = prefix + sep + tgName;
          }
          if (extensionPointMissing == null) {
            extensionPointMissing = OnMissingExtensionPoint.FAIL;
          }
          // defer extensionpoint resolution until the full
          // import stack has been processed
          helper.getExtensionStack().add(new String[] {tgName, name, extensionPointMissing.name()});
        }
      }
    }
예제 #2
0
  private List generateSequence(List projects) {
    DefaultModelFactory factory = new DefaultModelFactory();
    Repository repository = (Repository) getProject().getReference("q.project.repository");
    factory.setRepository(repository);

    // 1st pass: map artifacts generated from each project to a target representing their project
    // files
    Project tempProject = new Project();

    Map targetsByArtifact = new HashMap();
    Map targetsByProject = new HashMap();
    List models = new ArrayList();

    for (Iterator i = projects.iterator(); i.hasNext(); ) {
      File projectFile = (File) i.next();

      // For now, we assume the default profile will contain all dependencies
      ProjectModel model =
          factory.getProjectModel(
              projectFile, Collections.EMPTY_LIST, true, null, new TaskLogger(this), getProject());
      models.add(model);

      // Create a target for each project file
      Target target = new Target();
      target.setName(projectFile.getAbsolutePath());
      tempProject.addTarget(target);
      targetsByProject.put(model.getProject().getProjectFile(), target);

      // Map the artifacts to the target
      for (Iterator j = model.getProject().getArtifacts().iterator(); j.hasNext(); ) {
        Artifact artifact = (Artifact) j.next();
        targetsByArtifact.put(artifact.getId(), target);
      }
    }

    // 2nd pass: Process project dependencies. Where a dependency uses an artifactId found in the
    // 1st pass,
    // set up a dependency between the projects.
    for (Iterator i = models.iterator(); i.hasNext(); ) {
      ProjectModel model = (ProjectModel) i.next();
      Target projectTarget = (Target) targetsByProject.get(model.getProject().getProjectFile());

      Set dependencies = getDependencies(model);

      // Where there is a dependency between projects, mirror it in the targets
      for (Iterator j = dependencies.iterator(); j.hasNext(); ) {
        RepoArtifactId id = (RepoArtifactId) j.next();
        Target dependencyTarget = (Target) targetsByArtifact.get(id);

        if (dependencyTarget != null) {
          projectTarget.addDependency(dependencyTarget.getName());
        }
      }
    }

    // Use ANT's target dependency mechanism to produce a build sequence
    String anyTarget = ((Target) targetsByArtifact.values().iterator().next()).getName();
    Collection sequencedTargets = tempProject.topoSort(anyTarget, tempProject.getTargets());

    // Transform targets into a list of files
    List sequence = new ArrayList();

    for (Iterator i = sequencedTargets.iterator(); i.hasNext(); ) {
      Target seqTarget = (Target) i.next();
      sequence.add(new File(seqTarget.getName()));
    }

    return sequence;
  }
  /**
   * Parse a source xml input.
   *
   * @param project the current project
   * @param source the xml source
   * @exception BuildException if an error occurs
   */
  public void parse(Project project, Object source) throws BuildException {
    getImportStack().addElement(source);
    AntXMLContext context = null;
    context = (AntXMLContext) project.getReference(REFID_CONTEXT);
    if (context == null) {
      context = new AntXMLContext(project);
      project.addReference(REFID_CONTEXT, context);
      project.addReference(REFID_TARGETS, context.getTargets());
    }
    if (getImportStack().size() > 1) {
      // we are in an imported file.
      context.setIgnoreProjectTag(true);
      Target currentTarget = context.getCurrentTarget();
      Target currentImplicit = context.getImplicitTarget();
      Map currentTargets = context.getCurrentTargets();
      try {
        Target newCurrent = new Target();
        newCurrent.setProject(project);
        newCurrent.setName("");
        context.setCurrentTarget(newCurrent);
        context.setCurrentTargets(new HashMap());
        context.setImplicitTarget(newCurrent);
        parse(project, source, new RootHandler(context, mainHandler));
        newCurrent.execute();
      } finally {
        context.setCurrentTarget(currentTarget);
        context.setImplicitTarget(currentImplicit);
        context.setCurrentTargets(currentTargets);
      }
    } else {
      // top level file
      context.setCurrentTargets(new HashMap());
      parse(project, source, new RootHandler(context, mainHandler));
      // Execute the top-level target
      context.getImplicitTarget().execute();

      // resolve extensionOf attributes
      for (Iterator i = getExtensionStack().iterator(); i.hasNext(); ) {
        String[] extensionInfo = (String[]) i.next();
        String tgName = extensionInfo[0];
        String name = extensionInfo[1];
        OnMissingExtensionPoint missingBehaviour =
            OnMissingExtensionPoint.valueOf(extensionInfo[2]);
        Hashtable projectTargets = project.getTargets();
        if (!projectTargets.containsKey(tgName)) {
          String message =
              "can't add target "
                  + name
                  + " to extension-point "
                  + tgName
                  + " because the extension-point is unknown.";
          if (missingBehaviour == OnMissingExtensionPoint.FAIL) {
            throw new BuildException(message);
          } else if (missingBehaviour == OnMissingExtensionPoint.WARN) {
            Target target = (Target) projectTargets.get(name);
            context.getProject().log(target, "Warning: " + message, Project.MSG_WARN);
          }
        } else {
          Target t = (Target) projectTargets.get(tgName);
          if (!(t instanceof ExtensionPoint)) {
            throw new BuildException("referenced target " + tgName + " is not an extension-point");
          }
          t.addDependency(name);
        }
      }
    }
  }