All Downloads are FREE. Search and download functionalities are using the official Maven repository.

au.com.acegi.xmlformat.AbstractXmlPlugin Maven / Gradle / Ivy

The newest version!
/*-
 * #%L
 * XML Format Maven Plugin
 * %%
 * Copyright (C) 2011 - 2024 Acegi Technology Pty Limited
 * %%
 * Licensed 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.
 * #L%
 */

package au.com.acegi.xmlformat;

import static java.util.Arrays.asList;
import static java.util.Arrays.copyOf;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Parameter;
import org.codehaus.plexus.util.DirectoryScanner;
import org.dom4j.DocumentException;

/**
 * Common infrastructure for the various plugin goals.
 */
@SuppressWarnings("DesignForExtension")
public abstract class AbstractXmlPlugin extends AbstractMojo {

  /**
   * Quote character to use when writing attributes.
   */
  @Parameter(property = "attributeQuoteChar", defaultValue = "\"")
  @SuppressWarnings("PMD.ImmutableField")
  private char attributeQuoteChar = '"';

  /**
   * The base directory of the project.
   */
  @Parameter(defaultValue = ".", readonly = true, required = true, property = "project.basedir")
  private File baseDirectory;

  /**
   * The encoding format.
   */
  @Parameter(property = "encoding", defaultValue = "UTF-8")
  @SuppressWarnings("PMD.ImmutableField")
  private String encoding = "UTF-8";

  /**
   * A set of file patterns that allow you to exclude certain files/folders from
   * the formatting. In addition to these exclusions, the project build directory
   * (typically target) is always excluded if skipTargetFolder is
   * true.
   */
  @Parameter(property = "excludes")
  private String[] excludes;

  /**
   * Whether or not to expand empty elements to <tagName></tagName>.
   */
  @Parameter(property = "expandEmptyElements", defaultValue = "false")
  private boolean expandEmptyElements;

  /**
   * A set of file patterns that dictate which files should be included in the
   * formatting with each file pattern being relative to the base directory.
   */
  @Parameter(property = "includes")
  private String[] includes;

  /**
   * Indicates the number of spaces to apply when indenting.
   */
  @Parameter(property = "indentSize", defaultValue = "2")
  private int indentSize;

  /**
   * Use tabs instead of spaces for indents. If set to true,
   * indentSize will be ignored.
   */
  @Parameter(property = "tabIndent", defaultValue = "false")
  private boolean tabIndent;

