/******************************************************************************* * Copyright (c) 2004, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - Initial API and implementation *******************************************************************************/ package org.eclipse.wst.internet.monitor.core.internal.provisional; import java.util.Date; import java.util.Properties; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.Platform; import org.eclipse.wst.internet.monitor.core.internal.Monitor; import org.eclipse.wst.internet.monitor.core.internal.Trace; /** * Represents a TCP/IP request made between the client and the server. * Each request represents a request-response pair, where the request * is from client -> server, and the response is from server -> client. * <p> * Requests are created by a running monitor. They do not have a reference * back to the monitor because the monitor may have been deleted or modified * since the request was created. * </p> * <p> * This interface is intended to be extended only by clients * to extend the <code>protocolAdapters</code> extension point. * </p> */ public class Request implements IAdaptable { protected Monitor monitor; protected Date date; protected long responseTime = -1; protected int localPort; protected String remoteHost; protected int remotePort; protected byte[] request; protected byte[] response; protected String name; protected String protocolId; protected Properties properties; /** * Request2 content type (value 1) for the transport (header) of a request * or response. * * @see #getRequest(int) * @see #getResponse(int) */ public static final int TRANSPORT = 1; /** * Request2 content type (value 2) for the content (body) of a request * or response. * * @see #getRequest(int) * @see #getResponse(int) */ public static final int CONTENT = 2; /** * Request2 content type (value 3) for the entire content of a request * or response. * * @see #getRequest(int) * @see #getResponse(int) */ public static final int ALL = 3; /** * Create a new Request. * * @param monitor a monitor * @param protocolId the protocol id * @param localPort a local port number * @param remoteHost a remote hostname * @param remotePort a remote port number */ public Request(Monitor monitor, String protocolId, int localPort, String remoteHost, int remotePort) { super(); this.monitor = monitor; this.protocolId = protocolId; this.localPort = localPort; this.remoteHost = remoteHost; this.remotePort = remotePort; date = new Date(); properties = new Properties(); if (monitor != null) monitor.addRequest(this); } /** * Returns the protocol responsible for creating this request. * * @return the protocol id */ public String getProtocol() { return protocolId; } /** * Returns the time this request was made. * * @return the timestamp */ public Date getDate() { return date; } /** * Returns the local (client) port. * * @return the local port number */ public int getLocalPort() { return localPort; } /** * Returns the remote (server) host. * * @return the remote host */ public String getRemoteHost() { return remoteHost; } /** * Returns the remote (server) port. * * @return the remote port number */ public int getRemotePort() { return remotePort; } /** * Returns the selected content of the request portion of this request. * <p> * [issue: I don't know how to explain this. For basic TCP/IP requests, * distinction between transport and content is ignored. * For HTTP requests, this TRANSPORT returns just the HTTP header and * CONTENT returns just the HTTP body without the headers. What would * it mean for other protocols? * </p> * * @param type the content type: one of {@link #TRANSPORT}, * {@link #CONTENT}, or {@link #ALL} * @return the content bytes */ public byte[] getRequest(int type) { return request; } /** * Returns the selected content of the response portion of this request. * <p> * [issue: I don't know how to explain this. For basic TCP/IP requests, * distinction between transport and content is ignored. * For HTTP requests, this TRANSPORT returns just the HTTP header and * CONTENT returns just the HTTP body without the headers. What would * it mean for other protocols?] * </p> * * @param type the content type: one of {@link #TRANSPORT}, * {@link #CONTENT}, or {@link #ALL} * @return the content bytes */ public byte[] getResponse(int type) { return response; } /** * Returns the server's response time in milliseconds. If the request * has not been completed yet, -1 is returned. * * @return the server's response time, or -1 if there has been no * response yet */ public long getResponseTime() { return responseTime; } /** * Returns a name for this request. * * @return the name */ public String getName() { if (name == null) return getRemoteHost() + ":" + getRemotePort(); return name; } /** * Sets the name of this request. * * @param n the name */ protected void setName(String n) { name = n; } /** * Sets the given key-value property on this request. To remove a property, * set the value to null. * <p> * This method is typically called by protocol adapters to attach protocol- * specific fields to the request, but it may be called by any client. * </p> * * @param key the key * @param value the value */ public void setProperty(String key, Object value) { try { if (properties.containsKey(key)) properties.remove(key); if (value != null) properties.put(key, value); } catch (Exception e) { if (Trace.SEVERE) { Trace.trace(Trace.STRING_SEVERE, "Could not add property", e); } } monitor.requestChanged(this); } /** * Returns the value of the property with the given key from this request. * If the key does not exist, <code>null</code> is returned. * * @param key the property key * @return the property value */ public Object getProperty(String key) { try { return properties.get(key); } catch (Exception e) { return null; } } /** * Add to the request. * * @param addRequest byte[] */ public void addToRequest(byte[] addRequest) { if (addRequest == null || addRequest.length == 0) return; if (request == null || request.length == 0) { setRequest(addRequest); return; } int size = request.length + addRequest.length; byte[] b = new byte[size]; System.arraycopy(request, 0, b, 0, request.length); System.arraycopy(addRequest, 0, b, request.length, addRequest.length); request = b; fireChangedEvent(); } /** * Add to the response. * * @param addResponse byte[] */ public void addToResponse(byte[] addResponse) { if (addResponse == null || addResponse.length == 0) return; if (response == null || response.length == 0) { setResponse(addResponse); return; } int size = response.length + addResponse.length; byte[] b = new byte[size]; System.arraycopy(response, 0, b, 0, response.length); System.arraycopy(addResponse, 0, b, response.length, addResponse.length); response = b; fireChangedEvent(); } /** * Set the request. * * @param request byte[] */ protected void setRequest(byte[] request) { if (request == null || request.length == 0) return; this.request = request; monitor.requestChanged(this); } /** * Set the response. * * @param response byte[] */ protected void setResponse(byte[] response) { if (response == null || response.length == 0) return; this.response = response; responseTime = System.currentTimeMillis() - date.getTime(); monitor.requestChanged(this); } /** * Returns the monitor that created this request. * Change events will be fired from this monitor. * <p> * Note that the monitor may have been editted since this * request was created, so you cannot rely on the monitor's * hostname or port values. * </p> * * @return the monitor that created this request */ public IMonitor getMonitor() { return monitor; } /** * Fire a change event to notify monitor listeners that the request has changed. */ protected void fireChangedEvent() { if (monitor != null) monitor.requestChanged(this); } /** (non-Javadoc) * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) */ public Object getAdapter(Class adapter) { return Platform.getAdapterManager().getAdapter(this, adapter); } }