IO.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-1.5.0).
003  * Copyright (c) 2007-2013 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 java.io.File;
023 import java.io.FileInputStream;
024 import java.io.FileOutputStream;
025 import java.io.IOException;
026 import java.io.InputStream;
027 import java.io.ObjectInputStream;
028 import java.io.ObjectOutputStream;
029 import java.io.OutputStream;
030 import java.nio.file.Path;
031 
032 import javolution.xml.XMLObjectReader;
033 import javolution.xml.XMLObjectWriter;
034 import javolution.xml.stream.XMLStreamException;
035 
036 /**
037  * Class for object serialization. The following example shows how to write and
038  * reload a given population.
039  *
040  * [code]
041  * // Writing the population to disk.
042  * final File file = new File("population.xml");
043  * IO.xml.write(ga.getPopulation(), file);
044  *
045  * // Reading the population from disk.
046  * final Population<Float64Gene,Float64> population =
047  *     (Population<Float64Gene, Float64)IO.xml.read(file);
048  * ga.setPopulation(population);
049  * [/code]
050  *
051  * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
052  @since 1.0
053  @version 1.0 &mdash; <em>$Date: 2013-12-08 $</em>
054  */
055 public abstract class IO {
056 
057     protected IO() {
058     }
059 
060     /**
061      * IO implementation for <i>XML</i> serialization.
062      */
063     public static final IO xml = new IO() {
064 
065         @Override
066         public void write(final Object object, final OutputStream out)
067             throws IOException
068         {
069             try {
070                 final OutputStream nco = new NonClosableOutputStream(out);
071                 final XMLObjectWriter writer = XMLObjectWriter.newInstance(nco);
072                 writer.setIndentation("\t");
073                 try {
074                     writer.write(object);
075                     writer.flush();
076                 finally {
077                     writer.reset();
078                 }
079             catch (XMLStreamException e) {
080                 throw new IOException(e);
081             }
082         }
083 
084         @Override
085         public <T> T read(final Class<T> type, final InputStream in)
086             throws IOException
087         {
088             try {
089                 final InputStream nci = new NonClosableInputStream(in);
090                 final XMLObjectReader reader = XMLObjectReader.newInstance(nci);
091                 try {
092                     return type.cast(reader.read());
093                 finally {
094                     reader.reset();
095                 }
096             catch (XMLStreamException e) {
097                 throw new IOException(e);
098             }
099         }
100     };
101 
102     /**
103      * IO implementation for "native" <i>Java</i> serialization.
104      */
105     public static IO object = new IO() {
106 
107         @Override
108         public void write(final Object object, final OutputStream out)
109             throws IOException
110         {
111             final ObjectOutputStream oout = new ObjectOutputStream(out);
112             oout.writeObject(object);
113             out.flush();
114         }
115 
116         @Override
117         public <T> T read(final Class<T> type, final InputStream in)
118             throws IOException
119         {
120             final ObjectInputStream oin = new ObjectInputStream(in);
121             try {
122                 return type.cast(oin.readObject());
123             catch (ClassNotFoundException | ClassCastException e) {
124                 throw new IOException(e);
125             }
126         }
127     };
128 
129 
130     /**
131      * Write the (serializable) object to the given path.
132      *
133      @param object the object to serialize.
134      @param path the path to write the object to.
135      @throws NullPointerException if one of the arguments is {@code null}.
136      @throws IOException if the object could not be serialized.
137      */
138     public void write(final Object object, final String path)
139         throws IOException
140     {
141         write(object, new File(path));
142     }
143 
144     /**
145      * Write the (serializable) object to the given path.
146      *
147      @param object the object to serialize.
148      @param path the path to write the object to.
149      @throws NullPointerException if one of the arguments is {@code null}.
150      @throws IOException if the object could not be serialized.
151      */
152     public void write(final Object object, final Path path)
153         throws IOException
154     {
155         write(object, path.toFile());
156     }
157 
158     /**
159      * Write the (serializable) object to the given file.
160      *
161      @param object the object to serialize.
162      @param file the file to write the object to.
163      @throws NullPointerException if one of the arguments is {@code null}.
164      @throws IOException if the object could not be serialized.
165      */
166     public void write(final Object object, final File file)
167         throws IOException
168     {
169         try (final FileOutputStream out = new FileOutputStream(file)) {
170             write(object, out);
171         }
172     }
173 
174     /**
175      * Write the (serializable) object to the given output stream.
176      *
177      @param object the object to serialize.
178      @param out the output stream to write the object to.
179      @throws NullPointerException if one of the arguments is {@code null}.
180      @throws IOException if the object could not be serialized.
181      */
182     public abstract void write(final Object object, final OutputStream out)
183         throws IOException;
184 
185     /**
186      * Reads an object from the given file.
187      *
188      @param path the path to read from.
189      @param type the type of the read object.
190      @return the de-serialized object.
191      @throws NullPointerException if the input stream {@code in} is {@code null}.
192      @throws IOException if the object could not be read.
193      */
194     public <T> T read(final Class<T> type, final String path)
195         throws IOException
196     {
197         try (final FileInputStream in = new FileInputStream(new File(path))) {
198             return read(type, in);
199         }
200     }
201 
202     /**
203      * Reads an object from the given file.
204      *
205      @param path the path to read from.
206      @return the de-serialized object.
207      @throws NullPointerException if the input stream {@code in} is {@code null}.
208      @throws IOException if the object could not be read.
209      */
210     public Object read(final String paththrows IOException {
211         return read(Object.class, path);
212     }
213 
214     /**
215      * Reads an object from the given file.
216      *
217      @param path the path to read from.
218      @param type the type of the read object.
219      @return the de-serialized object.
220      @throws NullPointerException if the input stream {@code in} is {@code null}.
221      @throws IOException if the object could not be read.
222      */
223     public <T> T read(final Class<T> type, final Path path)
224         throws IOException
225     {
226         try (final FileInputStream in = new FileInputStream(path.toFile())) {
227             return read(type, in);
228         }
229     }
230 
231     /**
232      * Reads an object from the given file.
233      *
234      @param path the path to read from.
235      @return the de-serialized object.
236      @throws NullPointerException if the input stream {@code in} is {@code null}.
237      @throws IOException if the object could not be read.
238      */
239     public Object read(final Path paththrows IOException {
240         return read(Object.class, path);
241     }
242 
243     /**
244      * Reads an object from the given file.
245      *
246      @param file the file to read from.
247      @param type the type of the read object.
248      @return the de-serialized object.
249      @throws NullPointerException if the input stream {@code in} is {@code null}.
250      @throws IOException if the object could not be read.
251      */
252     public <T> T read(final Class<T> type, final File file)
253         throws IOException
254     {
255         try (final FileInputStream in = new FileInputStream(file)) {
256             return read(type, in);
257         }
258     }
259 
260     /**
261      * Reads an object from the given file.
262      *
263      @param file the file to read from.
264      @return the de-serialized object.
265      @throws NullPointerException if the input stream {@code in} is {@code null}.
266      @throws IOException if the object could not be read.
267      */
268     public Object read(final File filethrows IOException {
269         return read(Object.class, file);
270     }
271 
272     /**
273      * Reads an object from the given input stream.
274      *
275      @param in the input stream to read from.
276      @param type the type of the read object.
277      @return the de-serialized object.
278      @throws NullPointerException if the input stream {@code in} is {@code null}.
279      @throws IOException if the object could not be read.
280      */
281     public abstract <T> T read(final Class<T> type, final InputStream in)
282         throws IOException;
283 
284     /**
285      * Reads an object from the given input stream.
286      *
287      @param in the input stream to read from.
288      @return the de-serialized object.
289      @throws NullPointerException if the input stream {@code in} is {@code null}.
290      @throws IOException if the object could not be read.
291      */
292     public Object read(final InputStream inthrows IOException {
293         return read(Object.class, in);
294     }
295 
296 
297     /**
298      @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
299      @version 1.0 &mdash; <em>$Date: 2013-12-08 $</em>
300      */
301     private static final class NonClosableOutputStream extends OutputStream {
302         private final OutputStream _adoptee;
303 
304         public NonClosableOutputStream(final OutputStream adoptee) {
305             _adoptee = adoptee;
306         }
307 
308         @Override
309         public void close() throws IOException {
310             //Ignore close call.
311             _adoptee.flush();
312         }
313 
314         @Override
315         public boolean equals(final Object obj) {
316             return _adoptee.equals(obj);
317         }
318 
319         @Override
320         public void flush() throws IOException {
321             _adoptee.flush();
322         }
323 
324         @Override
325         public int hashCode() {
326             return _adoptee.hashCode();
327         }
328 
329         @Override
330         public String toString() {
331             return _adoptee.toString();
332         }
333 
334         @Override
335         public void write(byte[] b, int off, int lenthrows IOException {
336             _adoptee.write(b, off, len);
337         }
338 
339         @Override
340         public void write(byte[] bthrows IOException {
341             _adoptee.write(b);
342         }
343 
344         @Override
345         public void write(int bthrows IOException {
346             _adoptee.write(b);
347         }
348 
349     }
350 
351     /**
352      @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
353      @version 1.0 &mdash; <em>$Date: 2013-12-08 $</em>
354      */
355     private static final class NonClosableInputStream extends InputStream {
356         private final InputStream _adoptee;
357 
358         public NonClosableInputStream(final InputStream adoptee) {
359             _adoptee = adoptee;
360         }
361 
362         @Override
363         public int available() throws IOException {
364             return _adoptee.available();
365         }
366 
367         @Override
368         public void close() throws IOException {
369         }
370 
371         @Override
372         public void mark(int readlimit) {
373             _adoptee.mark(readlimit);
374         }
375 
376         @Override
377         public boolean markSupported() {
378             return _adoptee.markSupported();
379         }
380 
381         @Override
382         public int read() throws IOException {
383             return _adoptee.read();
384         }
385 
386         @Override
387         public int read(byte[] b, int off, int lenthrows IOException {
388             return _adoptee.read(b, off, len);
389         }
390 
391         @Override
392         public int read(byte[] bthrows IOException {
393             return _adoptee.read(b);
394         }
395 
396         @Override
397         public void reset() throws IOException {
398             _adoptee.reset();
399         }
400 
401         @Override
402         public long skip(long nthrows IOException {
403             return _adoptee.skip(n);
404         }
405     }
406 
407 }