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.FileNotFoundException;
022: import java.io.IOException;
023: import java.util.HashMap;
024: import java.util.Iterator;
025: import java.util.Map;
026:
027: import org.apache.jorphan.logging.LoggingManager;
028: import org.apache.log.Logger;
029:
030: /**
031: * This class wraps the FileRowColContainer for use across multiple threads.
032: *
033: * It does this by maintaining a list of open files, keyed by file name (or
034: * alias, if used). A list of open files is also maintained for each thread,
035: * together with the current line number.
036: *
037: * @version $Revision: 493781 $ $Date: 2007-01-07 17:52:05 +0000 (Sun, 07 Jan 2007) $
038: */
039: public class FileWrapper {
040:
041: private static final Logger log = LoggingManager
042: .getLoggerForClass();
043:
044: private FileRowColContainer container;
045:
046: private int currentRow;
047:
048: private static final int NO_LINE = -1;
049:
050: private static String defaultFile = ""; // for omitted file names //$NON-NLS-1$
051:
052: /*
053: * This Map serves two purposes:
054: * - maps file names to containers
055: * - ensures only one container per file across all threads
056: */
057: private static Map fileContainers = new HashMap();
058:
059: /*
060: * Only needed locally
061: */
062: private FileWrapper(FileRowColContainer fdc) {
063: super ();
064: container = fdc;
065: currentRow = -1;
066: }
067:
068: /* The cache of file packs - used to improve thread access */
069: private static ThreadLocal filePacks = new ThreadLocal() {
070: protected Object initialValue() {
071: return new HashMap();
072: }
073: };
074:
075: private static String checkDefault(String file) {
076: if (file.length() == 0) {
077: if (fileContainers.size() == 1 && defaultFile.length() > 0) {
078: log.warn("Using default: " + defaultFile);
079: file = defaultFile;
080: } else {
081: log.error("Cannot determine default file name");
082: }
083: }
084: return file;
085: }
086:
087: /*
088: * called by CSVRead(file,alias)
089: */
090: public static synchronized void open(String file, String alias) {
091: log.info("Opening " + file + " as " + alias);
092: file = checkDefault(file);
093: if (alias.length() == 0) {
094: log.error("Alias cannot be empty");
095: return;
096: }
097: Map m = (Map) filePacks.get();
098: if (m.get(alias) == null) {
099: FileRowColContainer frcc;
100: try {
101: frcc = getFile(file, alias);
102: log.info("Stored " + file + " as " + alias);
103: m.put(alias, new FileWrapper(frcc));
104: } catch (FileNotFoundException e) {
105: // Already logged
106: } catch (IOException e) {
107: // Already logged
108: }
109: }
110: }
111:
112: private static FileRowColContainer getFile(String file, String alias)
113: throws FileNotFoundException, IOException {
114: FileRowColContainer frcc;
115: if ((frcc = (FileRowColContainer) fileContainers.get(alias)) == null) {
116: frcc = new FileRowColContainer(file);
117: fileContainers.put(alias, frcc);
118: log.info("Saved " + file + " as " + alias + " delimiter=<"
119: + frcc.getDelimiter() + ">");
120: if (defaultFile.length() == 0) {
121: defaultFile = file;// Save in case needed later
122: }
123: }
124: return frcc;
125: }
126:
127: /*
128: * Called by CSVRead(x,next) - sets the row to nil so the next row will be
129: * picked up the next time round
130: *
131: */
132: public static void endRow(String file) {
133: file = checkDefault(file);
134: Map my = (Map) filePacks.get();
135: FileWrapper fw = (FileWrapper) (my).get(file);
136: if (fw == null) {
137: log.warn("endRow(): no entry for " + file);
138: } else {
139: fw.endRow();
140: }
141: }
142:
143: private void endRow() {
144: if (currentRow == NO_LINE) {
145: log.warn("endRow() called twice in succession");
146: }
147: currentRow = NO_LINE;
148: }
149:
150: public static String getColumn(String file, int col) {
151: Map my = (Map) filePacks.get();
152: FileWrapper fw = (FileWrapper) (my).get(file);
153: if (fw == null) // First call
154: {
155: if (file.startsWith("*")) { //$NON-NLS-1$
156: log.warn("Cannot perform initial open using alias "
157: + file);
158: } else {
159: file = checkDefault(file);
160: log.info("Attaching " + file);
161: open(file, file);
162: fw = (FileWrapper) my.get(file);
163: }
164: // TODO improve the error handling
165: if (fw == null)
166: return "";
167: }
168: return fw.getColumn(col);
169: }
170:
171: private String getColumn(int col) {
172: if (currentRow == NO_LINE) {
173: currentRow = container.nextRow();
174:
175: }
176: return container.getColumn(currentRow, col);
177: }
178:
179: /**
180: * Gets the current row number (mainly for error reporting)
181: *
182: * @param file
183: * @return the current row number for this thread
184: */
185: public static int getCurrentRow(String file) {
186:
187: Map my = (Map) filePacks.get();
188: FileWrapper fw = (FileWrapper) (my).get(file);
189: if (fw == null) // Not yet open
190: {
191: return -1;
192: }
193: return fw.currentRow;
194: }
195:
196: /**
197: *
198: */
199: public static void clearAll() {
200: log.debug("clearAll()");
201: Map my = (Map) filePacks.get();
202: for (Iterator i = my.entrySet().iterator(); i.hasNext();) {
203: Object fw = i.next();
204: log.info("Removing " + fw.toString());
205: i.remove();
206: }
207: fileContainers.clear();
208: defaultFile = ""; //$NON-NLS-1$
209: }
210: }
|