package org.apache.jmeter.protocol.http.proxy;
import java.net.*;
import java.io.*;
import java.util.*;
import org.apache.jmeter.protocol.http.config.UrlConfig;
import org.apache.jmeter.save.xml.TagHandler;
//
// Class: Proxy
// Abstract: Thread to handle one client request. get the requested
// object from the web server or from the cache, and delivers
// the bits to client.
//
/**
* Description of the Class
*
*@author mike
*@created June 8, 2001
*/
public class Proxy extends Thread
{
//
// Member variables
//
Socket ClientSocket = null;
// Socket to client
Socket SrvrSocket = null;
// Socket to web server
Cache cache = null;
// Static cache manager object
String localHostName = null;
// Local machine name
String localHostIP = null;
// Local machine IP address
String adminPath = null;
// Path of admin applet
Config config = null;
// Config object
UrlConfig urlConfig = null;
// UrlConfig object for saving test cases
//
// Public member methods
//
//
// Constructor
//
Proxy(Socket clientSocket, Cache CacheManager, Config configObject)
{
//
// Initialize member variables
//
config = configObject;
ClientSocket = clientSocket;
cache = CacheManager;
localHostName = config.getLocalHost();
localHostIP = config.getLocalIP();
adminPath = config.getAdminPath();
}
//
// run - Main work is done here:
//
/**
* Main processing method for the Proxy object
*/
public void run()
{
String serverName = "";
URL url;
byte line[];
HttpRequestHdr request = new HttpRequestHdr();
HttpReplyHdr reply = new HttpReplyHdr();
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
boolean TakenFromCache = false;
boolean isCachable = false;
try
{
//
// Read HTTP Request from client
//
request.parse(ClientSocket.getInputStream());
createUrlConfig(request);
config.increaseFilesCached();
url = new URL(request.url);
System.out.println("Request = " + url);
//
// Send Web page with applet to administrator
//
if (url.getFile().equalsIgnoreCase("/admin") &&
(url.getHost().equalsIgnoreCase(localHostName) ||
url.getHost().equalsIgnoreCase(localHostIP)))
{
sendAppletWebPage();
return;
}
//
// Send Applet Files to administrator
//
if ((url.getHost().equalsIgnoreCase(localHostName) ||
url.getHost().equalsIgnoreCase(localHostIP)))
{
sendAppletClass(url.getFile());
return;
}
//
// Check if accessing the URL is allowed by administrator
//
String[] denied = config.getDeniedHosts();
for (int i = 0; i < denied.length; i++)
{
if (url.toString().indexOf(denied[i]) != -1)
{
System.out.println("Access not allowed...");
DataOutputStream out =
new DataOutputStream(ClientSocket.getOutputStream());
out.writeBytes(reply.formNotAllowed());
out.flush();
ClientSocket.close();
return;
}
}
serverName = url.getHost();
System.out.println("Miss! Forwarding to server " +
serverName + "...");
config.increaseMisses();
SrvrSocket = new Socket(request.serverName(),
request.serverPort());
request.url = request.serverUrl();
DataOutputStream srvOut =
new DataOutputStream(SrvrSocket.getOutputStream());
//
// Send the url to web server (or father proxy)
//
srvOut.writeBytes(request.toString(false));
srvOut.flush();
//
// Send data to server (needed for post method)
//
StringBuffer buff = new StringBuffer();
int readValue;
for (int i = 0; i < request.contentLength; i++)
{
readValue = ClientSocket.getInputStream().read();
buff.append((char)readValue);
SrvrSocket.getOutputStream().write(readValue);
}
SrvrSocket.getOutputStream().flush();
urlConfig.parseArguments(buff.toString());
saveUrlConfig();
// Third, check reply headers (we must read first
// line of headers for that).
DataInputStream Din =
new DataInputStream(SrvrSocket.getInputStream());
DataOutputStream Dout =
new DataOutputStream(ClientSocket.getOutputStream());
String str = Din.readLine();
StringTokenizer s = new StringTokenizer(str);
String retCode = s.nextToken();
// first token is HTTP protocol
retCode = s.nextToken();
// second is return code
//
// First line was read - send it to client and cache it
//
String tempStr = new String(str + "\r\n");
Dout.writeBytes(tempStr);
//
// Read next lines in reply header, send them to
// client and cache them
//
if (str.length() > 0)
{
while (true)
{
str = Din.readLine();
tempStr = new String(str + "\r\n");
// Send bits to client
Dout.writeBytes(tempStr);
if (str.length() <= 0)
{
break;
}
}
}
Dout.flush();
//
// With the HTTP reply body do:
// (1) Send it to client.
// (2) Cache it.
//
InputStream in = SrvrSocket.getInputStream();
OutputStream out = ClientSocket.getOutputStream();
byte data[] = new byte[2000];
int count;
while ((count = in.read(data)) > 0)
{
// Send bits to client
out.write(data, 0, count);
}
out.flush();
}
catch (UnknownHostException uhe)
{
//
// Requested Server could not be located
//
System.out.println("Server Not Found.");
try
{
// Notify client that server not found
DataOutputStream out =
new DataOutputStream(ClientSocket.getOutputStream());
out.writeBytes(reply.formServerNotFound());
out.flush();
}
catch (Exception uhe2)
{
}
}
catch (Exception e)
{
e.printStackTrace();
try
{
if (TakenFromCache)
{
fileInputStream.close();
}
else if (isCachable)
{
fileOutputStream.close();
}
// Notify client that internal error accured in proxy
DataOutputStream out =
new DataOutputStream(ClientSocket.getOutputStream());
out.writeBytes(reply.formTimeout());
out.flush();
}
catch (Exception uhe2)
{
}
}
finally
{
try
{
ClientSocket.getOutputStream().flush();
ClientSocket.close();
}
catch (Exception e)
{
}
}
}
//
// Private methods
//
//
// Send to administrator web page containing reference to applet
//
private void sendAppletWebPage()
{
System.out.println("Sending the applet...");
String page = "";
try
{
File appletHtmlPage = new File(config.getAdminPath() +
File.separator + "Admin.html");
DataInputStream in = new DataInputStream(new FileInputStream(appletHtmlPage));
String s = null;
while ((s = in.readLine()) != null)
{
page += s;
}
page = page.substring(0, page.indexOf("PORT")) +
config.getAdminPort() +
page.substring(page.indexOf("PORT") + 4);
in.close();
DataOutputStream out = new DataOutputStream(ClientSocket.getOutputStream());
out.writeBytes(page);
out.flush();
out.close();
}
catch (Exception e)
{
System.out.println("Error: can't open applet html page");
}
}
//
// Send the applet to administrator
//
private void sendAppletClass(String className)
{
try
{
byte data[] = new byte[2000];
int count;
HttpReplyHdr reply = new HttpReplyHdr();
File appletFile = new File(adminPath + File.separatorChar + className);
long length = appletFile.length();
FileInputStream in = new FileInputStream(appletFile);
DataOutputStream out = new DataOutputStream(ClientSocket.getOutputStream());
out.writeBytes(reply.formOk("application/octet-stream", length));
while (-1 < (count = in.read(data)))
{
out.write(data, 0, count);
}
out.flush();
in.close();
out.close();
}
catch (Exception e)
{
}
}
private void createUrlConfig(HttpRequestHdr request)
{
System.out.println("extra stuff = " + request.unrecognized);
System.out.println("Everything = " + request.toString(false));
urlConfig = new UrlConfig();
urlConfig.setDomain(request.serverName());
urlConfig.setMethod(request.method);
urlConfig.setPath(request.serverUrl());
urlConfig.setName(urlConfig.getPath());
urlConfig.setProtocol(request.url.substring(0, request.url.indexOf(":")));
urlConfig.setPort(request.serverPort());
}
private void saveUrlConfig()
{
try
{
String name;
int index = urlConfig.getName().lastIndexOf("/");
if (index > -1)
{
name = urlConfig.getName().substring(index + 1);
}
else
{
name = urlConfig.getName();
}
FileWriter out = new FileWriter(System.getProperty("user.dir") +
File.separator + config.getJmxScriptDir() + File.separator + name +
"_" + config.getFilesCached() + ".jmx");
TagHandler handler = (TagHandler) urlConfig.getTagHandlerClass().newInstance();
handler.startSave(out);
handler.save(urlConfig, out);
out.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}