/*******************************************************************************
* Copyright (c) 2006-2010 eBay Inc. All Rights Reserved.
* 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
*******************************************************************************/
package org.ebayopensource.turmeric.runtime.tests.parser.nv;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import org.ebayopensource.turmeric.runtime.binding.impl.parser.NamespaceConvention;
import org.ebayopensource.turmeric.runtime.binding.impl.parser.nv.NVStreamParser;
import org.ebayopensource.turmeric.runtime.binding.impl.parser.nv.NVStreamWriter;
import org.ebayopensource.turmeric.runtime.binding.utils.URLDecoderInputStream;
import org.ebayopensource.turmeric.runtime.common.impl.internal.schema.DataElementSchemaImpl;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UTF8DecodingTest {
private final Logger logger = LoggerFactory
.getLogger(UTF8DecodingTest.class);
/**
* @param args
*/
@Test
public void payPalIinput() throws Exception {
logger.debug("Starting payPalIinput");
doTest("%CE%B5%CE%BB%CE%BB%CE%B7%CE%BD%CE%B9%CE%BA%CE%AE");
logger.debug("Finishing payPalIinput");
}
private static final String UNENCODED = "a%\u03a3\u304b";
private static final String ENCODED = "a%25%CE%A3%E3%81%8B";
private static final String ENCODING = "UTF-8";
private static final String NS = "http://foo.com";
private static final String LOCAL_NAME = "message";
@Test
public void encodeTest() throws Exception {
logger.debug("Starting encodeTest");
String nvEncoded = nvEncode(UNENCODED);
String javaNative = UNENCODED;
String javaEncoded = URLEncoder.encode(UNENCODED, ENCODING);
logger.debug("Encode Test");
logger.debug(" Original: " + nativeToAscii(UNENCODED));
logger.debug(" NV Encode: " + nativeToAscii(nvEncoded));
logger.debug(" URLEncoder: " + nativeToAscii(javaEncoded));
logger.debug(" Expected: " + nativeToAscii(ENCODED));
assertEquals(nativeToAscii(ENCODED), nativeToAscii(nvEncoded));
logger.debug("Finishing encodeTest");
}
@Test
public void decodeTest() throws Exception {
logger.debug("Starting decodeTest");
String nvDecoded = nvDecode(ENCODED);
String javaDecoded = URLDecoder.decode(ENCODED, ENCODING);
logger.debug("Decode Test");
logger.debug(" Original: " + nativeToAscii(ENCODED));
logger.debug(" NV Decode: " + nativeToAscii(nvDecoded));
logger.debug(" URLDecoder: " + nativeToAscii(javaDecoded));
logger.debug(" Expected: " + nativeToAscii(UNENCODED));
assertEquals(nativeToAscii(UNENCODED), nativeToAscii(nvDecoded));
logger.debug("Finishing decodeTest");
}
@Test
public void roundTripTest() throws Exception {
logger.debug("Starting roundTripTest");
String nvDecoded = nvDecode(ENCODED);
String nvEncoded = nvEncode(nvDecoded);
logger.debug("Round Trip Test");
logger.debug(" Original: " + nativeToAscii(ENCODED));
logger.debug(" NV Decode: " + nativeToAscii(nvDecoded));
logger.debug(" Expected: " + nativeToAscii(UNENCODED));
logger.debug(" NV Encode: " + nativeToAscii(nvEncoded));
logger.debug(" Expected: " + nativeToAscii(ENCODED));
assertEquals(nativeToAscii(ENCODED), nativeToAscii(nvEncoded));
assertEquals(nativeToAscii(UNENCODED), nativeToAscii(nvDecoded));
logger.debug("Finishing roundTripTest");
}
private static String nativeToAscii(String value) {
StringBuilder buf = new StringBuilder();
for (char c : value.toCharArray()) {
switch (c) {
case '\\':
buf.append("\\\\");
break;
case '\t':
buf.append("\\t");
break;
case '\n':
buf.append("\\n");
break;
case '\r':
buf.append("\\r");
break;
case '\f':
buf.append("\\f");
break;
default:
if ((c < 0x0020) || (c > 0x007e)) {
String hexValue = Integer.toHexString(c).toUpperCase();
while (hexValue.length() < 4) {
hexValue = "0" + hexValue;
}
buf.append("\\u" + hexValue);
} else {
buf.append("" + c);
}
}
}
return buf.toString();
}
private static String nvEncode(final String unencodedValue)
throws XMLStreamException, IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Map<String, String> opts = new HashMap<String, String>();
opts.put(NVStreamWriter.KEY_USE_SCHEMA_INFO, "true");
opts.put(NVStreamWriter.KEY_QUOTE_VALUE, "false");
opts.put(NVStreamWriter.KEY_ENCODE_VALUE, "true");
List<String> namespaces = new ArrayList<String>(1);
namespaces.add(NS);
Map<String, List<String>> ns2Prefix = new HashMap<String, List<String>>();
Map<String, String> prefix2NS = new HashMap<String, String>();
NamespaceConvention.buildNsPrefixes(namespaces, ns2Prefix, prefix2NS);
NamespaceConvention conv = NamespaceConvention
.createSerializationNSConvention(NS, prefix2NS, ns2Prefix);
QName name = new QName(NS, LOCAL_NAME);
NVStreamWriter writer = new NVStreamWriter(conv, baos,
Charset.forName(ENCODING), name, new DataElementSchemaImpl(
name, 1), opts, false);
writer.writeStartElement("", LOCAL_NAME, NS);
writer.writeCharacters(unencodedValue);
writer.writeEndElement();
writer.close();
baos.close();
// Convert to string and remove "message=".
return new String(baos.toByteArray(), ENCODING).replace(LOCAL_NAME
+ "=", "");
}
private static String nvDecode(final String encodedValue)
throws UnsupportedEncodingException, XMLStreamException {
String message = LOCAL_NAME + "=" + encodedValue;
ByteArrayInputStream bais = new ByteArrayInputStream(
message.getBytes(ENCODING));
NVStreamParser parser = new NVStreamParser(bais,
Charset.forName(ENCODING), null);
parser.parseLine();
String nvDecoded = parser.getValue();
return nvDecoded;
}
private void doTest(String inputString) throws Exception {
String decoded = URLDecoder.decode(inputString, "UTF-8");
ByteArrayInputStream is = new ByteArrayInputStream(
inputString.getBytes());
InputStreamReader isr = new InputStreamReader(
new URLDecoderInputStream(is), "UTF-8");
char[] buf = new char[30];
int count = isr.read(buf);
if (-1 == count) {
assertFalse("no input", false);
}
assertEquals(decoded, new String(buf, 0, count));
}
}