ObjectWriter.java
001 /*
002  *  ObjectWriter.java
003  *
004  *  Copyright (c) 1995-2010, The University of Sheffield. See the file
005  *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
006  *
007  *  This file is part of GATE (see http://gate.ac.uk/), and is free
008  *  software, licenced under the GNU Library General Public License,
009  *  Version 2, June 1991 (in the distribution as file licence.html,
010  *  and also available at http://gate.ac.uk/gate/licence.html).
011  *
012  *  Valentin Tablan 21 Feb 2000
013  *
014  *  $Id: ObjectWriter.java 12006 2009-12-01 17:24:28Z thomas_heitz $
015  */
016 
017 package gate.util;
018 
019 import java.io.*;
020 import java.util.Iterator;
021 import java.util.LinkedList;
022 
023 /** Writes an object to an PipedOutputStream wich can be connected to a
024   * PipedInputStream.
025   * Before writting the object it also writes it in a buffer and finds
026   * out its size so it can be reported via getSize method.
027   * All read/writes occur in separate threads to avoid a deadlock.
028   */
029 public class ObjectWriter extends Thread {
030 
031   /** Debug flag */
032   private static final boolean DEBUG = false;
033 
034   public ObjectWriter(Object objthrows IOException {
035     size = 0;
036     Writer writer = new Writer(obj);
037     InputStream is = writer.getInputStream();
038     writer.start();
039     boolean over = false;
040     buffer = new LinkedList();
041 
042     //how much space is available in lastBuff
043     int space = buffSize;
044 
045     //where to write in lastBuff
046     int writeOffset = 0;
047     byte lastBuff[] new byte[buffSize];
048 
049     while (!over) {
050       int read = is.read(lastBuff, writeOffset, space);
051       if(read == -1) {
052         lastOffset = writeOffset;
053         buffer.addLast(lastBuff);
054         over = true;
055       else {
056         space-= read;
057         size+=read;
058         if(space == 0) {
059           // no more space; we need a new buffer
060           buffer.addLast(lastBuff);
061           space = buffSize;
062           writeOffset = 0;
063           lastBuff = new byte[buffSize];
064         else {
065           // current buffer not full yet
066           writeOffset+=read;
067         }
068       }
069     };// while(!over)
070 
071     // will be used to write the data
072     outputStream = new PipedOutputStream();
073 
074     // will be returned for objects that want to read the object
075     inputStream = new PipedInputStream(outputStream);
076   }
077 
078   /**
079     * Returns a PipedInputStream from which the object given as parameter for
080     * the constructor can be read.
081     *
082     @return a PipedInputStream connected to PipedOutputStream which writes
083     * the object which this ObjectWriter was built for.
084     */
085   public InputStream getInputStream() {
086     return inputStream;
087   }
088 
089   /**
090     * Obtains the object size.
091     *
092     @return the size of the object recieved as parameter for the constructor.
093     */
094   public int getSize() {
095     return size;
096   }
097 
098   /** Writes all the buffers to the output stream
099     */
100   public void run() {
101     try{
102       Iterator buffIter = buffer.iterator();
103       while(buffIter.hasNext()){
104         byte currentBuff[] (byte[])buffIter.next();
105         if(buffIter.hasNext()) {
106           // is not the last buffer
107           outputStream.write(currentBuff,0,buffSize);
108         else {
109           // is the last buffer
110           // currentBuff[lastOffset] = '\u001a';
111           outputStream.write(currentBuff,0,lastOffset);
112         }
113       }// while(buffIter.hasNext())
114 
115       outputStream.flush();
116       outputStream.close();
117     catch(IOException ioe) {
118       throw new RuntimeException(ioe.toString());
119       // ioe.printStackTrace(Err.getPrintWriter());
120     }
121   }
122 
123 
124   /** I need a thread to write the object so I can read it in an buffer
125     * After that I know the size ana I can write it to the output stream
126     * after I report the size.
127     */
128   private class Writer extends Thread {
129     public Writer(Object _obj){
130       _object = _obj;
131       _outputStream = new PipedOutputStream();
132 
133       try {
134         _inputStream = new PipedInputStream(_outputStream);
135       catch(IOException ioe) {
136         ioe.printStackTrace(Err.getPrintWriter());
137       }
138     }
139 
140     public InputStream getInputStream(){
141       return _inputStream;
142     }
143 
144     /**
145       * Describe 'run' method here.
146       */
147     public void run(){
148       try {
149         ObjectOutputStream _oos = new ObjectOutputStream(_outputStream);
150         _oos.writeObject(_object);
151         _oos.close();
152       catch(IOException ioe) {
153         ioe.printStackTrace(Err.getPrintWriter());
154       }
155     }
156 
157     private Object _object;
158     private InputStream _inputStream;
159     private PipedOutputStream _outputStream;
160 
161   }
162 
163   private Object object;
164 
165   private InputStream inputStream ;
166 
167   private PipedOutputStream outputStream;
168 
169   private int size;
170 
171   private int lastOffset;
172 
173   private LinkedList buffer;
174 
175   private int buffSize = 1024;
176 
177 // class ObjectWriter