See my comments below...

> -----Original Message-----
> From: Brett Porter [mailto:[EMAIL PROTECTED] 
> Sent: Sunday, August 07, 2005 00:22
> To: Maven Developers List
> Subject: Re: Question About Reactor Operation
> 
> 
> Hi,
> 
> Allison, Bob wrote:
> 
> >(I was going to try to find the reactor code in my SVN tree before
> >asking this, but can't seem to find it :-(  )
> >  
> >
> It's in DefaultMaven presently (it may have moved to the
> DefaultLifecycleExecutor in part, I haven't looked since the recent
> aggregation changes).
> 
> >Use Case 1:  There are a number of project directories which do not
> >produce artifacts (the top level and all mid-level directories, for
> >example) as well as a few projects which are samples and 
> should not be
> >included in the production deliverables.
> >  
> >
> Set these to packaging "pom".
If I set the packaging to "pom" on a sample project that is supposed to
produce a deployable web application, won't that mess up the build
process for that project?  I want to be able to produce proper artifacts
from the sample projects, just be able to automatically exclude them
from production builds.
> 
> >Use Case 2:  When generating documentation, I need to include the top
> >level and mid-level directories in order to get the 
> lower-level projects
> >documented.  I also want some of the samples to be included in the
> >product documentation.
> >  
> >
> We're working on a proposal for having the site become 
> reactor aware out
> of the box.
I'm not talking about making site reactor-aware (something I am eagerly
awaiting).  I am referring to being able to automatically exclude some
projects from the documentation.
> 
> >Use Case 3:  Because of some constraints in the portal server we are
> >using, we need to combine a few of the portlets into a single web
> >application.  We would like to keep the portlets in 
> individual projects
> >and be able to deploy the portlet either by itself or as part of a
> >combined web application.
> >  
> >
> This should be done by creating a web application subproject that
> depends on the portlet projects.
The main problem with that, I think, is the portlet-specific deplyment
descriptors.  In the 1.0.2 build tree we are currently using I have done
a bit of work to have these descriptors generated from project
properties in such a way that the descriptor is correct whether I
aggregated the portlets or not.
> 
> >In case 2, I filter the list of projects by replacing the
> >"multiproject:projects-init" goal with one that has all of 
> the original
> >code plus some additional code to remove projects that do 
> not have one
> >of the use case properties set to true (case 1 is
> >"productname.production", case 2 is "productname.document", case 3 is
> >"productname.one-app").  For the other two cases, I wrote my 
> own search
> >goal and provide the reactor with a list of projects.
> >  
> >
> I didn't catch how this acheieved what you were doing for the site?
See details below...
> 
> >It would be really nice to be able to create a plugin which 
> can contain
> >a method that the reactor calls after finding the project but before
> >starting to work on it; the method could return a true/false 
> to indicate
> >whether or not the project passes the filter.  To make this 
> transparent
> >to plugins that don't need this functionality, we would need 
> a concrete
> >implementation of the method in AbstractMojo which always 
> returns true
> >(unfortunately, this doesn't help those which choose to implement the
> >interface rather than extend the abstract base class).
> >  
> >
> I'm not sure this is necessary: you can simply check what you need to
> know about the project at the start of the execute() method and return
> successfully if you don't deal with it.
> 
> What you might be wanting is when it works in an aggregate mode, which
> works differently - the plugin goal is run at the top level with a
> selection of projects instead of being run on the subprojects 
> - in this
> case you can again filter the project list in the execute() method.
> 
> Interesting idea, but I'd probably want to look at more use cases and
> check whether they are already covered or not.
> 
> Thanks,
> Brett
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
> 
> 

Here are the details on how the use cases are built:

Use Case 1:  The top-level project has goals named "install",
"install-release", "deploy", and "deploy-release", all close to
identical except for whether they use snapshots and where the completed
artifacts are placed.  The install goal is defined as follows:
  <goal name="install" prereqs="find-projects"
        description="Generate the snapshot artifacts for the entire
project">
    <property name="buildgoal" value="install"/>
    <attainGoal name="build-artifacts"/>
  </goal>
The find-projects goal goes through the entire source tree to find
production projects:
  <goal name="find-projects"
        description="Generate the list of projects">

    <!-- Collect info on all potential deliverables -->
    <j:set var="includes"
