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.IOException;
021import java.io.InputStreamReader;
022import java.text.DateFormat;
023import java.util.ArrayList;
024import java.util.Date;
025import java.util.StringTokenizer;
026
027import org.apache.commons.vfs2.FileContent;
028import org.apache.commons.vfs2.FileObject;
029import org.apache.commons.vfs2.FileSystemException;
030import org.apache.commons.vfs2.FileSystemManager;
031import org.apache.commons.vfs2.FileType;
032import org.apache.commons.vfs2.FileUtil;
033import org.apache.commons.vfs2.Selectors;
034import org.apache.commons.vfs2.VFS;
035
036/**
037 * A simple command-line shell for performing file operations.
038 */
039public class Shell
040{
041    private static final String SVN_ID = "$Id: Shell.html 899535 2014-02-28 16:53:18Z britter $";
042    private final FileSystemManager mgr;
043    private FileObject cwd;
044    private final BufferedReader reader;
045
046    public static void main(final String[] args)
047    {
048        try
049        {
050            new Shell().go();
051        }
052        catch (final Exception e)
053        {
054            e.printStackTrace();
055            System.exit(1);
056        }
057        System.exit(0);
058    }
059
060    private Shell() throws FileSystemException
061    {
062        mgr = VFS.getManager();
063        cwd = mgr.resolveFile(System.getProperty("user.dir"));
064        reader = new BufferedReader(new InputStreamReader(System.in));
065    }
066
067    private void go() throws Exception
068    {
069        System.out.println("VFS Shell [" + SVN_ID + "]");
070        while (true)
071        {
072            final String[] cmd = nextCommand();
073            if (cmd == null)
074            {
075                return;
076            }
077            if (cmd.length == 0)
078            {
079                continue;
080            }
081            final String cmdName = cmd[0];
082            if (cmdName.equalsIgnoreCase("exit") || cmdName.equalsIgnoreCase("quit"))
083            {
084                return;
085            }
086            try
087            {
088                handleCommand(cmd);
089            }
090            catch (final Exception e)
091            {
092                System.err.println("Command failed:");
093                e.printStackTrace(System.err);
094            }
095        }
096    }
097
098    /**
099     * Handles a command.
100     */
101    private void handleCommand(final String[] cmd) throws Exception
102    {
103        final String cmdName = cmd[0];
104        if (cmdName.equalsIgnoreCase("cat"))
105        {
106            cat(cmd);
107        }
108        else if (cmdName.equalsIgnoreCase("cd"))
109        {
110            cd(cmd);
111        }
112        else if (cmdName.equalsIgnoreCase("cp"))
113        {
114            cp(cmd);
115        }
116        else if (cmdName.equalsIgnoreCase("help"))
117        {
118            help();
119        }
120        else if (cmdName.equalsIgnoreCase("ls"))
121        {
122            ls(cmd);
123        }
124        else if (cmdName.equalsIgnoreCase("pwd"))
125        {
126            pwd();
127        }
128        else if (cmdName.equalsIgnoreCase("rm"))
129        {
130            rm(cmd);
131        }
132        else if (cmdName.equalsIgnoreCase("touch"))
133        {
134            touch(cmd);
135        }
136        else
137        {
138            System.err.println("Unknown command \"" + cmdName + "\".");
139        }
140    }
141
142    /**
143     * Does a 'help' command.
144     */
145    private void help()
146    {
147        System.out.println("Commands:");
148        System.out.println("cat <file>         Displays the contents of a file.");
149        System.out.println("cd [folder]        Changes current folder.");
150        System.out.println("cp <src> <dest>    Copies a file or folder.");
151        System.out.println("help               Shows this message.");
152        System.out.println("ls [-R] [path]     Lists contents of a file or folder.");
153        System.out.println("pwd                Displays current folder.");
154        System.out.println("rm <path>          Deletes a file or folder.");
155        System.out.println("touch <path>       Sets the last-modified time of a file.");
156        System.out.println("exit       Exits this program.");
157        System.out.println("quit       Exits this program.");
158    }
159
160    /**
161     * Does an 'rm' command.
162     */
163    private void rm(final String[] cmd) throws Exception
164    {
165        if (cmd.length < 2)
166        {
167            throw new Exception("USAGE: rm <path>");
168        }
169
170        final FileObject file = mgr.resolveFile(cwd, cmd[1]);
171        file.delete(Selectors.SELECT_SELF);
172    }
173
174    /**
175     * Does a 'cp' command.
176     */
177    private void cp(final String[] cmd) throws Exception
178    {
179        if (cmd.length < 3)
180        {
181            throw new Exception("USAGE: cp <src> <dest>");
182        }
183
184        final FileObject src = mgr.resolveFile(cwd, cmd[1]);
185        FileObject dest = mgr.resolveFile(cwd, cmd[2]);
186        if (dest.exists() && dest.getType() == FileType.FOLDER)
187        {
188            dest = dest.resolveFile(src.getName().getBaseName());
189        }
190
191        dest.copyFrom(src, Selectors.SELECT_ALL);
192    }
193
194    /**
195     * Does a 'cat' command.
196     */
197    private void cat(final String[] cmd) throws Exception
198    {
199        if (cmd.length < 2)
200        {
201            throw new Exception("USAGE: cat <path>");
202        }
203
204        // Locate the file
205        final FileObject file = mgr.resolveFile(cwd, cmd[1]);
206
207        // Dump the contents to System.out
208        FileUtil.writeContent(file, System.out);
209        System.out.println();
210    }
211
212    /**
213     * Does a 'pwd' command.
214     */
215    private void pwd()
216    {
217        System.out.println("Current folder is " + cwd.getName());
218    }
219
220    /**
221     * Does a 'cd' command.
222     * If the taget directory does not exist, a message is printed to <code>System.err</code>.
223     */
224    private void cd(final String[] cmd) throws Exception
225    {
226        final String path;
227        if (cmd.length > 1)
228        {
229            path = cmd[1];
230        }
231        else
232        {
233            path = System.getProperty("user.home");
234        }
235
236        // Locate and validate the folder
237        final FileObject tmp = mgr.resolveFile(cwd, path);
238        if (tmp.exists())
239        {
240            cwd = tmp;
241        }
242        else
243        {
244            System.out.println("Folder does not exist: " + tmp.getName());
245        }
246        System.out.println("Current folder is " + cwd.getName());
247    }
248
249    /**
250     * Does an 'ls' command.
251     */
252    private void ls(final String[] cmd) throws FileSystemException
253    {
254        int pos = 1;
255        final boolean recursive;
256        if (cmd.length > pos && cmd[pos].equals("-R"))
257        {
258            recursive = true;
259            pos++;
260        }
261        else
262        {
263            recursive = false;
264        }
265
266        final FileObject file;
267        if (cmd.length > pos)
268        {
269            file = mgr.resolveFile(cwd, cmd[pos]);
270        }
271        else
272        {
273            file = cwd;
274        }
275
276        if (file.getType() == FileType.FOLDER)
277        {
278            // List the contents
279            System.out.println("Contents of " + file.getName());
280            listChildren(file, recursive, "");
281        }
282        else
283        {
284            // Stat the file
285            System.out.println(file.getName());
286            final FileContent content = file.getContent();
287            System.out.println("Size: " + content.getSize() + " bytes.");
288            final DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
289            final String lastMod = dateFormat.format(new Date(content.getLastModifiedTime()));
290            System.out.println("Last modified: " + lastMod);
291        }
292    }
293
294    /**
295     * Does a 'touch' command.
296     */
297    private void touch(final String[] cmd) throws Exception
298    {
299        if (cmd.length < 2)
300        {
301            throw new Exception("USAGE: touch <path>");
302        }
303        final FileObject file = mgr.resolveFile(cwd, cmd[1]);
304        if (!file.exists())
305        {
306            file.createFile();
307        }
308        file.getContent().setLastModifiedTime(System.currentTimeMillis());
309    }
310
311    /**
312     * Lists the children of a folder.
313     */
314    private void listChildren(final FileObject dir,
315                              final boolean recursive,
316                              final String prefix)
317        throws FileSystemException
318    {
319        final FileObject[] children = dir.getChildren();
320        for (final FileObject child : children)
321        {
322            System.out.print(prefix);
323            System.out.print(child.getName().getBaseName());
324            if (child.getType() == FileType.FOLDER)
325            {
326                System.out.println("/");
327                if (recursive)
328                {
329                    listChildren(child, recursive, prefix + "    ");
330                }
331            }
332            else
333            {
334                System.out.println();
335            }
336        }
337    }
338
339    /**
340     * Returns the next command, split into tokens.
341     */
342    private String[] nextCommand() throws IOException
343    {
344        System.out.print("> ");
345        final String line = reader.readLine();
346        if (line == null)
347        {
348            return null;
349        }
350        final ArrayList<String> cmd = new ArrayList<String>();
351        final StringTokenizer tokens = new StringTokenizer(line);
352        while (tokens.hasMoreTokens())
353        {
354            cmd.add(tokens.nextToken());
355        }
356        return cmd.toArray(new String[cmd.size()]);
357    }
358}