001/*
002 * Copyright (C) 2012 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
020package org.crsh.jcr;
021
022import java.io.IOException;
023import java.util.logging.Level;
024import java.util.logging.Logger;
025
026abstract class FileSystemAction {
027
028  /** . */
029  private static final Logger log = Logger.getLogger(FileSystemAction.class.getName());
030
031  public static void read(SCPCommand cmd, FileSystem fs) throws IOException {
032    cmd.ack();
033    log.log(Level.FINE, "Want to read line");
034    String line = cmd.readLine();
035    log.log(Level.FINE, "Read line " + line);
036    FileSystemAction action = decode(line);
037    log.log(Level.FINE, "Action: " + action);
038    read(cmd, action, fs);
039  }
040
041  private static void read(final SCPCommand cmd, FileSystemAction action, FileSystem fs) throws IOException {
042    if (action instanceof StartDirectory) {
043      String directoryName = ((StartDirectory)action).name;
044      fs.beginDirectory(directoryName);
045
046      //
047      cmd.ack();
048
049      //
050      while (true) {
051        String nextLine = cmd.readLine();
052        FileSystemAction nextAction = decode(nextLine);
053        log.log(Level.FINE, "Next action: " + nextAction);
054        if (nextAction instanceof FileSystemAction.EndDirectory) {
055          fs.endDirectory(directoryName);
056          break;
057        } else {
058          read(cmd, nextAction, fs);
059        }
060      }
061
062      //
063      cmd.ack();
064    } else if (action instanceof File) {
065      File file = (File)action;
066
067      //
068      cmd.ack();
069
070      //
071      fs.file(file.name, file.length, cmd.read(file.length));
072
073      //
074      log.log(Level.FINE, "About to send ack for file");
075      cmd.ack();
076      cmd.readAck();
077    }
078  }
079
080  private static FileSystemAction decode(String line) {
081    if (line == null) {
082      throw new NullPointerException();
083    }
084    if (line.length() == 0) {
085      throw new IllegalArgumentException("Line has length zero");
086    }
087    char t = line.charAt(0);
088    if (t == 'C' || t == 'D') {
089
090      //
091      int length;
092      int endLength = line.indexOf(' ', 6);
093      if (endLength == -1) {
094        throw new IllegalArgumentException();
095      } else {
096        String s = line.substring(6, endLength);
097        if (s.length() == 1 && s.charAt(0) == '0') {
098          // Optimize for directories
099          length = 0;
100        } else {
101          try {
102            length = Integer.parseInt(s);
103          }
104          catch (NumberFormatException e) {
105            throw new IllegalArgumentException("Could not parse file length " + s);
106          }
107        }
108      }
109
110      //
111      String name = line.substring(endLength + 1);
112
113      //
114      if (t == 'D') {
115        return new StartDirectory(name);
116      } else {
117        return new File(name, length);
118      }
119    } else if (t == 'E') {
120      return new EndDirectory();
121    } else {
122      throw new IllegalArgumentException("Could not recognize file system action " + line);
123    }
124  }
125
126  private static class StartDirectory extends FileSystemAction {
127
128    /** . */
129    private final String name;
130
131    private StartDirectory(String name) {
132      this.name = name;
133    }
134
135    @Override
136    public String toString() {
137      return "StartDirectory[name=" + name + "]";
138    }
139  }
140
141  private static class File extends FileSystemAction {
142
143    /** . */
144    private final String name;
145
146    /** . */
147    private final int length;
148
149    private File(String name, int length) {
150      this.name = name;
151      this.length = length;
152    }
153
154    @Override
155    public String toString() {
156      return "File[name=" + name + ",length=" + length + "]";
157    }
158  }
159
160  private static class EndDirectory extends FileSystemAction {
161    private EndDirectory() {
162    }
163
164    @Override
165    public String toString() {
166      return "EndDirectory[]";
167    }
168  }
169}