/*
* Copyright (C) 2012 Sebastian Straub <sebastian-straub@gmx.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.nx42.wotcrawler.xml;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.SchemaOutputResolver;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
import de.nx42.wotcrawler.db.TanksDB;
/**
* Serializes java objects and deserializes XML documents using the JAXB library
*
* @author Sebastian Straub <sebastian-straub@gmx.net>
*/
public class Serializer {
private static final Logger log = LoggerFactory.getLogger(Serializer.class);
// -------------------- Serialize java objects --------------------
/**
* Serialize an object to XML using JAXB
* @param c the class of the object to serialize (wtf is wrong with reflection?!)
* @param instance the actual object instance to serialize
* @param schemaLocation schemalocation tag that is added to the xml
* @param output the file to write the xml into
*/
public static void serialize(Class c, Object instance, String schemaLocation, File output) {
try {
JAXBContext context = JAXBContext.newInstance(c);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, schemaLocation);
m.marshal(instance, output);
} catch (JAXBException ex) {
log.error("Error serializing object to XML", ex);
}
}
/**
* Serialize an object to XML using JAXB
* @param c the class of the object to serialize (wtf is wrong with reflection?!)
* @param instance the actual object instance to serialize
* @param output the file to write the xml into
*/
public static void serialize(Class c, Object instance, File output) {
try {
JAXBContext context = JAXBContext.newInstance(c);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(instance, output);
} catch (JAXBException ex) {
log.error("Error serializing object to XML", ex);
}
}
// -------------------- deserialize XML documents --------------------
/**
* Deserializes an XML document to a java object using JAXB
* @param <S> the type of the java object to create
* @param c the class of the object to create
* @param xml the xml file to deserialize
* @param schema the corresponding schema file, to check validity
* @return the deserialized java object
*/
public static <S> S deserialize(Class c, File xml, File schema) {
try {
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema s = sf.newSchema(schema);
return deserialize(c, xml, s);
} catch (SAXException ex) {
log.error("Error deserializing object from XML", ex);
return null;
}
}
/**
* Deserializes an XML document to a java object using JAXB
* @param <S> the type of the java object to create
* @param c the class of the object to create
* @param xml the xml file to deserialize
* @param schema the corresponding schema file, to check validity
* @return the deserialized java object
*/
public static <S> S deserialize(Class c, File xml, URL schema) {
try {
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema s = sf.newSchema(schema);
return deserialize(c, xml, s);
} catch (SAXException ex) {
log.error("Error deserializing object from XML", ex);
return null;
}
}
/**
* Deserializes an XML document to a java object using JAXB
* @param <S> the type of the java object to create
* @param c the class of the object to create
* @param xml the xml file to deserialize
* @param schema the corresponding schema file as Schema object
* @return the deserialized java object
*/
public static <S> S deserialize(Class c, File xml, Schema schema) {
try {
JAXBContext context = JAXBContext.newInstance(c);
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setSchema(schema);
S deserialized = (S) unmarshaller.unmarshal(xml);
return deserialized;
} catch (JAXBException ex) {
log.error("Error deserializing object from XML", ex);
return null;
}
}
/**
* Deserializes an XML document to a java object using JAXB.
* Warning: Using this method without specifying a schema is insecure!
* Invalid xml documents can generate corrupt java objects.
* @param <S> the type of the java object to create
* @param c the class of the object to create
* @param xml the xml file to deserialize
* @return the deserialized java object
*/
public static <S> S deserialize(Class c, File xml) {
try {
JAXBContext context = JAXBContext.newInstance(c);
Unmarshaller unmarshaller = context.createUnmarshaller();
S deserialized = (S) unmarshaller.unmarshal(xml);
return deserialized;
} catch (JAXBException ex) {
log.error("Error deserializing object from XML", ex);
return null;
}
}
// -------------------- XML schema --------------------
/**
* Generates an xml schema from the current TanksDB class
* @param dest the file where the schema shall be written in
*/
public static void generateSchema(String dest) {
try {
JAXBContext context = JAXBContext.newInstance(TanksDB.class);
context.generateSchema(new MySchemaOutputResolver(dest));
} catch (JAXBException ex) {
log.error("Error generating schema", ex);
} catch (IOException ex) {
log.error("Error writing schema", ex);
}
}
/**
* The schema is written to a file using this SchemaOutputResolver
*/
private static class MySchemaOutputResolver extends SchemaOutputResolver {
@Override
public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
return new StreamResult(new File(dest));
}
private String dest;
public MySchemaOutputResolver(String dest) {
this.dest = dest;
}
}
}