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.http.modifier;
020:
021: import java.io.Serializable;
022: import java.net.MalformedURLException;
023: import java.net.URL;
024: import java.util.ArrayList;
025: import java.util.Iterator;
026: import java.util.LinkedList;
027: import java.util.List;
028: import java.util.Random;
029:
030: import org.apache.jmeter.config.Argument;
031: import org.apache.jmeter.config.Arguments;
032: import org.apache.jmeter.config.ConfigElement;
033: import org.apache.jmeter.processor.PreProcessor;
034: import org.apache.jmeter.protocol.http.parser.HtmlParsingUtils;
035: import org.apache.jmeter.protocol.http.sampler.HTTPSampleResult;
036: import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase;
037: import org.apache.jmeter.protocol.http.util.HTTPConstants;
038: import org.apache.jmeter.samplers.SampleResult;
039: import org.apache.jmeter.samplers.Sampler;
040: import org.apache.jmeter.testelement.AbstractTestElement;
041: import org.apache.jmeter.testelement.property.PropertyIterator;
042: import org.apache.jmeter.threads.JMeterContext;
043: import org.apache.jorphan.logging.LoggingManager;
044: import org.apache.log.Logger;
045: import org.w3c.dom.Document;
046: import org.w3c.dom.NamedNodeMap;
047: import org.w3c.dom.Node;
048: import org.w3c.dom.NodeList;
049:
050: // For Unit tests, @see TestAnchorModifier
051:
052: /**
053: * @author Michael Stover
054: */
055: public class AnchorModifier extends AbstractTestElement implements
056: PreProcessor, Serializable {
057: private static final Logger log = LoggingManager
058: .getLoggerForClass();
059:
060: private static Random rand = new Random();
061:
062: public AnchorModifier() {
063: }
064:
065: /**
066: * Modifies an Entry object based on HTML response text.
067: */
068: public void process() {
069: JMeterContext context = getThreadContext();
070: Sampler sam = context.getCurrentSampler();
071: SampleResult res = context.getPreviousResult();
072: HTTPSamplerBase sampler = null;
073: HTTPSampleResult result = null;
074: if (res == null || !(sam instanceof HTTPSamplerBase)
075: || !(res instanceof HTTPSampleResult)) {
076: log.info("Can't apply HTML Link Parser when the previous"
077: + " sampler run is not an HTTP Request.");
078: return;
079: } else {
080: sampler = (HTTPSamplerBase) sam;
081: result = (HTTPSampleResult) res;
082: }
083: List potentialLinks = new ArrayList();
084: String responseText = ""; // $NON-NLS-1$
085: responseText = result.getResponseDataAsString();
086: Document html;
087: int index = responseText.indexOf("<"); // $NON-NLS-1$
088: if (index == -1) {
089: index = 0;
090: }
091: if (log.isDebugEnabled()) {
092: log.debug("Check for matches against: "
093: + sampler.toString());
094: }
095: html = (Document) HtmlParsingUtils.getDOM(responseText
096: .substring(index));
097: addAnchorUrls(html, result, sampler, potentialLinks);
098: addFormUrls(html, result, sampler, potentialLinks);
099: addFramesetUrls(html, result, sampler, potentialLinks);
100: if (potentialLinks.size() > 0) {
101: HTTPSamplerBase url = (HTTPSamplerBase) potentialLinks
102: .get(rand.nextInt(potentialLinks.size()));
103: if (log.isDebugEnabled()) {
104: log.debug("Selected: " + url.toString());
105: }
106: sampler.setDomain(url.getDomain());
107: sampler.setPath(url.getPath());
108: if (url.getMethod().equals(HTTPConstants.POST)) {
109: PropertyIterator iter = sampler.getArguments()
110: .iterator();
111: while (iter.hasNext()) {
112: Argument arg = (Argument) iter.next()
113: .getObjectValue();
114: modifyArgument(arg, url.getArguments());
115: }
116: } else {
117: sampler.setArguments(url.getArguments());
118: // config.parseArguments(url.getQueryString());
119: }
120: sampler.setProtocol(url.getProtocol());
121: return;
122: } else {
123: log.debug("No matches found");
124: }
125: return;
126: }
127:
128: private void modifyArgument(Argument arg, Arguments args) {
129: if (log.isDebugEnabled()) {
130: log.debug("Modifying argument: " + arg);
131: }
132: List possibleReplacements = new ArrayList();
133: PropertyIterator iter = args.iterator();
134: Argument replacementArg;
135: while (iter.hasNext()) {
136: replacementArg = (Argument) iter.next().getObjectValue();
137: try {
138: if (HtmlParsingUtils.isArgumentMatched(replacementArg,
139: arg)) {
140: possibleReplacements.add(replacementArg);
141: }
142: } catch (Exception ex) {
143: log.error("Problem adding Argument", ex);
144: }
145: }
146:
147: if (possibleReplacements.size() > 0) {
148: replacementArg = (Argument) possibleReplacements.get(rand
149: .nextInt(possibleReplacements.size()));
150: arg.setName(replacementArg.getName());
151: arg.setValue(replacementArg.getValue());
152: if (log.isDebugEnabled()) {
153: log.debug("Just set argument to values: "
154: + arg.getName() + " = " + arg.getValue());
155: }
156: args.removeArgument(replacementArg);
157: }
158: }
159:
160: public void addConfigElement(ConfigElement config) {
161: }
162:
163: private void addFormUrls(Document html, HTTPSampleResult result,
164: HTTPSamplerBase config, List potentialLinks) {
165: NodeList rootList = html.getChildNodes();
166: List urls = new LinkedList();
167: for (int x = 0; x < rootList.getLength(); x++) {
168: urls.addAll(HtmlParsingUtils.createURLFromForm(rootList
169: .item(x), result.getURL()));
170: }
171: Iterator iter = urls.iterator();
172: while (iter.hasNext()) {
173: HTTPSamplerBase newUrl = (HTTPSamplerBase) iter.next();
174: newUrl.setMethod(HTTPConstants.POST);
175: if (log.isDebugEnabled()) {
176: log.debug("Potential Form match: " + newUrl.toString());
177: }
178: if (HtmlParsingUtils.isAnchorMatched(newUrl, config)) {
179: log.debug("Matched!");
180: potentialLinks.add(newUrl);
181: }
182: }
183: }
184:
185: private void addAnchorUrls(Document html, HTTPSampleResult result,
186: HTTPSamplerBase config, List potentialLinks) {
187: String base = "";
188: NodeList baseList = html.getElementsByTagName("base"); // $NON-NLS-1$
189: if (baseList.getLength() > 0) {
190: base = baseList.item(0).getAttributes()
191: .getNamedItem("href").getNodeValue(); // $NON-NLS-1$
192: }
193: NodeList nodeList = html.getElementsByTagName("a"); // $NON-NLS-1$
194: for (int i = 0; i < nodeList.getLength(); i++) {
195: Node tempNode = nodeList.item(i);
196: NamedNodeMap nnm = tempNode.getAttributes();
197: Node namedItem = nnm.getNamedItem("href"); // $NON-NLS-1$
198: if (namedItem == null) {
199: continue;
200: }
201: String hrefStr = namedItem.getNodeValue();
202: if (hrefStr.startsWith("javascript:")) { // $NON-NLS-1$
203: continue; // No point trying these
204: }
205: try {
206: HTTPSamplerBase newUrl = HtmlParsingUtils
207: .createUrlFromAnchor(hrefStr, new URL(result
208: .getURL(), base));
209: newUrl.setMethod(HTTPConstants.GET);
210: if (log.isDebugEnabled()) {
211: log.debug("Potential <a href> match: " + newUrl);
212: }
213: if (HtmlParsingUtils.isAnchorMatched(newUrl, config)) {
214: log.debug("Matched!");
215: potentialLinks.add(newUrl);
216: }
217: } catch (MalformedURLException e) {
218: log.warn("Bad URL " + e);
219: }
220: }
221: }
222:
223: private void addFramesetUrls(Document html,
224: HTTPSampleResult result, HTTPSamplerBase config,
225: List potentialLinks) {
226: String base = "";
227: NodeList baseList = html.getElementsByTagName("base"); // $NON-NLS-1$
228: if (baseList.getLength() > 0) {
229: base = baseList.item(0).getAttributes()
230: .getNamedItem("href") // $NON-NLS-1$
231: .getNodeValue();
232: }
233: NodeList nodeList = html.getElementsByTagName("frame"); // $NON-NLS-1$
234: for (int i = 0; i < nodeList.getLength(); i++) {
235: Node tempNode = nodeList.item(i);
236: NamedNodeMap nnm = tempNode.getAttributes();
237: Node namedItem = nnm.getNamedItem("src"); // $NON-NLS-1$
238: if (namedItem == null) {
239: continue;
240: }
241: String hrefStr = namedItem.getNodeValue();
242: try {
243: HTTPSamplerBase newUrl = HtmlParsingUtils
244: .createUrlFromAnchor(hrefStr, new URL(result
245: .getURL(), base));
246: newUrl.setMethod(HTTPConstants.GET);
247: if (log.isDebugEnabled()) {
248: log.debug("Potential <frame src> match: " + newUrl);
249: }
250: if (HtmlParsingUtils.isAnchorMatched(newUrl, config)) {
251: log.debug("Matched!");
252: potentialLinks.add(newUrl);
253: }
254: } catch (MalformedURLException e) {
255: log.warn("Bad URL " + e);
256: }
257: }
258: }
259: }
|