blob: aacef2284206bcbe18c31cc40271347186e2661b [file] [log] [blame]
/*
* 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.faces;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.myfaces.buildtools.maven2.plugin.faces.generator.component.ComponentGenerator;
import org.apache.myfaces.buildtools.maven2.plugin.faces.generator.component.MyFacesComponentGenerator;
import org.apache.myfaces.buildtools.maven2.plugin.faces.generator.component.TrinidadComponentGenerator;
import org.apache.myfaces.buildtools.maven2.plugin.faces.io.PrettyWriter;
import org.apache.myfaces.buildtools.maven2.plugin.faces.parse.ComponentBean;
import org.apache.myfaces.buildtools.maven2.plugin.faces.parse.FacesConfigBean;
import org.apache.myfaces.buildtools.maven2.plugin.faces.util.ComponentFilter;
import org.apache.myfaces.buildtools.maven2.plugin.faces.util.FilteredIterator;
import org.apache.myfaces.buildtools.maven2.plugin.faces.util.SourceTemplate;
import org.apache.myfaces.buildtools.maven2.plugin.faces.util.Util;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.lang.reflect.Modifier;
import java.util.Iterator;
/**
* @version $Id$
* @requiresDependencyResolution compile
* @goal generate-components
* @phase generate-sources
*/
public class GenerateComponentsMojo extends AbstractFacesMojo
{
/**
* Execute the Mojo.
*/
public void execute() throws MojoExecutionException
{
try
{
processIndex(project, resourcePath);
_generateComponents();
}
catch (IOException e)
{
throw new MojoExecutionException("Error generating components", e);
}
}
/**
* Generates parsed components.
*/
private void _generateComponents() throws IOException, MojoExecutionException
{
// Make sure generated source directory
// is added to compilation source path
project.addCompileSourceRoot(generatedSourceDirectory.getCanonicalPath());
FacesConfigBean facesConfig = getFacesConfig();
if (!facesConfig.hasComponents())
{
getLog().info("Nothing to generate - no components found");
}
else
{
if (suppressListenerMethods)
{
getLog().warn("Event listener methods will not be generated");
}
Iterator components = facesConfig.components();
components = new FilteredIterator(components, new SkipFilter());
components = new FilteredIterator(components,
new ComponentTypeFilter(typePrefix));
// incremental unless forced
if (!force)
{
components = new FilteredIterator(components, new IfModifiedFilter());
}
if (!components.hasNext())
{
getLog().info("Nothing to generate - all components are up to date");
}
else
{
int count = 0;
while (components.hasNext())
{
ComponentBean component = (ComponentBean)components.next();
if (!component.isComponentClassExcluded()){
_generateComponent(component);
count++;
}
}
getLog().info("Generated " + count + " component(s)");
}
}
}
/**
* Generates a parsed component.
*
* @param component the parsed component metadata
*/
private void _generateComponent(
ComponentBean component) throws MojoExecutionException
{
ComponentGenerator generator;
String fullClassName = component.getComponentClass();
if (component.isTrinidadComponent())
{
generator = new TrinidadComponentGenerator(getLog(), _is12());
}
else
{
generator = new MyFacesComponentGenerator(getLog(),_is12() );
}
try
{
getLog().debug("Generating " + fullClassName+", with generator: "+generator.getClass().getName());
String sourcePath = Util.convertClassToSourcePath(fullClassName, ".java");
File targetFile = new File(generatedSourceDirectory, sourcePath);
StringWriter sw = new StringWriter();
PrettyWriter out = new PrettyWriter(sw);
String className = Util.getClassFromFullClass(fullClassName);
String componentFamily = component.findComponentFamily();
if (componentFamily == null)
{
getLog().warn("Missing <component-family> for \"" +
fullClassName + "\", generation of this Component is skipped");
}
else
{
String packageName = Util.getPackageFromFullClass(fullClassName);
String fullSuperclassName = component.findComponentSuperclass();
String superclassName = Util.getClassFromFullClass(fullSuperclassName);
// make class name fully qualified in case of collision
if (superclassName.equals(className))
superclassName = fullSuperclassName;
// TODO: remove this bogosity
if (superclassName.equals("UIXMenuHierarchy") ||
superclassName.equals("UIXTable") ||
superclassName.equals("UIXHierarchy") ||
superclassName.equals("UIXMenuTree") ||
className.equals("CoreTree"))
{
superclassName = fullSuperclassName;
}
String componentType = component.getComponentType();
// Use template file if it exists
String templatePath = Util.convertClassToSourcePath(fullClassName, "Template.java");
File templateFile = new File(templateSourceDirectory, templatePath);
SourceTemplate template = null;
if (templateFile.exists())
{
getLog().debug("Using template " + templatePath);
template = new SourceTemplate(templateFile);
template.substitute(className + "Template", className);
template.readPreface();
}
// header/copyright
writePreamble(out);
// package
out.println("package " + packageName + ";");
out.println();
// imports
generator.writeImports(out, template, packageName,
fullSuperclassName, superclassName,
component);
// class
generator.writeClassBegin(out, className, superclassName, component, template);
// static final constants
generator.writePropertyValueConstants(out, component);
generator.writePropertyConstants(out, superclassName, component);
generator.writeFacetConstants(out, component);
generator.writeGenericConstants(out, componentFamily, componentType);
// public constructors and methods
generator.writeConstructor(out, component, Modifier.PUBLIC);
// insert template code
if (template != null)
{
template.writeContent(out);
template.close();
}
generator.writeFacetMethods(out, component);
if (template == null)
{
generator.writePropertyMethods(out, component);
}
else
{
generator.writePropertyMethods(out, component, template.getIgnoreMethods());
}
if (!suppressListenerMethods)
{
generator.writeListenerMethods(out, component);
}
generator.writeStateManagementMethods(out, component);
generator.writeGetFamily(out);
// protected constructors and methods
// TODO: reverse this order, to make protected constructor go first
// for now we want consistency with previous code generation
generator.writeOther(out, component);
generator.writeClassEnd(out);
out.close();
// delay write in case of error
// timestamp should not be updated when an error occurs
// delete target file first, because it is readonly
targetFile.getParentFile().mkdirs();
targetFile.delete();
FileWriter fw = new FileWriter(targetFile);
StringBuffer buf = sw.getBuffer();
fw.write(buf.toString());
fw.close();
targetFile.setReadOnly();
}
}
catch (IOException e)
{
getLog().error("Error generating " + fullClassName, e);
}
}
private class IfModifiedFilter extends ComponentFilter
{
protected boolean accept(
ComponentBean component)
{
String componentClass = component.getComponentClass();
String sourcePath = Util.convertClassToSourcePath(componentClass, ".java");
String templatePath = Util.convertClassToSourcePath(componentClass, "Template.java");
File targetFile = new File(generatedSourceDirectory, sourcePath);
File templateFile = new File(templateSourceDirectory, templatePath);
// accept if templateFile is newer or component has been modified
return (templateFile.lastModified() > targetFile.lastModified() ||
component.isModifiedSince(targetFile.lastModified()));
}
}
private boolean _is12()
{
return "1.2".equals(jsfVersion) || "12".equals(jsfVersion);
}
/**
* @parameter expression="${project}"
* @readonly
*/
private MavenProject project;
/**
* @parameter
* @readonly
*/
private String resourcePath = "META-INF/maven-faces-plugin/index.lst";
/**
* @parameter expression="src/main/java-templates"
* @required
*/
private File templateSourceDirectory;
/**
* @parameter expression="${project.build.directory}/maven-faces-plugin/main/java"
* @required
*/
private File generatedSourceDirectory;
/**
* @parameter
* @required
*/
private String packageContains;
/**
* @parameter
* @required
*/
private String typePrefix;
/**
* @parameter
*/
private boolean force;
/**
* @parameter
*/
private boolean suppressListenerMethods;
/**
* @parameter
*/
private String jsfVersion;
}