2
* Licensed to the Apache Software Foundation (ASF) under one or more
3
* contributor license agreements. See the NOTICE file distributed with
4
* this work for additional information regarding copyright ownership.
5
* The ASF licenses this file to You under the Apache License, Version 2.0
6
* (the "License"); you may not use this file except in compliance with
7
* the License. You may obtain a copy of the License at
9
* http://www.apache.org/licenses/LICENSE-2.0
11
* Unless required by applicable law or agreed to in writing, software
12
* distributed under the License is distributed on an "AS IS" BASIS,
13
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
* See the License for the specific language governing permissions and
15
* limitations under the License.
18
package org.apache.solr.common.util;
20
import java.util.List;
21
import java.util.ArrayList;
22
import java.util.Collections;
23
import java.util.Locale;
24
import java.io.IOException;
26
import org.apache.solr.common.SolrException;
29
* @version $Id: StrUtils.java 1065586 2011-01-31 13:01:48Z rmuir $
31
public class StrUtils {
32
public static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6',
33
'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
36
* Split a string based on a separator, but don't split if it's inside
37
* a string. Assume '\' escapes the next char both inside and
40
public static List<String> splitSmart(String s, char separator) {
41
ArrayList<String> lst = new ArrayList<String>(4);
42
int pos=0, start=0, end=s.length();
48
if (ch=='\\') { // skip escaped chars
50
} else if (inString != 0 && ch==inString) {
52
} else if (ch=='\'' || ch=='"') {
53
// If char is directly preceeded by a number or letter
54
// then don't treat it as the start of a string.
55
// Examples: 50" TV, or can't
56
if (!Character.isLetterOrDigit(prevChar)) {
59
} else if (ch==separator && inString==0) {
60
lst.add(s.substring(start,pos-1));
65
lst.add(s.substring(start,end));
69
if (SolrCore.log.isLoggable(Level.FINEST)) {
70
SolrCore.log.trace("splitCommand=" + lst);
77
/** Splits a backslash escaped string on the separator.
79
* Current backslash escaping supported:
80
* <br> \n \t \r \b \f are escaped the same as a Java String
81
* <br> Other characters following a backslash are produced verbatim (\c => c)
83
* @param s the string to split
84
* @param separator the separator to split on
85
* @param decode decode backslash escaping
87
public static List<String> splitSmart(String s, String separator, boolean decode) {
88
ArrayList<String> lst = new ArrayList<String>(2);
89
StringBuilder sb = new StringBuilder();
90
int pos=0, end=s.length();
92
if (s.startsWith(separator,pos)) {
93
if (sb.length() > 0) {
94
lst.add(sb.toString());
95
sb=new StringBuilder();
97
pos+=separator.length();
101
char ch = s.charAt(pos++);
103
if (!decode) sb.append(ch);
104
if (pos>=end) break; // ERROR, or let it go?
105
ch = s.charAt(pos++);
108
case 'n' : ch='\n'; break;
109
case 't' : ch='\t'; break;
110
case 'r' : ch='\r'; break;
111
case 'b' : ch='\b'; break;
112
case 'f' : ch='\f'; break;
120
if (sb.length() > 0) {
121
lst.add(sb.toString());
128
* Splits file names separated by comma character.
129
* File names can contain comma characters escaped by backslash '\'
131
* @param fileNames the string containing file names
132
* @return a list of file names with the escaping backslashed removed
134
public static List<String> splitFileNames(String fileNames) {
135
if (fileNames == null)
136
return Collections.<String>emptyList();
138
List<String> result = new ArrayList<String>();
139
for (String file : fileNames.split("(?<!\\\\),")) {
140
result.add(file.replaceAll("\\\\(?=,)", ""));
146
/** Creates a backslash escaped string, joining all the items. */
147
public static String join(List<String> items, char separator) {
148
StringBuilder sb = new StringBuilder(items.size() << 3);
150
for (String item : items) {
154
sb.append(separator);
156
for (int i=0; i<item.length(); i++) {
157
char ch = item.charAt(i);
158
if (ch=='\\' || ch == separator) {
164
return sb.toString();
169
public static List<String> splitWS(String s, boolean decode) {
170
ArrayList<String> lst = new ArrayList<String>(2);
171
StringBuilder sb = new StringBuilder();
172
int pos=0, end=s.length();
174
char ch = s.charAt(pos++);
175
if (Character.isWhitespace(ch)) {
176
if (sb.length() > 0) {
177
lst.add(sb.toString());
178
sb=new StringBuilder();
184
if (!decode) sb.append(ch);
185
if (pos>=end) break; // ERROR, or let it go?
186
ch = s.charAt(pos++);
189
case 'n' : ch='\n'; break;
190
case 't' : ch='\t'; break;
191
case 'r' : ch='\r'; break;
192
case 'b' : ch='\b'; break;
193
case 'f' : ch='\f'; break;
201
if (sb.length() > 0) {
202
lst.add(sb.toString());
208
public static List<String> toLower(List<String> strings) {
209
ArrayList<String> ret = new ArrayList<String>(strings.size());
210
for (String str : strings) {
211
ret.add(str.toLowerCase(Locale.ENGLISH));
218
/** Return if a string starts with '1', 't', or 'T'
219
* and return false otherwise.
221
public static boolean parseBoolean(String s) {
222
char ch = s.length()>0 ? s.charAt(0) : 0;
223
return (ch=='1' || ch=='t' || ch=='T');
226
/** how to transform a String into a boolean... more flexible than
227
* Boolean.parseBoolean() to enable easier integration with html forms.
229
public static boolean parseBool(String s) {
231
if( s.startsWith("true") || s.startsWith("on") || s.startsWith("yes") ) {
234
if( s.startsWith("false") || s.startsWith("off") || s.equals("no") ) {
238
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "invalid boolean value: "+s );
242
* {@link NullPointerException} and {@link SolrException} free version of {@link #parseBool(String)}
245
* @return parsed boolean value (or def, if s is null or invalid)
247
public static boolean parseBool(String s, boolean def) {
249
if( s.startsWith("true") || s.startsWith("on") || s.startsWith("yes") ) {
252
if( s.startsWith("false") || s.startsWith("off") || s.equals("no") ) {
260
* URLEncodes a value, replacing only enough chars so that
261
* the URL may be unambiguously pasted back into a browser.
263
* Characters with a numeric value less than 32 are encoded.
264
* &,=,%,+,space are encoded.
267
public static void partialURLEncodeVal(Appendable dest, String val) throws IOException {
268
for (int i=0; i<val.length(); i++) {
269
char ch = val.charAt(i);
272
if (ch < 0x10) dest.append('0');
273
dest.append(Integer.toHexString(ch));
276
case ' ': dest.append('+'); break;
277
case '&': dest.append("%26"); break;
278
case '%': dest.append("%25"); break;
279
case '=': dest.append("%3D"); break;
280
case '+': dest.append("%2B"); break;
281
default : dest.append(ch); break;