IO.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-1.6.0).
003  * Copyright (c) 2007-2014 Franz Wilhelmstötter
004  *
005  * Licensed under the Apache License, Version 2.0 (the "License");
006  * you may not use this file except in compliance with the License.
007  * You may obtain a copy of the License at
008  *
009  *      http://www.apache.org/licenses/LICENSE-2.0
010  *
011  * Unless required by applicable law or agreed to in writing, software
012  * distributed under the License is distributed on an "AS IS" BASIS,
013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014  * See the License for the specific language governing permissions and
015  * limitations under the License.
016  *
017  * Author:
018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019  */
020 package org.jenetics.util;
021 
022 import static org.jenetics.internal.util.jaxb.CONTEXT;
023 import static org.jenetics.internal.util.jaxb.adapterFor;
024 
025 import java.io.File;
026 import java.io.FileInputStream;
027 import java.io.FileOutputStream;
028 import java.io.IOException;
029 import java.io.InputStream;
030 import java.io.ObjectInputStream;
031 import java.io.ObjectOutputStream;
032 import java.io.OutputStream;
033 import java.nio.file.Path;
034 
035 import javax.xml.bind.Marshaller;
036 import javax.xml.bind.Unmarshaller;
037 import javax.xml.bind.annotation.adapters.XmlAdapter;
038 
039 import javolution.xml.XMLObjectReader;
040 import javolution.xml.XMLObjectWriter;
041 import javolution.xml.stream.XMLStreamException;
042 
043 
044 /**
045  * Class for object serialization. The following example shows how to write and
046  * reload a given population.
047  *
048  * [code]
049  * // Writing the population to disk.
050  * final File file = new File("population.xml");
051  * IO.jaxb.write(ga.getPopulation(), file);
052  *
053  * // Reading the population from disk.
054  * final Population<Float64Gene,Float64> population =
055  *     (Population<Float64Gene, Float64)IO.jaxb.read(file);
056  * ga.setPopulation(population);
057  * [/code]
058  *
059  * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
060  @since 1.0
061  @version 1.6 &mdash; <em>$Date: 2014-02-27 $</em>
062  */
063 public abstract class IO {
064 
065     protected IO() {
066     }
067 
068     /**
069      * IO implementation for <i>XML</i> serialization.
070      *
071      @deprecated Will be removed when the Javolution is removed. Use the
072      *             {@link #jaxb} {@code IO} implementation instead, which is
073      *             compatible to the existing XML marshalling.
074      */
075     @Deprecated
076     public static final IO xml = new IO() {
077 
078         @Override
079         public void write(final Object object, final OutputStream out)
080             throws IOException
081         {
082             try {
083                 final OutputStream nco = new NonClosableOutputStream(out);
084                 final XMLObjectWriter writer = XMLObjectWriter.newInstance(nco);
085                 writer.setIndentation("\t");
086                 try {
087                     writer.write(object);
088                     writer.flush();
089                 finally {
090                     writer.reset();
091                 }
092             catch (XMLStreamException e) {
093                 throw new IOException(e);
094             }
095         }
096 
097         @Override
098         public <T> T read(final Class<T> type, final InputStream in)
099             throws IOException
100         {
101             try {
102                 final InputStream nci = new NonClosableInputStream(in);
103                 final XMLObjectReader reader = XMLObjectReader.newInstance(nci);
104                 try {
105                     return type.cast(reader.read());
106                 finally {
107                     reader.reset();
108                 }
109             catch (XMLStreamException e) {
110                 throw new IOException(e);
111             }
112         }
113     };
114 
115     /**
116      * JAXB for <i>XML</i> serialization. Is compatible to the existing,
117      * deprecated {@link #xml} marshalling.
118      */
119     public static final IO jaxb = new IO() {
120 
121         @Override
122         public void write(final Object object, final OutputStream out)
123             throws IOException
124         {
125             try {
126                 final Marshaller marshaller = CONTEXT.createMarshaller();
127                 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
128 
129                 //final XMLOutputFactory factory = XMLOutputFactory.newInstance();
130                 //final XMLStreamWriter writer = factory.createXMLStreamWriter(out);
131                 //try {
132                     final XmlAdapter<Object, Object> adapter = adapterFor(object);
133                     if (adapter != null) {
134                         marshaller.marshal(adapter.marshal(object), out);
135                     else {
136                         marshaller.marshal(object, out);
137                     }
138                 //} finally {
139                 //    writer.close();
140                 //}
141             catch (Exception e) {
142                 throw new IOException(e);
143             }
144         }
145 
146         @Override
147         public <T> T read(final Class<T> type, final InputStream in)
148             throws IOException
149         {
150             try {
151                 final Unmarshaller unmarshaller = CONTEXT.createUnmarshaller();
152 
153                 //final XMLInputFactory factory = XMLInputFactory.newInstance();
154                 //final XMLStreamReader reader = factory.createXMLStreamReader(in);
155                 //try {
156                     final Object object = unmarshaller.unmarshal(in);
157                     final XmlAdapter<Object, Object> adapter = adapterFor(object);
158                     if (adapter != null) {
159                         return type.cast(adapter.unmarshal(object));
160                     else {
161                         return type.cast(object);
162                     }
163                 //} finally {
164                 //    reader.close();
165                 //}
166             catch (Exception e) {
167                 throw new IOException(e);
168             }
169         }
170     };
171 
172     /**
173      * IO implementation for "native" <i>Java</i> serialization.
174      */
175     public static final IO object = new IO() {
176 
177         @Override
178         public void write(final Object object, final OutputStream out)
179             throws IOException
180         {
181             final ObjectOutputStream oout = new ObjectOutputStream(out);
182             oout.writeObject(object);
183             out.flush();
184         }
185 
186         @Override
187         public <T> T read(final Class<T> type, final InputStream in)
188             throws IOException
189         {
190             final ObjectInputStream oin = new ObjectInputStream(in);
191             try {
192                 return type.cast(oin.readObject());
193             catch (ClassNotFoundException | ClassCastException e) {
194                 throw new IOException(e);
195             }
196         }
197     };
198 
199 
200     /**
201      * Write the (serializable) object to the given path.
202      *
203      @param object the object to serialize.
204      @param path the path to write the object to.
205      @throws NullPointerException if one of the arguments is {@code null}.
206      @throws IOException if the object could not be serialized.
207      */
208     public void write(final Object object, final String path)
209         throws IOException
210     {
211         write(object, new File(path));
212     }
213 
214     /**
215      * Write the (serializable) object to the given path.
216      *
217      @param object the object to serialize.
218      @param path the path to write the object to.
219      @throws NullPointerException if one of the arguments is {@code null}.
220      @throws IOException if the object could not be serialized.
221      */
222     public void write(final Object object, final Path path)
223         throws IOException
224     {
225         write(object, path.toFile());
226     }
227 
228     /**
229      * Write the (serializable) object to the given file.
230      *
231      @param object the object to serialize.
232      @param file the file to write the object to.
233      @throws NullPointerException if one of the arguments is {@code null}.
234      @throws IOException if the object could not be serialized.
235      */
236     public void write(final Object object, final File file)
237         throws IOException
238     {
239         try (final FileOutputStream out = new FileOutputStream(file)) {
240             write(object, out);
241         }
242     }
243 
244     /**
245      * Write the (serializable) object to the given output stream.
246      *
247      @param object the object to serialize.
248      @param out the output stream to write the object to.
249      @throws NullPointerException if one of the arguments is {@code null}.
250      @throws IOException if the object could not be serialized.
251      */
252     public abstract void write(final Object object, final OutputStream out)
253         throws IOException;
254 
255     /**
256      * Reads an object from the given file.
257      *
258      @param path the path to read from.
259      @param type the type of the read object.
260      @return the de-serialized object.
261      @throws NullPointerException if the input stream {@code in} is {@code null}.
262      @throws IOException if the object could not be read.
263      */
264     public <T> T read(final Class<T> type, final String path)
265         throws IOException
266     {
267         try (final FileInputStream in = new FileInputStream(new File(path))) {
268             return read(type, in);
269         }
270     }
271 
272     /**
273      * Reads an object from the given file.
274      *
275      @param path the path to read from.
276      @return the de-serialized object.
277      @throws NullPointerException if the input stream {@code in} is {@code null}.
278      @throws IOException if the object could not be read.
279      */
280     public Object read(final String paththrows IOException {
281         return read(Object.class, path);
282     }
283 
284     /**
285      * Reads an object from the given file.
286      *
287      @param path the path to read from.
288      @param type the type of the read object.
289      @return the de-serialized object.
290      @throws NullPointerException if the input stream {@code in} is {@code null}.
291      @throws IOException if the object could not be read.
292      */
293     public <T> T read(final Class<T> type, final Path path)
294         throws IOException
295     {
296         try (final FileInputStream in = new FileInputStream(path.toFile())) {
297             return read(type, in);
298         }
299     }
300 
301     /**
302      * Reads an object from the given file.
303      *
304      @param path the path to read from.
305      @return the de-serialized object.
306      @throws NullPointerException if the input stream {@code in} is {@code null}.
307      @throws IOException if the object could not be read.
308      */
309     public Object read(final Path paththrows IOException {
310         return read(Object.class, path);
311     }
312 
313     /**
314      * Reads an object from the given file.
315      *
316      @param file the file to read from.
317      @param type the type of the read object.
318      @return the de-serialized object.
319      @throws NullPointerException if the input stream {@code in} is {@code null}.
320      @throws IOException if the object could not be read.
321      */
322     public <T> T read(final Class<T> type, final File file)
323         throws IOException
324     {
325         try (final FileInputStream in = new FileInputStream(file)) {
326             return read(type, in);
327         }
328     }
329 
330     /**
331      * Reads an object from the given file.
332      *
333      @param file the file to read from.
334      @return the de-serialized object.
335      @throws NullPointerException if the input stream {@code in} is {@code null}.
336      @throws IOException if the object could not be read.
337      */
338     public Object read(final File filethrows IOException {
339         return read(Object.class, file);
340     }
341 
342     /**
343      * Reads an object from the given input stream.
344      *
345      @param in the input stream to read from.
346      @param type the type of the read object.
347      @return the de-serialized object.
348      @throws NullPointerException if the input stream {@code in} is {@code null}.
349      @throws IOException if the object could not be read.
350      */
351     public abstract <T> T read(final Class<T> type, final InputStream in)
352         throws IOException;
353 
354     /**
355      * Reads an object from the given input stream.
356      *
357      @param in the input stream to read from.
358      @return the de-serialized object.
359      @throws NullPointerException if the input stream {@code in} is {@code null}.
360      @throws IOException if the object could not be read.
361      */
362     public Object read(final InputStream inthrows IOException {
363         return read(Object.class, in);
364     }
365 
366 
367     /**
368      @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
369      @version 1.0 &mdash; <em>$Date: 2014-02-27 $</em>
370      */
371     private static final class NonClosableOutputStream extends OutputStream {
372         private final OutputStream _adoptee;
373 
374         public NonClosableOutputStream(final OutputStream adoptee) {
375             _adoptee = adoptee;
376         }
377 
378         @Override
379         public void close() throws IOException {
380             //Ignore close call.
381             _adoptee.flush();
382         }
383 
384         @Override
385         public void flush() throws IOException {
386             _adoptee.flush();
387         }
388 
389         @Override
390         public String toString() {
391             return _adoptee.toString();
392         }
393 
394         @Override
395         public void write(byte[] b, int off, int lenthrows IOException {
396             _adoptee.write(b, off, len);
397         }
398 
399         @Override
400         public void write(byte[] bthrows IOException {
401             _adoptee.write(b);
402         }
403 
404         @Override
405         public void write(int bthrows IOException {
406             _adoptee.write(b);
407         }
408 
409     }
410 
411     /**
412      @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
413      @version 1.0 &mdash; <em>$Date: 2014-02-27 $</em>
414      */
415     private static final class NonClosableInputStream extends InputStream {
416         private final InputStream _adoptee;
417 
418         public NonClosableInputStream(final InputStream adoptee) {
419             _adoptee = adoptee;
420         }
421 
422         @Override
423         public int available() throws IOException {
424             return _adoptee.available();
425         }
426 
427         @Override
428         public void close() throws IOException {
429         }
430 
431         @Override
432         public void mark(int readlimit) {
433             _adoptee.mark(readlimit);
434         }
435 
436         @Override
437         public boolean markSupported() {
438             return _adoptee.markSupported();
439         }
440 
441         @Override
442         public int read() throws IOException {
443             return _adoptee.read();
444         }
445 
446         @Override
447         public int read(byte[] b, int off, int lenthrows IOException {
448             return _adoptee.read(b, off, len);
449         }
450 
451         @Override
452         public int read(byte[] bthrows IOException {
453             return _adoptee.read(b);
454         }
455 
456         @Override
457         public void reset() throws IOException {
458             _adoptee.reset();
459         }
460 
461         @Override
462         public long skip(long nthrows IOException {
463             return _adoptee.skip(n);
464         }
465     }
466 
467 }