/*
* Copyright 2015 herd contributors
*
* 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.finra.herd.dao.helper;
import java.io.IOException;
import java.io.Writer;
import org.eclipse.persistence.oxm.CharacterEscapeHandler;
import org.springframework.stereotype.Component;
/**
* A custom escape handler that escapes XML 1.1 restricted characters (http://www.w3.org/TR/xml11/#charsets).
*/
@Component
public class HerdCharacterEscapeHandler implements CharacterEscapeHandler
{
/**
* Escape restricted XML 1.1 characters inside the buffer and send the output to the Writer. The "&", "<", and ">" characters are always escaped. Single and
* double quotes are escaped when within an attribute. All XML 1.1 restricted characters are escaped using "(value);".
*
* @param buffer the buffer.
* @param start the start of the buffer.
* @param length the length of the buffer.
* @param isAttributeValue Flag that determines whether the buffer is an XML attribute or not.
* @param outputWriter the output writer.
*
* @throws IOException which will stop the marshalling process.
*/
@Override
public void escape(char[] buffer, int start, int length, boolean isAttributeValue, Writer outputWriter) throws IOException
{
// Loop through all characters in the buffer starting at "start" and going until the length has been reached.
for (int i = start; i < start + length; i++)
{
// Grab a character in the buffer.
char ch = buffer[i];
// Handle the standard XML tag escaping.
if (ch == '&')
{
outputWriter.write("&");
continue;
}
if (ch == '<')
{
outputWriter.write("<");
continue;
}
if (ch == '>')
{
outputWriter.write(">");
continue;
}
// Handle the single and double quote characters when attributes are present.
if (ch == '"' && isAttributeValue)
{
outputWriter.write(""");
continue;
}
if (ch == '\'' && isAttributeValue)
{
outputWriter.write("'");
continue;
}
// Escape the character if it's XML 1.1 restricted.
if (isXml11RestrictedCharacter(ch))
{
outputWriter.write("");
outputWriter.write(Integer.toHexString(ch));
outputWriter.write(";");
continue;
}
// In all other cases, output the character as is.
outputWriter.write(ch);
}
}
/**
* Returns whether the specified character is XML 1.1 restricted.
*
* @param ch the character to check.
*
* @return True if the character is restricted or false if not.
*/
public static boolean isXml11RestrictedCharacter(char ch)
{
return (((ch >= 0x1) && (ch <= 0x8)) ||
((ch >= 0xB) && (ch <= 0xC)) ||
((ch >= 0xE) && (ch <= 0x1F)) ||
((ch >= 0x7F) && (ch <= 0x84)) ||
((ch >= 0x86) && (ch <= 0x9F)));
}
}