1   /*
2    *  ObjectWriter.java
3    *
4    *  Copyright (c) 1998-2001, 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.11 2000/11/13 17:55:20 valyt Exp $
14   */
15  
16  package gate.util;
17  
18  import java.io.*;
19  import java.util.*;
20  
21  /** Writes an object to an PipedOutputStream wich can be connected to a
22    * PipedInputStream.
23    * Before writting the object it also writes it in a buffer and finds
24    * out its size so it can be reported via getSize method.
25    * All read/writes occur in separate threads to avoid a deadlock.
26    */
27  public class ObjectWriter extends Thread {
28  
29    /** Debug flag */
30    private static final boolean DEBUG = false;
31  
32    public ObjectWriter(Object obj) throws IOException {
33      size = 0;
34      Writer writer = new Writer(obj);
35      InputStream is = writer.getInputStream();
36      writer.start();
37      boolean over = false;
38      buffer = new LinkedList();
39  
40      //how much space is available in lastBuff
41      int space = buffSize;
42  
43      //where to write in lastBuff
44      int writeOffset = 0;
45      byte lastBuff[] = new byte[buffSize];
46  
47      while (!over) {
48        int read = is.read(lastBuff, writeOffset, space);
49        if(read == -1) {
50          lastOffset = writeOffset;
51          buffer.addLast(lastBuff);
52          over = true;
53        } else {
54          space-= read;
55          size+=read;
56          if(space == 0) {
57            // no more space; we need a new buffer
58            buffer.addLast(lastBuff);
59            space = buffSize;
60            writeOffset = 0;
61            lastBuff = new byte[buffSize];
62          } else {
63            // current buffer not full yet
64            writeOffset+=read;
65          }
66        }
67      };// while(!over)
68  
69      // will be used to write the data
70      outputStream = new PipedOutputStream();
71  
72      // will be returned for objects that want to read the object
73      inputStream = new PipedInputStream(outputStream);
74    }
75  
76    /**
77      * Returns a PipedInputStream from which the object given as parameter for
78      * the constructor can be read.
79      *
80      * @return a PipedInputStream connected to PipedOutputStream which writes
81      * the object which this ObjectWriter was built for.
82      */
83    public InputStream getInputStream() {
84      return inputStream;
85    }
86  
87    /**
88      * Obtains the object size.
89      *
90      * @return the size of the object recieved as parameter for the constructor.
91      */
92    public int getSize() {
93      return size;
94    }
95  
96    /** Writes all the buffers to the output stream
97      */
98    public void run() {
99      try{
100       Iterator buffIter = buffer.iterator();
101       while(buffIter.hasNext()){
102         byte currentBuff[] = (byte[])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     public void run(){
146       try {
147         ObjectOutputStream _oos = new ObjectOutputStream(_outputStream);
148         _oos.writeObject(_object);
149         _oos.close();
150       } catch(IOException ioe) {
151         ioe.printStackTrace(Err.getPrintWriter());
152       }
153     }
154 
155     private Object _object;
156     private InputStream _inputStream;
157     private PipedOutputStream _outputStream;
158 
159   }
160 
161   private Object object;
162 
163   private InputStream inputStream ;
164 
165   private PipedOutputStream outputStream;
166 
167   private int size;
168 
169   private int lastOffset;
170 
171   private LinkedList buffer;
172 
173   private int buffSize = 1024;
174 
175 } // class ObjectWriter
176