com.cerner.ccl.analysis.mojo.WhitenoiseMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of whitenoise-maven-plugin Show documentation
Show all versions of whitenoise-maven-plugin Show documentation
A plugin to perform static analysis of CCL code
package com.cerner.ccl.analysis.mojo;
import static org.codehaus.plexus.util.StringUtils.isEmpty;
import java.io.File;
import java.io.IOException;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import javax.security.auth.Subject;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.doxia.siterenderer.Renderer;
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.project.MavenProject;
import org.apache.maven.reporting.AbstractMavenReport;
import org.apache.maven.reporting.MavenReportException;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.codehaus.plexus.util.FileUtils;
import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException;
import com.cerner.ccl.analysis.data.AnalysisRule;
import com.cerner.ccl.analysis.data.Violation;
import com.cerner.ccl.analysis.engine.AnalysisEngine;
import com.cerner.ccl.analysis.engine.j4ccl.FtpProductProvider;
import com.cerner.ccl.analysis.engine.j4ccl.J4CclAnalysisEngine;
import com.cerner.ccl.analysis.exception.AnalysisRuleProvider;
import com.cerner.ccl.analysis.mojo.exclusions.ViolationFilterEngine;
import com.cerner.ccl.analysis.mojo.exclusions.jaxb.Exclusions;
import com.cerner.ccl.analysis.mojo.util.J4CclFtpProductProvider;
import com.cerner.ccl.j4ccl.CclExecutor;
import com.cerner.ccl.j4ccl.TerminalProperties;
import com.cerner.ccl.j4ccl.impl.jaas.BackendNodePasswordCredential;
import com.cerner.ccl.j4ccl.impl.jaas.BackendNodePrincipal;
/**
* A mojo to generate static analysis reports on CCL code.
*
* @author Joshua Hyde
*/
// TODO: test this class
@Mojo(name = "whitenoise-report", defaultPhase = LifecyclePhase.SITE)
public class WhitenoiseMojo extends AbstractMavenReport {
/**
* The output directory.
*/
@Parameter(property = "project.reporting.outputDirectory", readonly = true, required = true)
@SuppressWarnings("hiding")
protected File outputDirectory;
/**
* Maven Internal: The Doxia Site Renderer.
*/
@SuppressWarnings("hiding")
@Component()
protected Renderer siteRenderer;
/**
* Maven Internal: The Project descriptor.
*/
@SuppressWarnings("hiding")
@Parameter(property = "project", readonly = true, required = true)
protected MavenProject project;
/**
* The username to be used to log into the remote server.
*
* @see #hostCredentialsId
*/
@Parameter(property = "ccl-hostUsername")
protected String username;
/**
* The password to be used to log into the remote server.
*
* @see #hostCredentialsId
*/
@Parameter(property = "ccl-hostPassword")
protected String password;
/**
* The host to which the plugin is to connect to compile and translate the script.
*/
@Parameter(property = "ccl-host", required = true)
protected String hostAddress;
/**
* The environment to which the plugin will {@code envset} upon connecting to the remote server.
*/
@Parameter(property = "ccl-environment", required = true)
protected String environmentName;
/**
* The ID of a {@code <server />} tag within your settings.xml that provides the username and password used to
* connect to the remote server. If present, this will override the usage of {@link #username} and
* {@link #password}.
*
* @since 2.0
* @see #password
* @see #username
*/
@Parameter(property = "ccl-hostCredentialsId")
protected String hostCredentialsId;
/**
* A {@link SecDispatcher} used to decrypt encrypted passwords supplied via a {@code <server />} setting in
* the settings.xml.
*
* @see #hostCredentialsId
*/
@Component(hint = "mng-4384")
protected SecDispatcher securityDispatcher;
/**
* The settings provided by the {@code settings.xml} file.
*
*/
@Parameter(defaultValue = "${settings}", readonly = true)
protected Settings settings;
/**
* The timeout in milliseconds when waiting for a back-end command to complete. Does not apply to the execution of
* CCL commands using "go". Those will always be given unlimited time to execute.
*
* @since 2.0
*/
@Parameter(property = "ccl-expectationTimeout", defaultValue = "20000")
protected long expectationTimeout;
/**
* A regular expression that will match the back end operating system prompt for the configured user. This is used
* to recognize when the back end operating system has finished processing and is ready for another command The
* following value is constructed by default: "$ccl-domainUsername:ccl-environment@$ccl-host:[^@gt;]*@gt;\s*"
*
* @since 2.0
*/
@Parameter(property = "ccl-osPromptPattern", defaultValue = "")
protected String osPromptPattern;
/**
* The source directory from which CCL code is to be read.
*/
@Parameter(property = "ccl-sourceDirectory", defaultValue = "src/main/ccl", required = true)
protected File sourceDirectory;
/**
* A boolean indicator to control whether or not the source code is to be compiled before attempting to analyze it.
* This defaults {@code false} because the common use case is to use this in tandem with, or shortly after, the
* compilation of a CCL script. As such, to compile it again is needless; if, however, you are not compiling in a
* sufficiently-recent time relative to the generation of this report, then consider changing this parameter to
* {@code true}.
*/
@Parameter(defaultValue = "false", property = "doCompile", required = true)
protected boolean doCompile;
/**
* The location of the file of filters that can be optionally excluded from the report.
*/
@Parameter()
private File filterFile;
private final FtpProductProvider productProvider;
// used to construct the default OS prompt.
private String defaultOSPromptUsername;
/**
* Create a Whitenoise report mojo.
*/
public WhitenoiseMojo() {
this(new J4CclFtpProductProvider());
}
/**
* Create a Whitenoise report mojo.
*
* @param productProvider
* An {@link FtpProductProvider} used to provide authentication for uploading and downloading files.
* @throws IllegalArgumentException
* If the given provider is {@code null}.
*/
public WhitenoiseMojo(final FtpProductProvider productProvider) {
if (productProvider == null)
throw new IllegalArgumentException("FTP product provider cannot be null.");
this.productProvider = productProvider;
}
@Override
public boolean canGenerateReport() {
if (!sourceDirectory.exists()) {
getLog().info("sourceDirectory " + sourceDirectory.getPath() + " does not exist.");
return false;
}
try {
return !getFiles().isEmpty();
} catch (final MavenReportException e) {
throw new RuntimeException("Failed to determine whether or not the report can be generated.", e);
}
}
/**
* {@inheritDoc}
*/
public String getDescription(final Locale locale) {
return "A static analysis report of CCL code.";
}
/**
* {@inheritDoc}
*/
public String getName(final Locale locale) {
return "Whitenoise";
}
/**
* {@inheritDoc}
*/
public String getOutputName() {
return "whitenoise-report";
}
@Override
protected void executeReport(final Locale locale) throws MavenReportException {
final Sink sink = getSink();
sink.head();
sink.title();
sink.text(getName(Locale.getDefault()));
sink.title_();
sink.head_();
sink.body();
sink.sectionTitle1();
sink.text("Whitenoise Report");
sink.sectionTitle1_();
sink.paragraph();
sink.text(
"The Whitenoise Report is a static analysis of CCL code. It aims to find preventable, common issues that arise during development "
+ "of CCL.");
sink.link_();
sink.paragraph_();
try {
final Subject subject = getSubject();
TerminalProperties.setGlobalTerminalProperties(TerminalProperties.getNewBuilder()
.setOsPromptPattern(osPromptPattern != null && !osPromptPattern.isEmpty() ? osPromptPattern
: TerminalProperties.constructDefaultOsPromptPattern(hostAddress, environmentName,
defaultOSPromptUsername))
.setExpectationTimeout(expectationTimeout).setSpecifyDebugCcl(false).build());
final List files = getFiles();
if (doCompile) {
getLog().info(
"Mojo has been configured to compile scripts prior to analysis; preparing to compile scripts.");
doCompile(subject, files);
} else
getLog().debug("Mojo has been configured to not compile code prior to analysis.");
final AnalysisEngine engine = new J4CclAnalysisEngine(productProvider);
final Map> violations = Subject.doAs(subject,
new PrivilegedAction