View Javadoc

1   /*
2    * Copyright (c) 2005 The University of Reading
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    * 1. Redistributions of source code must retain the above copyright
9    *    notice, this list of conditions and the following disclaimer.
10   * 2. Redistributions in binary form must reproduce the above copyright
11   *    notice, this list of conditions and the following disclaimer in the
12   *    documentation and/or other materials provided with the distribution.
13   * 3. Neither the name of the University of Reading, nor the names of the
14   *    authors or contributors may be used to endorse or promote products
15   *    derived from this software without specific prior written permission.
16   * 
17   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20   * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27   */
28  
29  package uk.ac.rdg.resc.jstyx.server;
30  
31  import java.io.File;
32  import java.io.IOException;
33  
34  import uk.ac.rdg.resc.jstyx.StyxException;
35  
36  /***
37   * Class representing a directory on a hard disk (i.e. in the host filesystem)
38   * See also FileOnDisk.  To create a new file on the hard disk,
39   * use createChild().
40   *
41   * @author Jon Blower
42   * $Revision: 507 $
43   * $Date: 2005-12-01 08:21:56 +0000 (Thu, 01 Dec 2005) $
44   * $Log$
45   * Revision 1.7  2005/12/01 08:21:56  jonblower
46   * Fixed javadoc comments
47   *
48   * Revision 1.6  2005/06/20 17:21:26  jonblower
49   * Bug fix (listFiles() returns null if no permissions to read directory)
50   *
51   * Revision 1.5  2005/05/26 16:50:29  jonblower
52   * Made static method createFileOrDirectory()
53   *
54   * Revision 1.4  2005/05/19 14:46:51  jonblower
55   * Changed behaviour of StyxDirectory.createChild(): no longer adds file to namespace in this method
56   *
57   * Revision 1.3  2005/05/09 07:13:52  jonblower
58   * Changed getFileOnDisk() to getFileOrDirectoryOnDisk()
59   *
60   * Revision 1.2  2005/04/28 08:11:15  jonblower
61   * Modified permissions handling in documentation directory of SGS
62   *
63   * Revision 1.1.1.1  2005/02/16 18:58:31  jonblower
64   * Initial import
65   *
66   */
67  public class DirectoryOnDisk extends StyxDirectory
68  {
69      
70      protected File dir; // The java.io.File representing the directory
71      
72      public DirectoryOnDisk(String filename) throws StyxException
73      {
74          this(new File(filename));
75      }
76      
77      public DirectoryOnDisk(File dir) throws StyxException
78      {
79          this(dir, true);
80      }
81      
82      /***
83       * Creates a new instance of DirectoryOnDisk
84       * @param dir The directory to wrap
85       * @param searchChildren If this is true, we shall search through the
86       * immediate children of this directory and create StyxFile wrappers for 
87       * all of them
88       * @throws StyxException if the given filename does not represent
89       * an existing directory
90       */
91      private DirectoryOnDisk(File dir, boolean searchChildren) throws StyxException
92      {
93          super(dir.getName());
94          if (!(dir.exists() && dir.isDirectory()))
95          {
96              throw new StyxException(dir.getPath() + " is not a directory");
97          }
98          this.dir = dir;
99          this.refresh(searchChildren);
100     }
101     
102     /***
103      * Reads all metadata from underlying disk file
104      * @param updateChildren if this is true, all the immediate children of this
105      * directory will be updated (this parameter is meaningless if this is not a
106      * directory)
107      * @todo check for files that have been deleted in the host filesystem
108      */
109     protected synchronized void refresh(boolean updateChildren)
110     {
111         // Update the last modified time
112         this.lastModifiedTime = this.dir.lastModified() / 1000;
113         // Update the list of child files
114         if (updateChildren)
115         {
116             File[] files = this.dir.listFiles();
117             // If we don't have permission to look into this directory the
118             // files variable could be null
119             if (files != null)
120             {
121                 for (int i = 0; i < files.length; i++)
122                 {
123                     // Check to see if a file with this name is already known
124                     StyxFile sf = this.getChild(files[i].getName());
125                     if (sf == null)
126                     {
127                         try
128                         {
129                             sf = FileOnDisk.getFileOrDirectoryOnDisk(files[i]);
130                             // Set the permissions of the file correctly
131                             if (sf instanceof StyxDirectory)
132                             {
133                                 sf.setPermissions(this.getPermissions());
134                             }
135                             else
136                             {
137                                 // This is a StyxFile (a FileOnDisk). Set to the
138                                 // same permissions as this host directory without
139                                 // the "execute" flags
140                                 sf.setPermissions(this.getPermissions() & 0666);
141                             }
142                             this.addChild(sf);
143                         }
144                         catch(StyxException se)
145                         {
146                             // this exception is thrown if the file already exists.
147                             // We know this isn't the case so we can ignore it
148                         }
149                     }
150                     else
151                     {
152                         // File with this name already exists. Refresh the file
153                         // metadata but don't descend into subdirectories (could lead
154                         // to deep recursion)
155                         if (sf instanceof StyxDirectory)
156                         {
157                             StyxDirectory sd = (StyxDirectory)sf;
158                             sd.refresh(false);
159                         }
160                         else
161                         {
162                             sf.refresh();
163                         }
164                     }
165                 }
166             }
167         }
168     }
169     
170     /***
171      * Creates a new file and adds it to this directory. This method will create
172      * a new file in the underlying filesystem, then return it.
173      * A StyxException will be thrown if isAppOnly or isExclusive is true.
174      */
175     public StyxFile createChild(String name, int perm, boolean isDir,
176         boolean isAppOnly, boolean isExclusive)
177         throws StyxException
178     {
179         File f = new File(this.dir, name);
180         return createFileOrDirectory(f, isDir, perm);
181     }
182     
183     /***
184      * Removes the underlying directory from the disk
185      */
186     protected synchronized void delete()
187     {
188         this.dir.delete();
189     }
190     
191     /***
192      * Creates a file or directory, wraps it as a StyxFile with the given
193      * permissions and returns it
194      * @param f The java.io.File to be created
195      * @param isDir True if the file to be created is a directory
196      * @param perm The permissions to give the StyxFile
197      */
198     public static StyxFile createFileOrDirectory(File f, boolean isDir, int perm)
199         throws StyxException
200     {
201         if(isDir)
202         {
203             if (!f.mkdir())
204             {
205                 throw new StyxException("Directory " + f.getPath() + " could not be created");
206             }
207         }
208         else
209         {
210             try
211             {
212                 if (!f.createNewFile())
213                 {
214                     throw new StyxException("File " + f.getPath() + " could not be created");
215                 }
216             }
217             catch(IOException ioe)
218             {
219                 throw new StyxException("An IOException occurred when creating "
220                     + f.getPath() + ": " + ioe.getMessage());
221             }
222         }
223         // If we've got this far we must have created the file/directory
224         // successfully.  Now we can create the StyxFile wrapper and add it to
225         // this StyxDirectory.
226         StyxFile sf = FileOnDisk.getFileOrDirectoryOnDisk(f);
227         sf.setPermissions(perm);
228         return sf;
229     }
230     
231 }