org.nuiton.jaxx.plugin.GenerateMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jaxx-maven-plugin Show documentation
Show all versions of jaxx-maven-plugin Show documentation
Maven 2 plugin to generate java sources from JAXX files.
The newest version!
/*
* #%L
* JAXX :: Maven plugin
* %%
* Copyright (C) 2008 - 2017 CodeLutin
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
package org.nuiton.jaxx.plugin;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.nuiton.i18n.I18n;
import org.nuiton.io.MirroredFileUpdater;
import org.nuiton.jaxx.compiler.CompiledObjectDecorator;
import org.nuiton.jaxx.compiler.CompilerConfiguration;
import org.nuiton.jaxx.compiler.I18nHelper;
import org.nuiton.jaxx.compiler.JAXXCompiler;
import org.nuiton.jaxx.compiler.JAXXEngine;
import org.nuiton.jaxx.compiler.JAXXFactory;
import org.nuiton.jaxx.compiler.beans.BeanInfoUtil;
import org.nuiton.jaxx.compiler.binding.DataBindingHelper;
import org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer;
import org.nuiton.jaxx.compiler.spi.DefaultInitializer;
import org.nuiton.jaxx.compiler.spi.Initializer;
import org.nuiton.jaxx.runtime.JAXXContext;
import org.nuiton.jaxx.runtime.JAXXObject;
import org.nuiton.jaxx.runtime.spi.UIHandler;
import org.nuiton.jaxx.runtime.swing.help.JAXXHelpBroker;
import org.nuiton.jaxx.validator.swing.SwingValidator;
import org.nuiton.plugin.PluginHelper;
import java.beans.Introspector;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Generates some java code from jaxx files.
*
* @author Tony Chemit - [email protected]
*/
@Mojo(name = "generate", defaultPhase = LifecyclePhase.PROCESS_SOURCES,
requiresDependencyResolution = ResolutionScope.COMPILE, requiresProject = true)
public class GenerateMojo extends AbstractJaxxMojo implements CompilerConfiguration {
/**
* Directory where jaxx files are located.
*/
@Parameter(property = "jaxx.src", defaultValue = "${basedir}/src/main/java")
protected File src;
/**
* Where to generate java files.
*/
@Parameter(property = "jaxx.outJava", defaultValue = "${basedir}/target/generated-sources/java")
protected File outJava;
/**
* To filter file to treat.
*/
@Parameter(property = "jaxx.includes")
protected String[] includes;
/**
* To filter files to NOt treat.
*/
@Parameter(property = "jaxx.excludes")
protected String[] excludes;
/**
* FQN of compiler to use (by default swing one).
*/
@Parameter(property = "jaxx.compilerFQN", defaultValue = "org.nuiton.jaxx.compiler.JAXXCompiler", required = true)
protected String compilerFQN;
/**
* The name of implementation of {@link JAXXContext}to be used on {@link JAXXObject}.
*
* Must not be abstract.
*/
@Parameter(property = "jaxx.jaxxContextFQN", defaultValue = "org.nuiton.jaxx.runtime.context.DefaultJAXXContext", required = true)
protected String jaxxContextFQN;
/**
* The FQN of the ui to use for error notification.
*
* If not given, will use the one defined in validator
*/
@Parameter(property = "jaxx.defaultErrorUIFQN", defaultValue = "org.nuiton.jaxx.validator.swing.ui.ImageValidationUI")
protected String defaultErrorUIFQN;
/**
* The FQN of the ui to use for error notification.
*
* If not given, will use the one defined in validator
*
* @see CompiledObjectDecorator
*/
@Parameter(property = "jaxx.defaultDecoratorFQN", defaultValue = "org.nuiton.jaxx.compiler.decorators.DefaultCompiledObjectDecorator")
protected String defaultDecoratorFQN;
/**
* Flag to include in compiler classpath the java sources directories (src
* and outJava).
*
* By default, false.
*/
@Parameter(property = "jaxx.addSourcesToClassPath", defaultValue = "true")
protected boolean addSourcesToClassPath;
/**
* Flag to include in compiler classpath the java resources directories (src
* and outJava).
*
* By default, false.
*
* @since 1.6.0
*/
@Parameter(property = "jaxx.addResourcesToClassPath", defaultValue = "false")
protected boolean addResourcesToClassPath;
/**
* Flag to include in compiler classpath the compile class-path (can only be
* used in a test phase).
*
* By default, false.
*
* @since 1.6.0
*/
@Parameter(property = "jaxx.addCompileClassPath", defaultValue = "false")
protected boolean addCompileClassPath;
/**
* Flag to include in compiler classpath the project compile classpath.
*
* By default, false.
*/
@Parameter(property = "jaxx.addProjectClassPath", defaultValue = "true")
protected boolean addProjectClassPath;
/**
* A flag to mark the mojo to be used in a test phase. This will permits to
* add generated sources in test compile roots.
*
* @since 1.6.0
*/
@Parameter(property = "jaxx.testPhase", defaultValue = "false")
protected boolean testPhase;
/**
* To make compiler i18nable, says add the {@link I18n#t(String, Object...)}
* method invocation on {@link I18nHelper#I18N_ATTRIBUTES} attributes.
*
* @see I18nHelper
*/
@Parameter(property = "jaxx.i18nable", defaultValue = "true")
protected boolean i18nable;
/**
* To optimize generated code.
*/
@Parameter(property = "jaxx.optimize", defaultValue = "false")
protected boolean optimize;
/**
* To let jaxx recurses in css when a JAXX Object auto import css files
* for a jaxx file.
*
* Warning: This option will be removed in version 3.0 or at least
* default value will become {@code false}.
*
* @since 2.0.2
*/
@Parameter(property = "jaxx.autoRecurseInCss", defaultValue = "false")
protected boolean autoRecurseInCss;
/**
* Flag to add logger to each generated jaxx file.
*
* By default, always add it.
*/
@Parameter(property = "jaxx.addLogger", defaultValue = "true")
protected boolean addLogger;
/**
* Flag to keep compilers after the generate operation (usefull for tests.
*
* By default, always reset.
*/
@Parameter(property = "jaxx.resetAfterCompile", defaultValue = "true")
protected boolean resetAfterCompile;
/**
* Extra path to be added in {@link Introspector#setBeanInfoSearchPath(String[])}.
*
* add beanInfoSearchPath to be registred by {@link BeanInfoUtil#addJaxxBeanInfoPath(String...)}
*
* and then will be use by {@link DefaultInitializer#initialize()}.
*
*
* This permit to use real beanInfo of imported graphic libraries.
*/
@Parameter(property = "jaxx.beanInfoSearchPath")
protected String[] beanInfoSearchPath;
/**
* List of fqn of class toimport for all generated jaxx files.
*/
@Parameter(property = "jaxx.extraImportList")
protected String extraImportList;
/**
* A flag to use UIManager to retreave icons.
*/
@Parameter(property = "jaxx.useUIManagerForIcon", defaultValue = "true")
protected boolean useUIManagerForIcon;
/**
* flag to activate profile mode.
*
* By default, not active.
*/
@Parameter(property = "jaxx.profile", defaultValue = "false")
protected boolean profile;
/**
* To show detected bindings.
*
* By default, do not show them.
*
* @since 2.0.0
*/
@Parameter(property = "jaxx.showBinding", defaultValue = "false")
protected boolean showBinding;
/**
* the FQN of help broker
*
* By default, use the JAXX implementation {@link JAXXHelpBroker}.
*
* @since 1.3
*/
@Parameter(property = "jaxx.helpBrokerFQN", defaultValue = "org.nuiton.jaxx.runtime.swing.help.JAXXHelpBroker")
protected String helpBrokerFQN;
/**
* the FQN of validator factory.
*
* By default, use the JAXX implementation {@link SwingValidator}.
*
* @since 2.6
*/
@Parameter(property = "jaxx.validatorFactoryFQN", defaultValue = "org.nuiton.jaxx.validator.swing.SwingValidator")
protected String validatorFactoryFQN;
/**
* To trace class descriptor loading.
*
* By default, do not trace it.
*
* @since 2.4
*/
@Parameter(property = "jaxx.showClassDescriptorLoading", defaultValue = "false")
private boolean showClassDescriptorLoading;
/**
* For each jaxx file, try to add a {@link UIHandler} on it.
*
* The fqn of the handler must be jaxxFileName{@code Handler}.
*
* @since 2.6
*/
@Parameter(property = "jaxx.addAutoHandlerUI", defaultValue = "true")
private boolean addAutoHandlerUI;
/**
* For each jaxx file, generate the rules in the css files for the ids and style classes which have not been defined.
*
* @since 2.29
*/
@Parameter(property = "jaxx.generateMissingIdsInCss", defaultValue = "false")
private boolean generateMissingIdsAndStyleClassesInCss;
/**
* A optional common css to inject in all jaxx files.
*
* @since 2.13
*/
@Parameter(property = "jaxx.commonCss")
private File commonCss;
/**
* The extension of css files.
*
* @since 2.28
*/
@Parameter(property = "jaxx.cssExtension", defaultValue = DEFAULT_CSS_EXTENSION)
private String cssExtension;
/**
* Decorators available in engine.
*
* @since 2.0.2
*/
@Component(role = CompiledObjectDecorator.class)
protected Map decorators;
/**
* Finalizers available in engine.
*
* @since 2.0.2
*/
@Component(role = JAXXCompilerFinalizer.class)
protected Map finalizers;
/**
* Initializers available to init engine.
*
* @since 2.0.2
*/
@Component(role = Initializer.class)
protected Map initializers;
/** detected jaxx files in {@link #init()} method */
protected String[] files;
/**
* file updater used to detect jaxx files.
*
* Note: if {@link #verbose} flag is on, will ne be used
*/
protected MirroredFileUpdater updater;
/** type of error ui class (in validation) to use */
private Class> defaultErrorUIClass;
/** type of {@link CompiledObjectDecorator} to use */
private Class extends CompiledObjectDecorator> defaultDecoratorClass;
/** type of {@link JAXXContext} to use */
private Class extends JAXXContext> jaxxContextClass;
/** type of compiler to use */
private Class extends JAXXCompiler> compilerClass;
/** extra imports to always add in each generated java file */
private String[] extraImports;
/** internal state to known if a files has to be generated */
private boolean nofiles;
/** customized classloader to use in engine */
protected ClassLoader cl;
/** JAXX engine */
private JAXXEngine engine;
@SuppressWarnings("unchecked")
@Override
public void init() throws Exception {
if (getLog().isDebugEnabled()) {
// if debug is on, then verbose also
setVerbose(true);
}
fixCompileSourceRoots();
if (cssExtension == null) {
cssExtension = DEFAULT_CSS_EXTENSION;
}
if (includes == null || includes.length == 0) {
// use default includes
includes = new String[]{"**/*.jaxx", "**/*." + cssExtension};
}
updater = new JaxxFileUpdater(cssExtension, src, outJava);
Map result = new HashMap<>();
getFilesToTreateForRoots(
includes,
excludes,
Collections.singletonList(src.getAbsolutePath()),
result,
isForce() ? null : updater);
files = result.get(src);
// Evolution #435: Regenerates jaxx files when his css file is modified
// filter css and jaxx files to obtain only jaxx files
// if a css is modified, try to find the corresponding jaxx files
if (files != null && files.length > 0) {
Set filterFiles = new HashSet<>(files.length);
int cssExtensionLength = cssExtension.length() + 1;
for (String path : files) {
if (path.endsWith("." + cssExtension)) {
// take the jaxx file
String jaxxFilePath = path.substring(0, path.length() - cssExtensionLength) + ".jaxx";
File f = new File(src, jaxxFilePath);
if (f.exists()) {
if (isVerbose()) {
getLog().info("will treate jaxx file from css " +
f);
}
filterFiles.add(jaxxFilePath);
}
continue;
}
if (path.endsWith(".jaxx")) {
filterFiles.add(path);
}
}
files = filterFiles.toArray(new String[filterFiles.size()]);
}
nofiles = files == null || files.length == 0;
if (nofiles) {
if (getLog().isDebugEnabled()) {
getLog().debug("No file to treate.");
}
return;
}
cl = initClassLoader(getProject(),
src,
addSourcesToClassPath,
testPhase,
addResourcesToClassPath,
addCompileClassPath,
addProjectClassPath);
Thread.currentThread().setContextClassLoader(cl);
compilerClass = (Class extends JAXXCompiler>)
Class.forName(compilerFQN, false, cl);
defaultDecoratorClass = (Class extends CompiledObjectDecorator>)
Class.forName(defaultDecoratorFQN, false, cl);
jaxxContextClass = (Class extends JAXXContext>)
Class.forName(jaxxContextFQN, false, cl);
if (!JAXXContext.class.isAssignableFrom(jaxxContextClass)) {
throw new MojoExecutionException(
"jaxxContextFQN must be an implementation of " +
JAXXContext.class + " but was : " + jaxxContextClass);
}
// validatorClass = Class.forName(validatorFQN, false, cl);
if (defaultErrorUIFQN != null && !defaultErrorUIFQN.trim().isEmpty()) {
defaultErrorUIClass = Class.forName(defaultErrorUIFQN, false, cl);
}
if (beanInfoSearchPath != null && beanInfoSearchPath.length > 0) {
// register extra path
BeanInfoUtil.addJaxxBeanInfoPath(beanInfoSearchPath);
}
createDirectoryIfNecessary(getTargetDirectory());
// compute extra imports (can not use java classes since some of
// imports can not be still compiled)
if (extraImportList != null && !extraImportList.isEmpty()) {
String[] imports = extraImportList.split(",");
int i = 0;
for (String importS : imports) {
imports[i++] = importS.trim();
}
if (isVerbose()) {
getLog().info("extra imports " + Arrays.toString(imports));
}
extraImports = imports;
}
if (isVerbose()) {
// getLog().info(toString());
getLog().info("includes : " + Arrays.toString(includes));
for (String file : files) {
getLog().info("will parse " + file);
}
}
}
@Override
protected boolean checkSkip() {
if (nofiles) {
getLog().info("Nothing to generate - all files are up to date.");
return false;
}
return true;
}
@Override
public void doAction() throws Exception {
getLog().info("Detects " + files.length + " modified jaxx file(s). ");
if (showBinding) {
DataBindingHelper.SHOW_LOG = showBinding;
}
try {
long t0 = System.nanoTime();
// register configuration to factory
JAXXFactory.setConfiguration(this);
// create new engine
engine = JAXXFactory.newEngine(src, files);
//FIXME-TC20100502 remove this managment by -1 for error!
// run engine
int nbFiles = engine.run();
// report engine results (errors, warnings,...)
report(engine);
if (nbFiles == -1) {
throw new MojoExecutionException(
"Aborting due to errors reported by jaxxc");
}
String delay = PluginHelper.convertTime(System.nanoTime() - t0);
getLog().info("Generated " + nbFiles + " file(s) in " + delay);
} finally {
DataBindingHelper.SHOW_LOG = false;
}
}
@Override
public File getTargetDirectory() {
return outJava;
}
@Override
public void setTargetDirectory(File targetDirectory) {
outJava = targetDirectory;
}
@Override
public boolean getOptimize() {
return optimize;
}
@Override
public boolean isAutoRecurseInCss() {
return autoRecurseInCss;
}
@Override
public boolean isI18nable() {
return i18nable;
}
@Override
public boolean isUseUIManagerForIcon() {
return useUIManagerForIcon;
}
@Override
public boolean isAddLogger() {
return addLogger;
}
@Override
public boolean isShowClassDescriptorLoading() {
return showClassDescriptorLoading;
}
@Override
public boolean isAddAutoHandlerUI() {
return addAutoHandlerUI;
}
@Override
public void setAddAutoHandlerUI(boolean addAutoHandlerUI) {
this.addAutoHandlerUI = addAutoHandlerUI;
}
@Override
public boolean isGenerateMissingIdsAndStyleClassesInCss() {
return generateMissingIdsAndStyleClassesInCss;
}
@Override
public void setGenerateMissingIdsAndStyleClassesInCss(boolean generateMissingIdsAndStyleClassesInCss) {
this.generateMissingIdsAndStyleClassesInCss = generateMissingIdsAndStyleClassesInCss;
}
@Override
public Class extends JAXXContext> getJaxxContextClass() {
return jaxxContextClass;
}
@Override
public String[] getExtraImports() {
return extraImports;
}
@Override
public boolean isResetAfterCompile() {
return resetAfterCompile;
}
@Override
public boolean isOptimize() {
return optimize;
}
@Override
public Class> getDefaultErrorUI() {
return defaultErrorUIClass;
}
@Override
public ClassLoader getClassLoader() {
return cl;
}
@Override
public Class extends JAXXCompiler> getCompilerClass() {
return compilerClass;
}
@Override
public Class extends CompiledObjectDecorator> getDefaultDecoratorClass() {
return defaultDecoratorClass;
}
@Override
public boolean isProfile() {
return profile;
}
@Override
public boolean isGenerateHelp() {
return generateHelp;
}
@Override
public String getHelpBrokerFQN() {
return helpBrokerFQN;
}
@Override
public String getValidatorFactoryFQN() {
return validatorFactoryFQN;
}
@Override
public Map getDecorators() {
return decorators;
}
@Override
public Map getFinalizers() {
return finalizers;
}
@Override
public Map getInitializers() {
return initializers;
}
@Override
public File getCommonCss() {
return commonCss;
}
@Override
public String getCssExtension() {
return cssExtension;
}
public JAXXEngine getEngine() {
return engine;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(
this, ToStringStyle.MULTI_LINE_STYLE);
}
protected void fixCompileSourceRoots() {
//FIXME TC20091222 : why this test ? should always have a project ?
// even in tests...
if (getProject() == null) {
// no project defined, can not fix anything
// this case could appear if we wanted to do some tests of the plugin
return;
}
if (testPhase) {
addTestCompileSourceRoots(getTargetDirectory());
} else {
addCompileSourceRoots(getTargetDirectory());
}
}
protected void report(JAXXEngine engine) {
List warnings = engine.getWarnings();
if (!warnings.isEmpty()) {
StringBuilder buffer = new StringBuilder(
"JAXX detects " +
(warnings.size() == 1 ? "1 warning" :
warnings.size() + " warnings"));
buffer.append(" :");
for (String s : warnings) {
buffer.append("\n").append(s);
}
getLog().warn(buffer.toString());
}
List errors = engine.getErrors();
if (!errors.isEmpty()) {
StringBuilder buffer = new StringBuilder(
"JAXX detects " +
(errors.size() == 1 ? "1 error" :
errors.size() + " errors"));
buffer.append(" :");
for (String s : errors) {
buffer.append("\n").append(s);
}
getLog().error(buffer.toString());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy