242 lines
6.7 KiB
Java
Executable File
242 lines
6.7 KiB
Java
Executable File
package com.moparisthebest.sxf4j.impl;
|
|
|
|
import java.io.*;
|
|
import java.lang.reflect.Constructor;
|
|
|
|
public abstract class AbstractXmlElement implements XmlElement, XmlElementFactory {
|
|
|
|
public static final String implProperty = "xmlElementImpl";
|
|
|
|
// provided implementations
|
|
public static final String XPP3 = "Xpp3";
|
|
public static final String XPP = "Xpp";
|
|
public static final String DOM4J = "Dom4j";
|
|
public static final String XOM = "Xom";
|
|
public static final String W3C = "W3C";
|
|
|
|
public static XmlElementFactory getFactory() {
|
|
XmlElementFactory ret = null;
|
|
|
|
//ret = new W3CXmlElement();
|
|
//ret = new XppXmlElement();
|
|
//ret = new Xpp3XmlElement();
|
|
//ret = new Dom4jXmlElement();
|
|
//ret = new XomXmlElement();
|
|
final String xmlDocType = System.getProperty(implProperty);
|
|
//System.out.println("xmlDocType: "+xmlDocType);
|
|
String implPkgClass = AbstractXmlElement.class.getPackage().getName() + "." + xmlDocType;
|
|
if (ret == null && xmlDocType != null)
|
|
ret = objectForName(implPkgClass + "XmlElement", null);
|
|
if (ret == null && xmlDocType != null)
|
|
ret = objectForName(implPkgClass, null);
|
|
if (ret == null && xmlDocType != null)
|
|
ret = objectForName(xmlDocType, null);
|
|
// try them in a defined default order
|
|
if (ret == null) {
|
|
Class[] xmlDocs = new Class[]{XppXmlElement.class, Xpp3XmlElement.class, Dom4jXmlElement.class, XomXmlElement.class};
|
|
for (Class xmlDoc : xmlDocs) {
|
|
ret = objectForName(null, xmlDoc);
|
|
if (ret != null)
|
|
break;
|
|
}
|
|
}
|
|
// as a last resort, W3CXmlElement should ALWAYS be available
|
|
if (ret == null)
|
|
ret = new W3CXmlElement();
|
|
return ret;
|
|
}
|
|
|
|
@SuppressWarnings({"unchecked"})
|
|
private static <E> E objectForName(String name, Class clazz) {
|
|
try {
|
|
if (clazz == null)
|
|
clazz = Class.forName(name);
|
|
Constructor constructor = null;
|
|
try {
|
|
constructor = clazz.getDeclaredConstructor();
|
|
} catch (Exception e) {
|
|
// we would only reach here if there is no default no-arg constructor
|
|
// we must use sun classes to get around this, unfortunately
|
|
sun.reflect.ReflectionFactory rf = sun.reflect.ReflectionFactory.getReflectionFactory();
|
|
constructor = rf.newConstructorForSerialization(clazz, Object.class.getDeclaredConstructor(new Class[0]));
|
|
}
|
|
if (!constructor.isAccessible())
|
|
constructor.setAccessible(true);
|
|
return (E) constructor.newInstance();
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
} catch (Error e) {
|
|
e.printStackTrace();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
protected static String emptyForNull(String ret) {
|
|
return ret == null ? "" : ret;
|
|
}
|
|
|
|
protected void writeHeader(OutputStreamWriter osw, boolean newLine) throws IOException {
|
|
// only write the header if parent is null (top level)
|
|
if (getParent() != null)
|
|
return;
|
|
String header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
|
|
if (newLine)
|
|
header += "\n";
|
|
osw.write(header, 0, header.length());
|
|
}
|
|
|
|
@Override
|
|
public final XmlElement[] getChildren() {
|
|
return getChildren(null);
|
|
}
|
|
|
|
@Override
|
|
public void writeToFile(File file) throws Exception {
|
|
writeToStream(new FileOutputStream(file));
|
|
}
|
|
|
|
@Override
|
|
public void writeToFile(String fileName) throws Exception {
|
|
writeToFile(new File(fileName));
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
try {
|
|
writeToStream(bos);
|
|
return new String(bos.toByteArray(), "UTF-8");
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
return new String(bos.toByteArray());
|
|
}
|
|
|
|
@Override
|
|
public String toStringCompact() {
|
|
// this removes all whitespace between tags
|
|
String prettyXml = toString().replaceAll(">\\s+<", "><");
|
|
// now we have to remove all whitespace between attributes
|
|
StringBuilder compactXml = new StringBuilder(prettyXml.length());
|
|
boolean inTag = false;
|
|
boolean inAttribute = false;
|
|
boolean appendedWhitespace = false;
|
|
for (int x = 0; x < prettyXml.length(); ++x) {
|
|
char c = prettyXml.charAt(x);
|
|
if (c == '<')
|
|
inTag = true;
|
|
else if (c == '>')
|
|
inTag = false;
|
|
else if (c == '"') {
|
|
inAttribute = !inAttribute;
|
|
appendedWhitespace = false;
|
|
}
|
|
|
|
if (inTag && !inAttribute && Character.isWhitespace(c)) {
|
|
if (appendedWhitespace)
|
|
continue;
|
|
appendedWhitespace = true;
|
|
c = ' ';
|
|
}
|
|
|
|
compactXml.append(c);
|
|
}
|
|
return compactXml.toString();
|
|
}
|
|
|
|
private int byteLength(String s) {
|
|
try {
|
|
return s.getBytes("UTF-8").length;
|
|
} catch (Exception e) {
|
|
return s.getBytes().length;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int byteLength() {
|
|
return byteLength(toString());
|
|
}
|
|
|
|
@Override
|
|
public int byteLengthCompact() {
|
|
return byteLength(toStringCompact());
|
|
}
|
|
|
|
@Override
|
|
public XmlElement readFromFile(File file) throws Exception {
|
|
return readFromStream(new FileInputStream(file));
|
|
}
|
|
|
|
@Override
|
|
public XmlElement readFromFile(String file) throws Exception {
|
|
return readFromFile(new File(file));
|
|
}
|
|
|
|
@Override
|
|
public XmlElement readFromString(String string) throws Exception {
|
|
return readFromStream(new ByteArrayInputStream(string.getBytes()));
|
|
}
|
|
|
|
@Override
|
|
public boolean isWrapperFor(Class<?> iface) {
|
|
return iface != null && iface.isInstance(getInternal());
|
|
}
|
|
|
|
@Override
|
|
public <T> T unwrap(Class<T> iface) {
|
|
if (!isWrapperFor(iface))
|
|
return null;
|
|
return iface.cast(getInternal());
|
|
}
|
|
|
|
/**
|
|
* For isWrapperFor and unwrap implementation
|
|
*
|
|
* @return
|
|
*/
|
|
protected abstract Object getInternal();
|
|
|
|
protected XmlElement[] wrapArray(Object[] os) {
|
|
XmlElement[] ret = new XmlElement[os.length];
|
|
for (int x = 0; x < ret.length; ++x)
|
|
ret[x] = wrapObject(os[x]);
|
|
return ret;
|
|
}
|
|
|
|
protected XmlElement wrapParent(Object parent) {
|
|
return parent == null ? null : wrapObject(parent);
|
|
}
|
|
|
|
protected abstract XmlElement wrapObject(Object o);
|
|
|
|
public XmlElement copyTo(XmlElementFactory factory) throws Exception {
|
|
if (factory == null)
|
|
return null;
|
|
|
|
return factory.readFromString(this.toString());
|
|
}
|
|
|
|
/** old way, read/write above probably better
|
|
public XmlElement copyTo(XmlElementFactory factory) {
|
|
if (factory == null)
|
|
return null;
|
|
|
|
XmlElement ret = factory.getNewChildXmlElement(this.getName());
|
|
copyXmlElement(this, ret);
|
|
return ret;
|
|
}
|
|
|
|
private void copyXmlElement(XmlElement src, XmlElement dst) {
|
|
// set the value
|
|
if (src.getValue() != null)
|
|
dst.setValue(src.getValue());
|
|
// set all the attributes
|
|
for (String attName : src.getAttributeNames())
|
|
dst.setAttribute(attName, src.getAttribute(attName));
|
|
// recursively set all the children
|
|
for (XmlElement child : src.getChildren())
|
|
copyXmlElement(child, dst.getNewChildXmlElement(child.getName()));
|
|
}
|
|
*/
|
|
}
|