alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

// $Header: /home/cvs/jakarta-jmeter/src/protocol/http/org/apache/jmeter/protocol/http/sampler/WebServiceSampler.java,v 1.15 2004/03/13 19:44:14 sebb Exp $
/*
 * Copyright 2003-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
*/

package org.apache.jmeter.protocol.http.sampler;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Random;

import javax.xml.parsers.DocumentBuilder;

import org.xml.sax.InputSource;

import org.apache.jorphan.io.TextFile;

import org.apache.jmeter.gui.JMeterFileFilter;
import org.apache.jmeter.protocol.http.util.DOMPool;
import org.apache.jmeter.samplers.Entry;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.soap.Envelope;
import org.apache.soap.messaging.Message;
import org.apache.soap.transport.SOAPTransport;
import org.apache.soap.transport.http.SOAPHTTPConnection;
import org.apache.soap.util.xml.XMLParserUtils;
import org.w3c.dom.Document;

/**
 * Sampler to handle Web Service requests. It uses Apache SOAP drivers to
 * perform the XML generation, connection, SOAP encoding and other SOAP
 * functions.
 * 

* Created on: Jun 26, 2003 * * @version $Revision: 1.15 $ */ public class WebServiceSampler extends HTTPSampler { public static final String XML_DATA = "HTTPSamper.xml_data"; public static final String SOAP_ACTION = "Soap.Action"; public static final String XML_DATA_FILE = "WebServiceSampler.xml_data_file"; public static final String XML_PATH_LOC = "WebServiceSampler.xml_path_loc"; public static final String MEMORY_CACHE = "WebServiceSampler.memory_cache"; public static final String READ_RESPONSE = "WebServiceSampler.read_response"; public static final String USE_PROXY = "WebServiceSampler.use_proxy"; public static final String PROXY_HOST = "WebServiceSampler.proxy_host"; public static final String PROXY_PORT = "WebServiceSampler.proxy_port"; /** * The SOAPAction is required by MS * webservices and is defined by the * WSDL. */ protected String SOAPACTION = null; /** * SampleResult which holds the response */ transient SampleResult RESULT = null; /** * The XML document */ protected Document XMLMSG = null; /** * size of File[] array */ private int FILE_COUNT = -1; /** * List of files that have .xml extension */ private File[] FILE_LIST = null; /** * Random class for generating random * numbers. */ private Random RANDOM = new Random(); /** * We make DocumentBuilder static. I'm not sure that this is thread safe. * Should investigate this further to make sure it's ok. Making it * non-static could mean a performance hit to get a new DocumentBuilder for * each request. If it's not safe to use static here, then we should * consider using Apache commons pool to create a pool of document builders * or make sure XMLParserUtils creates builders efficiently. */ protected static DocumentBuilder XDB = null; protected String FILE_CONTENTS = null; /** * Set the path where XML messages are stored for random selection. */ public void setXmlPathLoc(String path) { setProperty(XML_PATH_LOC, path); } /** * Get the path where XML messages are stored. this is the directory where * JMeter will randomly select a file. */ public String getXmlPathLoc() { return getPropertyAsString(XML_PATH_LOC); } /** * it's kinda obvious, but we state it anyways. Set the xml file with a * string path. * @param filename */ public void setXmlFile(String filename) { setProperty(XML_DATA_FILE, filename); } /** * Get the file location of the xml file. * @return String file path. */ public String getXmlFile() { return getPropertyAsString(XML_DATA_FILE); } /** * Method uses jorphan TextFile class to load the contents of the file. I * wonder if we should cache the DOM Document to save on parsing the * message. Parsing XML is CPU intensive, so it could restrict the number * of threads a test plan can run effectively. To cache the documents, it * may be good to have an external class to provide caching that is * efficient. We could just use a HashMap, but for large tests, it will be * slow. Ideally, the cache would be indexed, so that large tests will * run efficiently. * @return String contents of the file */ private File retrieveRuntimeXmlData() { String file = getRandomFileName(); if (file.length() > 0) { if (this.getReadResponse()){ TextFile tfile = new TextFile(file); FILE_CONTENTS = tfile.getText(); } return new File(file); } else { return null; } } /** * Method is used internally to check if a random file should be used for * the message. Messages must be valid. This is one way to load test with * different messages. The limitation of this approach is parsing XML takes * CPU resources, so it could affect JMeter GUI responsiveness. * @return String filename */ protected String getRandomFileName() { if (this.getXmlPathLoc() != null) { File src = new File(this.getXmlPathLoc()); if (src.isDirectory() && src.list() != null) { FILE_LIST = src.listFiles( new JMeterFileFilter(new String[] { ".xml" })); this.FILE_COUNT = FILE_LIST.length; File one = FILE_LIST[RANDOM.nextInt(FILE_COUNT)]; // return the absolutePath of the file return one.getAbsolutePath(); } else { return getXmlFile(); } } else { return getXmlFile(); } } /** * Set the XML data. * @param data */ public void setXmlData(String data) { setProperty(XML_DATA, data); } /** * Get the XML data as a string. * @return String data */ public String getXmlData() { return getPropertyAsString(XML_DATA); } /** * Set the soap action which should be in the form of an URN. * @param data */ public void setSoapAction(String data) { setProperty(SOAP_ACTION, data); } /** * Return the soap action string. * @return String soap action */ public String getSoapAction() { return getPropertyAsString(SOAP_ACTION); } /** * Set the memory cache. * @param cache */ public void setMemoryCache(boolean cache) { setProperty(MEMORY_CACHE, String.valueOf(cache)); } /** * Get the memory cache. * @return boolean cache */ public boolean getMemoryCache() { return getPropertyAsBoolean(MEMORY_CACHE); } /** * Set whether the sampler should read the response or not. * @param read */ public void setReadResponse(boolean read) { setProperty(READ_RESPONSE, String.valueOf(read)); } /** * Return whether or not to read the response. * @return boolean */ public boolean getReadResponse() { return this.getPropertyAsBoolean(READ_RESPONSE); } /** * Set whether or not to use a proxy * @param proxy */ public void setUseProxy(boolean proxy){ setProperty(USE_PROXY, String.valueOf(proxy)); } /** * Return whether or not to use proxy * @return true if should use proxy */ public boolean getUseProxy(){ return this.getPropertyAsBoolean(USE_PROXY); } /** * Set the proxy hostname * @param host */ public void setProxyHost(String host){ setProperty(PROXY_HOST, host); } /** * Return the proxy hostname * @return the proxy hostname */ public String getProxyHost(){ this.checkProxy(); return this.getPropertyAsString(PROXY_HOST); } /** * Set the proxy port * @param port */ public void setProxyPort(String port){ setProperty(PROXY_PORT, port); } /** * Return the proxy port * @return the proxy port */ public int getProxyPort(){ this.checkProxy(); return this.getPropertyAsInt(PROXY_PORT); } /** * The method will check to see if JMeter was started * in NonGui mode. If it was, it will try to pick up * the proxy host and port values if they were passed * to JMeter.java. */ public void checkProxy(){ if (System.getProperty("JMeter.NonGui") != null && System.getProperty("JMeter.NonGui").equals("true")){ this.setUseProxy(true); // we check to see if the proxy host and port are set String port = this.getPropertyAsString(PROXY_PORT); String host = this.getPropertyAsString(PROXY_HOST); if (host == null || host.length() == 0){ // it's not set, lets check if the user passed // proxy host and port from command line if (System.getProperty("http.proxyHost") != null){ host = System.getProperty("http.proxyHost"); this.setProxyHost(host); } } if (port == null || port.length() == 0){ // it's not set, lets check if the user passed // proxy host and port from command line if (System.getProperty("http.proxyPort") != null){ port = System.getProperty("http.proxyPort"); this.setProxyPort(port); } } } } /** * This method uses Apache soap util to create the proper DOM elements. * @return Element */ public org.w3c.dom.Element createDocument() { if (getPropertyAsBoolean(MEMORY_CACHE)) { String next = this.getRandomFileName(); if (DOMPool.getDocument(next) != null) { return ((Document) DOMPool.getDocument(next)) .getDocumentElement(); } else { return openDocument(next).getDocumentElement(); } } else { return openDocument(null).getDocumentElement(); } } /** * Open the file and create a Document. * @param key * @return Document */ protected Document openDocument(String key) { if (XDB == null) { XDB = XMLParserUtils.getXMLDocBuilder(); } Document doc = null; // if either a file or path location is given, // get the file object. if (getXmlFile().length() > 0 || getXmlPathLoc().length() > 0){ try { doc = XDB.parse(new FileInputStream(retrieveRuntimeXmlData())); } catch (Exception e){ // there should be a file, if not fail silently } } else { FILE_CONTENTS = getXmlData(); if (FILE_CONTENTS != null && FILE_CONTENTS.length() > 0) { try { doc = XDB.parse( new InputSource(new StringReader(FILE_CONTENTS))); } catch (Exception ex) { // ex.printStackTrace(); } } } if (this.getPropertyAsBoolean(MEMORY_CACHE)) { DOMPool.putDocument(key, doc); } return doc; } /** * sample(Entry e) simply calls sample(). * @param e - ignored * @return the sample Result */ public SampleResult sample(Entry e) { return sample(); } /** * sample() does the following: create a new SampleResult, call * sampleWithApache, and return the result. * @return SampleResult */ public SampleResult sample() { RESULT = new SampleResult(); sampleWithApache(); return RESULT; } /** * Sample the URL using Apache SOAP driver. Implementation note for myself * and those that are curious. Current logic marks the end after the * response has been read. If read response is set to false, the buffered * reader will read, but do nothing with it. Essentially, the stream from * the server goes into the ether. */ public void sampleWithApache() { try { org.w3c.dom.Element rdoc = createDocument(); Envelope msgEnv = Envelope.unmarshall(rdoc); // create a new message Message msg = new Message(); RESULT.sampleStart(); SOAPHTTPConnection spconn = null; // if a blank HeaderManager exists, try to // get the SOAPHTTPConnection. After the first // request, there should be a connection object // stored with the cookie header info. if (this.getHeaderManager() != null && this.getHeaderManager().getSOAPHeader() != null) { spconn = (SOAPHTTPConnection)this.getHeaderManager(). getSOAPHeader(); } else { spconn = new SOAPHTTPConnection(); } // check the proxy String phost = ""; int pport = 0; // if use proxy is set, we try to pick up the // proxy host and port from either the text // fields or from JMeterUtil if they were passed // from command line if (this.getUseProxy()){ if (this.getProxyHost().length() > 0 && this.getProxyPort() > 0){ phost = this.getProxyHost(); pport = this.getProxyPort(); } else { if (System.getProperty("http.proxyHost") != null || System.getProperty("http.proxyPort") != null){ phost = System.getProperty("http.proxyHost"); pport = Integer.parseInt( System.getProperty("http.proxyPort")); } } // if for some reason the host is blank and the port is // zero, the sampler will fail silently if (phost.length() > 0 && pport > 0){ spconn.setProxyHost(phost); spconn.setProxyPort(pport); } } // by default we maintain the session. spconn.setMaintainSession(true); msg.setSOAPTransport(spconn); msg.send(this.getUrl(), this.getSoapAction(), msgEnv); if (this.getHeaderManager() != null){ this.getHeaderManager().setSOAPHeader(spconn); } SOAPTransport st = msg.getSOAPTransport(); BufferedReader br = st.receive(); RESULT.setDataType(SampleResult.TEXT); if (this.getPropertyAsBoolean(READ_RESPONSE)) { StringBuffer buf = new StringBuffer(); String line; while ((line = br.readLine()) != null) { buf.append(line); } RESULT.sampleEnd(); // set the response RESULT.setResponseData(buf.toString().getBytes()); } else { // by not reading the response // for real, it improves the // performance on slow clients br.read(); RESULT.sampleEnd(); RESULT.setResponseData( JMeterUtils .getResString("read_response_message") .getBytes()); } RESULT.setSuccessful(true); // 1-22-04 updated the sampler so that when read // response is set, it also sets SamplerData with // the XML message, so users can see what was // sent. if read response is not checked, it will // not set sampler data with the request message. // peter lin. RESULT.setSamplerData( getUrl().getProtocol() + "://" + getUrl().getHost() + "/" + getUrl().getFile() + "\n" + FILE_CONTENTS); RESULT.setDataEncoding( st.getResponseSOAPContext().getContentType()); // setting this is just a formality, since // soap will return a descriptive error // message, soap errors within the response // are preferred. RESULT.setResponseCode("200"); br.close(); msg = null; st = null; // reponse code doesn't really apply, since // the soap driver doesn't provide a // response code } catch (Exception exception) { // exception.printStackTrace(); RESULT.setSuccessful(false); } } /** * We override this to prevent the wrong encoding and provide no * implementation. We want to reuse the other parts of HTTPSampler, but not * the connection. The connection is handled by the Apache SOAP driver. */ public void addEncodedArgument(String name, String value, String metaData) { } /** * We override this to prevent the wrong encoding and provide no * implementation. We want to reuse the other parts of HTTPSampler, but not * the connection. The connection is handled by the Apache SOAP driver. */ protected HttpURLConnection setupConnection(URL u, String method) throws IOException { return null; } /** * We override this to prevent the wrong encoding and provide no * implementation. We want to reuse the other parts of HTTPSampler, but not * the connection. The connection is handled by the Apache SOAP driver. */ protected long connect() throws IOException { return -1; } }

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.