  /**
   * Sets the line-ending of files after formatting. Valid values are:
   * 
    *
  • "SYSTEM" - Use line endings of current system
  • *
  • "LF" - Use Unix and Mac style line endings
  • *
  • "CRLF" - Use DOS and Windows style line endings
  • *
  • "CR" - Use early Mac style line endings
  • *
* This property is only used if {@link #lineSeparator} has its default value. * Do not set any value for {@link #lineSeparator}. */ @Parameter(property = "lineEnding", defaultValue = "LF") @SuppressWarnings("PMD.ImmutableField") private LineEnding lineEnding = LineEnding.LF; /** * New line separator. * * @deprecated Please do not set this value; use {@link #lineEnding} instead */ @Parameter(property = "lineSeparator", defaultValue = "\n") @SuppressWarnings("PMD.ImmutableField") @Deprecated private String lineSeparator = "\n"; /** * Whether or not to print new line after the XML declaration. */ @Parameter(property = "newLineAfterDeclaration", defaultValue = "false") private boolean newLineAfterDeclaration; /** * Controls when to output a line.separator every so many tags in case of no * lines and total text trimming. */ @Parameter(property = "newLineAfterNTags", defaultValue = "0") private int newLineAfterNTags; /** * The default new line flag, set to do new lines only as in original document. */ @Parameter(property = "newlines", defaultValue = "true") private boolean newlines; /** * Whether or not to output the encoding in the XML declaration. */ @Parameter(property = "omitEncoding", defaultValue = "false") private boolean omitEncoding; /** * Pad string-element boundaries with whitespace. */ @Parameter(property = "padText", defaultValue = "false") private boolean padText; /** * Skip XML formatting. */ @Parameter(property = "xml-format.skip", defaultValue = "false") private boolean skip; /** * In addition to the exclusions, the project build directory (typically * target) is always excluded if true. */ @Parameter(property = "skipTargetFolder", defaultValue = "true") private boolean skipTargetFolder = true; /** * Whether or not to suppress the XML declaration. */ @Parameter(property = "suppressDeclaration", defaultValue = "false") private boolean suppressDeclaration; /** * The project target directory. This is always excluded from formatting. */ @Parameter(defaultValue = "${project.build.directory}", readonly = true, required = true) private File targetDirectory; /** * Should we preserve whitespace or not in text nodes. */ @Parameter(property = "trimText", defaultValue = "true") private boolean trimText; /** * Whether or not to use XHTML standard. */ @Parameter(property = "xhtml", defaultValue = "false") private boolean xhtml; /** * Whether to keep blank lines. A maximum of one line is preserved between each * tag. */ @Parameter(property = "keepBlankLines", defaultValue = "false") private boolean keepBlankLines; @Override public void execute() throws MojoExecutionException, MojoFailureException { assert baseDirectory != null; assert targetDirectory != null; if (skip) { getLog().info("[xml-format] Skipped"); return; } initializeIncludes(); initializeExcludes(); final XmlOutputFormat fmt = buildFormatter(); boolean success = true; boolean neededFormatting = false; for (final String inputName : find()) { final File input = new File(baseDirectory, inputName); try { neededFormatting |= processFile(input, fmt); } catch (final DocumentException | IOException ex) { success = false; getLog().error("[xml-format] Error for " + input, ex); } } if (!success) { throw new MojoFailureException("[xml-format] Failed)"); } afterAllProcessed(neededFormatting); } /** * Processes a single file found in the project. * * @param input the file to process * @param fmt the formatting options * @return true if the file required changes to match the formatting style * @throws DocumentException if input XML could not be parsed * @throws IOException if output XML stream could not be written */ protected abstract boolean processFile(File input, XmlOutputFormat fmt) throws DocumentException, IOException; /** * Invoked after all files in the project have been processed. * * @param neededFormatting whether any processed file required changes to match * the formatting style * @throws MojoExecutionException if the build must be failed */ protected abstract void afterAllProcessed(boolean neededFormatting) throws MojoExecutionException; void setBaseDirectory(final File baseDirectory) { this.baseDirectory = baseDirectory; } void setExcludes(final String... excludes) { this.excludes = excludes == null ? null : copyOf(excludes, excludes.length); } void setIncludes(final String... includes) { this.includes = includes == null ? null : copyOf(includes, includes.length); } void setSkip(final boolean skip) { this.skip = skip; } void setSkipTargetFolder(final boolean skipTargetFolder) { this.skipTargetFolder = skipTargetFolder; } void setTargetDirectory(final File targetDirectory) { this.targetDirectory = targetDirectory; } private XmlOutputFormat buildFormatter() { final XmlOutputFormat fmt = new XmlOutputFormat(); fmt.setAttributeQuoteCharacter(attributeQuoteChar); fmt.setEncoding(encoding); fmt.setExpandEmptyElements(expandEmptyElements); if (tabIndent) { fmt.setIndent("\t"); } else { fmt.setIndentSize(indentSize); } fmt.setLineSeparator(determineLineSeparator()); fmt.setNewLineAfterDeclaration(newLineAfterDeclaration); fmt.setNewLineAfterNTags(newLineAfterNTags); fmt.setNewlines(newlines); fmt.setOmitEncoding(omitEncoding); fmt.setPadText(padText); fmt.setSuppressDeclaration(suppressDeclaration); fmt.setTrimText(trimText); fmt.setXHTML(xhtml); fmt.setKeepBlankLines(keepBlankLines); return fmt; } private String determineLineSeparator() { return "\n".equals(lineSeparator) ? lineEnding.getChars() : lineSeparator; } private String[] find() { final DirectoryScanner dirScanner = new DirectoryScanner(); dirScanner.setBasedir(baseDirectory); dirScanner.setIncludes(includes); final List exclude = new ArrayList<>(asList(excludes)); if (skipTargetFolder && baseDirectory.equals(targetDirectory.getParentFile())) { exclude.add(targetDirectory.getName() + "/**"); } final String[] excluded = new String[exclude.size()]; dirScanner.setExcludes(exclude.toArray(excluded)); dirScanner.scan(); return dirScanner.getIncludedFiles(); } private void initializeExcludes() { if (excludes == null || excludes.length == 0) { excludes = new String[0]; } } private void initializeIncludes() { if (includes == null || includes.length == 0) { includes = new String[] {"**/*.xml"}; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy