| /* |
| * 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; |
| } |