1   /*
2    *  ObjectWriter.java
3    *
4    *  Copyright (c) 1998-2005, The University of Sheffield.
5    *
6    *  This file is part of GATE (see http://gate.ac.uk/), and is free
7    *  software, licenced under the GNU Library General Public License,
8    *  Version 2, June 1991 (in the distribution as file licence.html,
9    *  and also available at http://gate.ac.uk/gate/licence.html).
10   *
11   *  Valentin Tablan 21 Feb 2000
12   *
13   *  $Id: ObjectWriter.java,v 1.14 2005/01/11 13:51:37 ian Exp $
14   */
15  
16  package gate.util;
17  
18  import java.io.*;
19  import java.util.Iterator;
20  import java.util.LinkedList;
21  
22  /** Writes an object to an PipedOutputStream wich can be connected to a
23    * PipedInputStream.
24    * Before writting the object it also writes it in a buffer and finds
25    * out its size so it can be reported via getSize method.
26    * All read/writes occur in separate threads to avoid a deadlock.
27    */
28  public class ObjectWriter extends Thread {
29  
30    /** Debug flag */
31    private static final boolean DEBUG = false;
32  
33    public ObjectWriter(Object obj) throws IOException {
34      size = 0;
35      Writer writer = new Writer(obj);
36      InputStream is = writer.getInputStream();
37      writer.start();
38      boolean over = false;
39      buffer = new LinkedList();
40  
41      //how much space is available in lastBuff
42      int space = buffSize;
43  
44      //where to write in lastBuff
45      int writeOffset = 0;
46      byte lastBuff[] = new byte[buffSize];
47  
48      while (!over) {
49        int read = is.read(lastBuff, writeOffset, space);
50        if(read == -1) {
51          lastOffset = writeOffset;
52          buffer.addLast(lastBuff);
53          over = true;
54        } else {
55          space-= read;
56          size+=read;
57          if(space == 0) {
58            // no more space; we need a new buffer
59            buffer.addLast(lastBuff);
60            space = buffSize;
61            writeOffset = 0;
62            lastBuff = new byte[buffSize];
63          } else {
64            // current buffer not full yet
65            writeOffset+=read;
66          }
67        }
68      };// while(!over)
69  
70      // will be used to write the data
71      outputStream = new PipedOutputStream();
72  
73      // will be returned for objects that want to read the object
74      inputStream = new PipedInputStream(outputStream);
75    }
76  
77    /**
78      * Returns a PipedInputStream from which the object given as parameter for
79      * the constructor can be read.
80      *
81      * @return a PipedInputStream connected to PipedOutputStream which writes
82      * the object which this ObjectWriter was built for.
83      */
84    public InputStream getInputStream() {
85      return inputStream;
86    }
87  
88    /**
89      * Obtains the object size.
90      *
91      * @return the size of the object recieved as parameter for the constructor.
92      */
93    public int getSize() {
94      return size;
95    }
96  
97    /** Writes all the buffers to the output stream
98      */
99    public void run() {
100     try{
101       Iterator buffIter = buffer.iterator();
102       while(buffIter.hasNext()){
103         byte currentBuff[] = (byte[])buffIter.next();
104         if(buffIter.hasNext()) {
105           // is not the last buffer
106           outputStream.write(currentBuff,0,buffSize);
107         } else {
108           // is the last buffer
109           // currentBuff[lastOffset] = '\u001a';
110           outputStream.write(currentBuff,0,lastOffset);
111         }
112       }// while(buffIter.hasNext())
113 
114       outputStream.flush();
115       outputStream.close();
116     } catch(IOException ioe) {
117       throw new RuntimeException(ioe.toString());
118       // ioe.printStackTrace(Err.getPrintWriter());
119     }
120   }
121 
122 
123   /** I need a thread to write the object so I can read it in an buffer
124     * After that I know the size ana I can write it to the output stream
125     * after I report the size.
126     */
127   private class Writer extends Thread {
128     public Writer(Object _obj){
129       _object = _obj;
130       _outputStream = new PipedOutputStream();
131 
132       try {
133         _inputStream = new PipedInputStream(_outputStream);
134       } catch(IOException ioe) {
135         ioe.printStackTrace(Err.getPrintWriter());
136       }
137     }
138 
139     public InputStream getInputStream(){
140       return _inputStream;
141     }
142 
143     /**
144       * Describe 'run' method here.
145       */
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 Object object;
163 
164   private InputStream inputStream ;
165 
166   private PipedOutputStream outputStream;
167 
168   private int size;
169 
170   private int lastOffset;
171 
172   private LinkedList buffer;
173 
174   private int buffSize = 1024;
175 
176 } // class ObjectWriter
177