Skip to content

Instantly share code, notes, and snippets.

@mariofusco
Created April 8, 2015 13:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mariofusco/5814b873ad0a1af4f4a8 to your computer and use it in GitHub Desktop.
Save mariofusco/5814b873ad0a1af4f4a8 to your computer and use it in GitHub Desktop.
/**
* 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.camel.dataformat.xstream;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.stream.XMLStreamException;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.converter.jaxp.StaxConverter;
import org.apache.camel.spi.ClassResolver;
import org.apache.camel.spi.DataFormat;
import org.apache.camel.util.ObjectHelper;
/**
* An abstract class which implement <a href="http://camel.apache.org/data-format.html">data format</a>
* ({@link DataFormat}) interface which leverage the XStream library for XML or JSON's marshaling and unmarshaling
*/
public abstract class AbstractXStreamWrapper implements DataFormat {
private XStream xstream;
private HierarchicalStreamDriver xstreamDriver;
private StaxConverter staxConverter;
private List<String> converters;
private Map<String, String> aliases;
private Map<String, String[]> omitFields;
private Map<String, String[]> implicitCollections;
private String mode;
public AbstractXStreamWrapper() {
}
public AbstractXStreamWrapper(XStream xstream) {
this.xstream = xstream;
}
/**
* Resolves the XStream instance to be used by this data format. If XStream is not explicitly set, new instance will
* be created and cached.
*
* @param resolver class resolver to be used during a configuration of the XStream instance.
* @return XStream instance used by this data format.
*/
public XStream getXStream(ClassResolver resolver) {
if (xstream == null) {
xstream = createXStream(resolver);
}
return xstream;
}
/**
* Resolves the XStream instance to be used by this data format. If XStream is not explicitly set, new instance will
* be created and cached.
*
* @param context to be used during a configuration of the XStream instance
* @return XStream instance used by this data format.
*/
public XStream getXStream(CamelContext context) {
if (xstream == null) {
xstream = createXStream(context.getClassResolver(), context.getApplicationContextClassLoader());
}
return xstream;
}
public void setXStream(XStream xstream) {
this.xstream = xstream;
}
/**
* @deprecated Use {@link #createXStream(ClassResolver, ClassLoader)}
*/
protected XStream createXStream(ClassResolver resolver) {
return createXStream(resolver, null);
}
protected XStream createXStream(ClassResolver resolver, ClassLoader classLoader) {
if (xstreamDriver != null) {
xstream = new XStream(xstreamDriver);
} else {
xstream = new XStream();
}
if (mode != null) {
xstream.setMode(getModeFromString(mode));
}
if (classLoader != null) {
xstream.setClassLoader(classLoader); // <<------
}
try {
if (this.implicitCollections != null) {
for (Entry<String, String[]> entry : this.implicitCollections.entrySet()) {
for (String name : entry.getValue()) {
xstream.addImplicitCollection(resolver.resolveMandatoryClass(entry.getKey()), name);
}
}
}
if (this.aliases != null) {
for (Entry<String, String> entry : this.aliases.entrySet()) {
xstream.alias(entry.getKey(), resolver.resolveMandatoryClass(entry.getValue()));
// It can turn the auto-detection mode off
xstream.processAnnotations(resolver.resolveMandatoryClass(entry.getValue()));
}
}
if (this.omitFields != null) {
for (Entry<String, String[]> entry : this.omitFields.entrySet()) {
for (String name : entry.getValue()) {
xstream.omitField(resolver.resolveMandatoryClass(entry.getKey()), name);
}
}
}
if (this.converters != null) {
for (String name : this.converters) {
Class<Converter> converterClass = resolver.resolveMandatoryClass(name, Converter.class);
Converter converter;
Constructor<Converter> con = null;
try {
con = converterClass.getDeclaredConstructor(new Class[]{XStream.class});
} catch (Exception e) {
//swallow as we null check in a moment.
}
if (con != null) {
converter = con.newInstance(xstream);
} else {
converter = converterClass.newInstance();
try {
Method method = converterClass.getMethod("setXStream", new Class[]{XStream.class});
if (method != null) {
ObjectHelper.invokeMethod(method, converter, xstream);
}
} catch (Throwable e) {
// swallow, as it just means the user never add an XStream setter, which is optional
}
}
xstream.registerConverter(converter);
}
}
} catch (Exception e) {
throw new RuntimeException("Unable to build XStream instance", e);
}
return xstream;
}
protected int getModeFromString(String modeString) {
int result;
if ("NO_REFERENCES".equalsIgnoreCase(modeString)) {
result = XStream.NO_REFERENCES;
} else if ("ID_REFERENCES".equalsIgnoreCase(modeString)) {
result = XStream.ID_REFERENCES;
} else if ("XPATH_RELATIVE_REFERENCES".equalsIgnoreCase(modeString)) {
result = XStream.XPATH_RELATIVE_REFERENCES;
} else if ("XPATH_ABSOLUTE_REFERENCES".equalsIgnoreCase(modeString)) {
result = XStream.XPATH_ABSOLUTE_REFERENCES;
} else if ("SINGLE_NODE_XPATH_RELATIVE_REFERENCES".equalsIgnoreCase(modeString)) {
result = XStream.SINGLE_NODE_XPATH_RELATIVE_REFERENCES;
} else if ("SINGLE_NODE_XPATH_ABSOLUTE_REFERENCES".equalsIgnoreCase(modeString)) {
result = XStream.SINGLE_NODE_XPATH_ABSOLUTE_REFERENCES;
} else {
throw new IllegalArgumentException("Unknown mode : " + modeString);
}
return result;
}
public StaxConverter getStaxConverter() {
if (staxConverter == null) {
staxConverter = new StaxConverter();
}
return staxConverter;
}
public void setStaxConverter(StaxConverter staxConverter) {
this.staxConverter = staxConverter;
}
public List<String> getConverters() {
return converters;
}
public void setConverters(List<String> converters) {
this.converters = converters;
}
public Map<String, String> getAliases() {
return aliases;
}
public void setAliases(Map<String, String> aliases) {
this.aliases = aliases;
}
public Map<String, String[]> getImplicitCollections() {
return implicitCollections;
}
public void setImplicitCollections(Map<String, String[]> implicitCollections) {
this.implicitCollections = implicitCollections;
}
public Map<String, String[]> getOmitFields() {
return omitFields;
}
public void setOmitFields(Map<String, String[]> omitFields) {
this.omitFields = omitFields;
}
public HierarchicalStreamDriver getXstreamDriver() {
return xstreamDriver;
}
public void setXstreamDriver(HierarchicalStreamDriver xstreamDriver) {
this.xstreamDriver = xstreamDriver;
}
public String getMode() {
return mode;
}
public void setMode(String mode) {
this.mode = mode;
}
public XStream getXstream() {
return xstream;
}
public void setXstream(XStream xstream) {
this.xstream = xstream;
}
public void marshal(Exchange exchange, Object body, OutputStream stream) throws Exception {
HierarchicalStreamWriter writer = createHierarchicalStreamWriter(exchange, body, stream);
try {
getXStream(exchange.getContext()).marshal(body, writer);
} finally {
writer.close();
}
}
public Object unmarshal(Exchange exchange, InputStream stream) throws Exception {
HierarchicalStreamReader reader = createHierarchicalStreamReader(exchange, stream);
try {
return getXStream(exchange.getContext()).unmarshal(reader);
} finally {
reader.close();
}
}
protected abstract HierarchicalStreamWriter createHierarchicalStreamWriter(
Exchange exchange, Object body, OutputStream stream) throws XMLStreamException;
protected abstract HierarchicalStreamReader createHierarchicalStreamReader(
Exchange exchange, InputStream stream) throws XMLStreamException;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment