View Javadoc

1   /*
2    * %W% %E%
3    *
4    * Copyright 1997, 1998 Sun Microsystems, Inc. All Rights Reserved.
5    *
6    * Redistribution and use in source and binary forms, with or
7    * without modification, are permitted provided that the following
8    * conditions are met:
9    *
10   * - Redistributions of source code must retain the above copyright
11   *   notice, this list of conditions and the following disclaimer.
12   *
13   * - Redistribution in binary form must reproduce the above
14   *   copyright notice, this list of conditions and the following
15   *   disclaimer in the documentation and/or other materials
16   *   provided with the distribution.
17   *
18   * Neither the name of Sun Microsystems, Inc. or the names of
19   * contributors may be used to endorse or promote products derived
20   * from this software without specific prior written permission.
21   *
22   * This software is provided "AS IS," without a warranty of any
23   * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
24   * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
25   * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
26   * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY
27   * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR
28   * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE OR
29   * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE
30   * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT,
31   * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
32   * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF
33   * THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS
34   * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
35   *
36   * You acknowledge that this software is not designed, licensed or
37   * intended for use in the design, construction, operation or
38   * maintenance of any nuclear facility.
39   */
40  
41  package uk.ac.rdg.resc.jstyx.client.browser;
42  
43  import java.io.File;
44  import java.util.Date;
45  import java.net.InetSocketAddress;
46  import javax.swing.JOptionPane;
47  import uk.ac.rdg.resc.jstyx.StyxException;
48  import uk.ac.rdg.resc.jstyx.client.CStyxFile;
49  import uk.ac.rdg.resc.jstyx.client.StyxConnection;
50  
51  /***
52   * FileSystemModel is a TreeTableModel representing a hierarchical file
53   * system. Nodes in the FileSystemModel are FileNodes which, when they
54   * are directory nodes, cache their children to avoid repeatedly querying
55   * the real file system.
56   *
57   * @version %I% %G%
58   *
59   * @author Philip Milne
60   * @author Scott Violet
61   * @author Jon Blower: adapted this for a Styx hierarchy
62   */
63  
64  public class StyxFileSystemModel extends AbstractTreeTableModel
65      implements TreeTableModel
66  {
67      
68      private String host;
69      private int port;
70      
71      // Names of the columns.
72      static protected String[] cNames = {"Name", "Size", "Owner", "Group", "Permissions", "Modified"};
73      
74      // Types of the columns.
75      static protected Class[] cTypes = {TreeTableModel.class, Long.class,
76          String.class, String.class, String.class, Date.class};
77      
78      // The the returned file length for directories.
79      public static final Integer ZERO = new Integer(0);
80      
81      public StyxFileSystemModel(StyxConnection conn) throws Exception
82      {
83          super();
84          this.setRoot(new FileNode(conn.getRootDirectory()));
85      }
86      
87      //
88      // Some convenience methods.
89      //
90      
91      protected CStyxFile getFile(Object node)
92      {
93          FileNode fileNode = ((FileNode)node);
94          return fileNode.getFile();
95      }
96      
97      protected Object[] getChildren(Object node)
98      {
99          FileNode fileNode = ((FileNode)node);
100         return fileNode.getChildren();
101     }
102     
103     //
104     // The TreeModel interface
105     //
106     
107     public int getChildCount(Object node)
108     {
109         Object[] children = getChildren(node);
110         return (children == null) ? 0 : children.length;
111     }
112     
113     public Object getChild(Object node, int i)
114     {
115         return getChildren(node)[i];
116     }
117     
118     // The superclass's implementation would work, but this is more efficient.
119     public boolean isLeaf(Object node)
120     {
121         try
122         {
123             return !getFile(node).isDirectory();
124         }
125         catch (StyxException se)
126         {
127             return true;
128         }
129     }
130     
131     //
132     //  The TreeTableNode interface.
133     //
134     
135     public int getColumnCount()
136     {
137         return cNames.length;
138     }
139     
140     public String getColumnName(int column)
141     {
142         return cNames[column];
143     }
144     
145     public Class getColumnClass(int column)
146     {
147         return cTypes[column];
148     }
149     
150     public Object getValueAt(Object node, int column)
151     {
152         CStyxFile file = getFile(node);
153         try
154         {
155             switch(column)
156             {
157                 case 0:
158                     return file.getName();
159                 case 1:
160                     return new Long(file.getLength());
161                 case 2:
162                     return file.getOwner();
163                 case 3:
164                     return file.getGroup();
165                 case 4:
166                     return file.getDirEntry().getPermissionsAsString();
167                 case 5:
168                     return file.getLastModified();
169             }
170         }
171         catch (StyxException ste)
172         {
173         }
174         catch  (SecurityException se)
175         {
176         }
177         
178         return null;
179     }
180 }
181 
182 /* A FileNode is a derivative of the File class - though we delegate to
183  * the File object rather than subclassing it. It is used to maintain a
184  * cache of a directory's children and therefore avoid repeated access
185  * to the underlying file system during rendering.
186  */
187 class FileNode
188 {
189     CStyxFile  file;
190     Object[] children;
191     
192     public FileNode(CStyxFile file)
193     {
194         this.file = file;
195     }
196     
197     // Used to sort the file names.
198     static private MergeSort fileMS = new MergeSort()
199     {
200         public int compareElementsAt(int a, int b)
201         {
202             CStyxFile fa = (CStyxFile)toSort[a];
203             CStyxFile fb = (CStyxFile)toSort[b];
204             return fa.getName().compareTo(fb.getName());
205         }
206     };
207     
208     /***
209      * Returns the the string to be used to display this leaf in the JTree.
210      */
211     public String toString()
212     {
213         return this.file.getName();
214     }
215     
216     public CStyxFile getFile()
217     {
218         return this.file;
219     }
220     
221     /***
222      * Synchronizes the file's attributes and list of children if it has them
223      */
224     public void refresh()
225     {
226         try
227         {
228             this.file.refresh();
229             CStyxFile[] files = this.file.getChildren();
230             if(files != null)
231             {
232                 fileMS.sort(files);
233                 // TODO: make more efficient and use the existing array of children?
234                 children = new FileNode[files.length];
235                 for (int i = 0; i < files.length; i++)
236                 {
237                     children[i] = new FileNode(files[i]);
238                 }
239             }
240         }
241         catch (StyxException ste)
242         {
243             // Show an error dialog box
244             new ErrorMessage(ste.getMessage()).start();
245         }
246         catch (SecurityException se)
247         {
248         }
249     }
250     
251     /***
252      * Loads the children, caching the results in the children ivar.
253      */
254     protected Object[] getChildren()
255     {
256         if (children != null)
257         {
258             return children;
259         }
260         this.refresh();
261         return children;
262     }
263     
264     private class ErrorMessage extends Thread
265     {
266         private String message;
267         public ErrorMessage(String message)
268         {
269             this.message = message;
270             this.setDaemon(true);
271         }
272         public void run()
273         {
274             JOptionPane.showMessageDialog(null, this.message);
275         }
276     }
277 }
278 
279