blob: 5398e2bd2ed01da0306c67c75d28b0fc518ca4f3 [file] [log] [blame]
/**
* 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.cxf.maven_plugin.xml2fastinfoset;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.sonatype.plexus.build.incremental.BuildContext;
import org.xml.sax.SAXException;
import com.sun.xml.fastinfoset.sax.SAXDocumentSerializer;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.Scanner;
/**
* Compile XML resources to FastInfoset XML resources.
*
* @goal xml2fastinfoset
* @phase process-resources
* @threadSafe
*/
public class XML2FastInfosetCompilerMojo extends AbstractMojo {
private static final String[] EMPTY_STRING_ARRAY = {};
private static final String[] DEFAULT_INCLUDES = {"**/*.xml"};
/**
* @parameter expression="${project}"
* @required
* @readonly
*/
private MavenProject project;
/**
* The resource directories containing the XML files to be compiled.
*
* @parameter expression="${project.resources}"
* @required
* @readonly
*/
private List resources;
/**
* A list of inclusion filters.
*
* @parameter
*/
private Set includes = new HashSet();
/**
* A list of exclusion filters.
*
* @parameter
*/
private Set excludes = new HashSet();
/**
* The directory for the results.
*
* @parameter expression="${project.build.outputDirectory}"
* @required
*/
private File outputDirectory;
/** @component */
protected BuildContext buildContext;
@SuppressWarnings("unchecked")
public void execute() throws MojoExecutionException {
for (Iterator it = resources.iterator(); it.hasNext();) {
Resource resource = (Resource)it.next();
String targetPath = resource.getTargetPath();
File resourceDirectory = new File(resource.getDirectory());
if (!resourceDirectory.isAbsolute()) {
resourceDirectory = new File(project.getBasedir(), resourceDirectory.getPath());
}
if (!resourceDirectory.exists()) {
getLog().debug("Resource directory does not exist: " + resourceDirectory);
continue;
}
Scanner scanner = buildContext.newScanner(resourceDirectory);
if (includes != null && !includes.isEmpty()) {
scanner.setIncludes((String[])includes.toArray(EMPTY_STRING_ARRAY));
} else {
scanner.setIncludes(DEFAULT_INCLUDES);
}
if (excludes != null && !excludes.isEmpty()) {
scanner.setExcludes((String[])excludes.toArray(EMPTY_STRING_ARRAY));
}
scanner.addDefaultExcludes();
scanner.scan();
List includedFiles = Arrays.asList(scanner.getIncludedFiles());
getLog().debug("FastInfosetting " + includedFiles.size() + " resource"
+ (includedFiles.size() > 1 ? "s" : "")
+ (targetPath == null ? "" : " to " + targetPath));
if (includedFiles.size() > 0) {
// this part is required in case the user specified "../something"
// as destination
// see MNG-1345
if (!outputDirectory.exists() && !outputDirectory.mkdirs()) {
throw new MojoExecutionException("Cannot create resource output directory: "
+ outputDirectory);
}
}
for (Iterator j = includedFiles.iterator(); j.hasNext();) {
String name = (String)j.next();
String destination = name.replaceFirst("\\.xml$", ".fixml");
if (targetPath != null) {
destination = targetPath + "/" + name;
}
File source = new File(resourceDirectory, name);
File destinationFile = new File(outputDirectory, destination);
if (!destinationFile.getParentFile().exists()) {
destinationFile.getParentFile().mkdirs();
}
try {
compileFile(source, destinationFile);
} catch (Exception e) {
throw new MojoExecutionException("Error copying resource " + source, e);
}
buildContext.refresh(destinationFile);
}
}
}
private void compileFile(File sourceFile, File destinationFile) throws ParserConfigurationException,
SAXException, IOException {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(sourceFile);
fos = new FileOutputStream(destinationFile);
dehydrate(fis, fos);
fis.close();
fos.close();
} finally {
try {
if (fis != null) {
fis.close();
}
if (fos != null) {
fos.close();
}
} catch (Exception e) {
// nothing.
}
}
}
private void dehydrate(InputStream input, OutputStream output) throws ParserConfigurationException,
SAXException, IOException {
// Create Fast Infoset SAX serializer
SAXDocumentSerializer saxDocumentSerializer = new SAXDocumentSerializer();
// Set the output stream
saxDocumentSerializer.setOutputStream(output);
// Instantiate JAXP SAX parser factory
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
saxParserFactory.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
/*
* Set parser to be namespace aware Very important to do otherwise
* invalid FI documents will be created by the SAXDocumentSerializer
*/
saxParserFactory.setNamespaceAware(true);
// Instantiate the JAXP SAX parser
SAXParser saxParser = saxParserFactory.newSAXParser();
// Set the lexical handler
saxParser.setProperty("http://xml.org/sax/properties/lexical-handler", saxDocumentSerializer);
// Parse the XML document and convert to a fast infoset document
saxParser.parse(input, saxDocumentSerializer);
}
}