value="framework/*/project.xml,rpms/*/project.xml"/>
    <j:set var="includes" value="${includes},ejb/*/project.xml"/>
    <j:set var="includes" value="${includes},portlets/*/project.xml"/>
    <j:set var="includes" value="${includes},one-app/project.xml"/>
    <maven:reactor
        basedir="${basedir}"
        postProcessing="true"
        includes="${includes}"
        collectOnly="true"
        banner="Collecting info on"
        ignoreFailures="true"/>

    <!-- Make a list of the production deliverables -->
    <j:useList var="prodbits"/>
    <j:forEach var="proj" items="${reactorProjects}">
      <j:if
test="${proj.context.getVariable('productname.production')=='true'}">
        <j:set var="dummy" value="${prodbits.add(proj)}"/>
      </j:if>
    </j:forEach>
  </goal>
The build-artifacts goal uses this list of projects to build artifacts:
  <goal name="build-artifacts"
        description="Generate the artifacts for the entire project">

    <!-- Build each deliverable and install it in the local repository
-->
    <maven:reactor
        basedir="${basedir}"
        projectList="${prodbits}"
        goals="${buildgoal}"
        banner="Building"/>
  </goal>
In this manner, all production artifacts are generated but no samples.

Use Case 2:  The top-level project has a goal named "gendocs" which uses
multiproject to build the mid-level documentation:
  <goal name="gendocs" prereqs="multiproject:site">
  </goal>
The top-level project has an entry in their project.properties
"maven.multiproject.site.goals=gendocs" so that the mid-level projects
process their child projects.  The mid-level projects set
"maven.multiproject.site.goals=site" so that their children do not
recurse any further.  To filter the projects that should not be
documented, the top-level project replaces the goal
"multiproject:projects-init" as follows:
  <!-- This replaces the goal in the multiproject plug-in so that the
       list of items to be documented can be filtered  -->
  <goal name="multiproject:projects-init">
    <maven:reactor
        basedir="${maven.multiproject.basedir}"
        banner="Gathering project list"
        includes="${maven.multiproject.includes}"
        excludes="${maven.multiproject.excludes}"
        postProcessing="true"
        collectOnly="true"
        collectionVar="multiprojects"
        ignoreFailures="${maven.multiproject.ignoreFailures}"
      />
    <j:useList var="togo"/> <!-- projects to drop -->
    <j:forEach var="proj" items="${multiprojects}">
      <j:if
test="${proj.context.getVariable('productname.production')!='true'}">
        <j:if
test="${proj.context.getVariable('productname.one-app')!='true'}">
          <j:if
test="${proj.context.getVariable('productname.document')!='true'}">
            <j:set var="dummy" value="${togo.add(proj)}"/>
          </j:if>
        </j:if>
      </j:if>
    </j:forEach>
    <j:set var="dummy" value="${multiprojects.removeAll(togo)}"/>
  </goal>

Use Case 3:  This one is the most complicated since I need to build a
portlet.xml file differently depending on whther the project is part of
the consolidated web application or not.  To build the portlet.xml file,
I defined a postGoal for war:webapp as follows:
  <postGoal name="war:webapp">
    <attainGoal name="makePortletXML"/>

    <j:if test="${makeXMLmode == 'one-app'}">
      <j:file name="${maven.build.dir}/portlet.xml"
              escapeText="false" omitXmlDeclaration="true"
              trim="false">
${portletXML}
      </j:file>
    </j:if>
    <j:if test="${makeXMLmode != 'one-app'}">
      <j:file
name="${maven.build.dir}/${pom.artifactId}/WEB-INF/portlet.xml"
              escapeText="false"
              trim="false">
&lt;portlet-app
xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd";
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
 
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.x
sd /opt/SUNWps/dtd/portlet.xsd" version="1.0"&gt;
${portletXML}
&lt;/portlet-app&gt;
      </j:file>
      <j:file
name="${maven.build.dir}/${pom.artifactId}/WEB-INF/web.xml"
              escapeText="false"
              trim="false">
&lt;!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd"&gt;

&lt;web-app&gt;
    &lt;display-name&gt;${pom.name} Application&lt;/display-name&gt;
&lt;/web-app&gt;
      </j:file>
    </j:if>
  </postGoal>
The goal "makePortletXML" constructs the body of the portlet.xml file
based on a number of properties defined for the project.  This goal
writes the file to be either the body XML fragment or the complete file
based on what is being built.  The consolidated web application is built
from a separate mid-level directory.  This directory has a postGoal
defined for war:webapp which builds the components and creates the
aggregated portlet.xml file:
  <postGoal name="war:webapp">
    <attainGoal name="buildComponents"/>

    <!-- Make the portlet.xml file -->
    <j:file
