001    /*
002     * Copyright (C) 2003-2009 eXo Platform SAS.
003     *
004     * This is free software; you can redistribute it and/or modify it
005     * under the terms of the GNU Lesser General Public License as
006     * published by the Free Software Foundation; either version 2.1 of
007     * the License, or (at your option) any later version.
008     *
009     * This software is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012     * Lesser General Public License for more details.
013     *
014     * You should have received a copy of the GNU Lesser General Public
015     * License along with this software; if not, write to the Free
016     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018     */
019    
020    package org.crsh.jcr;
021    
022    import org.slf4j.Logger;
023    import org.slf4j.LoggerFactory;
024    
025    import java.io.IOException;
026    
027    /**
028     * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
029     * @version $Revision$
030     */
031    abstract class FileSystemAction {
032    
033      /** . */
034      private static final Logger log = LoggerFactory.getLogger(FileSystemAction.class);
035    
036      public static void read(SCPCommand cmd, FileSystem fs) throws IOException {
037        cmd.ack();
038        log.debug("Want to read line");
039        String line = cmd.readLine();
040        log.debug("Read line " + line);
041        FileSystemAction action = decode(line);
042        log.debug("Action: " + action);
043        read(cmd, action, fs);
044      }
045    
046      private static void read(final SCPCommand cmd, FileSystemAction action, FileSystem fs) throws IOException {
047        if (action instanceof StartDirectory) {
048          String directoryName = ((StartDirectory)action).name;
049          fs.startDirectory(directoryName);
050    
051          //
052          cmd.ack();
053    
054          //
055          while (true) {
056            String nextLine = cmd.readLine();
057            FileSystemAction nextAction = decode(nextLine);
058            log.debug("Next action: " + nextAction);
059            if (nextAction instanceof FileSystemAction.EndDirectory) {
060              fs.endDirectory(directoryName);
061              break;
062            } else {
063              read(cmd, nextAction, fs);
064            }
065          }
066    
067          //
068          cmd.ack();
069        } else if (action instanceof File) {
070          File file = (File)action;
071    
072          //
073          cmd.ack();
074    
075          //
076          fs.file(file.name, file.length, cmd.read(file.length));
077    
078          //
079          log.debug("About to send ack for file");
080          cmd.ack();
081          cmd.readAck();
082        }
083      }
084    
085      private static FileSystemAction decode(String line) {
086        if (line == null) {
087          throw new NullPointerException();
088        }
089        if (line.length() == 0) {
090          throw new IllegalArgumentException("Line has length zero");
091        }
092        char t = line.charAt(0);
093        if (t == 'C' || t == 'D') {
094    
095          //
096          int length;
097          int endLength = line.indexOf(' ', 6);
098          if (endLength == -1) {
099            throw new IllegalArgumentException();
100          } else {
101            String s = line.substring(6, endLength);
102            if (s.length() == 1 && s.charAt(0) == '0') {
103              // Optimize for directories
104              length = 0;
105            } else {
106              try {
107                length = Integer.parseInt(s);
108              }
109              catch (NumberFormatException e) {
110                throw new IllegalArgumentException("Could not parse file length " + s);
111              }
112            }
113          }
114    
115          //
116          String name = line.substring(endLength + 1);
117    
118          //
119          if (t == 'D') {
120            return new StartDirectory(name);
121          } else {
122            return new File(name, length);
123          }
124        } else if (t == 'E') {
125          return new EndDirectory();
126        } else {
127          throw new IllegalArgumentException("Could not recognize file system action " + line);
128        }
129      }
130    
131      private static class StartDirectory extends FileSystemAction {
132    
133        /** . */
134        private final String name;
135    
136        private StartDirectory(String name) {
137          this.name = name;
138        }
139    
140        @Override
141        public String toString() {
142          return "StartDirectory[name=" + name + "]";
143        }
144      }
145    
146      private static class File extends FileSystemAction {
147    
148        /** . */
149        private final String name;
150    
151        /** . */
152        private final int length;
153    
154        private File(String name, int length) {
155          this.name = name;
156          this.length = length;
157        }
158    
159        @Override
160        public String toString() {
161          return "File[name=" + name + ",length=" + length + "]";
162        }
163      }
164    
165      private static class EndDirectory extends FileSystemAction {
166        private EndDirectory() {
167        }
168    
169        @Override
170        public String toString() {
171          return "EndDirectory[]";
172        }
173      }
174    }