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 java.io.IOException;
023 import java.util.logging.Level;
024 import java.util.logging.Logger;
025
026 abstract 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 }