| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.myfaces.buildtools.maven2.plugin.builder; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.FileReader; |
| import java.io.IOException; |
| import java.io.OutputStreamWriter; |
| import java.io.Reader; |
| import java.io.StringWriter; |
| import java.io.Writer; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.maven.plugin.AbstractMojo; |
| import org.apache.maven.plugin.MojoExecutionException; |
| import org.apache.maven.project.MavenProject; |
| import org.apache.myfaces.buildtools.maven2.plugin.builder.model.Model; |
| import org.apache.myfaces.buildtools.maven2.plugin.builder.utils.BuildException; |
| import org.apache.myfaces.buildtools.maven2.plugin.builder.utils.MavenPluginConsoleLogSystem; |
| import org.apache.myfaces.buildtools.maven2.plugin.builder.utils.MyfacesUtils; |
| import org.apache.velocity.Template; |
| import org.apache.velocity.VelocityContext; |
| import org.apache.velocity.app.VelocityEngine; |
| import org.apache.velocity.exception.ParseErrorException; |
| import org.apache.velocity.exception.ResourceNotFoundException; |
| import org.apache.velocity.runtime.RuntimeConstants; |
| import org.codehaus.plexus.util.IOUtil; |
| import org.codehaus.plexus.util.xml.Xpp3Dom; |
| import org.codehaus.plexus.util.xml.Xpp3DomBuilder; |
| import org.codehaus.plexus.util.xml.Xpp3DomWriter; |
| import org.codehaus.plexus.util.xml.pull.XmlPullParserException; |
| |
| /** |
| * Creates taglib (tld) and faces-config files. |
| * <p> |
| * This Mojo actually provides a generic goal that will run a configurable |
| * velocity template file and generate a single output file. The template is |
| * passed the full metadata model object, and can select from the model whatever |
| * data it wants. |
| * </p> |
| * <p> |
| * The execution can be configured with: |
| * <ul> |
| * <li>The name of the input template to be executed</li> |
| * <li>The name of the output file to be created</li> |
| * <li>Any number of variables which are accessable from the template |
| * (string values only)</li> |
| * </ul> |
| * </p> |
| * <p> |
| * The executed template has the following variables available to it: |
| * <ul> |
| * <li>model: the full metadata model for this project</li> |
| * <li>modelIds: specifies which items from the model should be processed</li> |
| * <li>baseContent: the full text of the contents of the "xmlBaseFile" (if any)</li> |
| * <li>utils: an instance of MyfacesUtils that provides static helper methods</li> |
| * <li>and whatever (name,value) pairs were configured via the "params" property |
| * of this mojo.</li> |
| * </ul> |
| * </p> |
| * |
| * @requiresDependencyResolution compile |
| * @goal make-config |
| * @phase generate-sources |
| */ |
| public class MakeConfigMojo extends AbstractMojo |
| { |
| /** |
| * The current maven project (auto-injected by Maven). |
| * |
| * @parameter expression="${project}" |
| * @readonly |
| */ |
| private MavenProject project; |
| |
| /** |
| * Defines the directory where the metadata file (META-INF/myfaces-metadata.xml) is loaded, |
| * and the generated file named by xmlFile parameter is created. |
| * |
| * @parameter expression="${project.build.directory}/generated-resources/myfaces-builder-plugin" |
| */ |
| private File buildDirectory; |
| |
| /** |
| * Defines the directory where the resource will be output. |
| * |
| * @since 1.0.4 |
| * @parameter expression="${project.build.directory}/generated-resources/myfaces-builder-plugin" |
| */ |
| private File outputDirectory; |
| |
| /** |
| * Name of the file from which the metadata model passed to the |
| * template will be read. This file is typically generated by an earlier |
| * execution of the BuildMetaDataMojo goal for the same maven project. |
| * |
| * @parameter |
| */ |
| private String metadataFile = "META-INF/myfaces-metadata.xml"; |
| |
| /** |
| * Specifies the name of the output file to be created. |
| * |
| * @parameter |
| */ |
| private String xmlFile = "META-INF/faces-config.xml"; |
| |
| /** |
| * A list of metadata model ids. |
| * <p> |
| * If not defined, then this defaults to a list containing just one string whose |
| * value is the same as the current maven project's artifactId. |
| * </p> |
| * <p> |
| * The complete metadata model is passed to the velocity template. This contains |
| * data about not just the model items defined in the calling project, but also |
| * about items imported from other projects. Each item in the model is |
| * labelled with a "model id" indicating which project it was defined by. |
| * </p> |
| * <p> |
| * This list of model ids is also passed to the template. The template can |
| * then use that data to select the relevant items from the full model. |
| * </p> |
| * |
| * @parameter |
| */ |
| private List modelIds; |
| |
| /** |
| * The base directory used when resolving references to external files from |
| * velocity #include and #parse commands within the executed template. |
| * |
| * @parameter expression="src/main/resources/META-INF" |
| */ |
| private File templateSourceDirectory; |
| |
| /** |
| * When defined, specifies an xml file whose top-level elements are to be copied |
| * directly into the created file. |
| * <p> |
| * This allows a hand-written file to be created containing data that cannot be |
| * automatically generated. All content beneath the root element of the specified |
| * file (but not the root element itself) is placed into a Velocity variable |
| * named "baseContent" that the template can reference. |
| * </p> |
| * <p> |
| * The template can do whatever it wants with this variable, but it is expected |
| * that the template will simply output this immediately after writing the |
| * root element of the output xml file. |
| * file. |
| * </p> |
| * <p> |
| * Note that any attributes or namespaces defined on the root element of the |
| * xmlBaseFile are ignored. |
| * </p> |
| * |
| * @parameter expression="src/main/conf/META-INF/faces-config-base.xml" |
| */ |
| private File xmlBaseFile; |
| |
| /** |
| * Specifies the Velocity template file to be executed. |
| * |
| * @parameter expression="faces-config11.vm" |
| */ |
| private String templateFile; |
| |
| /** |
| * A map of (name, value) pairs to be made available as Velocity variables |
| * for the executed template to access. |
| * |
| * @parameter |
| */ |
| private Map params; |
| |
| /** |
| * Execute the Mojo. |
| * <p> |
| * The metadata model is loaded, and the specified template is executed with |
| * any template output being written to the specified output file. |
| * </p> |
| */ |
| public void execute() throws MojoExecutionException |
| { |
| try |
| { |
| if (modelIds == null) |
| { |
| modelIds = new ArrayList(); |
| modelIds.add(project.getArtifactId()); |
| } |
| |
| // Load the metadata file from an xml file (presumably generated |
| // by an earlier execution of the build-metadata goal. |
| Model model = IOUtils.loadModel(new File(buildDirectory, |
| metadataFile)); |
| |
| // Flatten the model so that the template can access every property |
| // of each model item directly, even when the property is actually |
| // defined on an ancestor class or interface. |
| new Flattener(model).flatten(); |
| |
| generateConfigFromVelocity(model); |
| } |
| catch (IOException e) |
| { |
| throw new MojoExecutionException("Error during config generation", e); |
| } |
| catch (BuildException e) |
| { |
| throw new MojoExecutionException("Error during config generation", e); |
| } |
| } |
| |
| private void generateConfigFromVelocity(Model model) throws IOException, |
| MojoExecutionException |
| { |
| VelocityEngine velocityEngine = initVelocity(); |
| |
| VelocityContext baseContext = new VelocityContext(); |
| baseContext.put("utils", new MyfacesUtils()); |
| |
| String baseContent = ""; |
| |
| if (xmlBaseFile != null && xmlBaseFile.exists()) |
| { |
| getLog().info("using base content file: "+xmlBaseFile.getPath()); |
| |
| Reader reader = null; |
| try |
| { |
| reader = new FileReader(xmlBaseFile); |
| Xpp3Dom root = Xpp3DomBuilder.build(reader); |
| |
| StringWriter writer = new StringWriter(); |
| |
| Xpp3Dom [] children = root.getChildren(); |
| |
| for (int i = 0; i< children.length; i++) |
| { |
| Xpp3Dom dom = children[i]; |
| Xpp3DomWriter.write(writer, dom); |
| writer.write('\n'); |
| } |
| baseContent = writer.toString(); |
| writer.close(); |
| } |
| catch (XmlPullParserException e) |
| { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } |
| finally |
| { |
| reader.close(); |
| } |
| } |
| |
| baseContext.put("baseContent", baseContent); |
| |
| baseContext.put("model", model); |
| |
| baseContext.put("modelIds", modelIds); |
| |
| if (params != null) |
| { |
| //Load all parameters to the context, so the template can |
| //load it. This allow to generate any config file we want |
| //(faces-config, tld, facelet,....) |
| for (Iterator it = params.keySet().iterator(); it.hasNext();) |
| { |
| String key = (String) it.next(); |
| baseContext.put(key,params.get(key)); |
| } |
| } |
| |
| Writer writer = null; |
| File outFile = null; |
| |
| try |
| { |
| outFile = new File(outputDirectory, xmlFile); |
| |
| if ( !outFile.getParentFile().exists() ) |
| { |
| outFile.getParentFile().mkdirs(); |
| } |
| |
| writer = new OutputStreamWriter(new FileOutputStream(outFile)); |
| |
| Template template = velocityEngine.getTemplate(templateFile); |
| |
| template.merge(baseContext, writer); |
| |
| writer.flush(); |
| } |
| catch (ResourceNotFoundException e) |
| { |
| throw new MojoExecutionException( |
| "Error merging velocity templates: " + e.getMessage(), e); |
| } |
| catch (ParseErrorException e) |
| { |
| throw new MojoExecutionException( |
| "Error merging velocity templates: " + e.getMessage(), e); |
| } |
| catch (Exception e) |
| { |
| throw new MojoExecutionException( |
| "Error merging velocity templates: " + e.getMessage(), e); |
| } |
| finally |
| { |
| IOUtil.close(writer); |
| writer = null; |
| } |
| } |
| |
| private VelocityEngine initVelocity() throws MojoExecutionException |
| { |
| VelocityEngine velocityEngine = new VelocityEngine(); |
| |
| try |
| { |
| velocityEngine.setProperty( "resource.loader", "file, class" ); |
| velocityEngine.setProperty( "file.resource.loader.class", |
| "org.apache.velocity.runtime.resource.loader.FileResourceLoader"); |
| velocityEngine.setProperty( "file.resource.loader.path", templateSourceDirectory.getPath()); |
| velocityEngine.setProperty( "class.resource.loader.class", |
| "org.apache.myfaces.buildtools.maven2.plugin.builder.utils.RelativeClasspathResourceLoader" ); |
| velocityEngine.setProperty( "class.resource.loader.path", "META-INF"); |
| velocityEngine.setProperty( "velocimacro.library", "xmlMacros.vm"); |
| velocityEngine.setProperty( "velocimacro.permissions.allow.inline","true"); |
| velocityEngine.setProperty( "velocimacro.permissions.allow.inline.local.scope", "true"); |
| velocityEngine.setProperty( "directive.foreach.counter.initial.value","0"); |
| //velocityEngine.setProperty( RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, |
| //"org.apache.myfaces.buildtools.maven2.plugin.builder.utils.ConsoleLogSystem" ); |
| |
| velocityEngine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, |
| new MavenPluginConsoleLogSystem(this.getLog())); |
| |
| velocityEngine.init(); |
| } |
| catch (Exception e) |
| { |
| throw new MojoExecutionException("Error creating VelocityEngine", e); |
| } |
| |
| return velocityEngine; |
| } |
| |
| } |