
org.apache.brooklyn.util.text.StringEscapes Maven / Gradle / Ivy
Show all versions of brooklyn-utils-common Show documentation
/*
* 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.brooklyn.util.text;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import org.apache.brooklyn.util.collections.MutableList;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.net.URLParamEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
public class StringEscapes {
private static final Logger log = LoggerFactory.getLogger(StringEscapes.class);
/** if s is wrapped in double quotes containing no unescaped double quotes */
public static boolean isWrappedInDoubleQuotes(String s) {
if (Strings.isEmpty(s)) return false;
if (!s.startsWith("\"") || !s.endsWith("\"")) return false;
return (s.substring(1, s.length()-1).replace("\\\\", "").replace("\\\"", "").indexOf("\"")==-1);
}
/** if s is wrapped in single quotes containing no unescaped single quotes */
public static boolean isWrappedInSingleQuotes(String s) {
if (Strings.isEmpty(s)) return false;
if (!s.startsWith("\'") || !s.endsWith("\'")) return false;
return (s.substring(1, s.length()-1).replace("\\\\", "").replace("\\\'", "").indexOf("\'")==-1);
}
/** if s is wrapped in single or double quotes containing no unescaped quotes of that type */
public static boolean isWrappedInMatchingQuotes(String s) {
return isWrappedInDoubleQuotes(s) || isWrappedInSingleQuotes(s);
}
/**
* Encodes a string suitable for use as a parameter in a URL.
*/
public static String escapeUrlParam(String input) {
return URLParamEncoder.encode(input);
}
/**
* Encodes a string suitable for use as a URL in an HTML form: space to +, and high-numbered chars assuming UTF-8.
* However, it will also convert the first "http://" to "http%3A%2F%2F" so is not suitable for converting an
* entire URL.
*
* Also note that parameter-conversion doesn't work in way you'd expect when trying to create a "normal" url.
* See http://stackoverflow.com/questions/724043/http-url-address-encoding-in-java
*
* @see escapeUrlParam(String), and consider using that instead.
*/
public static String escapeHtmlFormUrl(String url) {
try {
return URLEncoder.encode(url, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw Exceptions.propagate(e);
}
}
/** encodes a string to SQL, that is ' becomes '' */
public static String escapeSql(String x) {
//identical to apache commons StringEscapeUtils.escapeSql
if (x==null) return null;
return x.replaceAll("'", "''");
}
public static class BashStringEscapes {
// single quotes don't permit escapes! e.g. echo 'hello \' world' doesn't work;
// you must do 'hello '\'' world' (to get "hello ' world")
public static class WrapBashFunction implements Function {
@Override
public String apply(String input) {
return wrapBash(input);
}
}
public static Function wrapBash() {
return new WrapBashFunction();
}
/** wraps plain text in double quotes escaped for use in bash double-quoting */
public static String wrapBash(String value) {
StringBuilder out = new StringBuilder();
try {
wrapBash(value, out);
} catch (IOException e) {
//shouldn't happen for string buffer
throw Exceptions.propagate(e);
}
return out.toString();
}
/** @see #wrapBash(String) */
public static void wrapBash(String value, Appendable out) throws IOException {
out.append('"');
escapeLiteralForDoubleQuotedBash(value, out);
out.append('"');
}
private static void escapeLiteralForDoubleQuotedBash(String value, Appendable out) throws IOException {
for (int i=0; i wrapJavaStrings(Iterable values) {
if (values==null) return null;
List result = MutableList.of();
for (String v: values) result.add(wrapJavaString(v));
return result;
}
/** as {@link #unwrapJavaString(String)} if the given string is wrapped in double quotes;
* otherwise just returns the given string */
public static String unwrapJavaStringIfWrapped(String s) {
if (!StringEscapes.isWrappedInDoubleQuotes(s)) return s;
return unwrapJavaString(s);
}
/** converts normal string to java escaped for double-quotes and wrapped in those double quotes */
public static void wrapJavaString(String value, Appendable out) throws IOException {
if (value==null) {
out.append("null");
} else {
out.append('"');
escapeJavaString(value, out);
out.append('"');
}
}
/** converts normal string to java escaped for double-quotes (but not wrapped in double quotes) */
public static void escapeJavaString(@Nonnull String value, Appendable out) throws IOException {
for (int i=0; i unwrapQuotedJavaStringList(String s, String separator) {
List result = new ArrayList();
String remaining = s.trim();
while (remaining.length() > 0) {
int endIndex = findNextClosingQuoteOf(remaining);
result.add(unwrapJavaString(remaining.substring(0, endIndex+1)));
remaining = remaining.substring(endIndex+1).trim();
if (remaining.startsWith(separator)) {
remaining = remaining.substring(separator.length()).trim();
} else if (remaining.length() > 0) {
throw new IllegalArgumentException("String '"+s+"' has invalid separators, should be '"+separator+"'");
}
}
return result;
}
private static int findNextClosingQuoteOf(String s) {
boolean escaped = false;
boolean quoted = false;
for (int i=0; i
* this method does not throw exceptions on invalid input,
* but just returns that input
*
* specifically, uses the following rules (executed once in sequence:
*
1) if of form [ X ]
(in brackets after trim),
* then removes brackets and applies following rules to X (for any X including quoted or with commas)
* 2) if of form "X"
* (in double quotes after trim,
* where X contains no internal double quotes unless escaped with backslash)
* then returns list containing X unescaped (\x replaced by x)
* 3) if of form X
or X, Y, ...
* (where X, Y, ... each satisfy the constraint given in 2, or have no double quotes or commas in them)
* then returns the concatenation of rule 2 applied to non-empty X, Y, ...
* (if you want an empty string in a list, you must double quote it)
* 4) for any other form X returns [ X ], including empty list for empty string
*
* @see #unwrapOptionallyQuotedJavaStringList(String)
**/
public static List unwrapJsonishListIfPossible(String input) {
try {
return unwrapOptionallyQuotedJavaStringList(input);
} catch (Exception e) {
Exceptions.propagateIfFatal(e);
if (e instanceof IllegalArgumentException) {
if (log.isDebugEnabled())
log.debug("Unable to parse JSON list '"+input+"' ("+e+"); treating as single-element string list");
} else {
log.warn("Unable to parse JSON list '"+input+"' ("+e+"); treating as single-element string list", e);
}
return MutableList.of(input);
}
}
/** as {@link #unwrapJsonishListIfPossible(String)} but throwing errors
* if something which looks like a string or set of brackets is not well-formed
* (this does the work for that method)
* @throws IllegalArgumentException if looks to have quoted list or surrounding brackets but they are not syntactically valid */
public static List unwrapOptionallyQuotedJavaStringList(String input) {
if (input==null) return null;
MutableList result = MutableList.of();
String i1 = input.trim();
boolean inBrackets = (i1.startsWith("[") && i1.endsWith("]"));
if (inBrackets) i1 = i1.substring(1, i1.length()-1).trim();
QuotedStringTokenizer qst = new QuotedStringTokenizer(i1, "\"", true, ",", false);
while (qst.hasMoreTokens()) {
String t = qst.nextToken().trim();
if (isWrappedInDoubleQuotes(t))
result.add(unwrapJavaString(t));
else {
if (inBrackets && (t.indexOf('[')>=0 || t.indexOf(']')>=0))
throw new IllegalArgumentException("Literal square brackets must be quoted, in element '"+t+"'");
result.add(t.trim());
}
}
return result;
}
}
private static void appendEscaped(Appendable out, char c) throws IOException {
out.append('\\');
out.append(c);
}
private static String applyUnquoteAndUnescape(String s, String mode, boolean allowMultipleQuotes) {
StringBuilder result = new StringBuilder();
boolean escaped = false;
boolean quoted = false;
for (int i=0; i