001package co.codewizards.cloudstore.core.dto.jaxb;
002
003import static co.codewizards.cloudstore.core.util.Util.*;
004
005import java.io.BufferedInputStream;
006import java.io.BufferedOutputStream;
007import java.io.File;
008import java.io.FileInputStream;
009import java.io.FileOutputStream;
010import java.io.IOException;
011import java.io.InputStream;
012import java.io.OutputStream;
013import java.lang.reflect.ParameterizedType;
014import java.lang.reflect.Type;
015
016import javax.xml.bind.JAXBException;
017import javax.xml.bind.Marshaller;
018import javax.xml.bind.Unmarshaller;
019
020public abstract class DTOIO <D> {
021
022        private final Class<D> dtoClass;
023
024        private Marshaller marshaller;
025        private Unmarshaller unmarshaller;
026
027        protected DTOIO() {
028                ParameterizedType superclass = (ParameterizedType) getClass().getGenericSuperclass();
029                Type[] actualTypeArguments = superclass.getActualTypeArguments();
030                if (actualTypeArguments == null || actualTypeArguments.length < 1)
031                        throw new IllegalStateException("Subclass " + getClass().getName() + " has no generic type argument!");
032
033                @SuppressWarnings("unchecked")
034                Class<D> c = (Class<D>) actualTypeArguments[0];
035                this.dtoClass = c;
036                if (this.dtoClass == null)
037                        throw new IllegalStateException("Subclass " + getClass().getName() + " has no generic type argument!");
038        }
039
040        public void serialize(D dto, OutputStream out) {
041                assertNotNull("dto", dto);
042                assertNotNull("out", out);
043                try {
044                        getMarshaller().marshal(dto, out);
045                } catch (JAXBException e) {
046                        throw new RuntimeException(e);
047                }
048        }
049
050        public void serialize(final D dto, final File file) {
051                assertNotNull("dto", dto);
052                assertNotNull("file", file);
053                try {
054                        // Even though https://github.com/cloudstore/cloudstore/issues/31 seems to affect only unmarshal(File),
055                        // we manage the OutputStream ourself, as well.
056                        final OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
057                        try {
058                                getMarshaller().marshal(dto, out);
059                        } finally {
060                                out.close();
061                        }
062                } catch (JAXBException | IOException e) {
063                        throw new RuntimeException("Writing file '" + file.getAbsolutePath() + "' failed: " + e, e);
064                }
065        }
066
067        public D deserialize(InputStream in) {
068                assertNotNull("in", in);
069                try {
070                        return dtoClass.cast(getUnmarshaller().unmarshal(in));
071                } catch (JAXBException e) {
072                        throw new RuntimeException(e);
073                }
074        }
075
076        public D deserialize(final File file) {
077                assertNotNull("file", file);
078                try {
079                        // Because of https://github.com/cloudstore/cloudstore/issues/31 we do not use unmarshal(File), anymore.
080                        final InputStream in = new BufferedInputStream(new FileInputStream(file));
081                        try {
082                                return dtoClass.cast(getUnmarshaller().unmarshal(in));
083                        } finally {
084                                in.close();
085                        }
086                } catch (JAXBException | IOException e) {
087                        throw new RuntimeException("Reading file '" + file.getAbsolutePath() + "' failed: " + e, e);
088                }
089        }
090
091        private Marshaller getMarshaller() {
092                if (marshaller == null) {
093                        try {
094                                marshaller = CloudStoreJaxbContext.getJaxbContext().createMarshaller();
095                        } catch (JAXBException e) {
096                                throw new RuntimeException(e);
097                        }
098                }
099                return marshaller;
100        }
101
102        private Unmarshaller getUnmarshaller() {
103                if (unmarshaller == null) {
104                        try {
105                                unmarshaller = CloudStoreJaxbContext.getJaxbContext().createUnmarshaller();
106                        } catch (JAXBException e) {
107                                throw new RuntimeException(e);
108                        }
109                }
110                return unmarshaller;
111        }
112
113}