name="${maven.build.dir}/${pom.artifactId}/WEB-INF/portlet.xml"
            escapeText="false"
            trim="false">
&lt;portlet-app
xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd";
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
 
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.x
sd /opt/SUNWps/dtd/portlet.xsd" version="1.0"&gt;
${portletXML}
&lt;/portlet-app&gt;
    </j:file>
    <j:file name="${maven.build.dir}/${pom.artifactId}/WEB-INF/web.xml"
            escapeText="false"
            trim="false">
&lt;!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd"&gt;

&lt;web-app&gt;
    &lt;display-name&gt;${pom.name} Application&lt;/display-name&gt;
&lt;/web-app&gt;
    </j:file>
  </postGoal>
The goal to build the components depends on a goal which finds the
components:
  <goal name="findComponents"
        description="Find the list of components that go into this
project">
    <!-- Collect information on the portlets -->
    <maven:reactor basedir="${basedir}/../portlets"
                   banner="Collecting info on"
                   includes="*/project.xml"
                   collectOnly="true"
                   postProcessing="true"/>
    <j:useList var="allcomps"/>
    <j:useList var="portlets"/>
    <j:forEach var="proj" items="${reactorProjects}">
      <j:if
test="${proj.context.getVariable('qaccess.one-app')=='true'}">
        <j:set var="dummy" value="${portlets.add(proj)}"/>
        <j:set var="dummy" value="${allcomps.add(proj)}"/>
        ${proj.context.setVariable('makeXMLmode', 'one-app')}
      </j:if>
    </j:forEach>

    <!-- Collect information on the web applications -->
    <maven:reactor basedir="${basedir}/../web-apps"
                   banner="Collecting info on"
                   includes="*/project.xml"
                   collectOnly="true"
                   postProcessing="true"/>
    <j:useList var="webapps"/>
    <j:forEach var="proj" items="${reactorProjects}">
      <j:if
test="${proj.context.getVariable('qaccess.one-app')=='true'}">
        <j:set var="dummy" value="${webapps.add(proj)}"/>
        <j:set var="dummy" value="${allcomps.add(proj)}"/>
      </j:if>
    </j:forEach>
  </goal>
The goal to build the components attains the war:webapp goal in each
component using the reactor, then walks back through all of the
component projects and collects files and information into its project's
target directory:
  <goal name="buildComponents"
        prereqs="findComponents"
        description="Build the components that go into this project">

    <!-- Build each web application -->
    <maven:reactor basedir="${basedir}/../portlets"
                   banner="Building"
                   projectList="${allcomps}"
                   goals="clean,war:webapp"
                   postProcessing="true"/>

    <!-- Copy each portlet's application and collect XML info -->
    <j:set var="portletXML" value=""/>
    <j:set var="webXML" value=""/>
    <j:forEach var="proj" items="${portlets}">
      <j:set var="projbld"
             value="${proj.context.getVariable('maven.build.dir')}"/>

      <util:available file="${projbld}/portlet.xml">
        <util:loadText var="xml" file="${projbld}/portlet.xml"/>
        <j:set var="portletXML"
value="${portletXML}${line.separator}${xml}"/>
      </util:available>

      <util:available file="${projbld}/web.xml">
        <util:loadText var="xml" file="${projbld}/web.xml"/>
        <j:set var="webXML" value="${webXML}${line.separator}${xml}"/>
      </util:available>

      <j:set var="projdest"
value="${maven.build.dir}/${pom.artifactId}"/>
      <ant:mkdir dir="${projdest}/${proj.artifactId}"/>

      <copy toDir="${projdest}/${proj.artifactId}">
        <fileset dir="${projbld}/${proj.artifactId}"
                 includes="**"
                 excludes="WEB-INF/**"/>
      </copy>

      <copy toDir="${projdest}/WEB-INF/classes">
        <fileset dir="${projbld}/${proj.artifactId}/WEB-INF/classes"
                 includes="**"/>
      </copy>

      <copy toDir="${projdest}/WEB-INF/lib">
        <fileset dir="${projbld}/${proj.artifactId}/WEB-INF/lib"
                 includes="**"/>
      </copy>
    </j:forEach>
  </goal>

Does what I am doing make more sense now?

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to