001/* An interface for Attributes and Parameters that access files or URLs.
002
003 Copyright (c) 2007-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027 */
028package ptolemy.kernel.attributes;
029
030import java.io.BufferedReader;
031import java.io.File;
032import java.io.Writer;
033import java.net.URI;
034import java.net.URL;
035
036import ptolemy.kernel.util.IllegalActionException;
037import ptolemy.kernel.util.NamedObj;
038import ptolemy.kernel.util.Settable;
039
040///////////////////////////////////////////////////////////////////
041//// FileOrURLAccessor
042
043/**
044 An interface for Attributes and Parameters that access files or URLs.
045
046 <p>This interface is necessary because Java does not support multiple
047 inheritance and we have two classes (FileParameter and FilePortParameter)
048 that have a common interface, but do not have an immediate parent class.
049 In addition,
050 {@link ptolemy.kernel.attributes.FileAttribute} shares this interface.
051
052 <p>This interface is implemented by an Attribute or Parameter that
053 specifies a file or URL.  The value of this Attribute or Parameter,
054 accessed by getExpression(), is a string that names a file or URL. If
055 the model containing this attribute has been saved to a MoML file,
056 then the file name can be given relative to the directory containing
057 that MoML file.  If the model has not been saved to a file, then the
058 classpath is used for identifying relative file names.
059
060 <p> Files can be given relative to a <i>base</i>, where the base is
061 the URI of the first container above this one that has a URIAttribute.
062 Normally, this URI specifies the file or URL containing the model
063 definition. Thus, files that are referred to here can be kept in the
064 same directory as the model, or in a related directory, and can
065 moved together with the model.
066
067 <p>
068 The following special file names are understood:
069 <ul>
070 <li> System.in: Standard input.
071 <li> System.out: Standard output.
072 </ul>
073 Note, however, that these file names cannot be converted to URLs
074 using the asURL() method.
075 <p>
076 A file name can also contain the following strings that start
077 with "$", which get substituted
078 with the appropriate values
079 <table>
080 <caption>Preset values</caption>
081 <tr>
082 <th>String</th>
083 <th>Description</th>
084 <th>Property</th>
085 </tr>
086 <tr>
087 <td><code>$CWD</code></td>
088 <td>The current working directory</td>
089 <td><code>user.dir</code></td>
090 </tr>
091 <tr>
092 <td><code>$HOME</code></td>
093 <td>The user's home directory</td>
094 <td><code>user.home</code></td>
095 </tr>
096 <tr>
097 <td><code>$PTII</code></td>
098 <td>The home directory of the Ptolemy II installation</td>
099 <td><code>ptolemy.ptII.dir</code></td>
100 </tr>
101 <tr>
102 <td><code>$TMPDIR</code></td>
103 <td>The temporary directory</td>
104 <td><code>java.io.tmpdir</code></td>
105 </tr>
106 </table>
107 The above properties are normally set when a Ptolemy II application starts.
108 <p>
109 If a file name begins with the string "$CLASSPATH", followed by either
110 "/" or "\", then when the file
111 is opened for reading, the openForReading() method
112 will search for the file relative to the classpath (using the
113 getResource() method of the current class loader).  This will only
114 work for a file that exists, and thus the openForWriting() method
115 will not understand the "$CLASSPATH" string; this makes sense
116 since the classpath typically has several directories, and it
117 would not be obvious where to create the file.  The asURL()
118 method also recognizes the "$CLASSPATH" string, but not the asFile()
119 method (which is typically used when accessing a file for writing).
120 <p>
121 @author Christopher Brooks, based on FileAttribute by Edward A. Lee
122 @version $Id$
123 @see URIAttribute
124 @since Ptolemy II 6.1
125 @Pt.ProposedRating Red (cxh)
126 @Pt.AcceptedRating Red (cxh)
127 */
128public interface FileOrURLAccessor extends Settable {
129    ///////////////////////////////////////////////////////////////////
130    ////                         public methods                    ////
131
132    /** Return the file as a File object.  This method first attempts
133     *  to directly use the file name to construct the File. If the
134     *  resulting File is not absolute, then it attempts to resolve it
135     *  relative to the base directory returned by getBaseDirectory().
136     *  If there is no such base URI, then it simply returns the
137     *  relative File object.
138     *  <p>
139     *  The file need not exist for this method to succeed.  Thus,
140     *  this method can be used to determine whether a file with a given
141     *  name exists, prior to calling openForWriting().
142     *  A typical usage looks like this:
143     *  <pre>
144     *      FileAttribute fileAttribute;
145     *      ...
146     *      File file = fileAttribute.asFile();
147     *      if (file.exists()) {
148     *         ... Ask the user if it's OK to overwrite...
149     *         ... Throw an exception if not...
150     *      }
151     *      // The following will overwrite an existing file.
152     *      Writer writer = new PrintWriter(fileAttribute.openForWriting());
153     *  </pre>
154     *  @return A File, or null if no file name has been specified.
155     *  @see #getBaseDirectory()
156     *  @exception IllegalActionException If a parse error occurs
157     *   reading the file name.
158     */
159    public File asFile() throws IllegalActionException;
160
161    /** Return the file as a URL.  If the file name is relative, then
162     *  it is interpreted as being relative to the directory returned
163     *  by getBaseDirectory(). If the name begins with "$CLASSPATH",
164     *  then search for the file relative to the classpath.
165     *  If no file is found, then it throws an exception.
166     *  @return A URL, or null if no file name or URL has been specified.
167     *  @exception IllegalActionException If the file cannot be read, or
168     *   if the file cannot be represented as a URL (e.g. System.in).
169     */
170    public URL asURL() throws IllegalActionException;
171
172    /** Close the file. If it has not been opened using openForReading()
173     *  or openForWriting(), then do nothing.  Also, if the file is
174     *  System.in or System.out, then do not close it (it does not make
175     *  sense to close these files).
176     *  @exception IllegalActionException If the file or URL cannot be
177     *   closed.
178     */
179    public void close() throws IllegalActionException;
180
181    /** Return the directory to use as the base for relative file or URL names.
182     *  If setBaseDirectory() has been called, then that directory is
183     *  returned.  Otherwise, the directory containing the file returned
184     *  by URIAttribute.getModelURI() is returned, which is the URI
185     *  of the first container above this attribute in the hierarchy that
186     *  has a URIAttribute, or null if there none.
187     *  @return A directory name, or null if there is none.
188     *  @see #setBaseDirectory(URI)
189     *  @see URIAttribute#getModelURI(NamedObj)
190     */
191    public URI getBaseDirectory();
192
193    /** Open the file or URL for reading. If the name begins with
194     *  "$CLASSPATH", then search for the file relative to the classpath.
195     *  If the name is relative, then it is relative to the directory
196     *  returned by getBaseDirectory().
197     *  @return A buffered reader.
198     *  @see #getBaseDirectory()
199     *  @exception IllegalActionException If the file or URL cannot be
200     *   opened.
201     */
202    public BufferedReader openForReading() throws IllegalActionException;
203
204    /** Open the file for writing.  If the file does not exist, then
205     *  create it.  If the file name is not absolute, the it is assumed
206     *  to be relative to the base directory returned by getBaseDirectory().
207     *  If permitted, this method will return a Writer that will simply
208     *  overwrite the contents of the file. It is up to the user of this
209     *  method to check whether this is OK (by first calling asFile()
210     *  and calling exists() on the returned value).
211     *  @see #getBaseDirectory()
212     *  @see #asFile()
213     *  @return A writer, or null if no file name has been specified.
214     *  @exception IllegalActionException If the file cannot be opened
215     *   or created.
216     */
217    public Writer openForWriting() throws IllegalActionException;
218
219    /** Open the file for writing or appending.
220     *  If the file does not exist, then
221     *  create it.  If the file name is not absolute, the it is assumed
222     *  to be relative to the base directory returned by getBaseDirectory().
223     *  If permitted, this method will return a Writer that will simply
224     *  overwrite the contents of the file. It is up to the user of this
225     *  method to check whether this is OK (by first calling asFile()
226     *  and calling exists() on the returned value).
227     *  @see #getBaseDirectory()
228     *  @see #asFile()
229     *  @param append If true, then append to the file rather than
230     *   overwriting.
231     *  @return A writer, or null if no file name has been specified.
232     *  @exception IllegalActionException If the file cannot be opened
233     *   or created.
234     */
235    public Writer openForWriting(boolean append) throws IllegalActionException;
236
237    /** Set the directory to use as the base for relative file or URL names.
238     *  If this is not called, then the default is the directory
239     *  containing the file returned by URIAttribute.getModelURI().
240     *  @param directory The base directory.
241     *  @see #getBaseDirectory()
242     *  @see URIAttribute#getModelURI(NamedObj)
243     */
244    public void setBaseDirectory(URI directory);
245}