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