001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.jmeter.protocol.ftp.sampler;
020:
021: import java.io.ByteArrayOutputStream;
022: import java.io.File;
023: import java.io.FileInputStream;
024: import java.io.FileOutputStream;
025: import java.io.IOException;
026: import java.io.InputStream;
027: import java.io.OutputStream;
028:
029: import org.apache.commons.io.IOUtils;
030: import org.apache.commons.io.output.NullOutputStream;
031: import org.apache.commons.io.output.TeeOutputStream;
032: import org.apache.commons.net.ftp.FTP;
033: import org.apache.commons.net.ftp.FTPClient;
034: import org.apache.commons.net.ftp.FTPReply;
035: import org.apache.jmeter.config.ConfigTestElement;
036: import org.apache.jmeter.samplers.AbstractSampler;
037: import org.apache.jmeter.samplers.Entry;
038: import org.apache.jmeter.samplers.SampleResult;
039:
040: /**
041: * A sampler which understands FTP file requests.
042: *
043: */
044: public class FTPSampler extends AbstractSampler {
045: public final static String SERVER = "FTPSampler.server"; // $NON-NLS-1$
046:
047: // N.B. Originally there was only one filename, and only get(RETR) was supported
048: // To maintain backwards compatibility, the property name needs to remain the same
049: public final static String REMOTE_FILENAME = "FTPSampler.filename"; // $NON-NLS-1$
050:
051: public final static String LOCAL_FILENAME = "FTPSampler.localfilename"; // $NON-NLS-1$
052:
053: // Use binary mode file transfer?
054: public final static String BINARY_MODE = "FTPSampler.binarymode"; // $NON-NLS-1$
055:
056: // Are we uploading?
057: public final static String UPLOAD_FILE = "FTPSampler.upload"; // $NON-NLS-1$
058:
059: // Should the file data be saved in the response?
060: public final static String SAVE_RESPONSE = "FTPSampler.saveresponse"; // $NON-NLS-1$
061:
062: public FTPSampler() {
063: }
064:
065: public String getUsername() {
066: return getPropertyAsString(ConfigTestElement.USERNAME);
067: }
068:
069: public String getPassword() {
070: return getPropertyAsString(ConfigTestElement.PASSWORD);
071: }
072:
073: public void setServer(String newServer) {
074: this .setProperty(SERVER, newServer);
075: }
076:
077: public String getServer() {
078: return getPropertyAsString(SERVER);
079: }
080:
081: public String getRemoteFilename() {
082: return getPropertyAsString(REMOTE_FILENAME);
083: }
084:
085: public String getLocalFilename() {
086: return getPropertyAsString(LOCAL_FILENAME);
087: }
088:
089: public boolean isBinaryMode() {
090: return getPropertyAsBoolean(BINARY_MODE, false);
091: }
092:
093: public boolean isSaveResponse() {
094: return getPropertyAsBoolean(SAVE_RESPONSE, false);
095: }
096:
097: public boolean isUpload() {
098: return getPropertyAsBoolean(UPLOAD_FILE, false);
099: }
100:
101: /**
102: * Returns a formatted string label describing this sampler Example output:
103: * ftp://ftp.nowhere.com/pub/README.txt
104: *
105: * @return a formatted string label describing this sampler
106: */
107: public String getLabel() {
108: return ("ftp://" + getServer() + "/" + getRemoteFilename() // $NON-NLS-1$ $NON-NLS-2$
109: + (isBinaryMode() ? " (Binary) " : " (Ascii) ") // $NON-NLS-1$ $NON-NLS-2$
110: + (isUpload() ? " <- " : " -> ") // $NON-NLS-1$ $NON-NLS-2$
111: + getLocalFilename());
112: }
113:
114: public SampleResult sample(Entry e) {
115: SampleResult res = new SampleResult();
116: res.setSuccessful(false);
117: String remote = getRemoteFilename();
118: String local = getLocalFilename();
119: boolean binaryTransfer = isBinaryMode();
120: res.setSampleLabel(getName());
121: res.setSamplerData(getLabel());
122: InputStream input = null;
123: OutputStream output = null;
124:
125: res.sampleStart();
126: FTPClient ftp = new FTPClient();
127: try {
128: ftp.connect(getServer());
129: int reply = ftp.getReplyCode();
130: if (FTPReply.isPositiveCompletion(reply)) {
131: if (ftp.login(getUsername(), getPassword())) {
132: if (binaryTransfer) {
133: ftp.setFileType(FTP.BINARY_FILE_TYPE);
134: }
135: ftp.enterLocalPassiveMode();// should probably come from the setup dialog
136: boolean ftpOK = false;
137: if (isUpload()) {
138: File infile = new File(local);
139: input = new FileInputStream(infile);
140: ftpOK = ftp.storeFile(remote, input);
141: res.setBytes((int) infile.length());
142: } else {
143: final boolean saveResponse = isSaveResponse();
144: ByteArrayOutputStream baos = null; // No need to close this
145: OutputStream target = null; // No need to close this
146: if (saveResponse) {
147: baos = new ByteArrayOutputStream();
148: target = baos;
149: }
150: if (local.length() > 0) {
151: output = new FileOutputStream(local);
152: if (target == null) {
153: target = output;
154: } else {
155: target = new TeeOutputStream(output,
156: baos);
157: }
158: }
159: if (target == null) {
160: target = new NullOutputStream();
161: }
162: input = ftp.retrieveFileStream(remote);
163: long bytes = IOUtils.copy(input, target);
164: ftpOK = bytes > 0;
165: if (saveResponse) {
166: res.setResponseData(baos.toByteArray());
167: if (!binaryTransfer) {
168: res.setDataType(SampleResult.TEXT);
169: }
170: } else {
171: res.setBytes((int) bytes);
172: }
173: }
174:
175: if (ftpOK) {
176: res.setResponseCodeOK();
177: res.setResponseMessageOK();
178: res.setSuccessful(true);
179: } else {
180: res.setResponseCode(Integer.toString(ftp
181: .getReplyCode()));
182: res.setResponseMessage(ftp.getReplyString());
183: }
184: } else {
185: res.setResponseCode(Integer.toString(ftp
186: .getReplyCode()));
187: res.setResponseMessage(ftp.getReplyString());
188: }
189: } else {
190: res.setResponseCode("501"); // TODO
191: res.setResponseMessage("Could not connect");
192: //res.setResponseCode(Integer.toString(ftp.getReplyCode()));
193: res.setResponseMessage(ftp.getReplyString());
194: }
195: } catch (IOException ex) {
196: res.setResponseCode("000"); // TODO
197: res.setResponseMessage(ex.toString());
198: } finally {
199: if (ftp != null && ftp.isConnected()) {
200: try {
201: ftp.disconnect();
202: } catch (IOException ignored) {
203: }
204: }
205: IOUtils.closeQuietly(input);
206: IOUtils.closeQuietly(output);
207: }
208:
209: res.sampleEnd();
210: return res;
211: }
212: }
|