/** * 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.camel.component.exec.impl; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; /** * Utility class for parsing, used by the Camel Exec component.<br> * Note: the class should be dropped, when the the commons-exec library * implements similar functionality. */ public final class ExecParseUtils { public static final String WHITESPACE = " "; public static final String QUOTE_CHAR = "\""; private ExecParseUtils() { } /** * Splits the input line string by {@link #WHITESPACE}. Supports quoting the * white-spaces with a {@link #QUOTE_CHAR}. A quote itself can also be * enclosed within #{@link #QUOTE_CHAR}#{@link #QUOTE_CHAR}. More than two * double-quotes in a sequence is not allowed. Nested quotes are not * allowed.<br> * E.g. The string * <code>"arg 1" arg2<code> will return the tokens <code>arg 1</code>, * <code>arg2</code><br> * The string * <code>""arg 1"" "arg2" arg 3<code> will return the tokens <code>"arg 1"</code> * , <code>arg2</code>,<code>arg</code> and <code>3</code> <br> * * @param input the input to split. * @return a not-null list of tokens */ public static List<String> splitToWhiteSpaceSeparatedTokens(String input) { if (input == null) { return new ArrayList<String>(); } StringTokenizer tokenizer = new StringTokenizer(input.trim(), QUOTE_CHAR + WHITESPACE, true); List<String> tokens = new ArrayList<String>(); StringBuilder quotedText = new StringBuilder(); while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); if (QUOTE_CHAR.equals(token)) { // if we have a quote, add the next tokens to the quoted text // until the quoting has finished quotedText.append(QUOTE_CHAR); String buffer = quotedText.toString(); if (isSingleQuoted(buffer) || isDoubleQuoted(buffer)) { tokens.add(buffer.substring(1, buffer.length() - 1)); quotedText = new StringBuilder(); } } else if (WHITESPACE.equals(token)) { // a white space, if in quote, add the white space, otherwise // skip it if (quotedText.length() > 0) { quotedText.append(WHITESPACE); } } else { if (quotedText.length() > 0) { quotedText.append(token); } else { tokens.add(token); } } } if (quotedText.length() > 0) { throw new IllegalArgumentException("Invalid quoting found in args " + quotedText); } return tokens; } /** * Tests if the input is enclosed within {@link #QUOTE_CHAR} characters * * @param input a not null String * @return true if the regular expression is matched */ protected static boolean isSingleQuoted(String input) { if (input == null || input.trim().length() == 0) { return false; } return input.matches("(^" + QUOTE_CHAR + "{1}([^" + QUOTE_CHAR + "]+)" + QUOTE_CHAR + "{1})"); } /** * Tests if the input is enclosed within a double-{@link #QUOTE_CHAR} string * * @param input a not null String * @return true if the regular expression is matched */ protected static boolean isDoubleQuoted(String input) { if (input == null || input.trim().length() == 0) { return false; } return input.matches("(^" + QUOTE_CHAR + "{2}([^" + QUOTE_CHAR + "]+)" + QUOTE_CHAR + "{2})"); } }