ObjectWriter.java
001 /*
002  *  ObjectWriter.java
003  *
004  *  Copyright (c) 1995-2012, 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 17600 2014-03-08 18:47:11Z markagreenwood $
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   public ObjectWriter(Object objthrows IOException {
032     size = 0;
033     Writer writer = new Writer(obj);
034     InputStream is = writer.getInputStream();
035     writer.start();
036     boolean over = false;
037     buffer = new LinkedList<byte[]>();
038 
039     //how much space is available in lastBuff
040     int space = buffSize;
041 
042     //where to write in lastBuff
043     int writeOffset = 0;
044     byte lastBuff[] new byte[buffSize];
045 
046     while (!over) {
047       int read = is.read(lastBuff, writeOffset, space);
048       if(read == -1) {
049         lastOffset = writeOffset;
050         buffer.addLast(lastBuff);
051         over = true;
052       else {
053         space-= read;
054         size+=read;
055         if(space == 0) {
056           // no more space; we need a new buffer
057           buffer.addLast(lastBuff);
058           space = buffSize;
059           writeOffset = 0;
060           lastBuff = new byte[buffSize];
061         else {
062           // current buffer not full yet
063           writeOffset+=read;
064         }
065       }
066     };// while(!over)
067 
068     // will be used to write the data
069     outputStream = new PipedOutputStream();
070 
071     // will be returned for objects that want to read the object
072     inputStream = new PipedInputStream(outputStream);
073   }
074 
075   /**
076     * Returns a PipedInputStream from which the object given as parameter for
077     * the constructor can be read.
078     *
079     @return a PipedInputStream connected to PipedOutputStream which writes
080     * the object which this ObjectWriter was built for.
081     */
082   public InputStream getInputStream() {
083     return inputStream;
084   }
085 
086   /**
087     * Obtains the object size.
088     *
089     @return the size of the object recieved as parameter for the constructor.
090     */
091   public int getSize() {
092     return size;
093   }
094 
095   /** Writes all the buffers to the output stream
096     */
097   @Override
098   public void run() {
099     try{
100       Iterator<byte[]> buffIter = buffer.iterator();
101       while(buffIter.hasNext()){
102         byte currentBuff[] = buffIter.next();
103         if(buffIter.hasNext()) {
104           // is not the last buffer
105           outputStream.write(currentBuff,0,buffSize);
106         else {
107           // is the last buffer
108           // currentBuff[lastOffset] = '\u001a';
109           outputStream.write(currentBuff,0,lastOffset);
110         }
111       }// while(buffIter.hasNext())
112 
113       outputStream.flush();
114       outputStream.close();
115     catch(IOException ioe) {
116       throw new RuntimeException(ioe.toString());
117       // ioe.printStackTrace(Err.getPrintWriter());
118     }
119   }
120 
121 
122   /** I need a thread to write the object so I can read it in an buffer
123     * After that I know the size ana I can write it to the output stream
124     * after I report the size.
125     */
126   private class Writer extends Thread {
127     public Writer(Object _obj){
128       _object = _obj;
129       _outputStream = new PipedOutputStream();
130 
131       try {
132         _inputStream = new PipedInputStream(_outputStream);
133       catch(IOException ioe) {
134         ioe.printStackTrace(Err.getPrintWriter());
135       }
136     }
137 
138     public InputStream getInputStream(){
139       return _inputStream;
140     }
141 
142     /**
143       * Describe 'run' method here.
144       */
145     @Override
146     public void run(){
147       try {
148         ObjectOutputStream _oos = new ObjectOutputStream(_outputStream);
149         _oos.writeObject(_object);
150         _oos.close();
151       catch(IOException ioe) {
152         ioe.printStackTrace(Err.getPrintWriter());
153       }
154     }
155 
156     private Object _object;
157     private InputStream _inputStream;
158     private PipedOutputStream _outputStream;
159 
160   }
161 
162   private InputStream inputStream ;
163 
164   private PipedOutputStream outputStream;
165 
166   private int size;
167 
168   private int lastOffset;
169 
170   private LinkedList<byte[]> buffer;
171 
172   private int buffSize = 1024;
173 
174 // class ObjectWriter