View Javadoc

1   /*
2    * $Id: LibraryEntry.java,v 1.13 2005/06/01 19:55:51 jlerner Exp $
3    *
4    * Copyright (c) 1999-2004, BBN Technologies, LLC.
5    * All rights reserved.
6    * http://www.daml.org/legal/opensource/bbn_license.html
7    */
8    
9   package com.bbn.swede.core.libraries;
10  
11  import java.io.BufferedInputStream;
12  import java.io.BufferedOutputStream;
13  import java.io.File;
14  import java.io.FileInputStream;
15  import java.io.IOException;
16  import java.io.InputStream;
17  import java.io.ObjectInputStream;
18  import java.io.ObjectOutputStream;
19  import java.io.OutputStream;
20  import java.util.Properties;
21  import java.util.zip.ZipEntry;
22  import java.util.zip.ZipFile;
23  
24  import com.bbn.swede.core.OWLCore;
25  import com.bbn.swede.core.dom.IOWLAbstractSyntaxTree;
26  import com.bbn.swede.core.dom.OAST;
27  
28  /***
29   * This class implements the lower-level functionality related to 
30   * a library entry.
31   * <br /> <br />
32   * This is not a public package, and is expected to be accessed only 
33   * by Library, LibraryDescriptor and ILibraryEntryDescriptor. 
34   * <br /> <br />
35   * For a more detailed explanation of Librarys, library entrys and how 
36   * they relate, see {@link Library}.
37   * <br /><br />
38   * Note that support for serialized IOWLAbstractSyntaxTrees is not 
39   * yet implemented; it exists here to allow for better compatability 
40   * when that support is added. 
41   * 
42   * 
43   * @see Library
44   * @author aperezlo
45   */
46  class LibraryEntry implements ILibraryEntry
47  {
48     private Library _library;
49     
50     private LibraryEntryDescriptor _descriptor;
51     private ZipEntry _propertiesEntry;
52     private ZipEntry _fileEntry;
53     private ZipEntry _oastEntry;
54     
55     private IOWLAbstractSyntaxTree _oast;
56     private File _file;
57     private Properties _properties;
58     
59     private boolean _hasOAST;
60     private InputStream _fileStream;
61     
62     private String _filename;
63     
64     // create a new entry based on what's in a library file on disk...
65     /***
66      * This constructor is used to create a LibraryEntry from an 
67      * already-existing library.
68      * 
69      * 
70      * @param lib the library to which this 'Entry will belong
71      * @param file the compressed file that this 'Entry represents
72      * @param props the compressed file that holds this 'Entry's properties
73      * @param oast the compressed file that holds the serialized version of the OAST
74      */
75     LibraryEntry(Library lib, ZipEntry file, ZipEntry props, ZipEntry oast)
76     {
77        _library = lib;
78        _propertiesEntry = props;
79        _fileEntry = file;
80        _oastEntry = oast;
81        _filename = _fileEntry.getName();
82        _filename = _filename.replaceAll("////", "/");
83        _filename = _filename.substring(_filename.lastIndexOf("/") + 1, _filename.lastIndexOf("."));
84     }
85     
86     // Create a new entry programmatically...
87     /***
88      * This constructor is used to create a LibraryEntry from a file 
89      * that exists on the filesystem, but not yet in a library.
90      * 
91      * @param lib the library to which this 'Entry will belong
92      * @param file the file, on disk, that this 'Entry represents
93      * @param props the properties, in memory, that describe this 'Entry's file
94      * @param oast the IOWLAbstractSyntaxTree to be serialized 
95      */
96     LibraryEntry(Library lib, File file, Properties props, IOWLAbstractSyntaxTree oast)
97     {
98        _library = lib;
99        _file = file;
100       _properties = props;
101       _oast = oast;
102       _filename = file.getName();
103    }
104 
105    /***
106     * Retrieves the library that contains this entry.
107     * @return The containing library
108     */
109    Library getLibrary()
110    {
111       return _library;
112    }
113    
114    /***
115     * Retrieves the local filename of this entry.
116     * @return the name of the file this 'Entry represents
117     */
118    String getFilename()
119    {
120       return _filename;
121    }
122    
123    /***
124     * Attempts to return an InputStream to the file represented by this 'Entry.  
125     * That stream could be to a file on disk, or to a compressed file within the 
126     * library ZIP, depending on what type of 'Entry this is.
127     * <br />
128     * If neither of those locations are available for reading, then this method 
129     * returns null
130     * @see java.io.InputStream
131     * @return a new InputStream to this 'Entry's file, or null 
132     */
133    InputStream getFile()
134    {
135       if(_fileStream != null)
136       {
137          try
138          {
139             _fileStream.close();
140          }
141          catch(Exception e)
142          {
143             OWLCore.logWarning(OWLCore.getID(), "Unable to close file stream", e);
144          }
145       }
146       try
147       {
148          if((_fileEntry != null) && (_library.getZipFile() != null))
149          {
150             ZipFile zf = _library.getZipFile();
151             _fileStream = zf.getInputStream(_fileEntry);
152          }
153          else if((_file != null) && (_file.canRead()))
154          {
155             _fileStream = new FileInputStream(_file);
156          }
157       }
158       catch(Exception e)
159       {
160          e.printStackTrace();
161       }
162       return _fileStream;
163    }
164 
165    /* (non-Javadoc)
166     * @see com.bbn.swede.core.libraries.ILibraryEntry#createDescriptor()
167     */
168    public ILibraryEntryDescriptor createDescriptor()
169    {
170       if(_descriptor == null)
171       {
172          _descriptor = new LibraryEntryDescriptor(this);
173       }
174       return _descriptor;
175    }
176    
177    /***
178     * Set the file for this LibraryEntry.
179     * 
180     * @param newFile the new file this 'Entry should represent
181     */
182    void setFile(File newFile)
183    {
184       _file = newFile;
185       _filename = _file.getName();
186    }
187    
188    /***
189     * Sets the properties of the library entry.
190     * @param props The new properties for the entry.
191     */
192    void setProperties(Properties props)
193    {
194       _properties = props;
195    }
196    
197    
198    /***
199     * Note: This functionality does not yet work properly, and its 
200     * behaviour is undefined.
201     * @param newOAST an OAST that this represents this 'Entry's file, or null 
202     */
203    void setOAST(IOWLAbstractSyntaxTree newOAST)
204    {
205       _oast = newOAST;
206       _hasOAST = ((newOAST == null) ? false : true);
207    }
208    
209    /***
210     * This method will return the OAST value for this 'Entry, 
211     * rebuilding it from a serialized version on disk if neccessary.
212     * <br /> <br />
213     * Note: This functionality does not yet work properly, and its  
214     * behaviour is undefined.
215     * 
216     * @return the OAST that represents this 'Entry's file.
217     */
218    IOWLAbstractSyntaxTree getOAST()
219    {
220       IOWLAbstractSyntaxTree toReturn = null;
221       ObjectInputStream stream = null;
222       if(_hasOAST)
223       {
224          if(_oast == null)
225          {
226             try
227             {
228                stream = new ObjectInputStream(_library.getZipFile().getInputStream(_fileEntry));
229                _oast = (OAST) stream.readObject();
230             }
231             catch(Exception e)
232             {
233                _hasOAST = false;
234             }
235             finally
236             {
237                try
238                {
239                   stream.close();
240                }
241                catch(Exception e)
242                {
243                   OWLCore.logWarning(OWLCore.getID(), "Unable to close stream for serialized OAST", e);
244                }
245             }
246          }
247       }
248       toReturn = _oast;
249       return toReturn;
250    }
251 
252    /***
253     * This method returns the {@link Properties} of this LibraryEntry, 
254     * reading them from the library ZIP file if required.
255     * 
256     * @see Properties#load(java.io.InputStream)
257     * @return the {@link Properties} of this 'Entry's file
258     */
259    Properties getProperties()
260    {
261       Properties toReturn = _properties;
262       InputStream stream = null;
263  
264       if(toReturn == null)
265       {
266          try
267          {
268             toReturn = new Properties();
269             stream = _library.getZipFile().getInputStream(_propertiesEntry);
270             toReturn.load(stream);
271             _properties = toReturn;
272          }
273          catch(Exception e)
274          {
275             e.printStackTrace();
276          }
277          finally
278          {
279             try
280             {
281                stream.close();
282             }
283             catch(Exception e)
284             {
285                OWLCore.logWarning(OWLCore.getID(),
286                   "Couldn't close properties stream for library '" + _filename
287                      + "'", e);
288             }
289          }
290       }
291       return toReturn;
292    }
293 
294    /***
295     * This method attempts to close all file handles and release all 
296     * system resources held by this LibraryEntry.
297     * 
298     * @return true if the operation was successful, false otherwise
299     */
300    boolean close()
301    {
302       boolean toReturn = true;
303       try
304       {
305          if(_fileStream != null)
306          {
307             synchronized (_fileStream)
308             {
309                _fileStream.close();
310             }
311          }
312       }
313       catch(Exception e)
314       {
315          toReturn = false;
316       }
317       return toReturn;
318    }
319    
320    /***
321     * This method uses the {@link Properties#store(java.io.OutputStream, java.lang.String)} 
322     * method to write properties to an OutputStream.  The stream is not closed as a 
323     * result of an invokation of this method.
324     * 
325     * @see Properties#store(java.io.OutputStream, java.lang.String)
326     * @param outstream the stream to which this 'Entry's properties should be written
327     */
328    void writeProperties(OutputStream outstream)
329    {
330       try
331       {
332          _properties.store(outstream, "'" + _filename + "' Entry Properties");
333       }
334       catch(Exception e)
335       {
336          OWLCore.logWarning(OWLCore.getID(), "Couldn't write properties for '"
337             + _filename + "' library entry writing...", e);
338       }
339    }
340    
341    /***
342     * This method write this LibraryEntry's file to the outstream 
343     * provided.  This method does not close the OutputStream
344     * 
345     * @param outstream the stream to which this 'Entry's file should be written
346     */
347    void writeFile(OutputStream outstream)
348    {
349       BufferedInputStream input = null;
350       BufferedOutputStream out = null;
351       final int iChunkSize = 1024;
352       byte[] bytes = new byte[iChunkSize]; 
353       int offset = 0;
354       int length = iChunkSize;
355       synchronized (_file == null ? new Object() : _file)
356       {
357          out = new BufferedOutputStream(outstream);
358          if(_file == null)
359          {
360             input = new BufferedInputStream(getFile());
361          }
362          else
363          {
364             try
365             {
366                input = new BufferedInputStream(new FileInputStream(_file));
367             }
368             catch(Exception e)
369             {
370                OWLCore.logWarning(OWLCore.getID(), "Couldn't open file '"
371                   + _file + "' to read for library writing...", e);
372             }
373          }
374          try
375          {
376             while(length > -1)
377             {
378                length = iChunkSize;
379                length = input.read(bytes, offset, length);
380                if(length > -1)
381                {
382                   out.write(bytes, offset, length);
383                }
384             }
385             out.flush();
386          }      
387          catch(Exception e)
388          {
389             OWLCore.logWarning(OWLCore.getID(), "Couldn't read file '" + _file + "' for library writing...", e);
390          }
391          finally
392          {
393             try
394             {
395                input.close();
396             }
397             catch (IOException e1)
398             {
399                OWLCore.logWarning(OWLCore.getID(), "Couldn't close library file for writing...", e1);
400             }
401          }
402       }
403    }
404    
405    /***
406     * Note: This functionality does not yet work properly, and its
407     * behaviour is undefined.
408     * <br />
409     * <br />
410     * This method will not close the output stream.
411     * 
412     * @param outstream the stream to which the OAST should be written
413     */
414    void writeOAST(OutputStream outstream)
415    {
416       IOWLAbstractSyntaxTree toWrite = getOAST();
417       ObjectOutputStream out = null;
418       try
419       {
420          out = new ObjectOutputStream(outstream);
421          out.writeObject(toWrite);
422       }
423       catch(Exception e)
424       {
425          OWLCore.logWarning(OWLCore.getID(), "Unable to serialize OAST", e);
426       }
427    }
428 }