AbstractArgumentsBean.java
/*
* Copyright (c) 2025-2026, Marc Mazas <mazas.marc@gmail.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.javacc.mojo;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
/**
* Super class of the concrete beans managing common specific processor arguments (options).
*
* <p>
* As some goals run one processor and others run two or more of them, and<br>
* as each processor has its own set of options, and<br>
* as some processors (preprocessors) use part of other processors (generators) options, and<br>
* as the (corresponding) parameters must be managed by the goal mojos,<br>
* then<br>
* in order to factorize code,<br>
* the set of options / parameters are copied to and managed in the concrete beans, and <br>
* the goal mojos handle references to one or more of these beans (a common way in Java to handle
* multiple inheritance).
*
* <p>
* Most of the processors options are transparent for the plugin, so none are declared as single
* parameters as in previous versions of the plugin; since 3.8.0 they are declared as a List of
* Strings holding each a full argument (like <code>-OPTION=value</code>); this for the benefit that
* processors options additions or removals should not impact the plugin and therefore not lead to a
* new release of the plugin.<br>
* A few specific options are read and used by the plugin, in this class or in subclasses.
*
* @since 3.8.0
* @author Maͫzͣaͬsͨ
* @see AbstractPluginMojo
* @see AbstractProcessor
*/
abstract class AbstractArgumentsBean {
/** The logger. */
protected Log log;
/**
* Abstract getter for the list of single full command line arguments, which should be in the form
* accepted by the processor.<br>
*
* @return the list of single full command line arguments
*/
protected abstract List<String> getProcCmdLineArgs();
/**
* Abstract setter for the list of single full command line arguments, which should be in the form
* accepted by the processor.<br>
*
* @param argsList - the list of single full command line arguments
*/
protected abstract void setProcCmdLineArgs(List<String> argsList);
/** The default grammar file encoding. */
protected static final String defaultGrammarFileEncoding = System.getProperty("file.encoding");
/** The grammar file encoding option value. */
protected String grammarFileEncodingOptionValue = null;
/** The default output language. */
protected static final Language defaultLanguage = Language.JAVA;
/** The output language option value. */
protected Language languageOptionValue = null;
/** The processor output directories (may be more than one). */
protected File[] processorOutputDirectories = null;
/** The regex to find the code generator option. */
protected static final String codeGen = "-[cC][oO][dD][eE]_[gG][eE][nN][eE][rR][aA][tT][oO][rR][=:]\"(.*)\"";
/** The regex to find the grammar encoding option. */
protected static final String gramEnc = "-[gG][rR][aA][mM][mM][aA][rR]_[eE][nN][cC][oO][dD][iI][nN][gG][=:]\"(.*)\"";
/**
* Retrieve common specific processor options needed by the plugin.
*
* @param project - the current maven project
* @param param - the command line arguments parameter name (for debug display)
* @param procOutDirPatterns - the patterns compiled from the regex to find the processor output
* directories options
* @param subDir - the sub directories of the project's build directory to form the default
* processor output directories
* @throws PluginException if invalid language option value
*/
protected void findSpecificOptions(final MavenProject project, final String param,
final Pattern[] procOutDirPatterns, final String[] subDir) throws PluginException {
if (procOutDirPatterns == null) {
return;
}
final Pattern codeGenPatt = Pattern.compile(codeGen);
final Pattern gramEncPatt = Pattern.compile(gramEnc);
processorOutputDirectories = new File[procOutDirPatterns.length];
for (final String arg : getProcCmdLineArgs()) {
log.debug(param + " / arg = '" + arg + "'");
Matcher matcher;
String opt;
matcher = codeGenPatt.matcher(arg);
if (matcher.find()) {
opt = matcher.group(1);
log.debug("Code generator option is '" + opt + "', -> language");
languageOptionValue = Language.getLanguageFrom(opt);
}
matcher = gramEncPatt.matcher(arg);
if (matcher.find()) {
opt = matcher.group(1);
log.debug("Grammar file encoding option is '" + opt + "', -> grammarFileEncoding");
grammarFileEncodingOptionValue = opt;
}
for (int i = 0; i < procOutDirPatterns.length; i++) {
matcher = procOutDirPatterns[i].matcher(arg);
if (matcher.find()) {
opt = matcher.group(1);
log.debug(
"Output directory option is '" + opt + "', -> processorOutputDirectories[" + i + "]");
processorOutputDirectories[i] = new File(opt);
}
} // end for outDirPatt 1
} // end for getProcCmdLineArgs
for (int i = 0; i < procOutDirPatterns.length; i++) {
if (processorOutputDirectories[i] == null) {
// if no option set, the plugin will copy the generated files to the build (sub)directory
processorOutputDirectories[i] = new File(project.getBuild().getDirectory(), subDir[i]);
log.debug("No output directory option set, defaulting to '"
+ processorOutputDirectories[i].getPath() + "', -> processorOutputDirectories[" + i
+ "]");
}
// if processorOutputDirectory does not exist, it will be created by the processor
if (processorOutputDirectories[i].exists() && !processorOutputDirectories[i].isDirectory()) {
throw new PluginException(
"Output directory '" + processorOutputDirectories[i] + "' is an existing file");
}
try {
final String podcp = processorOutputDirectories[i].getCanonicalPath();
if (!podcp.equals(processorOutputDirectories[i].getPath())) {
log.debug(
"Output directory " + i + " transformed to its canonical pathname '" + podcp + "'");
processorOutputDirectories[i] = new File(podcp);
}
}
catch (final IOException e) {
throw new PluginException("Output directory '" + processorOutputDirectories[i]
+ "' looks invalid: '" + e.getMessage() + "'");
}
} // end for outDirPatt 2
}
/**
* Retrieve some specific processor options needed by the plugin.
*
* @param project - the current maven project
* @param param - the command line arguments parameter name (for debug display)
* @throws PluginException if invalid option value
*/
protected abstract void findSpecificOptions(final MavenProject project, final String param)
throws PluginException;
}