You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by sk...@apache.org on 2008/06/21 21:46:06 UTC
svn commit: r670250 - in
/myfaces/myfaces-build-tools/trunk/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder:
BuildMetaDataMojo.java IOUtils.java
Author: skitching
Date: Sat Jun 21 12:46:05 2008
New Revision: 670250
URL: http://svn.apache.org/viewvc?rev=670250&view=rev
Log:
* add documentation
* simplify handling of dependencyModelIds; just load them all and discard some later.
This removes duplicated code in the IOUtils class.
Modified:
myfaces/myfaces-build-tools/trunk/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/BuildMetaDataMojo.java
myfaces/myfaces-build-tools/trunk/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/IOUtils.java
Modified: myfaces/myfaces-build-tools/trunk/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/BuildMetaDataMojo.java
URL: http://svn.apache.org/viewvc/myfaces/myfaces-build-tools/trunk/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/BuildMetaDataMojo.java?rev=670250&r1=670249&r2=670250&view=diff
==============================================================================
--- myfaces/myfaces-build-tools/trunk/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/BuildMetaDataMojo.java (original)
+++ myfaces/myfaces-build-tools/trunk/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/BuildMetaDataMojo.java Sat Jun 21 12:46:05 2008
@@ -26,8 +26,6 @@
import java.util.List;
import java.util.Map;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
@@ -44,6 +42,15 @@
* xml file for use by other goals of this plugin.
* <p>
* By default, the generated file is named "META-INF/myfaces-metadata.xml".
+ * This file will be included in the final artifact for this project. Having
+ * that metadata file embedded in the generated jarfile is useful for two
+ * purposes:
+ * <ul>
+ * <li>It is needed if other projects then use the maven-builder-plugin to
+ * create subclasses of the jsf classes in this project.
+ * <li>It is good documentation (more precise than the tld and faces-config.xml
+ * files).
+ * </ul>
* <p>
* Note that the generated file contains all the metadata needed by this
* project, including a copy of all the metadata from other projects that
@@ -58,8 +65,6 @@
*/
public class BuildMetaDataMojo extends AbstractMojo
{
- final Log log = LogFactory.getLog(BuildMetaDataMojo.class.getName());
-
/**
* Injected Maven project object.
*
@@ -69,27 +74,58 @@
private MavenProject project;
/**
- * Injected build directory for all generated stuff.
+ * Build directory for all generated stuff.
+ * <p>
+ * This mojo registers the specified directory with Maven as a resource dir. The
+ * maven-resources-plugin will then read the files from this dir and copy them
+ * into the "central" target directory from which the jarfile is built.
*
- * @parameter expression="${project.build.directory}/maven-faces-plugin/main/resources"
+ * @parameter expression="${project.build.directory}/myfaces-builder-plugin/main/resources"
*/
private File targetDirectory;
/**
- * Injected name of file to generate, relative to targetDirectory.
+ * Name of the metadata file to generate, relative to targetDirectory.
*
* @parameter
*/
private String outputFile = "META-INF/myfaces-metadata.xml";
/**
- *
+ * The modelId to associate with all model items discovered in the
+ * source directories of this project.
+ * <p>
+ * This value <i>must</i> be unique for each project. If not specified,
+ * then it defaults to the artifactId of the current maven project.
+ * <p>
+ * In later phases, goals are passed the complete metadata model which
+ * mixes items discovered here with items imported from metadata in
+ * other projects. The modelId is used to figure out which of the
+ * items should be processed (ie which ones are associated with this
+ * project) and which should be ignored.
+ * <p>
+ *
* @parameter expression="${project.artifactId}"
*/
private String modelId;
/**
- * Replace the package prefix
+ * Replace the package prefix.
+ * <p>
+ * This allows a project that inherits metadata from some other project to force
+ * copies of the Tag classes to be created in a namespace of its own choosing.
+ * <p>
+ * This is used in particular to create copies of the Tag classes in myfaces-impl
+ * within other projects so that they can be used as base classes for other tags
+ * within that project. The original tag present in the myfaces-impl.jar cannot
+ * be used as a base because that would prevent the derived project from running
+ * with other JSF implementations.
+ * <p>
+ * The child project first defines this (and replacePackagePrefixTagTo); as the
+ * inherited metadata is merged the tagClass attribute is modified. Then during
+ * the tag class generation goal, the modelId of the inherited project is included
+ * in the list of modelIds to process. That causes the tag classes to be generated
+ * again - but this time in a different package.
*
* @parameter
*/
@@ -97,76 +133,124 @@
/**
* Replace the package prefix
+ * <p>
+ * See replacePackagePrefixTagTo.
*
* @parameter
*/
private String replacePackagePrefixTagTo;
/**
+ * Specify the order in which models are to be merged (not usually needed).
+ * <p>
+ * When two different models define exactly the same item (ie the "class" attribute
+ * for two items is the same) then the one from the model that is merged first is
+ * used, and the later one is ignored.
+ * <p>
+ * This property allows the order of merging to be controlled; models are merged in
+ * the order specified in this list. Any models whose ids are not in this list are
+ * then merged in an undefined order at the end.
+ * <p>
+ * Setting this property is not normally necessary; typically models inherited from
+ * dependencies define different model items (ie have no overlap). However consider
+ * the situation where project A defines a model, project B extends A, then project C
+ * extends B. In this case, both A and B are in the dependencies, but the metadata in
+ * project B contains a complete copy of all the data from A. However B's metadata is
+ * from <i>the version of A that it was compiled against</i> which might not be the
+ * version of A that is in the dependencies. For safety in this case, it is better to
+ * ensure that project B's metadata is loaded first; this can possibly hide any new
+ * features (or bugfixes) from the new release of A, but also ensures that classes
+ * in C which extend classes in B do not declare features that B does not support.
+ * <p>
+ * This property is only needed in rare situations; normally it can be omitted.
*
* @parameter
*/
private List orderModelIds;
/**
+ * An optional list of models to import from dependency jars.
+ * <p>
+ * The default behaviour is to scan all jar dependencies for metadata files, and
+ * merge all the data into the model for this project. If this property is set,
+ * then metadata found in dependencies is only merged if the modelId matches one
+ * in this list.
+ * <p>
+ * Note that by default, a project's modelId is the same as the artifactId.
+ *
* @parameter
*/
private List dependencyModelIds;
/**
- * Alternate file to read model definition and merge it to the
- * current model, usually used when it is necessary to avoid dependencies.
- *
- * One example is when it is necessary a release of the library (tomahawk for
- * example), but the previous version of the scanned dependency library
- * (myfaces-api) does not have META-INF/myfaces-metadata.xml in his jar,
- * so when the metadata is generated the result is a lot of errors due to
- * the model is incomplete.
- *
- * Other use is when it is necessary to add some custom model definitions to
- * the model to be built, but this should be avoided. Instead, this goal should
- * be used on the dependency library, release the dependency library and
- * then the library that consume the metadata.
+ * The name of a metadata file to merge into the model for the current project.
+ * <p>
+ * This file is always loaded first, before any metadata from dependencies is
+ * loaded, and before scanning of the source directories for the current
+ * project is done.
+ * <p>
+ * The specified filename is relative to the current working directory.
+ * <p>
+ * Normally, this option is not used and any models that this project extends
+ * are simply automatically detected via scanning of the maven dependencies and
+ * loaded from the dependency jarfile. However there are a couple of situations
+ * where it is useful to specify an explicit metadata file to load instead.
+ * <p>
+ * One example is when a project extends components in a project which was not
+ * built with the myfaces-builder-plugin (or where myfaces-builder-plugin
+ * support is only in a not-yet-released version). In this case, a metadata file
+ * can be created by hand (or generated from the unreleased trunk version) and
+ * explicitly loaded via this property.
+ * <p>
+ * A second example is when it is necessary to add some custom model definitions to
+ * the model to be built, eg to override buggy or missing metadata in a project
+ * that this project extends. Of course this is hopefully not needed; it would be
+ * better to get a bugfix release of the parent project out instead!
*
* @parameter
*/
private File inputFile;
/**
- * Execute the Mojo.
+ * Create a metadata file containing information imported from other projects
+ * plus data extracted from annotated classes in this project.
*/
public void execute() throws MojoExecutionException
{
- try {
+ try
+ {
+ // Tell Maven to add this directory to its "resources" path.
+ // The maven-resources-plugin will then copy all the files
+ // from this directory to its own target directory, which is
+ // where the final jar artifact is built from.
addResourceRoot(project, targetDirectory.getCanonicalPath());
- }catch(IOException e){
+ }
+ catch(IOException e)
+ {
throw new MojoExecutionException("Error during generation", e);
}
+ List models = IOUtils.getModelsFromArtifacts(project);
+ models = sortModels(models);
+
Model model = new Model();
- List models = null;
- if (dependencyModelIds != null)
- {
- models = IOUtils.getModelsFromArtifacts(project,dependencyModelIds);
- }
- else
- {
- models = IOUtils.getModelsFromArtifacts(project);
- }
-
if (inputFile != null)
{
+ // An explicitly-specified input model takes precedence
Model fileModel = IOUtils.loadModel(inputFile);
- //The input model takes precedence
model.merge(fileModel);
}
- models = sortModels(models);
- for (Iterator it = models.iterator(); it.hasNext();){
+ for (Iterator it = models.iterator(); it.hasNext();)
+ {
Model artifactModel = (Model) it.next();
- model.merge(artifactModel);
+
+ if ((dependencyModelIds == null) || dependencyModelIds.contains(artifactModel.getModelId()))
+ {
+ model.merge(artifactModel);
+ }
}
buildModel(model, project);
@@ -178,10 +262,15 @@
}
/**
- * This function order the models as suggested by the modelIdOrder.
+ * Order the models as specified by the modelIdOrder property.
+ * <p>
* Tomahawk sandbox depends from myfaces-api and tomahawk core, so
* the myfaces-metadata.xml of tomahawk core must be merged first
* and then myfaces-api.
+ * <p>
+ * In some cases, the same metadata can be imported multiple times.
+ * For example, Project A has metadata. Project B extends A, and
+ * Project C extends B.
*
* @param models
* @return
@@ -196,12 +285,14 @@
Map modelsMap = new HashMap();
List modelsSorted = new ArrayList();
-
+
+ // First, put all models into a map keyed by modelId.
for (Iterator it = models.iterator(); it.hasNext();){
Model artifactModel = (Model) it.next();
modelsMap.put(artifactModel.getModelId(), artifactModel);
}
-
+
+ // now pull them out of the map in the order specified by orderModelIds.
for (Iterator it = orderModelIds.iterator(); it.hasNext();){
String modelId = (String) it.next();
@@ -212,7 +303,9 @@
modelsSorted.add(artifactModel);
}
}
-
+
+ // and any of the ones that remain in the map (ie had no order specified)
+ // now get added to the end of the list.
modelsSorted.addAll(modelsMap.values());
return modelsSorted;
@@ -237,7 +330,6 @@
{
comp.setTagClass(StringUtils.replaceOnce(
comp.getTagClass(), replacePackagePrefixTagFrom, replacePackagePrefixTagTo));
- log.info("Tag class changed to:"+comp.getTagClass());
}
}
}
Modified: myfaces/myfaces-build-tools/trunk/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/IOUtils.java
URL: http://svn.apache.org/viewvc/myfaces/myfaces-build-tools/trunk/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/IOUtils.java?rev=670250&r1=670249&r2=670250&view=diff
==============================================================================
--- myfaces/myfaces-build-tools/trunk/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/IOUtils.java (original)
+++ myfaces/myfaces-build-tools/trunk/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/IOUtils.java Sat Jun 21 12:46:05 2008
@@ -234,7 +234,12 @@
return model;
}
-
+
+ /**
+ * Scan every jarfile that this maven project has a dependency on, looking for metadata files.
+ * <p>
+ * Each file found is loaded into memory as a Model object and added to the list.
+ */
public static List getModelsFromArtifacts(MavenProject project)
throws MojoExecutionException
{
@@ -264,121 +269,14 @@
is = getStream(MYFACES_METADATA, archetypeJarLoader);
- if (is == null)
- {
-
- //System.out.println("Artifact: "
- // + artifact.getFile().getName()
- // + " does not have META-INF/myfaces-metadata.xml");
- }
- else
- {
- Reader r = null;
- try
- {
- r = new InputStreamReader(is);
- Model m = readModel(r);
- models.add(m);
- r.close();
- }
- catch (IOException e)
- {
- throw new MojoExecutionException(
- "Error reading myfaces-metadata.xml form "
- + artifact.getFile().getName(), e);
- }
- finally
- {
- if (r != null)
- {
- try
- {
- r.close();
- }
- catch (IOException e)
- {
- //ignore
- }
- }
- }
-
- System.out.println("Artifact: "
- + artifact.getFile().getName()
- + " have META-INF/myfaces-metadata.xml");
- }
- }
- catch (IOException e)
- {
- throw new MojoExecutionException(
- "Error reading myfaces-metadata.xml form "
- + artifact.getFile().getName(), e);
- }
- finally
- {
if (is != null)
{
- try
- {
- is.close();
- }
- catch (IOException ex)
- {
- //ignore
- }
- }
- }
- }
- }
- return models;
- }
-
- public static List getModelsFromArtifacts(MavenProject project,
- List dependencyModelIds) throws MojoExecutionException
- {
- List models = new ArrayList();
-
- for (Iterator it = project.getArtifacts().iterator(); it.hasNext();)
- {
-
- Artifact artifact = (Artifact) it.next();
-
- if ("compile".equals(artifact.getScope())
- || "provided".equals(artifact.getScope())
- || "system".equals(artifact.getScope()))
- {
- //This is safe since we have all depencencies on the
- //pom, so they are downloaded first by maven.
- File jarFile = artifact.getFile();
-
- URLClassLoader archetypeJarLoader;
-
- InputStream is = null;
- try
- {
- URL[] urls = new URL[1];
- urls[0] = jarFile.toURL();
- archetypeJarLoader = new URLClassLoader(urls);
-
- is = getStream(MYFACES_METADATA, archetypeJarLoader);
-
- if (is == null)
- {
-
- //System.out.println("Artifact: "
- // + artifact.getFile().getName()
- // + " does not have META-INF/myfaces-metadata.xml");
- }
- else
- {
Reader r = null;
try
{
r = new InputStreamReader(is);
Model m = readModel(r);
- if (dependencyModelIds.contains(m.getModelId()))
- {
- models.add(m);
- }
+ models.add(m);
r.close();
}
catch (IOException e)
@@ -431,7 +329,6 @@
}
return models;
}
-
private static InputStream getStream( String name,
ClassLoader loader )