001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.vfs2.example; 018 019import java.io.BufferedReader; 020import java.io.File; 021import java.io.IOException; 022import java.io.InputStreamReader; 023import java.nio.charset.Charset; 024import java.text.DateFormat; 025import java.util.ArrayList; 026import java.util.Collection; 027import java.util.Date; 028import java.util.List; 029import java.util.StringTokenizer; 030 031import org.apache.commons.vfs2.Capability; 032import org.apache.commons.vfs2.FileContent; 033import org.apache.commons.vfs2.FileObject; 034import org.apache.commons.vfs2.FileSystemException; 035import org.apache.commons.vfs2.FileSystemManager; 036import org.apache.commons.vfs2.FileType; 037import org.apache.commons.vfs2.FileUtil; 038import org.apache.commons.vfs2.Selectors; 039import org.apache.commons.vfs2.VFS; 040import org.apache.commons.vfs2.operations.FileOperationProvider; 041 042/** 043 * A simple command-line shell for performing file operations. 044 * <p> 045 * See <a href="https://wiki.apache.org/commons/VfsExampleShell">Commons VFS Shell Examples</a> in Apache Commons Wiki. 046 */ 047public final class Shell { 048 private final FileSystemManager mgr; 049 private FileObject cwd; 050 private final BufferedReader reader; 051 052 private Shell() throws IOException { 053 mgr = VFS.getManager(); 054 cwd = mgr.toFileObject(new File(System.getProperty("user.dir"))); 055 reader = new BufferedReader(new InputStreamReader(System.in, Charset.defaultCharset())); 056 } 057 058 public static void main(final String[] args) { 059 try { 060 new Shell().go(); 061 } catch (final Exception e) { 062 e.printStackTrace(); 063 System.exit(1); 064 } 065 System.exit(0); 066 } 067 068 private void go() throws Exception { 069 System.out.println("VFS Shell " + getVersion(Shell.class)); 070 while (true) { 071 final String[] cmd = nextCommand(); 072 if (cmd == null) { 073 return; 074 } 075 if (cmd.length == 0) { 076 continue; 077 } 078 final String cmdName = cmd[0]; 079 if (cmdName.equalsIgnoreCase("exit") || cmdName.equalsIgnoreCase("quit")) { 080 return; 081 } 082 try { 083 handleCommand(cmd); 084 } catch (final Exception e) { 085 System.err.println("Command failed:"); 086 e.printStackTrace(System.err); 087 } 088 } 089 } 090 091 /** 092 * Handles a command. 093 */ 094 private void handleCommand(final String[] cmd) throws Exception { 095 final String cmdName = cmd[0]; 096 if (cmdName.equalsIgnoreCase("cat")) { 097 cat(cmd); 098 } else if (cmdName.equalsIgnoreCase("cd")) { 099 cd(cmd); 100 } else if (cmdName.equalsIgnoreCase("cp")) { 101 cp(cmd); 102 } else if (cmdName.equalsIgnoreCase("help") || cmdName.equals("?")) { 103 help(); 104 } else if (cmdName.equalsIgnoreCase("ls")) { 105 ls(cmd); 106 } else if (cmdName.equalsIgnoreCase("pwd")) { 107 pwd(); 108 } else if (cmdName.equalsIgnoreCase("rm")) { 109 rm(cmd); 110 } else if (cmdName.equalsIgnoreCase("touch")) { 111 touch(cmd); 112 } else if (cmdName.equalsIgnoreCase("info")) { 113 info(cmd); 114 } else { 115 System.err.println("Unknown command \"" + cmdName + "\" (Try 'help')."); 116 } 117 } 118 119 private void info(String[] cmd) throws Exception { 120 if (cmd.length > 1) { 121 info(cmd[1]); 122 } else { 123 System.out.println( 124 "Default manager: \"" + mgr.getClass().getName() + "\" " + "version " + getVersion(mgr.getClass())); 125 String[] schemes = mgr.getSchemes(); 126 List<String> virtual = new ArrayList<>(); 127 List<String> physical = new ArrayList<>(); 128 for (int i = 0; i < schemes.length; i++) { 129 Collection<Capability> caps = mgr.getProviderCapabilities(schemes[i]); 130 if (caps != null) { 131 if (caps.contains(Capability.VIRTUAL) || caps.contains(Capability.COMPRESS) 132 || caps.contains(Capability.DISPATCHER)) { 133 virtual.add(schemes[i]); 134 } else { 135 physical.add(schemes[i]); 136 } 137 } 138 } 139 if (!physical.isEmpty()) { 140 System.out.println(" Provider Schemes: " + physical); 141 } 142 if (!virtual.isEmpty()) { 143 System.out.println(" Virtual Schemes: " + virtual); 144 } 145 } 146 } 147 148 private void info(String scheme) throws Exception { 149 System.out.println("Provider Info for scheme \"" + scheme + "\":"); 150 Collection<Capability> caps; 151 caps = mgr.getProviderCapabilities(scheme); 152 if (caps != null && !caps.isEmpty()) { 153 System.out.println(" capabilities: " + caps); 154 } 155 FileOperationProvider[] ops = mgr.getOperationProviders(scheme); 156 if (ops != null && ops.length > 0) { 157 System.out.println(" operations: " + ops); 158 } 159 } 160 161 /** 162 * Does a 'help' command. 163 */ 164 private void help() { 165 System.out.println("Commands:"); 166 System.out.println("cat <file> Displays the contents of a file."); 167 System.out.println("cd [folder] Changes current folder."); 168 System.out.println("cp <src> <dest> Copies a file or folder."); 169 System.out.println("help Shows this message."); 170 System.out.println("info [scheme] Displays information about providers."); 171 System.out.println("ls [-R] [path] Lists contents of a file or folder."); 172 System.out.println("pwd Displays current folder."); 173 System.out.println("rm <path> Deletes a file or folder."); 174 System.out.println("touch <path> Sets the last-modified time of a file."); 175 System.out.println("exit, quit Exits this program."); 176 } 177 178 /** 179 * Does an 'rm' command. 180 */ 181 private void rm(final String[] cmd) throws Exception { 182 if (cmd.length < 2) { 183 throw new Exception("USAGE: rm <path>"); 184 } 185 186 final FileObject file = mgr.resolveFile(cwd, cmd[1]); 187 file.delete(Selectors.SELECT_SELF); 188 } 189 190 /** 191 * Does a 'cp' command. 192 */ 193 private void cp(final String[] cmd) throws Exception { 194 if (cmd.length < 3) { 195 throw new Exception("USAGE: cp <src> <dest>"); 196 } 197 198 final FileObject src = mgr.resolveFile(cwd, cmd[1]); 199 FileObject dest = mgr.resolveFile(cwd, cmd[2]); 200 if (dest.exists() && dest.getType() == FileType.FOLDER) { 201 dest = dest.resolveFile(src.getName().getBaseName()); 202 } 203 204 dest.copyFrom(src, Selectors.SELECT_ALL); 205 } 206 207 /** 208 * Does a 'cat' command. 209 */ 210 private void cat(final String[] cmd) throws Exception { 211 if (cmd.length < 2) { 212 throw new Exception("USAGE: cat <path>"); 213 } 214 215 // Locate the file 216 final FileObject file = mgr.resolveFile(cwd, cmd[1]); 217 218 // Dump the contents to System.out 219 FileUtil.writeContent(file, System.out); 220 System.out.println(); 221 } 222 223 /** 224 * Does a 'pwd' command. 225 */ 226 private void pwd() { 227 System.out.println("Current folder is " + cwd.getName()); 228 } 229 230 /** 231 * Does a 'cd' command. If the taget directory does not exist, a message is printed to <code>System.err</code>. 232 */ 233 private void cd(final String[] cmd) throws Exception { 234 final String path; 235 if (cmd.length > 1) { 236 path = cmd[1]; 237 } else { 238 path = System.getProperty("user.home"); 239 } 240 241 // Locate and validate the folder 242 final FileObject tmp = mgr.resolveFile(cwd, path); 243 if (tmp.exists()) { 244 cwd = tmp; 245 } else { 246 System.out.println("Folder does not exist: " + tmp.getName()); 247 } 248 System.out.println("Current folder is " + cwd.getName()); 249 } 250 251 /** 252 * Does an 'ls' command. 253 */ 254 private void ls(final String[] cmd) throws FileSystemException { 255 int pos = 1; 256 final boolean recursive; 257 if (cmd.length > pos && cmd[pos].equals("-R")) { 258 recursive = true; 259 pos++; 260 } else { 261 recursive = false; 262 } 263 264 final FileObject file; 265 if (cmd.length > pos) { 266 file = mgr.resolveFile(cwd, cmd[pos]); 267 } else { 268 file = cwd; 269 } 270 271 if (file.getType() == FileType.FOLDER) { 272 // List the contents 273 System.out.println("Contents of " + file.getName()); 274 listChildren(file, recursive, ""); 275 } else { 276 // Stat the file 277 System.out.println(file.getName()); 278 final FileContent content = file.getContent(); 279 System.out.println("Size: " + content.getSize() + " bytes."); 280 final DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM); 281 final String lastMod = dateFormat.format(new Date(content.getLastModifiedTime())); 282 System.out.println("Last modified: " + lastMod); 283 } 284 } 285 286 /** 287 * Does a 'touch' command. 288 */ 289 private void touch(final String[] cmd) throws Exception { 290 if (cmd.length < 2) { 291 throw new Exception("USAGE: touch <path>"); 292 } 293 final FileObject file = mgr.resolveFile(cwd, cmd[1]); 294 if (!file.exists()) { 295 file.createFile(); 296 } 297 file.getContent().setLastModifiedTime(System.currentTimeMillis()); 298 } 299 300 /** 301 * Lists the children of a folder. 302 */ 303 private void listChildren(final FileObject dir, final boolean recursive, final String prefix) 304 throws FileSystemException { 305 final FileObject[] children = dir.getChildren(); 306 for (final FileObject child : children) { 307 System.out.print(prefix); 308 System.out.print(child.getName().getBaseName()); 309 if (child.getType() == FileType.FOLDER) { 310 System.out.println("/"); 311 if (recursive) { 312 listChildren(child, recursive, prefix + " "); 313 } 314 } else { 315 System.out.println(); 316 } 317 } 318 } 319 320 /** 321 * Returns the next command, split into tokens. 322 */ 323 private String[] nextCommand() throws IOException { 324 System.out.print("> "); 325 final String line = reader.readLine(); 326 if (line == null) { 327 return null; 328 } 329 final ArrayList<String> cmd = new ArrayList<>(); 330 final StringTokenizer tokens = new StringTokenizer(line); 331 while (tokens.hasMoreTokens()) { 332 cmd.add(tokens.nextToken()); 333 } 334 return cmd.toArray(new String[cmd.size()]); 335 } 336 337 private static String getVersion(Class<?> cls) { 338 try { 339 return cls.getPackage().getImplementationVersion(); 340 } catch (Exception ignored) { 341 return "N/A"; 342 } 343 } 344}