/**
* Copyright 2011-2014 the original author or authors.
*/
package com.jetdrone.vertx.yoke.util;
import org.jetbrains.annotations.NotNull;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.*;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Set;
public final class Utils {
// no instantiation
private Utils () {}
/**
* Avoid using this method for constant reads, use it only for one time only reads from resources in the classpath
*/
public static Buffer readResourceToBuffer(@NotNull Class<?> clazz, @NotNull String resource) {
try {
Buffer buffer = Buffer.buffer(0);
try (InputStream in = clazz.getResourceAsStream(resource)) {
int read;
byte[] data = new byte[4096];
while ((read = in.read(data, 0, data.length)) != -1) {
if (read == data.length) {
buffer.appendBytes(data);
} else {
byte[] slice = new byte[read];
System.arraycopy(data, 0, slice, 0, slice.length);
buffer.appendBytes(slice);
}
}
}
return buffer;
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
/**
* Avoid using this method for constant reads, use it only for one time only reads from resources in the classpath
*/
public static String readResourceToString(@NotNull Class<?> clazz, @NotNull String resource) {
try {
try (Reader r = new BufferedReader(new InputStreamReader(clazz.getResourceAsStream(resource), "UTF-8"))) {
Writer writer = new StringWriter();
char[] buffer = new char[1024];
int n;
while ((n = r.read(buffer)) != -1) {
writer.write(buffer, 0, n);
}
return writer.toString();
}
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
/**
* Avoid using this method for constant reads, use it only for one time only reads from resources in the classpath
*/
public static String readFileToString(@NotNull String resource) {
try {
try (Reader r = new BufferedReader(new InputStreamReader(new FileInputStream(resource), "UTF-8"))) {
Writer writer = new StringWriter();
char[] buffer = new char[1024];
int n;
while ((n = r.read(buffer)) != -1) {
writer.write(buffer, 0, n);
}
return writer.toString();
}
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
/**
* Avoid using this method for constant reads, use it only for one time only reads from resources in the classpath
*/
public static String readURLToString(@NotNull String resource) {
try {
try (Reader r = new BufferedReader(new InputStreamReader(new URL(resource).openStream(), "UTF-8"))) {
Writer writer = new StringWriter();
char[] buffer = new char[1024];
int n;
while ((n = r.read(buffer)) != -1) {
writer.write(buffer, 0, n);
}
return writer.toString();
}
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
public static String escape(@NotNull String html) {
return html
.replaceAll("&", "&")
.replaceAll("\"", """)
.replaceAll("<", "<")
.replaceAll(">", ">");
}
private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance();
private static final String XSLT = Utils.readResourceToString(Utils.class, "xml-to-json.xsl");
public static JsonObject xmlToJson(@NotNull String xml) throws TransformerException {
// allocate the size of the xml (this is probably is more than needed but avoid re-allocations)
StringWriter out = new StringWriter(xml.length());
Transformer transformer = TRANSFORMER_FACTORY.newTransformer(new StreamSource(new StringReader(XSLT)));
transformer.transform(new StreamSource(new StringReader(xml)), new StreamResult(out));
return new JsonObject(out.toString());
}
private static final XMLOutputFactory XML_OUTPUT_FACTORY = XMLOutputFactory.newInstance();
public static String jsonToXml(@NotNull JsonObject json, @NotNull String rootName) throws XMLStreamException {
Writer xml = new StringWriter();
// Create an XML stream writer
XMLStreamWriter xmlw = XML_OUTPUT_FACTORY.createXMLStreamWriter(xml);
// Write XML prologue
xmlw.writeStartDocument();
// perform real conversion
jsonToXml(xmlw, json, rootName);
// Close the writer to flush the output
xmlw.close();
return xml.toString();
}
private static void jsonToXml(XMLStreamWriter writer, JsonObject json, String name) throws XMLStreamException {
// get all field names
Set<String> fields = json.fieldNames();
if (fields.size() == 0) {
// start with element name
writer.writeEmptyElement(name);
return;
}
// start with element name
writer.writeStartElement(name);
for (String field : fields) {
Object value = json.getValue(field);
if (value != null) {
if (value instanceof JsonObject) {
// process child
jsonToXml(writer, (JsonObject) value, field);
} else if (value instanceof JsonArray) {
jsonToXml(writer, (JsonArray) value, field);
} else {
// Writing a few attributes
if (field.charAt(0) == '@') {
writer.writeAttribute(field.substring(1), json.getValue(field).toString());
} else if ("$".equals(field)) {
writer.writeCharacters(json.getValue(field).toString());
}
}
}
}
// end with element name
writer.writeEndElement();
}
private static void jsonToXml(XMLStreamWriter writer, JsonArray json, String name) throws XMLStreamException {
if (json.size() == 0) {
// start with element name
writer.writeEmptyElement(name);
return;
}
for (int i = 0 ; i < json.size(); i++) {
Object element = json.getValue(i);
if (element == null) {
writer.writeEmptyElement(name);
continue;
}
if (element instanceof JsonObject) {
jsonToXml(writer, (JsonObject) element, name);
continue;
}
if (element instanceof JsonArray) {
jsonToXml(writer, (JsonArray) element, name);
continue;
}
// start with element name
writer.writeStartElement(name);
writer.writeCharacters(element.toString());
// end with element name
writer.writeEndElement();
}
}
public static String encodeURIComponent(@NotNull String s) {
String result;
try {
result = URLEncoder.encode(s, "UTF-8")
.replaceAll("\\+", "%20")
.replaceAll("%21", "!")
.replaceAll("%27", "'")
.replaceAll("%28", "(")
.replaceAll("%29", ")")
.replaceAll("%7E", "~");
} catch (UnsupportedEncodingException e) {
result = s;
}
return result;
}
public static String decodeURIComponent(@NotNull String s) {
String result;
try {
result = URLDecoder.decode(s, "UTF-8");
} catch (UnsupportedEncodingException e) {
result = s;
}
return result;
}
}