package cz.cuni.mff.d3s.been.bpk; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.net.URL; import java.nio.file.Path; import javax.xml.XMLConstants; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; /** * Utility class for working with BpkConfiguration. * * @author Martin Sixta */ public class BpkConfigUtils { /** slf4j logger */ private static final Logger log = LoggerFactory.getLogger(BpkConfigUtils.class); /** * Where the XSD file for BpkConfiguration is located relative to resources. */ public static final String SCHEMA_RESOURCE_FILE = "bpk-config.xsd"; /** * JAXBContext for BpkConfiguration. Don't use directly, use getContext() * instead! */ private static JAXBContext __context = null; /** * Schema for BpkConfiguration. Don't use directly, use getSchema instead! */ private static Schema __schema = null; /** * * Creating context is not cheap. Let's do it only once. * * @return JAXB context fot BpkConfiguration * @throws JAXBException * when context cannot be created */ private static synchronized JAXBContext getContext() throws JAXBException { if (__context == null) { __context = JAXBContext.newInstance(BpkConfiguration.class); } return __context; } /** * * Creating schema is not cheap. Let's do it only once. * * @return Schema for BpkConfiguration * @throws SAXException * when schema cannot be created */ private static synchronized Schema getSchema() throws SAXException { if (__schema == null) { SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); URL url = BpkConfigUtils.class.getResource(SCHEMA_RESOURCE_FILE); log.debug("Loading BPK config schema from {}", url); try { log.debug("Loaded BPK config schema:{}", url.getContent()); } catch (IOException e) { log.debug("Failed loading BPK config schema because", e); } __schema = sf.newSchema(url); } return __schema; } /** * Converts BpkConfiguration to it's XML representation. * * @param bpkConfiguration * configuration to parse * @return XML representation of bpkConfiguration * @throws BpkConfigurationException * when it rains */ public static String toXml(BpkConfiguration bpkConfiguration) throws BpkConfigurationException { try { // create and init marshaller Marshaller marshaller = getContext().createMarshaller(); marshaller.setSchema(getSchema()); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // write it StringWriter writer = new StringWriter(); marshaller.marshal(bpkConfiguration, writer); return writer.toString(); } catch (Exception e) { String message = "Cannot convert to XML"; throw new BpkConfigurationException(message, e); } } /** * Parses BpkConfiguration from an InputStream. * * @param input * the input stream to parse * @return the parsed BPK configuration * @throws BpkConfigurationException * when the input is invalid or an I/O error occurs */ public static BpkConfiguration fromXml(InputStream input) throws BpkConfigurationException { try { // create and init unmarshaller Unmarshaller unmarshaller = getContext().createUnmarshaller(); unmarshaller.setSchema(getSchema()); return (BpkConfiguration) unmarshaller.unmarshal(input); } catch (Exception e) { String message = "Cannot parse XML!"; e.printStackTrace(); throw new BpkConfigurationException(message, e); } } /** * Parses BpkConfiguration from a File. * * @param input * the input file to parse * @return the parsed BPK configuration * @throws BpkConfigurationException * when the input is invalid or an I/O error occurs */ public static BpkConfiguration fromXml(File input) throws BpkConfigurationException { try { // create and init unmarshaller Unmarshaller unmarshaller = getContext().createUnmarshaller(); unmarshaller.setSchema(getSchema()); return (BpkConfiguration) unmarshaller.unmarshal(input); } catch (Exception e) { throw new BpkConfigurationException("Cannot parse BPK configuration XML.", e); } } /** * Parses BpkConfiguration from a Path. * * @param input * the path to the input file to parse * @return parsed BPK configuration * @throws BpkConfigurationException * when the input is invalid or an I/O error occurs */ public static BpkConfiguration fromXml(Path input) throws BpkConfigurationException { return fromXml(input.toFile()); } }