blob: 0e6556b6162eac6abb4b8ad16f95889feb8db741 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. 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.jackrabbit.command.cli;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.chain.Catalog;
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;
import org.apache.commons.chain.config.ConfigParser;
import org.apache.commons.chain.impl.CatalogFactoryBase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Input Parser
*/
public class JcrParser {
/** parser */
private static Log log = LogFactory.getLog(JcrParser.class);
static {
try {
ConfigParser parser = new ConfigParser();
parser.parse(JcrParser.class.getResource("command.xml"));
} catch (Exception e) {
e.printStackTrace();
log.error(e);
}
}
/** catalog */
private Catalog catalog = CatalogFactoryBase.getInstance().getCatalog();
/** Command */
private Command cmd;
/** Command Line */
private CommandLine cl;
/**
* Constructor
*/
public JcrParser() {
super();
}
/**
* Parse the user's input.
* @param input
* user's input
* @throws JcrParserException
* if the input is illegal
* @throws ConfigurationException
* if the mapped command can't be mapped to a Commons Chain Command
*/
public void parse(String input) throws JcrParserException,
ConfigurationException {
this.cl = null;
this.cmd = null;
// Validate input
if (input == null || input.length() == 0) {
throw new JcrParserException("exception.parse.input.empty");
}
// Extract arguments
LinkedList args = this.getArguments(input);
// The first arg is the command name
String cmdName = (String) args.getFirst();
args.removeFirst();
// Get the command line descriptor
cl = CommandLineFactory.getInstance().getCommandLine(cmdName);
// populate with the given params
populate(cl, args);
// validate the command line
validate(cl);
// Create Chain Command
String impl = cl.getImpl();
if (impl == null) {
impl = cl.getName();
}
cmd = catalog.getCommand(impl);
if (cmd == null) {
throw new JcrParserException("no chain command for name " + impl);
}
}
/**
* Tokenize user's input
* @param input
* the user's input
* @return a <code>List</code> containing the arguments
*/
private LinkedList getArguments(String input) {
LinkedList args = new LinkedList();
int length = input.length();
boolean insideSingleQuote = false;
boolean insideDoubleQuote = false;
int escape = -1;
StringBuffer arg = new StringBuffer();
for (int i = 0; i < length; ++i) {
char c = input.charAt(i);
// end of argument?
if ((!insideSingleQuote & !insideDoubleQuote & Character
.isWhitespace(c))) {
if (arg.toString().trim().length() > 0) {
args.add(arg.toString().trim());
arg = new StringBuffer();
}
continue;
}
if (i == escape) { // escaped char
arg.append(c);
} else { // unescaped char
switch (c) {
case '\\':
escape = i + 1;
break;
case '"':
insideDoubleQuote = !insideDoubleQuote;
break;
case '\'':
insideSingleQuote = !insideSingleQuote;
break;
default:
arg.append(c);
break;
}
}
}
if (arg.toString().trim().length() > 0) {
args.add(arg.toString());
}
return args;
}
/**
* Populate the <code>Context</code> with the attributes needed by the
* <code>Command</code>
* @param ctx
* the <code>Context</code>
*/
public void populateContext(Context ctx) {
Iterator iter = cl.getAllParameters();
while (iter.hasNext()) {
AbstractParameter param = (AbstractParameter) iter.next();
log.debug("add ctx attr: " + param.getContextKey() + "="
+ param.getValue());
ctx.put(param.getContextKey(), param.getValue());
}
}
/**
* Remove <code>Context</code> attribute specific to the parsed
* <code>Command</code>
* @param ctx
* the <code>Context</code>
*/
public void depopulateContext(Context ctx) {
Iterator iter = cl.getAllParameters();
while (iter.hasNext()) {
AbstractParameter param = (AbstractParameter) iter.next();
String ctxKey = param.getContextKey();
log.debug("remove ctx attr: " + ctxKey + "=" + param.getValue());
ctx.remove(ctxKey);
}
}
/**
* @return the <code>Command</code>
*/
public Command getCommand() {
return cmd;
}
/**
* Populate the <code>CommandLine</code> with the given parameters
* @param cl
* the <code>CommandLine</code>
* @param valList
* the arguments
* @throws JcrParserException
* if the user's input is illegal
*/
private void populate(CommandLine cl, List valList)
throws JcrParserException {
String[] values = (String[]) valList
.toArray(new String[valList.size()]);
// Command Line parameters
Map options = cl.getOptions();
Map flags = cl.getFlags();
Map clArgs = cl.getArguments();
// Input arguments
List args = new ArrayList();
for (int i = 0; i < values.length; i++) {
String value = values[i];
if (value.startsWith("-")) {
// option
if (i + 1 < values.length && !values[i + 1].startsWith("-")) {
Option opt = (Option) options.get(value.substring(1));
if (opt == null) {
throw new JcrParserException("exception.no.opt.for.name",
new String[] {
value.substring(1)
});
}
opt.setValue(values[i + 1]);
i++;
} else {
// flag
Flag flag = (Flag) flags.get(value.substring(1));
if (flag == null) {
throw new JcrParserException("exception.no.flag.for.name",
new String[] {
value
});
}
flag.setPresent(true);
}
} else {
// collect arguments
args.add(value);
}
}
// set arguments
String[] argValues = (String[]) args.toArray(new String[args.size()]);
for (int j = 0; j < argValues.length; j++) {
Argument arg = (Argument) clArgs.get(new Integer(j));
if (arg == null) {
throw new JcrParserException("exception.more.arguments.than.expected");
}
arg.setValue(argValues[j]);
}
}
/**
* Validate the <code>CommandLine</code>
* @param cl
* the <code>CommandLine</code>
* @throws JcrParserException
* if a required parameter is not present in the user's input
*/
private void validate(CommandLine cl) throws JcrParserException {
Iterator iter = cl.getRequiredParameters();
while (iter.hasNext()) {
AbstractParameter param = (AbstractParameter) iter.next();
if (param.getValue() == null) {
throw new JcrParserException("exception.missing.paramater", new String[] {
param.getName()
});
}
}
}
}