package org.rapidbeans.xslt;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Map.Entry;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
/**
* The Java wrapper class for executing and XSL transformation with XalanJ.
*
* @author Martin Bluemel
*/
public final class XalanWrapper {
private static final String DQUOTE = "\"";
private static final int ARG_COUNT_EXPECTED = 3;
private static final int ERROR_CODE_INVALID_OPTION = 1;
private static final int ERROR_CODE_ARGUMENT_COUNT = 2;
private static final int ERROR_CODE_FILE = 3;
private static final int ERROR_CODE_EXCEPTION = 4;
/**
* Prevent using the default constructor.
*/
private XalanWrapper() {
}
/**
* The Java wrapper method for executing and XSL transformation with XalanJ.
*
* @param args
* the command line arguments.
*/
public static void main(String[] args) {
int argCount = 0;
String sIn = null;
String sStyle = null;
String sOut = null;
final Map<String, String> parameterMap = new HashMap<String, String>();
for (final String arg : args) {
if (arg.startsWith("-")) {
if (arg.startsWith("-p")) {
final String nameAndVal = arg.substring(2);
final List<String> tokens = split(nameAndVal, "=");
if (!(tokens.size() == 2)) {
System.err.println("ERROR: invalid parameter option \"" + arg + DQUOTE);
printUsage();
System.exit(ERROR_CODE_INVALID_OPTION);
}
parameterMap.put(tokens.get(0), tokens.get(1));
} else if (arg == "-h" || arg == "--h" || arg == "-help" || arg == "--help") {
printUsage();
} else {
System.err.println("ERROR: invalid option \"" + arg + DQUOTE);
printUsage();
System.exit(ERROR_CODE_INVALID_OPTION);
}
} else {
switch (argCount) {
case 0:
sIn = arg;
argCount++;
break;
case 1:
sStyle = arg;
argCount++;
break;
case 2:
sOut = arg;
argCount++;
break;
default:
System.err.println("ERROR: too much arguments");
printUsage();
System.exit(ERROR_CODE_ARGUMENT_COUNT);
}
}
}
if (argCount < ARG_COUNT_EXPECTED) {
System.err.println("ERROR: too less arguments");
printUsage();
System.exit(ERROR_CODE_ARGUMENT_COUNT);
}
final File in = new File(sIn);
final File style = new File(sStyle);
final File out = new File(sOut);
final int ret = xslt(in, style, out, parameterMap);
System.exit(ret);
}
/**
* @param in
* the XML file
* @param style
* the XSLT style sheet
* @param out
* the output file
* @param parameters
* the parameter map
*
* @return the error code or 0 is succeeded
*
* @throws TransformerFactoryConfigurationError
* in case of XML / XSLT transformer problems
*/
public static int xslt(final File in, final File style, final File out, final Map<String, String> parameters)
throws TransformerFactoryConfigurationError {
int error = 0;
try {
Map<String, String> parameterMap = parameters;
if (parameterMap == null) {
parameterMap = new HashMap<String, String>();
}
if (!in.exists()) {
System.err.println("ERROR: can't find input XML file \"" + in.getAbsolutePath() + DQUOTE);
printUsage();
error = ERROR_CODE_FILE;
}
if (error == 0 && !in.canRead()) {
System.err.println("ERROR: can't read input XML file \"" + in.getAbsolutePath() + DQUOTE);
printUsage();
error = ERROR_CODE_FILE;
}
if (error == 0 && !style.exists()) {
System.err.println("ERROR: can't find XSL style sheet file \"" + style.getAbsolutePath() + DQUOTE);
printUsage();
error = ERROR_CODE_ARGUMENT_COUNT;
}
if (error == 0 && !style.canRead()) {
System.err.println("ERROR: can't read XSL style sheet file \"" + style.getAbsolutePath() + DQUOTE);
printUsage();
error = ERROR_CODE_FILE;
}
if (error == 0 && !out.getParentFile().exists()) {
if (!out.getParentFile().mkdirs()) {
System.err.println("ERROR: can't create parent folder for output file \"" + style.getAbsolutePath()
+ DQUOTE);
error = ERROR_CODE_ARGUMENT_COUNT;
}
}
if (error == 0 && out.exists() && (!out.canWrite())) {
System.err.println("ERROR: can't write \"" + style.getAbsolutePath() + DQUOTE);
error = ERROR_CODE_ARGUMENT_COUNT;
}
if (error == 0) {
TransformerFactory tFactory = javax.xml.transform.TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer(new StreamSource(style));
for (final Entry<String, String> param : parameterMap.entrySet()) {
transformer.setParameter(param.getKey(), param.getValue());
}
transformer.transform(new StreamSource(in), new StreamResult(new FileOutputStream(out)));
}
} catch (TransformerConfigurationException e) {
e.printStackTrace();
error = ERROR_CODE_EXCEPTION;
} catch (FileNotFoundException e) {
e.printStackTrace();
error = ERROR_CODE_EXCEPTION;
} catch (TransformerException e) {
e.printStackTrace();
error = ERROR_CODE_EXCEPTION;
} catch (RuntimeException e) {
e.printStackTrace();
error = ERROR_CODE_EXCEPTION;
}
return error;
}
/**
* Splits a string into tokens using one or multiple delimiter characters.
*
* @param string
* the string to spit.
* @param delimChars
* a string containing all delimiter characters
*
* @return a list containing all tokens
*/
private static List<String> split(final String string, final String delimChars) {
final ArrayList<String> list = new ArrayList<String>();
final StringTokenizer tokenizer = new StringTokenizer(string, delimChars);
while (tokenizer.hasMoreTokens()) {
list.add(tokenizer.nextToken());
}
return list;
}
/**
* Print the command line help.
*/
private static void printUsage() {
System.out.println(" Usage: xslt [ <parameter option> ... ] <in> <style> <out>");
System.out.println(" in: the input XML file");
System.out.println(" style: the XSL style sheet file");
System.out.println(" out: the output file");
System.out.println(" parameter option: -p<name>=<value>");
}
}