org.apache.jackrabbit.test.api.EscapeJCRUtil Maven / Gradle / Ivy
/*
* 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.jackrabbit.test.api;
import org.apache.jackrabbit.test.XMLChar;
/**
* Class providing some character escape methods. The escape schemata are
* defined in chapter 6.4.3 (for JCR names) and (6.4.4 for JCR values) in the
* JCR specification.
*/
public class EscapeJCRUtil {
private static final String utf16esc = "_x[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]_";
private static char[] Utf16Padding = {'0', '0', '0'};
private static int utf16length = 4;
public static String escapeJCRValues(String str) {
return escapeValues(str);
}
public static String escapeJCRNames(String str) {
return escapeNames(str);
}
//----------------------- private methods ----------------------------------
private static String escapeNames(String str) {
String[] split = str.split(":");
if (split.length == 2) {
// prefix should yet be a valid xml name
String localname = escape(split[1]);
String name = split[0] + ":" + localname;
return name;
} else {
String localname = escape(split[0]);
return localname;
}
}
private static String escapeValues(String str) {
char[] chars = str.toCharArray();
StringBuffer buf = new StringBuffer();
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
if (c == '\u0020'
|| c == '\u0009'
|| c == '\n'
|| c == '\r') {
buf.append(escapeChar(c));
} else {
buf.append(c);
}
}
return buf.toString();
}
/**
* Check if a substring can be misinterpreted as an escape sequence.
*
* @param str
* @return
*/
private static boolean canMisinterpret(String str) {
boolean misinterprete = false;
// check if is like "_xXXXX_"
if (str.length() >= 7) {
String sub16 = str.substring(0, 7);
if (sub16.matches(utf16esc)) {
misinterprete = true;
}
}
return misinterprete;
}
/**
* Escapes a single (invalid xml) character.
*
* @param c
* @return
*/
private static String escapeChar(char c) {
String unicodeRepr = Integer.toHexString(c);
StringBuffer escaped = new StringBuffer();
escaped.append("_x");
escaped.append(Utf16Padding, 0, utf16length - unicodeRepr.length());
escaped.append(unicodeRepr);
escaped.append("_");
return escaped.toString();
}
/**
* Escapes a string containing invalid xml character(s).
*
* @param str
* @return
*/
private static String escape(String str) {
char[] chars = str.toCharArray();
StringBuffer buf = new StringBuffer();
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
// handle start character
if (i == 0) {
if (!XMLChar.isNameStart(c)) {
String escaped = escapeChar(c);
buf.append(escaped);
} else {
String substr = str.substring(i, str.length());
if (canMisinterpret(substr)) {
buf.append(escapeChar(c));
} else {
buf.append(c);
}
}
} else {
if (!XMLChar.isName(c)) {
buf.append(escapeChar(c));
} else {
String substr = str.substring(i, str.length());
if (canMisinterpret(substr)) {
buf.append(escapeChar(c));
} else {
buf.append(c);
}
}
}
}
return buf.toString();
}
}