View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.vfs2.example;
18  
19  import java.io.BufferedReader;
20  import java.io.File;
21  import java.io.IOException;
22  import java.io.InputStreamReader;
23  import java.net.URL;
24  import java.nio.charset.Charset;
25  import java.text.DateFormat;
26  import java.util.ArrayList;
27  import java.util.Arrays;
28  import java.util.Collection;
29  import java.util.Date;
30  import java.util.List;
31  import java.util.StringTokenizer;
32  
33  import org.apache.commons.vfs2.Capability;
34  import org.apache.commons.vfs2.FileContent;
35  import org.apache.commons.vfs2.FileObject;
36  import org.apache.commons.vfs2.FileSystemException;
37  import org.apache.commons.vfs2.FileSystemManager;
38  import org.apache.commons.vfs2.FileType;
39  import org.apache.commons.vfs2.FileUtil;
40  import org.apache.commons.vfs2.Selectors;
41  import org.apache.commons.vfs2.VFS;
42  import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
43  import org.apache.commons.vfs2.impl.StandardFileSystemManager;
44  import org.apache.commons.vfs2.operations.FileOperationProvider;
45  import org.apache.commons.vfs2.provider.FileProvider;
46  
47  /**
48   * A simple command-line shell for performing file operations.
49   * <p>
50   * See <a href="https://wiki.apache.org/commons/VfsExampleShell">Commons VFS Shell Examples</a> in Apache Commons Wiki.
51   */
52  public final class Shell {
53  
54      private final FileSystemManager mgr;
55      private FileObject cwd;
56      private final BufferedReader reader;
57  
58      private Shell() throws IOException {
59          final String providers = System.getProperty("providers");
60          final URL providersUrl = (providers != null) ? Shell.class.getResource("/" + providers) : null;
61  
62          if (providersUrl != null) {
63              mgr = new StandardFileSystemManager();
64              System.out.println("Custom providers configuration used: " + providersUrl);
65              ((StandardFileSystemManager) mgr).setConfiguration(providersUrl);
66              ((StandardFileSystemManager) mgr).init();
67          } else {
68              mgr = VFS.getManager();
69          }
70  
71          // TODO: VFS-360 - Remove this manual registration of http4 once http4 becomes part of standard providers.
72          boolean httpClient4Available = false;
73          try {
74              Class.forName("org.apache.http.client.HttpClient");
75              httpClient4Available = true;
76              final DefaultFileSystemManagerapache/commons/vfs2/impl/DefaultFileSystemManager.html#DefaultFileSystemManager">DefaultFileSystemManager manager = (DefaultFileSystemManager) VFS.getManager();
77              if (!manager.hasProvider("http4")) {
78                  manager.addProvider("http4", (FileProvider) Class.forName("org.apache.commons.vfs2.provider.http4.Http4FileProvider").newInstance());
79                  manager.addProvider("http4s", (FileProvider) Class.forName("org.apache.commons.vfs2.provider.http4s.Http4sFileProvider").newInstance());
80              }
81          } catch (final Exception e) {
82              if (httpClient4Available) {
83                  e.printStackTrace();
84              }
85          }
86  
87          cwd = mgr.toFileObject(new File(System.getProperty("user.dir")));
88          reader = new BufferedReader(new InputStreamReader(System.in, Charset.defaultCharset()));
89      }
90  
91      public static void main(final String[] args) {
92          try {
93              new Shell().go();
94          } catch (final Exception e) {
95              e.printStackTrace();
96              System.exit(1);
97          }
98          System.exit(0);
99      }
100 
101     private void go() throws Exception {
102         System.out.println("VFS Shell " + getVersion(Shell.class));
103         while (true) {
104             final String[] cmd = nextCommand();
105             if (cmd == null) {
106                 return;
107             }
108             if (cmd.length == 0) {
109                 continue;
110             }
111             final String cmdName = cmd[0];
112             if (cmdName.equalsIgnoreCase("exit") || cmdName.equalsIgnoreCase("quit")) {
113                 return;
114             }
115             try {
116                 handleCommand(cmd);
117             } catch (final Exception e) {
118                 System.err.println("Command failed:");
119                 e.printStackTrace(System.err);
120             }
121         }
122     }
123 
124     /**
125      * Handles a command.
126      */
127     private void handleCommand(final String[] cmd) throws Exception {
128         final String cmdName = cmd[0];
129         if (cmdName.equalsIgnoreCase("cat")) {
130             cat(cmd);
131         } else if (cmdName.equalsIgnoreCase("cd")) {
132             cd(cmd);
133         } else if (cmdName.equalsIgnoreCase("cp")) {
134             cp(cmd);
135         } else if (cmdName.equalsIgnoreCase("help") || cmdName.equals("?")) {
136             help();
137         } else if (cmdName.equalsIgnoreCase("ls")) {
138             ls(cmd);
139         } else if (cmdName.equalsIgnoreCase("pwd")) {
140             pwd();
141         } else if (cmdName.equalsIgnoreCase("pwfs")) {
142             pwfs();
143         } else if (cmdName.equalsIgnoreCase("rm")) {
144             rm(cmd);
145         } else if (cmdName.equalsIgnoreCase("touch")) {
146             touch(cmd);
147         } else if (cmdName.equalsIgnoreCase("info")) {
148             info(cmd);
149         } else {
150             System.err.println("Unknown command \"" + cmdName + "\" (Try 'help').");
151         }
152     }
153 
154     private void info(final String[] cmd) throws Exception {
155         if (cmd.length > 1) {
156             info(cmd[1]);
157         } else {
158             System.out.println(
159                     "Default manager: \"" + mgr.getClass().getName() + "\" " + "version " + getVersion(mgr.getClass()));
160             final String[] schemes = mgr.getSchemes();
161             final List<String> virtual = new ArrayList<>();
162             final List<String> physical = new ArrayList<>();
163             for (String scheme : schemes) {
164                 final Collection<Capability> caps = mgr.getProviderCapabilities(scheme);
165                 if (caps != null) {
166                     if (caps.contains(Capability.VIRTUAL) || caps.contains(Capability.COMPRESS)
167                             || caps.contains(Capability.DISPATCHER)) {
168                         virtual.add(scheme);
169                     } else {
170                         physical.add(scheme);
171                     }
172                 }
173             }
174             if (!physical.isEmpty()) {
175                 System.out.println("  Provider Schemes: " + physical);
176             }
177             if (!virtual.isEmpty()) {
178                 System.out.println("   Virtual Schemes: " + virtual);
179             }
180         }
181     }
182 
183     private void info(final String scheme) throws Exception {
184         System.out.println("Provider Info for scheme \"" + scheme + "\":");
185         Collection<Capability> caps;
186         caps = mgr.getProviderCapabilities(scheme);
187         if (caps != null && !caps.isEmpty()) {
188             System.out.println("  capabilities: " + caps);
189         }
190         final FileOperationProvider[] ops = mgr.getOperationProviders(scheme);
191         if (ops != null && ops.length > 0) {
192             System.out.println("  operations: " + Arrays.toString(ops));
193         }
194     }
195 
196     /**
197      * Does a 'help' command.
198      */
199     private void help() {
200         System.out.println("Commands:");
201         System.out.println("cat <file>         Displays the contents of a file.");
202         System.out.println("cd [folder]        Changes current folder.");
203         System.out.println("cp <src> <dest>    Copies a file or folder.");
204         System.out.println("help               Shows this message.");
205         System.out.println("info [scheme]      Displays information about providers.");
206         System.out.println("ls [-R] [path]     Lists contents of a file or folder.");
207         System.out.println("pwd                Displays current folder.");
208         System.out.println("pwfs               Displays current file system.");
209         System.out.println("rm <path>          Deletes a file or folder.");
210         System.out.println("touch <path>       Sets the last-modified time of a file.");
211         System.out.println("exit, quit         Exits this program.");
212     }
213 
214     /**
215      * Does an 'rm' command.
216      */
217     private void rm(final String[] cmd) throws Exception {
218         if (cmd.length < 2) {
219             throw new Exception("USAGE: rm <path>");
220         }
221 
222         final FileObject file = mgr.resolveFile(cwd, cmd[1]);
223         file.delete(Selectors.SELECT_SELF);
224     }
225 
226     /**
227      * Does a 'cp' command.
228      */
229     private void cp(final String[] cmd) throws Exception {
230         if (cmd.length < 3) {
231             throw new Exception("USAGE: cp <src> <dest>");
232         }
233 
234         final FileObject src = mgr.resolveFile(cwd, cmd[1]);
235         FileObject dest = mgr.resolveFile(cwd, cmd[2]);
236         if (dest.exists() && dest.getType() == FileType.FOLDER) {
237             dest = dest.resolveFile(src.getName().getBaseName());
238         }
239 
240         dest.copyFrom(src, Selectors.SELECT_ALL);
241     }
242 
243     /**
244      * Does a 'cat' command.
245      */
246     private void cat(final String[] cmd) throws Exception {
247         if (cmd.length < 2) {
248             throw new Exception("USAGE: cat <path>");
249         }
250 
251         // Locate the file
252         final FileObject file = mgr.resolveFile(cwd, cmd[1]);
253 
254         // Dump the contents to System.out
255         FileUtil.writeContent(file, System.out);
256         System.out.println();
257     }
258 
259     /**
260      * Does a 'pwd' command.
261      */
262     private void pwd() {
263         System.out.println("Current folder is " + cwd.getName());
264     }
265 
266     /**
267      * Does a 'pwfs' command.
268      */
269     private void pwfs() {
270         System.out.println("FileSystem of current folder is " + cwd.getFileSystem() + " (root: "
271                 + cwd.getFileSystem().getRootURI() + ")");
272     }
273 
274     /**
275      * Does a 'cd' command. If the taget directory does not exist, a message is printed to <code>System.err</code>.
276      */
277     private void cd(final String[] cmd) throws Exception {
278         final String path;
279         if (cmd.length > 1) {
280             path = cmd[1];
281         } else {
282             path = System.getProperty("user.home");
283         }
284 
285         // Locate and validate the folder
286         final FileObject tmp = mgr.resolveFile(cwd, path);
287         if (tmp.exists()) {
288             cwd = tmp;
289         } else {
290             System.out.println("Folder does not exist: " + tmp.getName());
291         }
292         System.out.println("Current folder is " + cwd.getName());
293     }
294 
295     /**
296      * Does an 'ls' command.
297      */
298     private void ls(final String[] cmd) throws FileSystemException {
299         int pos = 1;
300         final boolean recursive;
301         if (cmd.length > pos && cmd[pos].equals("-R")) {
302             recursive = true;
303             pos++;
304         } else {
305             recursive = false;
306         }
307 
308         final FileObject file;
309         if (cmd.length > pos) {
310             file = mgr.resolveFile(cwd, cmd[pos]);
311         } else {
312             file = cwd;
313         }
314 
315         if (file.getType() == FileType.FOLDER) {
316             // List the contents
317             System.out.println("Contents of " + file.getName());
318             listChildren(file, recursive, "");
319         } else {
320             // Stat the file
321             System.out.println(file.getName());
322             final FileContent content = file.getContent();
323             System.out.println("Size: " + content.getSize() + " bytes.");
324             final DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
325             final String lastMod = dateFormat.format(new Date(content.getLastModifiedTime()));
326             System.out.println("Last modified: " + lastMod);
327         }
328     }
329 
330     /**
331      * Does a 'touch' command.
332      */
333     private void touch(final String[] cmd) throws Exception {
334         if (cmd.length < 2) {
335             throw new Exception("USAGE: touch <path>");
336         }
337         final FileObject file = mgr.resolveFile(cwd, cmd[1]);
338         if (!file.exists()) {
339             file.createFile();
340         }
341         file.getContent().setLastModifiedTime(System.currentTimeMillis());
342     }
343 
344     /**
345      * Lists the children of a folder.
346      */
347     private void listChildren(final FileObject dir, final boolean recursive, final String prefix)
348             throws FileSystemException {
349         final FileObject[] children = dir.getChildren();
350         for (final FileObject child : children) {
351             System.out.print(prefix);
352             System.out.print(child.getName().getBaseName());
353             if (child.getType() == FileType.FOLDER) {
354                 System.out.println("/");
355                 if (recursive) {
356                     listChildren(child, recursive, prefix + "    ");
357                 }
358             } else {
359                 System.out.println();
360             }
361         }
362     }
363 
364     /**
365      * Returns the next command, split into tokens.
366      */
367     private String[] nextCommand() throws IOException {
368         System.out.print("> ");
369         final String line = reader.readLine();
370         if (line == null) {
371             return null;
372         }
373         final ArrayList<String> cmd = new ArrayList<>();
374         final StringTokenizer tokens = new StringTokenizer(line);
375         while (tokens.hasMoreTokens()) {
376             cmd.add(tokens.nextToken());
377         }
378         return cmd.toArray(new String[cmd.size()]);
379     }
380 
381     private static String getVersion(final Class<?> cls) {
382         try {
383             return cls.getPackage().getImplementationVersion();
384         } catch (final Exception ignored) {
385             return "N/A";
386         }
387     }
388 }