source: ComponentRegistry/trunk/ComponentRegistry/src/main/java/clarin/cmdi/componentregistry/MDMarshaller.java @ 1816

Last change on this file since 1816 was 1816, checked in by twagoo, 12 years ago

Merged changes made in ComponentRegistry-schematron branch to trunk and made some additional changes to make support for schematron rules in general component schema final:

  • CMDValidator is now 1.0, referenced as such as dependency by ComponentRegistry and included as module in the parent project
  • Added two lines about this to CHANGES document
  • Referenced general-component-schema.xsd on lux16, which has menwin's schematron rules, in TEST spring configuration
  • Some minor code cleanups
File size: 7.2 KB
Line 
1package clarin.cmdi.componentregistry;
2
3import clarin.cmdi.componentregistry.components.CMDComponentSpec;
4import java.io.ByteArrayInputStream;
5import java.io.ByteArrayOutputStream;
6import java.io.File;
7import java.io.FileInputStream;
8import java.io.IOException;
9import java.io.InputStream;
10import java.io.OutputStream;
11import java.io.OutputStreamWriter;
12import java.io.UnsupportedEncodingException;
13import java.io.Writer;
14import java.net.MalformedURLException;
15import java.net.URL;
16import javax.xml.bind.JAXBContext;
17import javax.xml.bind.JAXBException;
18import javax.xml.bind.Marshaller;
19import javax.xml.bind.Unmarshaller;
20import javax.xml.transform.Templates;
21import javax.xml.transform.Transformer;
22import javax.xml.transform.TransformerConfigurationException;
23import javax.xml.transform.TransformerException;
24import javax.xml.transform.TransformerFactory;
25import javax.xml.transform.stream.StreamResult;
26import javax.xml.transform.stream.StreamSource;
27import javax.xml.validation.Schema;
28import javax.xml.validation.SchemaFactory;
29import org.apache.xml.resolver.tools.CatalogResolver;
30import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
32import org.w3c.dom.bootstrap.DOMImplementationRegistry;
33import org.w3c.dom.ls.DOMImplementationLS;
34import org.w3c.dom.ls.LSInput;
35import org.w3c.dom.ls.LSResourceResolver;
36import org.xml.sax.InputSource;
37import org.xml.sax.SAXException;
38
39public class MDMarshaller {
40
41    private final static Logger LOG = LoggerFactory.getLogger(MDMarshaller.class);
42    /**
43     * I define W3C_XML_SCHEMA_NS_URI here cannot get it from @see XMLConstants there is a conflict between stax-api and java5.
44     */
45    private static final String W3C_XML_SCHEMA_NS_URI = "http://www.w3.org/2001/XMLSchema";
46    private static Schema generalComponentSchema;
47
48    private MDMarshaller() {
49    }
50
51    /**
52     * Helper method that logs errors and returns null if unmarshal failed
53     */
54    public static <T> T unmarshal(Class<T> docClass, File file, Schema schema) {
55        T result = null;
56        try {
57            result = unmarshal(docClass, new FileInputStream(file), schema);
58        } catch (JAXBException e) {
59            LOG.error("Cannot unmarshal xml file: " + file, e);
60        } catch (IOException e) {
61            LOG.error("Cannot retrieve content from file: " + file, e);
62        }
63        return result;
64    }
65
66    /**
67     *
68     * @param docClass
69     * @param inputStream
70     * @param schema to validate against, can be null for no validation.
71     * @return
72     * @throws JAXBException
73     */
74    public static <T> T unmarshal(Class<T> docClass, InputStream inputStream, Schema schema) throws JAXBException {
75        String packageName = docClass.getPackage().getName();
76        JAXBContext jc = JAXBContext.newInstance(packageName);
77        Unmarshaller u = jc.createUnmarshaller();
78
79        if (schema != null) {
80            u.setSchema(schema);
81        }
82        Object unmarshal = u.unmarshal(inputStream);
83        T doc = (T) unmarshal;
84        return doc;
85    }
86
87    /**
88     * Will wrap the Outputstream in a OutputStreamWriter with encoding set to UTF-8. This to make sure profiles are stored correctly.
89     */
90    public static <T> void marshal(T marshallableObject, OutputStream out) throws JAXBException, UnsupportedEncodingException {
91        String packageName = marshallableObject.getClass().getPackage().getName();
92        JAXBContext jc = JAXBContext.newInstance(packageName);
93
94        Marshaller m = jc.createMarshaller();
95        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
96        String schemaLocation = Configuration.getInstance().getSchemaLocation(marshallableObject.getClass().getName());
97        if (schemaLocation != null) {
98            m.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, schemaLocation);
99        }
100        Writer writer = new OutputStreamWriter(out, "UTF-8");
101        m.marshal(marshallableObject, writer);
102    }
103
104    public static Schema getCMDComponentSchema() {
105        if (generalComponentSchema == null) {
106            try {
107                SchemaFactory schemaFactory = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
108                schemaFactory.setResourceResolver(new LSResourceResolver() {
109                    private CatalogResolver catRes = new CatalogResolver();
110
111                    @Override
112                    public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {
113                        InputSource resolveEntity = catRes.resolveEntity(publicId, systemId);
114                        resolveEntity.setEncoding("UTF-8");
115                        DOMImplementationLS domImplementation;
116                        try {
117                            domImplementation = (DOMImplementationLS) DOMImplementationRegistry.newInstance().getDOMImplementation("LS");
118                        } catch (ClassCastException e) {
119                            throw new RuntimeException(e);
120                        } catch (ClassNotFoundException e) {
121                            throw new RuntimeException(e);
122                        } catch (InstantiationException e) {
123                            throw new RuntimeException(e);
124                        } catch (IllegalAccessException e) {
125                            throw new RuntimeException(e);
126                        }
127                        LSInput lsInput = domImplementation.createLSInput();
128                        lsInput.setEncoding("UTF-8");
129                        lsInput.setByteStream(resolveEntity.getByteStream());
130                        lsInput.setCharacterStream(resolveEntity.getCharacterStream());
131                        return lsInput;
132                    }
133                });
134                generalComponentSchema = schemaFactory.newSchema(new URL(Configuration.getInstance().getGeneralComponentSchema()));
135            } catch (MalformedURLException e) {
136                LOG.error("Cannot instantiate schema", e);
137            } catch (SAXException e) {
138                LOG.error("Cannot instantiate schema", e);
139            }
140        }
141        return generalComponentSchema;
142    }
143
144    public static void generateXsd(CMDComponentSpec spec, OutputStream outputStream) {
145        Templates componentToSchemaTemplates;
146        try {
147            System.setProperty("javax.xml.transform.TransformerFactory", net.sf.saxon.TransformerFactoryImpl.class.getName());
148            componentToSchemaTemplates = TransformerFactory.newInstance().newTemplates(
149                    new StreamSource(Configuration.getInstance().getComponent2SchemaXsl()));
150        } catch (TransformerConfigurationException e) {
151            LOG.error("Cannot create Template", e);
152            return;
153        }
154        try {
155            Transformer transformer = componentToSchemaTemplates.newTransformer();
156            ByteArrayOutputStream out = new ByteArrayOutputStream();
157            MDMarshaller.marshal(spec, out);
158            ByteArrayInputStream input = new ByteArrayInputStream(out.toByteArray());
159            transformer.transform(new StreamSource(input), new StreamResult(outputStream));
160        } catch (TransformerConfigurationException e) {
161            LOG.error("Cannot create Transformer", e);
162        } catch (TransformerException e) {
163            LOG.error("Cannot transform xml file: " + getSpecId(spec), e);
164        } catch (UnsupportedEncodingException e) {
165            LOG.error("Error in encoding: ", e);
166        } catch (JAXBException e) {
167            LOG.error("Cannot marshall spec: " + getSpecId(spec), e);
168        }
169    }
170
171   
172   
173    private static String getSpecId(CMDComponentSpec spec) {
174        String result = "";
175        if (spec != null && spec.getHeader() != null) {
176            result = spec.getHeader().getID();
177        }
178        return result;
179    }
180
181    /**
182     * @param marshallableObject
183     * @return the xml representation of the marshallableObject
184     * @throws jaxb exceptions are wrapped in RuntimeExceptions
185     */
186    public static <T> String marshalToString(T marshallableObject) {
187        ByteArrayOutputStream out = new ByteArrayOutputStream();
188        try {
189            marshal(marshallableObject, out);
190            return out.toString("UTF-8");
191        } catch (UnsupportedEncodingException e) {
192            throw new RuntimeException(e);
193        } catch (JAXBException e) {
194            throw new RuntimeException(e);
195        }
196    }
197}
Note: See TracBrowser for help on using the repository browser.