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.lang3.ArrayUtils;
34  import org.apache.commons.lang3.SystemProperties;
35  import org.apache.commons.vfs2.Capability;
36  import org.apache.commons.vfs2.FileContent;
37  import org.apache.commons.vfs2.FileObject;
38  import org.apache.commons.vfs2.FileSystemException;
39  import org.apache.commons.vfs2.FileSystemManager;
40  import org.apache.commons.vfs2.FileType;
41  import org.apache.commons.vfs2.Selectors;
42  import org.apache.commons.vfs2.VFS;
43  import org.apache.commons.vfs2.impl.StandardFileSystemManager;
44  import org.apache.commons.vfs2.operations.FileOperationProvider;
45  import org.apache.commons.vfs2.util.FileObjectUtils;
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 static String getVersion(final Class<?> cls) {
55          try {
56              return cls.getPackage().getImplementationVersion();
57          } catch (final Exception ignored) {
58              return "N/A";
59          }
60      }
61      /**
62       * Invokes this example from the command line.
63       *
64       * @param args Arguments TODO
65       */
66      public static void main(final String[] args) {
67          try {
68              new Shell().go();
69          } catch (final Exception e) {
70              e.printStackTrace();
71              System.exit(1);
72          }
73          System.exit(0);
74      }
75      private final FileSystemManager mgr;
76  
77      private FileObject cwd;
78  
79      private final BufferedReader reader;
80  
81      private Shell() throws IOException {
82          final String providers = System.getProperty("providers");
83          final URL providersUrl = providers != null ? Shell.class.getResource("/" + providers) : null;
84  
85          if (providersUrl != null) {
86              mgr = new StandardFileSystemManager();
87              System.out.println("Custom providers configuration used: " + providersUrl);
88              ((StandardFileSystemManager) mgr).setConfiguration(providersUrl);
89              ((StandardFileSystemManager) mgr).init();
90          } else {
91              mgr = VFS.getManager();
92          }
93  
94          cwd = mgr.toFileObject(new File(System.getProperty("user.dir")));
95          reader = new BufferedReader(new InputStreamReader(System.in, Charset.defaultCharset()));
96      }
97  
98      /**
99       * Does a 'cat' command.
100      */
101     private void cat(final String[] cmd) throws Exception {
102         if (cmd.length < 2) {
103             throw new Exception("USAGE: cat <path>");
104         }
105 
106         // Locate the file
107         final FileObject file = mgr.resolveFile(cwd, cmd[1]);
108 
109         // Dump the contents to System.out
110         FileObjectUtils.writeContent(file, System.out);
111         System.out.println();
112     }
113 
114     /**
115      * Does a 'cd' command. If the taget directory does not exist, a message is printed to {@code System.err}.
116      */
117     private void cd(final String[] cmd) throws Exception {
118         final String path;
119         if (cmd.length > 1) {
120             path = cmd[1];
121         } else {
122             path = SystemProperties.getUserHome();
123         }
124 
125         // Locate and validate the folder
126         final FileObject tmp = mgr.resolveFile(cwd, path);
127         if (tmp.exists()) {
128             cwd = tmp;
129         } else {
130             System.out.println("Folder does not exist: " + tmp.getName());
131         }
132         System.out.println("Current folder is " + cwd.getName());
133     }
134 
135     /**
136      * Does a 'cp' command.
137      */
138     private void cp(final String[] cmd) throws Exception {
139         if (cmd.length < 3) {
140             throw new Exception("USAGE: cp <src> <dest>");
141         }
142 
143         final FileObject src = mgr.resolveFile(cwd, cmd[1]);
144         FileObject dest = mgr.resolveFile(cwd, cmd[2]);
145         if (dest.exists() && dest.getType() == FileType.FOLDER) {
146             dest = dest.resolveFile(src.getName().getBaseName());
147         }
148 
149         dest.copyFrom(src, Selectors.SELECT_ALL);
150     }
151 
152     private void go() throws Exception {
153         System.out.println("VFS Shell " + getVersion(Shell.class));
154         while (true) {
155             final String[] commands = nextCommand();
156             if (commands == null) {
157                 return;
158             }
159             if (commands.length == 0) {
160                 continue;
161             }
162             final String cmdName = commands[0];
163             if (cmdName.equalsIgnoreCase("exit") || cmdName.equalsIgnoreCase("quit")) {
164                 return;
165             }
166             try {
167                 handleCommand(commands);
168             } catch (final Exception e) {
169                 System.err.println("Command failed:");
170                 e.printStackTrace(System.err);
171             }
172         }
173     }
174 
175     /**
176      * Handles a command.
177      */
178     private void handleCommand(final String[] cmd) throws Exception {
179         final String cmdName = cmd[0];
180         if (cmdName.equalsIgnoreCase("cat")) {
181             cat(cmd);
182         } else if (cmdName.equalsIgnoreCase("cd")) {
183             cd(cmd);
184         } else if (cmdName.equalsIgnoreCase("cp")) {
185             cp(cmd);
186         } else if (cmdName.equalsIgnoreCase("help") || cmdName.equals("?")) {
187             help();
188         } else if (cmdName.equalsIgnoreCase("ls")) {
189             ls(cmd);
190         } else if (cmdName.equalsIgnoreCase("pwd")) {
191             pwd();
192         } else if (cmdName.equalsIgnoreCase("pwfs")) {
193             pwfs();
194         } else if (cmdName.equalsIgnoreCase("rm")) {
195             rm(cmd);
196         } else if (cmdName.equalsIgnoreCase("touch")) {
197             touch(cmd);
198         } else if (cmdName.equalsIgnoreCase("info")) {
199             info(cmd);
200         } else {
201             System.err.println("Unknown command \"" + cmdName + "\" (Try 'help').");
202         }
203     }
204 
205     /**
206      * Does a 'help' command.
207      */
208     private void help() {
209         System.out.println("Commands:");
210         System.out.println("cat <file>         Displays the contents of a file.");
211         System.out.println("cd [folder]        Changes current folder.");
212         System.out.println("cp <src> <dest>    Copies a file or folder.");
213         System.out.println("help               Shows this message.");
214         System.out.println("info [scheme]      Displays information about providers.");
215         System.out.println("ls [-R] [path]     Lists contents of a file or folder.");
216         System.out.println("pwd                Displays current folder.");
217         System.out.println("pwfs               Displays current file system.");
218         System.out.println("rm <path>          Deletes a file or folder.");
219         System.out.println("touch <path>       Sets the last-modified time of a file.");
220         System.out.println("exit, quit         Exits this program.");
221     }
222 
223     private void info(final String scheme) throws Exception {
224         System.out.println("Provider Info for scheme \"" + scheme + "\":");
225         final Collection<Capability> caps;
226         caps = mgr.getProviderCapabilities(scheme);
227         if (caps != null && !caps.isEmpty()) {
228             System.out.println("  capabilities: " + caps);
229         }
230         final FileOperationProvider[] ops = mgr.getOperationProviders(scheme);
231         if (ops != null && ops.length > 0) {
232             System.out.println("  operations: " + Arrays.toString(ops));
233         }
234     }
235 
236     private void info(final String[] cmd) throws Exception {
237         if (cmd.length > 1) {
238             info(cmd[1]);
239         } else {
240             System.out.println("Default manager: \"" + mgr.getClass().getName() + "\" " + "version " + getVersion(mgr.getClass()));
241             final String[] schemes = mgr.getSchemes();
242             final List<String> virtual = new ArrayList<>();
243             final List<String> physical = new ArrayList<>();
244             for (final String scheme : schemes) {
245                 final Collection<Capability> caps = mgr.getProviderCapabilities(scheme);
246                 if (caps != null) {
247                     if (caps.contains(Capability.VIRTUAL) || caps.contains(Capability.COMPRESS) || caps.contains(Capability.DISPATCHER)) {
248                         virtual.add(scheme);
249                     } else {
250                         physical.add(scheme);
251                     }
252                 }
253             }
254             if (!physical.isEmpty()) {
255                 System.out.println("  Provider Schemes: " + physical);
256             }
257             if (!virtual.isEmpty()) {
258                 System.out.println("   Virtual Schemes: " + virtual);
259             }
260         }
261     }
262 
263     /**
264      * Lists the children of a folder.
265      */
266     private void listChildren(final FileObject dir, final boolean recursive, final String prefix) throws FileSystemException {
267         final FileObject[] children = dir.getChildren();
268         for (final FileObject child : children) {
269             System.out.print(prefix);
270             System.out.print(child.getName().getBaseName());
271             if (child.getType() == FileType.FOLDER) {
272                 System.out.println("/");
273                 if (recursive) {
274                     listChildren(child, true, prefix + "    ");
275                 }
276             } else {
277                 System.out.println();
278             }
279         }
280     }
281 
282     /**
283      * Does an 'ls' command.
284      */
285     private void ls(final String[] cmd) throws FileSystemException {
286         int pos = 1;
287         final boolean recursive;
288         if (cmd.length > pos && cmd[pos].equals("-R")) {
289             recursive = true;
290             pos++;
291         } else {
292             recursive = false;
293         }
294 
295         final FileObject file;
296         if (cmd.length > pos) {
297             file = mgr.resolveFile(cwd, cmd[pos]);
298         } else {
299             file = cwd;
300         }
301 
302         if (file.getType() == FileType.FOLDER) {
303             // List the contents
304             System.out.println("Contents of " + file.getName());
305             listChildren(file, recursive, "");
306         } else {
307             // Stat the file
308             System.out.println(file.getName());
309             final FileContent content = file.getContent();
310             System.out.println("Size: " + content.getSize() + " bytes.");
311             final DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
312             final String lastMod = dateFormat.format(new Date(content.getLastModifiedTime()));
313             System.out.println("Last modified: " + lastMod);
314         }
315     }
316 
317     /**
318      * Returns the next command, split into tokens.
319      */
320     private String[] nextCommand() throws IOException {
321         System.out.print("> ");
322         final String line = reader.readLine();
323         if (line == null) {
324             return null;
325         }
326         final ArrayList<String> cmd = new ArrayList<>();
327         final StringTokenizer tokens = new StringTokenizer(line);
328         while (tokens.hasMoreTokens()) {
329             cmd.add(tokens.nextToken());
330         }
331         return cmd.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
332     }
333 
334     /**
335      * Does a 'pwd' command.
336      */
337     private void pwd() {
338         System.out.println("Current folder is " + cwd.getName());
339     }
340 
341     /**
342      * Does a 'pwfs' command.
343      */
344     private void pwfs() {
345         System.out.println("FileSystem of current folder is " + cwd.getFileSystem() + " (root: " + cwd.getFileSystem().getRootURI() + ")");
346     }
347 
348     /**
349      * Does an 'rm' command.
350      */
351     private void rm(final String[] cmd) throws Exception {
352         if (cmd.length < 2) {
353             throw new Exception("USAGE: rm <path>");
354         }
355 
356         final FileObject file = mgr.resolveFile(cwd, cmd[1]);
357         file.delete(Selectors.SELECT_SELF);
358     }
359 
360     /**
361      * Does a 'touch' command.
362      */
363     private void touch(final String[] cmd) throws Exception {
364         if (cmd.length < 2) {
365             throw new Exception("USAGE: touch <path>");
366         }
367         final FileObject file = mgr.resolveFile(cwd, cmd[1]);
368         if (!file.exists()) {
369             file.createFile();
370         }
371         file.getContent().setLastModifiedTime(System.currentTimeMillis());
372     }
373 }