
org.enhydra.xml.xmlc.commands.options.OptionsParser Maven / Gradle / Ivy
The newest version!
/*
* Enhydra Java Application Server Project
*
* The contents of this file are subject to the Enhydra Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License on
* the Enhydra web site ( http://www.enhydra.org/ ).
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific terms governing rights and limitations
* under the License.
*
* The Initial Developer of the Enhydra Application Server is Lutris
* Technologies, Inc. The Enhydra Application Server and portions created
* by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
* All Rights Reserved.
*
* Contributor(s):
*
* $Id: OptionsParser.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
*/
package org.enhydra.xml.xmlc.commands.options;
import java.io.IOException;
import org.enhydra.xml.io.ErrorReporter;
import org.enhydra.xml.io.InputSourceOps;
import org.enhydra.xml.xmlc.XMLCException;
import org.enhydra.xml.xmlc.metadata.MetaData;
import org.enhydra.xml.xmlc.metadata.MetaDataDocument;
import org.xml.sax.InputSource;
// FIXME: The integration of metadata is not as smooth as it should be.
// probably need to be able to parse multiple metadata files and
// then merge them. Also would be nice to not have this handle
// metadata at all, doing that with a derived class.
// FIXME: this whole approach to parsing options seems to be more complex
// necessary
/**
* Parse XMLC options, including options files.
*/
public class OptionsParser {
/*
* Enabled debug tracing.
*/
private static final boolean DEBUG = false;
/*
* Suffix for metadata and options files.
*/
static final private String OPT_FILE_SUFFIX = ".xmlc";
/*
* Command line arguments and index to next argument.
*/
private String[] fCommandArgs;
private int fCommandArgIdx;
/*
* Options definition table.
*/
private OptionSet fOptions;
/*
* Used to report errors parsing metadata file.
*/
private ErrorReporter fErrorReporter;
/*
* Ordered list of metadata or options files from cmd line.
*/
private InputSource[] fMetaDataOptionsFiles;
/**
* Track what kind of files we have parsed.
*/
private boolean fParsedMetaData = false;
private boolean fParsedOptionsFile = false;
/**
* Metadata object being constructed.
*/
private MetaData fMetaData;
/**
* Positional arguments.
*/
private String[] posArgs;
/**
* Check to see if we are at the end of the command line options.
* Will skip the `--' end of line marker.
*/
private boolean endOfCmdOptions() {
if (fCommandArgIdx >= fCommandArgs.length) {
return true; // No more args
}
if (fCommandArgs[fCommandArgIdx].equals("--")) {
// End of options marker.
fCommandArgIdx++;
return true;
}
if (!fCommandArgs[fCommandArgIdx].startsWith("-")) {
return true; // No more -options
}
return false;
}
/**
* Generate error for invalid options.
*/
private void invalidOptionError(String name,
InputSource inputSource) throws XMLCException {
StringBuffer msg = new StringBuffer();
msg.append("Invalid option \"" + name + "\"");
if (inputSource != null) {
msg.append(" in " + InputSourceOps.getName(inputSource));
}
msg.append(", valid options are:\n");
msg.append(fOptions.getOptionsMsg());
throw new XMLCException(msg.toString());
}
/**
* Generate error about mixing metadata and options files.
*/
private void mixedMetaDataOptionsFileError() throws XMLCException {
throw new XMLCException("command line specifies both metadata and options files, which is not supported.");
}
/**
* Parse a single command line option.
*/
private void parseCmdOption(boolean parseArguments) throws XMLCException {
if (DEBUG) {
System.err.println("parseCmdOption: " + fCommandArgs[fCommandArgIdx]);
}
Option option = fOptions.findOption(fCommandArgs[fCommandArgIdx]);
if (option == null) {
invalidOptionError(fCommandArgs[fCommandArgIdx], null);
}
fCommandArgIdx++;
int numArgs= option.getNumArgs();
if (numArgs > (fCommandArgs.length-fCommandArgIdx)) {
throw new XMLCException("Insufficient number of arguments for option \""
+ option.getName() + ": " + option.getHelp());
}
if (parseArguments) {
String[] args = new String[numArgs];
System.arraycopy(fCommandArgs, fCommandArgIdx, args, 0, numArgs);
option.parse(args, fErrorReporter, fMetaData);
}
fCommandArgIdx += numArgs;
}
/**
* Parse options. A preparse can be done to find the positional
* arguments or a full parse to get the option arguments. This is
* needed to find the positional arguments.
*/
private void parseOptions(boolean parseArguments) throws XMLCException {
fCommandArgIdx = 0;
while (!endOfCmdOptions()) {
parseCmdOption(parseArguments);
}
}
/**
* Parse an options file line.
*/
private void parseOptionsFileEntry(InputSource inputSource,
String[] entry)
throws XMLCException {
Option option = fOptions.findOption(entry[0]);
if (option == null) {
invalidOptionError(entry[0], inputSource);
}
int numArgs= option.getNumArgs();
if (entry.length-1 != numArgs) {
throw new XMLCException("wrong number of arguments for option \""
+ option.getName()
+ " in " + InputSourceOps.getName(inputSource)
+ ": " + option.getHelp());
}
String[] args = new String[entry.length-1];
System.arraycopy(entry, 1, args, 0, entry.length-1);
option.parse(args, fErrorReporter, fMetaData);
}
/**
* Parse an options file.
*/
private void parseOptionsFile(InputSource inputSource)
throws XMLCException {
if (fParsedMetaData) {
mixedMetaDataOptionsFileError();
}
fParsedOptionsFile = true;
OptionFileParser parsedOpts = new OptionFileParser(inputSource);
String[][] opts = parsedOpts.getOptions();
for (int idx = 0; idx < opts.length; idx++) {
parseOptionsFileEntry(inputSource, opts[idx]);
}
}
/**
* Parse a metadata file.
*/
private void parseMetaDataFile(InputSource inputSource)
throws XMLCException {
if (fParsedOptionsFile) {
mixedMetaDataOptionsFileError();
}
if (fParsedMetaData) {
throw new XMLCException("Multiple XMLC metadata files specified, which is supported; use document with external entity references instead");
}
fParsedMetaData = true;
MetaDataDocument metaDataDoc
= MetaDataDocument.parseMetaData(inputSource, fErrorReporter,
null);
fMetaData = metaDataDoc.getMetaData();
}
/**
* Parse a metadata or options file.
*/
private void parseMetaDataOptionsFile(InputSource inputSource)
throws XMLCException {
// Determine if its a metadata file. If it doesn't look like an
// XML file, assume its an options file.
try {
if (InputSourceOps.isXMLDocument(inputSource)) {
parseMetaDataFile(inputSource);
} else {
parseOptionsFile(inputSource);
}
} catch (IOException except) {
throw new XMLCException("parse of " + inputSource + " failed",
except);
}
}
/**
* Parse metadata or options files.
*/
private void parseMetaDataOptionsFiles()
throws XMLCException {
// Parse backwards so first one overrides
for (int idx = fMetaDataOptionsFiles.length-1; idx >= 0; idx--) {
parseMetaDataOptionsFile(fMetaDataOptionsFiles[idx]);
}
}
/**
* Parse the positional arguments.
*/
private void parsePositionalArgs() throws XMLCException {
// Find *.xmlc metadata or options files.
int idx;
int mdCnt = 0;
for (idx = fCommandArgIdx;
(idx < fCommandArgs.length) && fCommandArgs[idx].endsWith(OPT_FILE_SUFFIX);
idx++) {
mdCnt++;
}
fMetaDataOptionsFiles = new InputSource[mdCnt];
idx = 0;
while ((fCommandArgIdx < fCommandArgs.length)
&& fCommandArgs[fCommandArgIdx].endsWith(OPT_FILE_SUFFIX)) {
fMetaDataOptionsFiles[idx++] = new InputSource(fCommandArgs[fCommandArgIdx]);
fCommandArgIdx++;
}
// Save the remaining positional arguments.
int len = fCommandArgs.length-fCommandArgIdx;
posArgs = new String[len];
System.arraycopy(fCommandArgs, fCommandArgIdx, posArgs, 0, len);
}
/**
* Constructor.
*
* @param optionsSet The set of options to parse, all value are stored in
* this object.
* @param errorReporter Use to reporrt metadata parse errors.
*/
public OptionsParser(OptionSet options,
ErrorReporter errorReporter) {
fOptions = options;
fErrorReporter = errorReporter;
}
/**
* Parse options.
*
* @param args The arguments.
*/
public void parse(String[] args) throws XMLCException {
fCommandArgs = args;
fCommandArgIdx = 0;
// Must parse once to find the positional arguments.
parseOptions(false);
parsePositionalArgs();
// Create metaData object, if not already created.
getMetaData(); // creates as side affect
// Process the option or metadata files.
parseMetaDataOptionsFiles();
// Parse the command line for real, which will override options files.
parseOptions(true);
fMetaData.getDocument().completeModifications();
}
/**
* Get the parsed options.
*/
public OptionSet getOptions() {
return fOptions;
}
/**
* Get the metadata object, create if it doesn't exists.
*/
public MetaData getMetaData() {
if (fMetaData == null) {
fMetaData = MetaDataDocument.newInstance().getMetaData();
}
return fMetaData;
}
/**
* Get the positional arguments. Options files (.xmlc) will
* have been removed.
*/
public String[] getPositionalArgs() {
return posArgs;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy