| /* |
| * Copyright 2004-2005 The Apache Software Foundation or its licensors, |
| * as applicable. |
| * |
| * 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. |
| */ |
| 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() |
| }); |
| } |
| } |
| } |
| |
| } |