001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (license2)
004: * Initial Developer: H2 Group
005: */
006: package org.h2.test.unit;
007:
008: import java.io.BufferedReader;
009: import java.io.ByteArrayOutputStream;
010: import java.io.IOException;
011: import java.io.InputStream;
012: import java.io.InputStreamReader;
013: import java.io.OutputStream;
014: import java.io.OutputStreamWriter;
015: import java.io.PrintWriter;
016: import java.net.InetAddress;
017: import java.net.Socket;
018: import java.sql.SQLException;
019:
020: import org.h2.engine.Constants;
021: import org.h2.util.IOUtils;
022: import org.h2.util.NetUtils;
023: import org.h2.util.StringUtils;
024:
025: /**
026: * A simple standalone FTP client.
027: */
028: public class FtpClient {
029: private Socket socket;
030: private BufferedReader reader;
031: private PrintWriter writer;
032: private int code;
033: private String message;
034: private Socket socketData;
035: private InputStream inData;
036: private OutputStream outData;
037:
038: public static FtpClient open(String url) throws SQLException,
039: IOException {
040: FtpClient client = new FtpClient();
041: client.connect(url);
042: return client;
043: }
044:
045: private FtpClient() {
046: }
047:
048: private void connect(String url) throws SQLException, IOException {
049: socket = NetUtils.createSocket(url, 21, false);
050: InputStream in = socket.getInputStream();
051: OutputStream out = socket.getOutputStream();
052: reader = new BufferedReader(new InputStreamReader(in));
053: writer = new PrintWriter(new OutputStreamWriter(out,
054: Constants.UTF8));
055: readCode(220);
056: }
057:
058: private void readLine() throws IOException {
059: message = reader.readLine();
060: int idx = message.indexOf(' ');
061: if (idx < 0) {
062: code = 0;
063: } else {
064: code = Integer.parseInt(message.substring(0, idx));
065: message = message.substring(idx + 1);
066: }
067: }
068:
069: private void readCode(int expected) throws IOException {
070: readLine();
071: if (code != expected) {
072: throw new IOException("Expected: " + expected + " got: "
073: + message);
074: }
075: }
076:
077: private void send(String command) throws IOException {
078: writer.println(command);
079: writer.flush();
080: }
081:
082: public void login(String userName, String password)
083: throws IOException {
084: send("USER " + userName);
085: readCode(331);
086: send("PASS " + password);
087: readCode(230);
088: send("SYST");
089: readCode(215);
090: send("SITE");
091: readCode(500);
092: send("STRU F");
093: readCode(200);
094: send("TYPE I");
095: readCode(200);
096: }
097:
098: public void close() throws IOException {
099: if (socket != null) {
100: send("QUIT");
101: readCode(221);
102: socket.close();
103: }
104: }
105:
106: public void changeWorkingDirectory(String dir) throws IOException {
107: send("CWD " + dir);
108: readCode(250);
109: }
110:
111: public void changeDirectoryUp() throws IOException {
112: send("CDUP");
113: readCode(250);
114: }
115:
116: public void delete(String fileName) throws IOException {
117: send("DELE " + fileName);
118: readCode(250);
119: }
120:
121: public void makeDirectory(String dir) throws IOException {
122: send("MKD " + dir);
123: readCode(257);
124: }
125:
126: public void mode(String mode) throws IOException {
127: send("MODE " + mode);
128: readCode(200);
129: }
130:
131: public void modificationTime(String fileName) throws IOException {
132: send("MDTM " + fileName);
133:
134: readCode(213);
135: }
136:
137: public void noOperation() throws IOException {
138: send("NOOP");
139: readCode(200);
140: }
141:
142: public String printWorkingDirectory() throws IOException {
143: send("PWD");
144: readCode(257);
145: return removeQuotes();
146: }
147:
148: private String removeQuotes() {
149: int first = message.indexOf('"') + 1;
150: int last = message.lastIndexOf('"');
151: StringBuffer buff = new StringBuffer();
152: for (int i = first; i < last; i++) {
153: char ch = message.charAt(i);
154: buff.append(ch);
155: if (ch == '\"') {
156: i++;
157: }
158: }
159: return buff.toString();
160: }
161:
162: private void passive() throws IOException, SQLException {
163: send("PASV");
164: readCode(227);
165: int first = message.indexOf('(') + 1;
166: int last = message.indexOf(')');
167: String[] address = StringUtils.arraySplit(message.substring(
168: first, last), ',', true);
169: StringBuffer buff = new StringBuffer();
170: for (int i = 0; i < 4; i++) {
171: if (i > 0) {
172: buff.append('.');
173: }
174: buff.append(address[i]);
175: }
176: String ip = buff.toString();
177: InetAddress addr = InetAddress.getByName(ip);
178: int port = (Integer.parseInt(address[4]) << 8)
179: | Integer.parseInt(address[5]);
180: socketData = NetUtils.createSocket(addr, port, false);
181: inData = socketData.getInputStream();
182: outData = socketData.getOutputStream();
183: }
184:
185: public void rename(String fromFileName, String toFileName)
186: throws IOException {
187: send("RNFR " + fromFileName);
188: readCode(350);
189: send("RNTO " + toFileName);
190: readCode(250);
191: }
192:
193: public void retrieve(String fileName, OutputStream out,
194: long restartAt) throws IOException, SQLException {
195: passive();
196: if (restartAt > 0) {
197: send("REST " + restartAt);
198: readCode(350);
199: }
200: send("RETR " + fileName);
201: IOUtils.copyAndClose(inData, out);
202: readCode(226);
203: }
204:
205: public void removeDirectory(String dir) throws IOException {
206: send("RMD " + dir);
207: readCode(250);
208: }
209:
210: public long size(String fileName) throws IOException {
211: send("SIZE " + fileName);
212: readCode(250);
213: long size = Long.parseLong(message);
214: return size;
215: }
216:
217: public void store(String fileName, InputStream in)
218: throws IOException, SQLException {
219: passive();
220: send("STOR " + fileName);
221: readCode(150);
222: IOUtils.copyAndClose(in, outData);
223: readCode(226);
224: }
225:
226: public String nameList(String dir) throws IOException, SQLException {
227: passive();
228: send("NLST " + dir);
229: readCode(150);
230: ByteArrayOutputStream out = new ByteArrayOutputStream();
231: IOUtils.copyAndClose(inData, out);
232: readCode(226);
233: byte[] data = out.toByteArray();
234: return new String(data);
235: }
236:
237: public String list(String dir) throws IOException, SQLException {
238: passive();
239: send("LIST " + dir);
240: readCode(150);
241: ByteArrayOutputStream out = new ByteArrayOutputStream();
242: IOUtils.copyAndClose(inData, out);
243: readCode(226);
244: byte[] data = out.toByteArray();
245: return new String(data);
246: }
247:
248: }
|