View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   // MillScript: an Open Spice interpreter and batch website creation tool
3   // Copyright (C) 2005 Kevin Rogers
4   //
5   // This file is part of MillScript.
6   //
7   // MillScript is free software; you can redistribute it and/or modify it under
8   // the terms of the GNU General Public License as published by the Free
9   // Software Foundation; either version 2 of the License, or (at your option)
10  // any later version.
11  //
12  // MillScript is distributed in the hope that it will be useful, but WITHOUT
13  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  // more details.
16  //
17  // You should have received a copy of the GNU General Public License along with
18  // MillScript; if not, write to the Free Software Foundation, Inc., 59 Temple
19  // Place, Suite 330, Boston, MA  02111-1307  USA
20  ////////////////////////////////////////////////////////////////////////////////
21  package org.millscript.commons.vfs.protocols.ftp;
22  
23  import org.millscript.commons.alert.alerts.IOAlert;
24  import org.millscript.commons.vfs.AbstractVFolder;
25  import org.millscript.commons.vfs.VEntry;
26  import org.millscript.commons.vfs.VFile;
27  import org.millscript.commons.vfs.VFolder;
28  import org.millscript.commons.vfs.alerts.VEntryNotFoundAlert;
29  
30  import gnu.inet.ftp.FTPException;
31  
32  import java.io.IOException;
33  import java.io.InputStream;
34  import java.util.ArrayList;
35  import java.util.List;
36  import java.util.ListIterator;
37  
38  /**
39   * This class implements a virtual filesystem folder for an FTP filesystem
40   * folder.
41   */
42  public class FtpFolder extends AbstractVFolder< FtpVolume > {
43  
44      /**
45       * Constructs a new FTP virtual filesystem folder with the specified name,
46       * parent folder and volume.
47       *
48       * @param vol   the volume this entry is held on
49       * @param parent    the parent folder for this folder
50       * @param name  the name of the folder
51       */
52      FtpFolder( final FtpVolume vol, final VFolder parent, final String name ) {
53          super( vol, parent, name );
54      }
55  
56      /**
57       * Constructs a new FTP virtual filesystem folder with the specified name,
58       * parent folder. This folder will belong to the same volume as the
59       * specified parent folder.
60       *
61       * @param parent    the parent folder for this folder
62       * @param name  the name of the folder
63       */
64      FtpFolder( final FtpFolder parent, final String name ) {
65          super( parent.getVolume(), parent, name );
66      }
67  
68      /**
69       * @see org.millscript.commons.vfs.VFolder#checkVEntry(java.lang.String)
70       */
71      public VEntry checkVEntry( final String segment ) {
72          final StringBuffer uri = this.appendAbsolutePath( new StringBuffer() ).append( segment );
73          final FtpVolume vol = this.getVolume();
74          try {
75              // TODO - use the cwd() and list() methods to determine if the
76              // entry exists and what type it is
77              // Treat the entry as a folder and try to change into it
78              if ( vol.ftpConnection.changeWorkingDirectory( uri.toString() ) ) {
79                  // Ooo, we succeeded, so this entry is a folder
80                  return new FtpFolder( this, segment );
81              } else {
82                  // Ok, the segment isn't a folder so let's try and find out if
83                  // it exists. We can't use STAT, so lets try LIST.
84                  // TODO - Check this does throw an FTPException if the path
85                  // doesn't exist
86                  final InputStream listStream = vol.ftpConnection.list( uri.toString() );
87                  listStream.close();
88                  // We're still here, so this entry must be a file
89                  return new FtpFile( this, segment );
90              }
91          } catch ( FTPException ex  ) {
92              // An FTP excetion should mean the entry doesn't exist
93              throw VEntryNotFoundAlert.entryDoesNotExist( segment ).mishap();
94          } catch ( IOException ex ) {
95              // Alert - an i/o problem
96              throw new IOAlert(
97                  "Cannot dispatch the FTP request"
98              ).culprit( "message", ex.getMessage() ).setParentThrowable( ex ).mishap();
99          }
100     }
101 
102     /**
103      * @see org.millscript.commons.vfs.VFolder#checkVFile(java.lang.String)
104      */
105     public FtpFile checkVFile( final String segment ) {
106         final StringBuffer uri = this.appendAbsolutePath( new StringBuffer() ).append( segment );
107         final FtpVolume vol = this.getVolume();
108         try {
109             // Treat the entry as a folder and try to change into it
110             if ( vol.ftpConnection.changeWorkingDirectory( uri.toString() ) ) {
111                 // Ooo, we succeeded, so this entry is a folder
112                 throw VEntryNotFoundAlert.entryIsNotAFile( segment ).mishap();
113             } else {
114                 // Ok, the segment isn't a folder so let's try and find out if
115                 // it exists. We can't use STAT, so lets try LIST.
116                 // TODO - Check this does throw an FTPException if the path
117                 // doesn't exist
118                 final InputStream listStream = vol.ftpConnection.list( uri.toString() );
119                 listStream.close();
120                 // We're still here, so this entry must be a file
121                 return new FtpFile( this, segment );
122             }
123         } catch ( FTPException ex  ) {
124             // An FTP excetion should mean the entry doesn't exist
125             throw VEntryNotFoundAlert.entryDoesNotExist( segment ).mishap();
126         } catch ( IOException ex ) {
127             // Alert - an i/o problem
128             throw new IOAlert(
129                 "Cannot dispatch the FTP request"
130             ).culprit( "message", ex.getMessage() ).setParentThrowable( ex ).mishap();
131         }
132     }
133 
134     /**
135      * @see org.millscript.commons.vfs.VFolder#checkVFolder(java.lang.String)
136      */
137     public FtpFolder checkVFolder( final String segment ) {
138         final StringBuffer uri = this.appendAbsolutePath( new StringBuffer() ).append( segment );
139         try {
140             // Treat the entry as a folder and try to change into it
141             // TODO - Check this does throw an FTPException if the path is not
142             // a folder
143             if ( this.getVolume().ftpConnection.changeWorkingDirectory( uri.toString() ) ) {
144                 // Ooo, we succeeded, so this entry is a folder
145                 return new FtpFolder( this, segment );
146             } else {
147                 // Failed, so this entry must be a file
148                 throw VEntryNotFoundAlert.entryDoesNotExist( segment ).mishap();
149             }
150         } catch ( FTPException ex ) {
151             // An FTP excetion should mean the entry exists but isn't a folder
152             throw VEntryNotFoundAlert.entryIsNotAFolder( segment ).mishap();
153         } catch ( IOException ex ) {
154             // Alert - an i/o problem
155             throw new IOAlert(
156                 "Cannot dispatch the FTP request"
157             ).culprit( "message", ex.getMessage() ).setParentThrowable( ex ).mishap();
158         }
159     }
160 
161     /**
162      * @see org.millscript.commons.vfs.VEntry#exists()
163      */
164     public boolean exists() {
165         final StringBuffer uri = this.appendAbsolutePath( new StringBuffer() );
166         try {
167             // Treat the entry as a folder and try to change into it
168             if ( this.getVolume().ftpConnection.changeWorkingDirectory( uri.toString() ) ) {
169                 // Ooo, we succeeded, so this entry is a folder
170                 return true;
171             } else {
172                 // Ok, the segment isn't a folder
173                 return false;
174             }
175         } catch ( IOException ex ) {
176             // Alert - an i/o problem
177             throw new IOAlert(
178                 "Cannot dispatch the FTP request"
179             ).culprit( "message", ex.getMessage() ).setParentThrowable( ex ).mishap();
180         }
181     }
182 
183     /**
184      * @see org.millscript.commons.vfs.VFolder#getVFile(java.lang.String)
185      */
186     public FtpFile getVFile( final String segment ) {
187         return new FtpFile( this, segment );
188     }
189 
190     /**
191      * @see org.millscript.commons.vfs.VFolder#getVFolder(java.lang.String)
192      */
193     public FtpFolder getVFolder( final String segment ) {
194         return new FtpFolder( this, segment );
195     }
196 
197     /**
198      * @see org.millscript.commons.vfs.VFolder#listEntries()
199      */
200     public List< VEntry > listEntries() {
201         // The path for this folder
202         final String thisAbsPath = this.getAbsolutePath();
203         // The length of the path for this folder
204         final int pathLength = thisAbsPath.length();
205         final FtpVolume vol = this.getVolume();
206         try {
207             final ArrayList< VEntry > result = new ArrayList< VEntry >();
208             final List list = vol.ftpConnection.nameList( thisAbsPath );
209             final ListIterator it = list.listIterator();
210             while ( it.hasNext() ) {
211                 final String childAbsPath = (String) it.next();
212                 // Get the position of the first / in the entry name starting at
213                 // the end of this folders path.
214                 final int n = childAbsPath.indexOf( '/', pathLength );
215                 // Check if the entry has a slash in it.
216                 if ( n == -1  ) {
217                     // Treat the entry as a folder and try to change into it
218                     if ( vol.ftpConnection.changeWorkingDirectory( childAbsPath ) ) {
219                         // Ooo, we succeeded, so this entry is a folder
220                         result.add( new FtpFolder( this, childAbsPath.substring( pathLength ) ) );
221                     } else {
222                         // Failed, so this entry must be a file
223                         result.add( new FtpFile( this, childAbsPath.substring( pathLength ) ) );
224                     }
225                 } else {
226                     // Treat the entry as a folder and try to change into it
227                     if ( vol.ftpConnection.changeWorkingDirectory( childAbsPath ) ) {
228                         // Ooo, we succeeded, so this entry is a folder
229                         result.add( new FtpFolder( this, childAbsPath.substring( pathLength, n ) ) );
230                     } else {
231                         // Failed, so this entry must be a file
232                         result.add( new FtpFile( this, childAbsPath.substring( pathLength, n ) ) );
233                     }
234                 }
235             }
236             return result;
237         } catch ( IOException ex ) {
238             // Alert - an i/o problem
239             throw new IOAlert(
240                 "Could not get folder listing"
241             ).culprit( "message", ex.getMessage() ).setParentThrowable( ex ).mishap();
242         }
243     }
244 
245     /**
246      * @see org.millscript.commons.vfs.VFolder#listFiles()
247      */
248     public List< VFile > listFiles() {
249         // The path for this folder
250         final String thisAbsPath = this.getAbsolutePath();
251         // The length of the path for this folder
252         final int pathLength = thisAbsPath.length();
253         final FtpVolume vol = this.getVolume();
254         try {
255             final ArrayList< VFile > result = new ArrayList< VFile >();
256             final List list = vol.ftpConnection.nameList( thisAbsPath );
257             final ListIterator it = list.listIterator();
258             while ( it.hasNext() ) {
259                 final String childAbsPath = (String) it.next();
260                 // Get the position of the first / in the entry name starting at
261                 // the end of this folders path.
262                 final int n = childAbsPath.indexOf( '/', pathLength );
263                 // Check if the entry has a slash in it.
264                 if ( n == -1  ) {
265                     // Treat the entry as a folder and try to change into it
266                     if ( !vol.ftpConnection.changeWorkingDirectory( childAbsPath ) ) {
267                         // Failed, so this entry must be a file
268                         result.add( new FtpFile( this, childAbsPath.substring( pathLength ) ) );
269                     }
270                 } else {
271                     // Treat the entry as a folder and try to change into it
272                     if ( !vol.ftpConnection.changeWorkingDirectory( childAbsPath ) ) {
273                         // Failed, so this entry must be a file
274                         result.add( new FtpFile( this, childAbsPath.substring( pathLength, n ) ) );
275                     }
276                 }
277             }
278             return result;
279         } catch ( IOException ex ) {
280             // Alert - an i/o problem
281             throw new IOAlert(
282                 "Could not get folder listing"
283             ).culprit( "message", ex.getMessage() ).setParentThrowable( ex ).mishap();
284         }
285     }
286 
287     /**
288      * @see org.millscript.commons.vfs.VFolder#listFolders()
289      */
290     public List< VFolder > listFolders() {
291         // The path for this folder
292         final String thisAbsPath = this.getAbsolutePath();
293         // The length of the path for this folder
294         final int pathLength = thisAbsPath.length();
295         final FtpVolume vol = this.getVolume();
296         try {
297             final ArrayList< VFolder > result = new ArrayList< VFolder >();
298             final List list = vol.ftpConnection.nameList( thisAbsPath );
299             final ListIterator it = list.listIterator();
300             while ( it.hasNext() ) {
301                 final String childAbsPath = (String) it.next();
302                 // Get the position of the first / in the entry name starting at
303                 // the end of this folders path.
304                 final int n = childAbsPath.indexOf( '/', pathLength );
305                 // Check if the entry has a slash in it.
306                 if ( n == -1  ) {
307                     // Treat the entry as a folder and try to change into it
308                     if ( vol.ftpConnection.changeWorkingDirectory( childAbsPath ) ) {
309                         // Failed, so this entry must be a file
310                         result.add( new FtpFolder( this, childAbsPath.substring( pathLength ) ) );
311                     }
312                 } else {
313                     // Treat the entry as a folder and try to change into it
314                     if ( vol.ftpConnection.changeWorkingDirectory( childAbsPath ) ) {
315                         // Failed, so this entry must be a file
316                         result.add( new FtpFolder( this, childAbsPath.substring( pathLength, n ) ) );
317                     }
318                 }
319             }
320             return result;
321         } catch ( IOException ex ) {
322             // Alert - an i/o problem
323             throw new IOAlert(
324                 "Could not get folder listing"
325             ).culprit( "message", ex.getMessage() ).setParentThrowable( ex ).mishap();
326         }
327     }
328 
329     /**
330      * @see org.millscript.commons.vfs.VFolder#make()
331      */
332     public VFolder make() {
333         // TODO Auto-generated method stub
334         return null;
335     }
336 
337 }