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.functions;
020:
021: import java.io.BufferedReader;
022: import java.io.FileNotFoundException;
023: import java.io.FileReader;
024: import java.io.IOException;
025: import java.util.ArrayList;
026: import java.util.StringTokenizer;
027:
028: import org.apache.jmeter.util.JMeterUtils;
029: import org.apache.jorphan.logging.LoggingManager;
030: import org.apache.log.Logger;
031:
032: /**
033: * File data container for CSV (and similar delimited) files Data is accessible
034: * via row and column number
035: *
036: * @version $Revision: 493781 $
037: */
038: public class FileRowColContainer {
039:
040: private static final Logger log = LoggingManager
041: .getLoggerForClass();
042:
043: private ArrayList fileData; // Lines in the file, split into columns
044:
045: private String fileName; // name of the file
046:
047: public static final String DELIMITER = JMeterUtils.getPropDefault(
048: "csvread.delimiter", // $NON-NLS-1$
049: ","); // $NON-NLS-1$
050:
051: /** Keeping track of which row is next to be read. */
052: private int nextRow;
053:
054: /** Delimiter for this file */
055: private String delimiter;
056:
057: private FileRowColContainer()// Not intended to be called directly
058: {
059: }
060:
061: public FileRowColContainer(String file, String delim)
062: throws IOException, FileNotFoundException {
063: log.debug("FRCC(" + file + "," + delim + ")");
064: fileName = file;
065: delimiter = delim;
066: nextRow = 0;
067: load();
068: }
069:
070: public FileRowColContainer(String file) throws IOException,
071: FileNotFoundException {
072: log.debug("FRCC(" + file + ")[" + DELIMITER + "]");
073: fileName = file;
074: delimiter = DELIMITER;
075: nextRow = 0;
076: load();
077: }
078:
079: private void load() throws IOException, FileNotFoundException {
080: fileData = new ArrayList();
081:
082: BufferedReader myBread = null;
083: try {
084: FileReader fis = new FileReader(fileName);
085: myBread = new BufferedReader(fis);
086: String line = myBread.readLine();
087: /*
088: * N.B. Stop reading the file if we get a blank line: This allows
089: * for trailing comments in the file
090: */
091: while (line != null && line.length() > 0) {
092: fileData.add(splitLine(line, delimiter));
093: line = myBread.readLine();
094: }
095: } catch (FileNotFoundException e) {
096: fileData = null;
097: log.warn(e.toString());
098: throw e;
099: } catch (IOException e) {
100: fileData = null;
101: log.warn(e.toString());
102: throw e;
103: } finally {
104: if (myBread != null)
105: myBread.close();
106: }
107: }
108:
109: /**
110: * Get the string for the column from the current row
111: *
112: * @param row
113: * row number (from 0)
114: * @param col
115: * column number (from 0)
116: * @return the string (empty if out of bounds)
117: * @throws IndexOutOfBoundsException
118: * if the column number is out of bounds
119: */
120: public String getColumn(int row, int col)
121: throws IndexOutOfBoundsException {
122: String colData;
123: colData = (String) ((ArrayList) fileData.get(row)).get(col);
124: log.debug(fileName + "(" + row + "," + col + "): " + colData);
125: return colData;
126: }
127:
128: /**
129: * Returns the next row to the caller, and updates it, allowing for wrap
130: * round
131: *
132: * @return the first free (unread) row
133: *
134: */
135: public int nextRow() {
136: int row = nextRow;
137: nextRow++;
138: if (nextRow >= fileData.size())// 0-based
139: {
140: nextRow = 0;
141: }
142: log.debug("Row: " + row);
143: return row;
144: }
145:
146: /**
147: * Splits the line according to the specified delimiter
148: *
149: * @return an ArrayList of Strings containing one element for each value in
150: * the line
151: */
152: private static ArrayList splitLine(String theLine, String delim) {
153: ArrayList result = new ArrayList();
154: StringTokenizer tokener = new StringTokenizer(theLine, delim,
155: true);
156: /*
157: * the beginning of the line is a "delimiter" so that ,a,b,c returns ""
158: * "a" "b" "c"
159: */
160: boolean lastWasDelim = true;
161: while (tokener.hasMoreTokens()) {
162: String token = tokener.nextToken();
163: if (token.equals(delim)) {
164: if (lastWasDelim) {
165: // two delimiters in a row; add an empty String
166: result.add("");
167: }
168: lastWasDelim = true;
169: } else {
170: lastWasDelim = false;
171: result.add(token);
172: }
173: }
174: if (lastWasDelim) // Catch the trailing delimiter
175: {
176: result.add(""); // $NON-NLS-1$
177: }
178: return result;
179: }
180:
181: /**
182: * @return the file name for this class
183: */
184: public String getFileName() {
185: return fileName;
186: }
187:
188: /**
189: * @return Returns the delimiter.
190: */
191: final String getDelimiter() {
192: return delimiter;
193: }
194:
195: // Added to support external testing
196: public int getSize() {
197: return fileData.size();
198: }
199: }
|