001: /*
002: * This file is part of DrFTPD, Distributed FTP Daemon.
003: *
004: * DrFTPD is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU General Public License as published by
006: * the Free Software Foundation; either version 2 of the License, or
007: * (at your option) any later version.
008: *
009: * DrFTPD 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
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with DrFTPD; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018: package org.drftpd.remotefile;
019:
020: import net.sf.drftpd.master.config.ConfigInterface;
021: import org.apache.log4j.Logger;
022: import org.drftpd.Checksum;
023: import org.drftpd.master.ConnectionManager;
024: import org.drftpd.master.RemoteSlave;
025: import org.drftpd.remotefile.LinkedRemoteFile.NonExistingFile;
026:
027: import java.io.FileReader;
028: import java.io.IOException;
029: import java.io.LineNumberReader;
030: import java.io.OutputStream;
031: import java.io.PrintWriter;
032: import java.io.Reader;
033: import java.io.Writer;
034:
035: import java.text.ParseException;
036: import java.text.SimpleDateFormat;
037:
038: import java.util.ArrayList;
039: import java.util.Date;
040: import java.util.Hashtable;
041: import java.util.Iterator;
042: import java.util.List;
043: import java.util.StringTokenizer;
044:
045: /**
046: * @author mog
047: * @version $Id: MLSTSerialize.java 1513 2006-10-13 22:41:08Z tdsoul $
048: */
049: public class MLSTSerialize {
050: private static final Logger logger = Logger
051: .getLogger(MLSTSerialize.class);
052: public static final SimpleDateFormat timeval = new SimpleDateFormat(
053: "yyyyMMddHHmmss.SSS");
054:
055: public static void serialize(LinkedRemoteFileInterface dir,
056: PrintWriter out) {
057: out.println(dir.getPath() + ":");
058:
059: for (Iterator iter = dir.getMap().values().iterator(); iter
060: .hasNext();) {
061: LinkedRemoteFile file = (LinkedRemoteFile) iter.next();
062: out.println(toMLST(file));
063: }
064:
065: out.println();
066:
067: //Iterator iter = dir.getFiles().iterator();
068: for (Iterator iter = dir.getMap().values().iterator(); iter
069: .hasNext();) {
070: LinkedRemoteFileInterface file = (LinkedRemoteFileInterface) iter
071: .next();
072:
073: if (file.isDirectory() && !file.isLink()) {
074: serialize(file, out);
075: }
076: }
077: }
078:
079: public static String toMLST(RemoteFileInterface file) {
080: StringBuffer ret = new StringBuffer();
081:
082: if (file.isLink()) {
083: ret
084: .append("type=OS.unix=slink:" + file.getLinkPath()
085: + ";");
086: } else if (file.isFile()) {
087: ret.append("type=file;");
088: } else if (file.isDirectory()) {
089: ret.append("type=dir;");
090: } else {
091: throw new RuntimeException("type");
092: }
093:
094: if (file.getCheckSumCached() != 0) {
095: ret.append("x.crc32="
096: + Checksum.formatChecksum(file.getCheckSumCached())
097: + ";");
098: }
099:
100: ret.append("size=" + file.length() + ";");
101: ret.append("modify="
102: + timeval.format(new Date(file.lastModified())) + ";");
103:
104: ret.append("unix.owner=" + file.getUsername() + ";");
105: ret.append("unix.group=" + file.getGroupname() + ";");
106:
107: if (file.isFile()) {
108: Iterator iter = file.getSlaves().iterator();
109: ret.append("x.slaves=");
110:
111: if (iter.hasNext()) {
112: ret.append(((RemoteSlave) iter.next()).getName());
113:
114: while (iter.hasNext()) {
115: ret.append(","
116: + ((RemoteSlave) iter.next()).getName());
117: }
118: }
119:
120: ret.append(";");
121: }
122:
123: if (file.getXfertime() != 0) {
124: ret.append("x.xfertime=" + file.getXfertime() + ";");
125: }
126:
127: ret.append(" " + file.getName());
128:
129: return ret.toString();
130: }
131:
132: private static void unserialize(LineNumberReader in,
133: LinkedRemoteFileInterface dir, Hashtable allRslaves,
134: String path) throws IOException {
135: for (String line = in.readLine();; line = in.readLine()) {
136: boolean isFile = false;
137: boolean isDir = false;
138:
139: if (line == null) {
140: throw new CorruptFileListException("Unexpected EOF");
141: }
142:
143: if (line.equals("")) {
144: return;
145: }
146:
147: int pos = line.indexOf(' ');
148:
149: if (pos == -1) {
150: throw new CorruptFileListException("\"" + line
151: + "\" is invalid");
152: }
153:
154: String filename = line.substring(pos + 1);
155: StaticRemoteFile file = new StaticRemoteFile(filename);
156: StringTokenizer st = new StringTokenizer(line.substring(0,
157: pos), ";");
158:
159: while (st.hasMoreElements()) {
160: String entry = st.nextToken();
161: pos = entry.indexOf('=');
162:
163: if (pos == -1) {
164: throw new CorruptFileListException("\"" + entry
165: + " is corrupt, line " + in.getLineNumber());
166: }
167:
168: String k = entry.substring(0, pos);
169: String v = entry.substring(pos + 1);
170:
171: if ("type".equals(k)) {
172: //assert v.equals("file") || v.equals("dir") : v;
173: if (v.startsWith("unix.slink:")) {
174: // kept here for conversion of old files.mlst
175: file.setLink(v
176: .substring("unix.slink:".length()));
177: isDir = true;
178: } else if (v.startsWith("OS.unix=slink:")) {
179: file.setLink(v.substring("OS.unix=slink:"
180: .length()));
181: isDir = true;
182: } else {
183: isFile = "file".equals(v);
184: isDir = "dir".equals(v);
185:
186: if (!(isFile || isDir)) {
187: throw new RuntimeException(
188: "!(isFile || isDir)");
189: }
190: }
191: } else if ("modify".equals(k)) {
192: try {
193: file
194: .setLastModified(timeval.parse(v)
195: .getTime());
196: } catch (ParseException e) {
197: throw new CorruptFileListException(e);
198: }
199: } else if ("x.crc32".equals(k)) {
200: file.setCheckSum(Long.parseLong(v, 16));
201: } else if ("unix.owner".equals(k)) {
202: file.setUsername(v);
203: } else if ("unix.group".equals(k)) {
204: file.setGroupname(v);
205:
206: // } else if ("x.deleted".equals(k)) {
207: // if (file.isLink()) {
208: // isFile = true;
209: // }
210: //
211: // file.setDeleted(true);
212: } else if ("size".equals(k)) {
213: file.setLength(Long.parseLong(v));
214: } else if ("x.slaves".equals(k)) {
215: if (file.isLink() && isFile) {
216: isFile = true;
217: isDir = false;
218: }
219:
220: ArrayList<RemoteSlave> rslaves = new ArrayList<RemoteSlave>();
221: StringTokenizer st2 = new StringTokenizer(v, ",");
222:
223: while (st2.hasMoreTokens()) {
224: String slavename = st2.nextToken();
225: RemoteSlave rslave = (RemoteSlave) allRslaves
226: .get(slavename);
227:
228: if (rslave == null) {
229: continue;
230: }
231: rslaves.add(rslave);
232: }
233:
234: file.setRSlaves(rslaves);
235: } else if ("x.xfertime".equals(k)) {
236: file.setXfertime(Long.parseLong(v));
237: }
238: }
239:
240: //if(isFile && !file.isFile()) file.setRSlaves(Collections.EMPTY_LIST);
241: if ((isFile != file.isFile())
242: && (isDir != file.isDirectory())) {
243: throw new CorruptFileListException(
244: "entry is a file but had no x.slaves entry: "
245: + line);
246: }
247:
248: try {
249: dir.putFile(file);
250: } catch (IllegalStateException e) {
251: logger.warn("", e);
252: }
253: }
254: }
255:
256: public static LinkedRemoteFile unserialize(ConfigInterface conf,
257: Reader in, List rslaves) throws IOException,
258: CorruptFileListException {
259: LinkedRemoteFile root = new LinkedRemoteFile(conf);
260:
261: LineNumberReader in2 = new LineNumberReader(in);
262:
263: for (String line = in2.readLine(); line != null; line = in2
264: .readLine()) {
265: if (!line.endsWith(":")) {
266: throw new CorruptFileListException(
267: "expecting path, not \"" + line + "\" line "
268: + in2.getLineNumber());
269: }
270:
271: String path = line.substring(0, line.length() - 1);
272: NonExistingFile ret = root.lookupNonExistingFile(path);
273: LinkedRemoteFileInterface dir;
274: dir = ret.getFile();
275:
276: if (!ret.exists()) {
277: throw new CorruptFileListException(path
278: + " doesn't exist");
279: }
280:
281: unserialize(in2, dir, RemoteSlave
282: .rslavesToHashtable(rslaves), path);
283: }
284:
285: return root;
286: }
287:
288: public static LinkedRemoteFile loadMLSTFileDatabase(List rslaves,
289: ConnectionManager cm) throws IOException {
290: FileReader fr = null;
291: try {
292: fr = new FileReader("files.mlst");
293: return MLSTSerialize
294: .unserialize((cm != null) ? cm.getGlobalContext()
295: .getConfig() : null, fr, rslaves);
296: } finally {
297: if (fr != null) {
298: fr.close();
299: }
300: }
301: }
302: }
|