Monitor API changes
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/ContentFilterDelegate.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/ContentFilterDelegate.java
index 2137876..3d4721c 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/ContentFilterDelegate.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/ContentFilterDelegate.java
@@ -11,11 +11,21 @@
 package org.eclipse.wst.internet.monitor.core;
 
 import java.io.IOException;
+
 /**
  * A content filter that filters contents from the monitor traffic on a request.
  * <p>
- * This abstract class is intended to be extended only by clients
+ * This abstract class is intended to be subclassed only by clients
  * to extend the <code>contentFilters</code> extension point.
+ * The subclass must have a public 0-argument constructor, which will be used
+ * automatically to instantiate the delegate when required. 
+ * </p>
+ * <p>
+ * [issue: The notion of content filters is a UI/presentation
+ * concern, not something that is makes sense to have as core
+ * functionality. The contentFilters extension point, IContentFilter,
+ * and ContentFilterDelegate should all move to the o.e.wst.internet.monitor.ui
+ * plug-in.]
  * </p>
  * 
  * @since 1.0
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IMonitor.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IMonitor.java
index f07de72..20346af 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IMonitor.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IMonitor.java
@@ -9,9 +9,26 @@
  *    IBM - Initial API and implementation
  **********************************************************************/
 package org.eclipse.wst.internet.monitor.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
 /**
- * Represents the monitor that monitors the network traffic between a server and a client.
+ * Represents a monitor.
+ * The monitor watches all network traffic between a local client (talking
+ * on a given local port) and a remote server (identified by host and port).
  * The global list of known monitors is available via {@link MonitorCore.getMonitors()}.
+ * IMonitor is thread-safe.
+ * <p>
+ * IMonitors are read-only. To make changes to a monitor, you must create an
+ * IMonitorWorkingCopy by calling createWorkingCopy(). Changes to the working copy
+ * are applied when the working copy is saved. Monitors and monitor working copies
+ * have the following properties:
+ *   * equals() returns true for a monitor and it's working copy
+ * <p>
+ * [issue: Why the built-in assumption that the client is local? A monitor
+ * would make just as much sense sitting between a client on a remote machine
+ * and a server.]
+ * </p>
  * <p>
  * This interface is not intended to be implemented by clients.
  * </p>
@@ -24,65 +41,157 @@
 	 * Each monitor has a distinct, fixed id. Ids are intended to be used internally as keys;
 	 * they are not intended to be shown to end users.
 	 * 
-	 * @return the element id
+	 * @return the monitor id
 	 */
 	public String getId();
 
 	/**
-	 * Returns the remote host name of the server to be monitored. 
+	 * Returns the remote host name of the server being monitored.
 	 * 
 	 * @return the remote host name
 	 */
 	public String getRemoteHost();
 	
 	/**
-	 * Returns the remote port number of the server to be monitored.
+	 * Returns the remote port number of the server being monitored.
 	 *  
 	 * @return the remote port number
 	 */
 	public int getRemotePort();
 	
 	/**
-	 * Returns the local port number of the client that monitor traffic will used.
+	 * Returns the local port number of the client being monitored. This
+	 * is the port that the client is talking to the remote server on.
 	 *  
 	 * @return the local port number
 	 */
 	public int getLocalPort();
 	
 	/**
-	 * Returns the protocol adapter that the monitor will be used to read the monitor traffic.
-	 *   
-	 * @return the protocol adapter
-	 */
-	public IProtocolAdapter getProtocolAdapter();
-	
-	/**
-	 * Returns whether this monitor is currently running.
+	 * Returns the protocol that this monitor uses to read network
+	 * traffic.
 	 * 
-	 * @return <code>true</code> if the monitor is currently running; otherwise, return <code>false</code>.
+	 * @return the protocol id
+	 */
+	public String getProtocol();
+
+	/**
+	 * Returns whether this monitor is currently running. Monitor working
+	 * copies will always return false (since they cannot be run).
+	 * 
+	 * @return <code>true</code> if the monitor is currently running, or
+	 *    <code>false</code> otherwise
 	 */
 	public boolean isRunning();
 	
 	/**
-	 * Deletes this monitor. The monitor will no longer be available to users.
-	 * This method has no effect if the monitor has already been deleted.
+	 * Deletes this monitor. The monitor will no longer be available to clients.
+	 * If the monitor is currently running, it will be stopped first.
+	 * This method has no effect if the monitor has already been deleted or if
+	 * it is called on a working copy. Clients have no obligation to delete
+	 * working copies.
 	 */
 	public void delete();
 	
 	/**
 	 * Returns whether this monitor is a working copy. Monitors which return
-	 * <code>true</code> to this method can be safely cast to 
-	 * <code>org.eclipse.wst.internet.monitor.core.IMonitorWorkingCopy</code>
+	 * <code>true</code> to this method can be safely cast to
+	 * {@link IMonitorWorkingCopy}.
 	 * 
-	 * @return whether this monitor is a working copy
+	 * @return <code>true</code> if this monitor is a working copy, and
+	 * <code>false</code> otherwise
 	 */
 	public boolean isWorkingCopy();
 	
 	/**
-	 * Returns a working copy of this monitor. Changes to the working copy will be
-	 * applied to this monitor when saved.
+	 * Returns a working copy for this monitor. If the receiver is not a
+	 * working copy, a new working copy will be created and initialized to have
+	 * the same attributes as this monitor. If the receiver is a working copy,
+	 * this method simply returns the receiver. After configuring attributes on
+	 * the working copy, calling {@link IMonitorWorkingCopy#save()} applies
+	 * the changes to the original monitor.
 	 * 
 	 * @return a working copy of this monitor
 	 */
-	public IMonitorWorkingCopy getWorkingCopy();
+	public IMonitorWorkingCopy createWorkingCopy();
+	
+	/**
+	 * Starts the given monitor listening on its client port. This method is
+	 * synchronous and the monitor will be running and ready for use by the
+	 * time that the method returns. This method has no effect if the monitor
+	 * is already running.
+	 * <p>
+	 * A CoreException is thrown if the monitor is not valid, the local port
+	 * is in use, or if another problem occurs when starting the monitor. 
+	 * </p>
+	 * <p>
+	 * This method must not be called on a working copy or after the monitor
+	 * has been deleted.
+	 * </p>
+	 * 
+	 * @throws CoreException thrown if the monitor's properties are invalid,
+	 *   if it fails to start because the port is in use, or another problem occurs
+	 */
+	public void start() throws CoreException;
+
+	/**
+	 * Stops the given monitor and frees up all underlying operating 
+	 * system resources. This method is synchronous and the monitor will be
+	 * running and ready for use by the time that the method returns.
+	 * This method has no effect if the monitor was not already running.
+	 * <p>
+	 * After returning from this method, the monitor may be restarted at
+	 * any time. This method must not be called on a working copy or after
+	 * the monitor has been deleted.
+	 * </p>
+	 */
+	public void stop();
+
+	/**
+	 * Adds a request listener.
+	 * Once registered, a listener starts receiving notification of 
+	 * changes to the global list of requests. The listener continues to receive
+	 * notifications until it is removed.
+	 * Has no effect if an identical listener is already registered.
+	 * <p>
+	 * If a listener is added to a working copy, it will automatically be added
+	 * to the original monitor. If the monitor does not exist yet (when the working
+	 * copy was just created from MonitorCore.createMonitor()), the listener will
+	 * be added to the created monitor when (if) the working copy is saved. 
+	 * </p>
+	 *
+	 * @param listener the request listener
+	 * @see #removeRequestListener(IRequestListener)
+	 */
+	public void addRequestListener(IRequestListener listener);
+	
+	/**
+	 * Removes the given request listener. Has no effect if the listener is
+	 * not registered.
+	 * <p>
+	 * If a listener is removed from a working copy, it will automatically be
+	 * removed from the corresponding original monitor. Removing a monitor from
+	 * a newly created monitor has no effect unless the monitor had already been
+	 * added, in which case it is removed from notification and will not be added
+	 * to the created monitor when (if) the working copy is saved. 
+	 * </p>
+	 * 
+	 * @param listener the listener
+	 * @see #addRequestListener(IRequestListener)
+	 */
+	public void removeRequestListener(IRequestListener listener);
+	
+	/**
+	 * Validates this monitor. This method should return an error if the monitor
+	 * has invalid ports or remote hostname.
+	 * <p>
+	 * This method is not on the working copy so that the runtime can be validated
+	 * at any time.
+	 * </p>
+	 *
+	 * @return a status object with code <code>IStatus.OK</code> if this
+	 *   runtime is valid, otherwise a status object indicating what is
+	 *   wrong with it
+	 */
+	public IStatus validate();
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IMonitorListener.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IMonitorListener.java
index 3e4d107..cbfe06d 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IMonitorListener.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IMonitorListener.java
@@ -9,30 +9,39 @@
  *    IBM - Initial API and implementation
  **********************************************************************/
 package org.eclipse.wst.internet.monitor.core;
+
 /**
- * Listener that listen to the monitor add, remove and changes.
+ * Listener for global changes affecting monitors.
+ * <p>
+ * Clients should implement this interface and register
+ * their listener via {@linkMonitorCore#addMonitorListener(IMonitorListener)}.
+ * </p>
  * 
  * @since 1.0
  */
 public interface IMonitorListener {
+	
 	/**
-	 * This method is being called when a monitor is added.
+	 * Notification that the given monitor has been created (added to the
+	 * global list of known monitors).
 	 * 
-	 * @param monitor the monitor that has been added
+	 * @param monitor the newly-created monitor
 	 */
 	public void monitorAdded(IMonitor monitor);
 	
 	/**
-	 * This method is being called when a monitor is changed.
+	 * Notification that the given monitor has been changed.
+     * Note that the monitor is never a working copy.
 	 * 
 	 * @param monitor the monitor that has been changed
 	 */
 	public void monitorChanged(IMonitor monitor);
 	
 	/**
-	 * This method is being called when a monitor is removed.
+	 * Notification that the given monitor has been deleted (removed
+	 * from the global list of known monitors).
 	 * 
-	 * @param monitor the monitor that has been removed
+	 * @param monitor the monitor that has been deleted
 	 */
 	public void monitorRemoved(IMonitor monitor);
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IMonitorWorkingCopy.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IMonitorWorkingCopy.java
index ab49196..f35c419 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IMonitorWorkingCopy.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IMonitorWorkingCopy.java
@@ -9,8 +9,15 @@
  *    IBM - Initial API and implementation
  **********************************************************************/
 package org.eclipse.wst.internet.monitor.core;
+
+import org.eclipse.core.runtime.CoreException;
 /**
- * Represents a working copy of a monitor. A working copy is a copy that the attributes can be changed.
+ * Represents a working copy of a monitor. A working copy is a copy that the
+ * attributes can be changed.
+ * IMonitorWorkingCopy is thread-safe. However, working copies instances
+ * should be short-lived to reduce the chance of multiple working copies
+ * being created by different clients and one client overwritting changes
+ * made to the other working copy. 
  * <p>
  * This interface is not intended to be implemented by clients.
  * </p>
@@ -19,39 +26,70 @@
  */
 public interface IMonitorWorkingCopy extends IMonitor {
 	/**
-	 * Set the remote (server) host name.
+	 * Returns the original monitor that this working copy corresponds to, or
+	 * <code>null</code> if this working copy was just created from
+	 * MonitorCore.createMonitor().
 	 * 
-	 * @param host the new host name
+	 * @return the original monitor, or <code>null</code> if this working copy
+	 *    was just created
 	 */
-	public void setRemoteHost(String host);
+	public IMonitor getOriginal();
 
 	/**
-	 * Set the remote (server) host port number.
-	 * 
-	 * @param port the new port number
-	 */
-	public void setRemotePort(int port);
-
-	/**
-	 * Set the local (client) port number.
+	 * Sets the local port number of the client to be monitored.
 	 * 
 	 * @param port the local (client) port number
+	 * @see IMonitor#getLocalPort()
 	 */
 	public void setLocalPort(int port);
 
 	/**
-	 * Set the protocol adapter. This protocol adapter is responsible for translating 
-	 * network traffic between the server and the client.
+	 * Sets the remote host name of the server to be monitored.
 	 * 
-	 * @param type the protocol adapter.
-	 * 
+	 * @param host the new remote host name
+	 * @see IMonitor#getRemoteHost()
 	 */
-	public void setProtocolAdapter(IProtocolAdapter protocolAdapter);
+	public void setRemoteHost(String host);
 
 	/**
-	 * Saves the changes to this working copy and returns the resulting monitor.
-	 *
-	 * @return the modified or created monitor
+	 * Sets the remote port number of the server to be monitored.
+	 * 
+	 * @param port the new remote port number
+	 * @see IMonitor#getRemotePort()
 	 */
-	public IMonitor save();
+	public void setRemotePort(int port);
+
+	/**
+	 * Sets the protocol to be used to read network
+	 * traffic between the server and the client.
+	 * 
+	 * @param protocolId the protocol id
+	 * @see IMonitor#getProtocol()
+	 */
+	public void setProtocol(String protocolId);
+
+	/**
+	 * Saves the changes made to this working copy.
+	 * For a brand new working copy (created by
+	 * {@link MonitorCore#createMonitor()}, and not yet saved), this method
+	 * creates a new monitor instance with attributes matching this working copy.
+	 * For a working copy cloned from an existing monitor instance (by
+	 * {@link IMonitor#createWorkingCopy()}), this method stops the existing
+	 * monitor (using {@link MonitorCore#stopMonitor(IMonitor)}) if necessary,
+	 * and then sets the attributes of the monitor instance to match this
+	 * working copy (the monitor instance is returned).
+	 * <p>
+	 * Saving a working copy for a monitor that was already deleted will cause
+	 * the monitor to get recreated (with any changes in the working copy).
+	 * </p>
+	 * <p>
+	 * This method throws a CoreException if there is a problem saving the
+	 * monitor. No validation checks occur when saving the monitor. This can be
+	 * done by calling IMonitor.validate() prior to saving.
+	 * </p>
+	 *
+	 * @return the affected monitor
+	 * @throws CoreException thrown if a problem occurs while saving the monitor 
+	 */
+	public IMonitor save() throws CoreException;
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IProtocolAdapter.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IProtocolAdapter.java
deleted file mode 100644
index 62f1105..0000000
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IProtocolAdapter.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**********************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- *    IBM - Initial API and implementation
- **********************************************************************/
-package org.eclipse.wst.internet.monitor.core;
-/**
- * A protocol adapter allows the monitor to support a new protocol between a client
- * and server, and manages the message passing between the two.
- * The global list of known protocol adapters is available via
- * {@link MonitorCore.getProtocolAdapters()}.
- * <p>
- * This interface is not intended to be implemented by clients.
- * </p>
- * @since 1.0
- */
-public interface IProtocolAdapter {
-	/**
-	 * Returns the id of this adapter.
-	 * Each adapter has a distinct, fixed id. Ids are intended to be used internally as keys;
-	 * they are not intended to be shown to end users.
-	 * 
-	 * @return the element id
-	 */
-	public String getId();
-
-	/**
-	 * Returns the displayable (translated) name for this adapter.
-	 *
-	 * @return a displayable name
-	 */
-	public String getName();
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IRequest.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IRequest.java
index ab7e3de..32deb9d 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IRequest.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IRequest.java
@@ -14,8 +14,41 @@
 
 import org.eclipse.core.runtime.IAdaptable;
 /**
- * Represents a request that has been made between the client and a server.
- * The global list of known requests is available via {@link MonitorCore.getRequests()}.
+ * Represents a request made between the client and the server.
+ * <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>
+ * [issue: Would it be fair to say that these are TCP/IP requests?]
+ * [issue: Is this always a request-response pair where the request
+ * went from client to server, and the response from server to client?
+ * Or are there a separate IRequest objects for responses?]
+ * </p>
+ * <p>
+ * [issue: Since the intent is that someone should be able to define 
+ * a new protocol adapter, that party will need to be able to create
+ * IRequest objects and register them along with the other. Currently,
+ * there is no way to do this at the API. The class Request
+ * is the only code that knows about the MonitorManager (also internal)
+ * that maintains the global list of requests. But Request is itself internal,
+ * meaning that the protocol adapter provider would be out of luck.
+ * The wisdom is: If you contribute an extension to your own extension
+ * point, and the intent is that other can do likewise, then it's important to
+ * write your extensions following the same rules you're expect others to
+ * follow.
+ * ]
+ * </p>
+ * <p>
+ * This interface is intended to be implemented only by clients
+ * to extend the <code>protocolAdapters</code> extension point. 
+ * </p>
+ * <p>
+ * [issue: It would probably be better for the API to provide a concrete, final
+ * Request class that the protocol adapter delegate would simply
+ * instantiate.]
+ * </p>
  * 
  * @since 1.0
  */
@@ -48,14 +81,18 @@
 	public static final int ALL = 3;
 
 	/**
-	 * Return the protocol adapter of the request.
+	 * Returns the protocol responsible for creating this request.
+	 * <p>
+	 * [issue: If the response was linked to the monitor that's listening to
+	 * the conversation, this method would not be necessary.]
+	 * </p>
 	 * 
-	 * @return org.eclipse.wst.internet.monitor.core.IProtocolAdapter
+	 * @return the protocol id
 	 */
-	public IProtocolAdapter getProtocolAdapter();
+	public String getProtocol();
 
 	/**
-	 * Return the date/time of this request.
+	 * Returns the time this request was made.
 	 *
 	 * @return the timestamp
 	 */
@@ -83,76 +120,104 @@
 	public int getRemotePort();
 
 	/**
-	 * Returns the request as a byte array.
+	 * 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 (IRequest.X)
-	 * @return the request content
+	 * @param type the content type: one of {@link #TRANSPORT},
+	 * {@link #CONTENT}, or {@link #ALL}
+	 * @return the content bytes
 	 */
 	public byte[] getRequest(int type);
 
 	/**
-	 * Returns the response as a byte array.
+	 * 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 (IRequest.X)
-	 * @return the response content
+	 * @param type the content type: one of {@link #TRANSPORT},
+	 * {@link #CONTENT}, or {@link #ALL}
+	 * @return the content bytes
 	 */
 	public byte[] getResponse(int type);
 
 	/**
-	 * Returns the response time in milliseconds.
+	 * 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
+	 * @return the server's response time, or -1 if there has been no
+	 *    response yet
 	 */
 	public long getResponseTime();
 
 	/**
 	 * Returns a label for this request.
+	 * <p>
+	 * [issue: At the core level, these objects probably should
+	 * not have labels or anything like that. They are just objects.
+	 * The current implementation uses getHost()+":"+getPort(),
+	 * which is not even unique between requests.
+	 * If a client needs a label, it is better to let them compute
+	 * one. This method should be deleted.]
+	 * </p>
 	 *
 	 * @return the label
 	 */
 	public String getLabel();
 
 	/**
-	 * Add a property to the request.
+	 * Sets the given key-value property on this request. To remove a property,
+	 * set the value to null.
+	 * <p>
+	 * [issue: Is this supposed to be called by the protocol
+	 * adapter (only)?]
+	 * </p>
 	 * 
-	 * @param key the key of the property to be added
-	 * @param value the value of the property to be added
+	 * @param key the key
+	 * @param value the value
 	 */
-	public void addProperty(String key, Object value);
+	public void setProperty(String key, Object value);
 
 	/**
-	 * Get a string property with a given key from the request.
+	 * 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 key of the property
-	 * @return the value of property
+	 * @param key the property key 
+	 * @return the property value
 	 */
-	public String getStringProperty(String key);
+	public Object getProperty(String key);
 
 	/**
-	 * Get a integer property with a given key from the request.
-	 * 
-	 * @param key the key of the property
-	 * @return the value of property
-	 */
-	public Integer getIntegerProperty(String key);
-
-	/**
-	 * Get a property with a given key from the request.
-	 * 
-	 * @param key the key of the property
-	 * @return the value of property
-	 */
-	public Object getObjectProperty(String key);
-
-	/**
-	 * Hook to allow other plugins that implement IRequest to fire a change event.
+	 * Hook to allow other plug-ins that implement IRequest to fire a change event.
 	 * After the internal values have changed, call this method to invoke a request
 	 * change event to all registered listeners.
+	 * <p>
+	 * [issue: This doesn't make sense as a method on an interface, since
+	 * anyone implementing this interface themselves would be unable to do
+	 * anything meaningful. It only makes sense in a world where the protocol
+	 * adapter is subclassing or instantiating a class that provides a
+	 * built-in implementation of this method.]
+	 * </p>
 	 */
-	public void fireChangedEvent();
+	//public void fireChangedEvent();
 
 	/**
-	 * Add a resend request to this request.
+	 * Adds a resend request to this request.
+	 * <p>
+	 * [issue: Explain what a resend request is and how they
+	 * would be used. Who is expect to call this method? The protocol adapter
+	 * delegate? If yes, why does it need to be exposed at API?]
+	 * </p>
 	 * 
 	 * @param request the resend request to add
 	 */
@@ -160,8 +225,13 @@
 
 	/**
 	 * Returns an array of resend requests based on this request. 
+	 * <p>
+	 * [issue: Explain what a resend request is and how they
+	 * would be used. Who is expect to call this method? The protocol adapter
+	 * delegate? If yes, why does it need to be exposed at API?]
+	 * </p>
 	 * 
-	 * @return The array of resend requests based on this request
+	 * @return the array of resend requests based on this request
 	 */
 	public IResendRequest[] getResendRequests();
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IRequestListener.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IRequestListener.java
index 02dbb08..6695c5c 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IRequestListener.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IRequestListener.java
@@ -10,29 +10,41 @@
  **********************************************************************/
 package org.eclipse.wst.internet.monitor.core;
 /**
- * A listener for changes to the requests.
+ * Listener for changes affecting the global list of outstanding
+ * message traffic between monitored clients and servers.
+ * <p>
+ * [issue: When the global list of requests goes away, this
+ * interface should be "re-purposed" to notify an interested
+ * party that a request has just passed between the
+ * monitor's client and server; e.g., message(IRequest).
+ * ]
+ * [issue: This is related to an issue flagged on 
+ * MonitorCore.getRequests(). If a client creates a particular
+ * monitor, expect them to be interested only in requests on that
+ * monitor. Either pass the relevant monitor as a parameter
+ * to these methods, or make it easy for a client to find this
+ * info out from the IRequest itself.]
+ * </p>
  * 
+ * @see IMonitor#addRequestListener(IRequestListener)
  * @since 1.0
  */
 public interface IRequestListener {
 	/**
-	 * The given request has been added to the list.
+	 * Notification that the given request was created.
 	 * 
 	 * @param request the request that has been added
 	 */
 	public void requestAdded(IRequest request);
-	
+
 	/**
-	 * The given request has been changed.
+	 * Notification that the given request has been changed.
+	 * <p>
+	 * [issue: Requests can't change after they are created,
+	 * can they?]
+	 * </p>
 	 * 
 	 * @param request the request that has been changed
 	 */
 	public void requestChanged(IRequest request);
-	
-	/**
-	 * The given request is been removed from the list.
-	 * 
-	 * @param request the request that has been removed
-	 */
-	public void requestRemoved(IRequest request);
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IResendRequest.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IResendRequest.java
index 6a6baaa..27428ef 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IResendRequest.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/IResendRequest.java
@@ -9,40 +9,59 @@
  *    IBM - Initial API and implementation
  **********************************************************************/
 package org.eclipse.wst.internet.monitor.core;
+
 /**
- * A representation of a request that is to be resent. This interface is not
- * meant to be implemented by clients.
+ * A representation of a request that is to be resent.
+ * Resend requests are used when a client wants to modify and resend a
+ * previously monitored request back to the server.
  * <p>
- * Resend requests are used when a client wants to modify and resend a previously
- * monitored request back to the server.
+ * [issue: This violates the premise that
+ * the monitor merely monitors traffic between client and server.]
+ * </p>
+ * <p>
+ * This interface is not meant to be implemented by clients.
+ * </p>
+ * <p>
+ * [issue: From looking at implemenation, resend request are HTTP-specific.
+ * It is unclear how to make sense of these in an open-ended world of
+ * protocols including simple TCP/IP.]
+ * </p>
+ * <p>
+ * [issue: There seems to be no way for a protocol adapter to 
+ * create one of these objects.]
  * </p>
  * 
  * @since 1.0
  */
 public interface IResendRequest extends IRequest {
+	
 	/**
-	 * Send the request
+	 * Sends this request.
 	 */
 	public void sendRequest();
 
 	/**
-	 * Returns <code>true</code> if this request has been sent, and
-	 * <code>false</code> otherwise.
+	 * Returns whether this request has been sent.
 	 * 
-	 * @return <code>true</code> if this request has been sent, <code>false</code> otherwise
+	 * @return <code>true</code> if this request has been sent,
+	 * and <code>false</code> otherwise
 	 */
 	public boolean hasBeenSent();
 
 	/**
-	 * Set the request.
+	 * Sets the bytes that make up the select portion of the request.
+	 * <p>
+	 * [issue: Again, I don't know how to explain this.
+	 * </p>
 	 * 
 	 * @param request the request to set
-	 * @param type the type of the request to set
+	 * @param type the content type: one of {@link IRequest#TRANSPORT},
+	 * {@link IRequest#CONTENT}, or {@link IRequest#ALL}
 	 */
 	public void setRequest(byte[] request, int type);
 
 	/**
-	 * Get the original request that this request is based on.
+	 * Returns the original request that this request is based on.
 	 * 
 	 * @return the original request that this request is based on, or
 	 *    <code>null</code> if there is none
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/MonitorCore.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/MonitorCore.java
index a8c58f5..6364e3a 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/MonitorCore.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/MonitorCore.java
@@ -10,50 +10,33 @@
  **********************************************************************/
 package org.eclipse.wst.internet.monitor.core;
 
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.InputStreamReader;
 import java.util.List;
 
 import org.eclipse.wst.internet.monitor.core.internal.MonitorManager;
 import org.eclipse.wst.internet.monitor.core.internal.MonitorPlugin;
-import org.eclipse.wst.internet.monitor.core.internal.Trace;
+import org.eclipse.wst.internet.monitor.core.internal.Request;
 import org.eclipse.wst.internet.monitor.core.internal.http.ResendHTTPRequest;
 /**
- * Base class for obtaining references to monitor models. This class also provide methods
- * to do operations on a monitor.
+ * Main class for creating new monitors and locating existing ones. The methods on
+ * this class are thread safe.
+ * <p>
+ * This class provides all functionality through static members. It is not intended
+ * to be instantiated or subclassed.
+ * </p>
  * 
  * @since 1.0
  */
-public class MonitorCore {
-	/**
-	 * Protocol adapter id (value "TCPIP") for TCP/IP. Provided here for convenience;
-	 * other protocol adapters may be available.
-	 * 
-	 * @see #findProtocolAdapter(String)
-	 */
-	public static String TCPIP_PROTOCOL_ID = "TCPIP";
-
-	/**
-	 * Protocol adapter id (value "HTTP") for HTTP. Provided here for convenience;
-	 * other protocol adapters may be available.
-	 * 
-	 * @see #findProtocolAdapter(String)
-	 */
-	public static String HTTP_PROTOCOL_ID = "HTTP";
-
+public final class MonitorCore {
 	private static MonitorManager manager = MonitorManager.getInstance();
-	
-	private static final String lineSeparator = System.getProperty("line.separator");
-	
+
 	/**
-	 * Returns an array of all known monitor instances. The list will not contain any
-	 * working copies.
+	 * Returns a list of all known monitor instances. The list will not contain any
+	 * working copies and is persisted between workbench sessions.
 	 * <p>
-	 * A new array is returned on each call, so clients may store or modify the result.
+	 * A new array is returned on each call; clients may safely store or modify the result.
 	 * </p>
 	 * 
-	 * @return a possibly-empty array of monitor instances {@link IMonitor}
+	 * @return a possibly-empty array of monitor instances
 	 */
 	public static IMonitor[] getMonitors() {
 		List list = manager.getMonitors();
@@ -61,97 +44,62 @@
 		list.toArray(m);
 		return m;
 	}
-	
+
 	/**
-	 * Create a new monitor. The monitor will not exist for use until
-	 * the save() method has been called.
+	 * Creates a new monitor working copy. After configuring parameters on
+	 * the working copy, calling {@link IMonitorWorkingCopy#save()} brings
+	 * the monitor into existence.
+	 * <p>
+	 * Note that the client is responsible for calling {@link IMonitor#delete()}
+	 * to delete the monitor once it is no longer needed.
+	 * </p>
+	 * <p>
+	 * When monitors are created, the local and remote port values default to
+	 * <code>80</code>, but they do not have a protocol or remote host (values
+	 * are <code>null</code>).
+	 * </p> 
 	 * 
-	 * @return a working copy of the created monitor
+	 * @return a monitor working copy
 	 */
 	public static IMonitorWorkingCopy createMonitor() {
 		return manager.createMonitor();
 	}
-	
-	/**
-	 * Start the given monitor listening on it's client port.
-	 * The monitor must not be null.
-	 * 
-	 * @param monitor the monitor to be started
-	 * @throws Exception thrown if the monitor fails to start because the port
-	 *    is in use or another problem occurs
-	 */
-	public static void startMonitor(IMonitor monitor) throws Exception {
-		if (monitor == null)
-			throw new IllegalArgumentException();
-		manager.startMonitor(monitor);
-	}
-	
-	/**
-	 * Stop the given monitor and removes all resources.
-	 * The monitor must not be null.
-	 * 
-	 * @param monitor the monitor to be stopped
-	 */
-	public static void stopMonitor(IMonitor monitor) {
-		if (monitor == null)
-			throw new IllegalArgumentException();
-		manager.stopMonitor(monitor);
-	}
-	
-	/**
-	 * Returns an array of all known protocol adapter instances.
-	 * <p>
-	 * A new array is returned on each call, so clients may store or modify the result.
-	 * </p>
-	 * 
-	 * @return a possibly-empty array of protocol adapter instances {@link IProtocolAdater}
-	 */
-	public static IProtocolAdapter[] getProtocolAdapters() {
-		return MonitorPlugin.getInstance().getProtocolAdapters();
-	}
-	
-	/**
-	 * Returns the protocol adapter with the given id, or <code>null</code>
-	 * if none. This convenience method searches the list of known
-	 * protocol adapter ({@link #getProtocolAdapters()}) for the one with a
-	 * matching id ({@link IProtocolAdater#getId()}). The id may not be null.
-	 *
-	 * @param the protocol adapter id
-	 * @return the protocol adapter instance, or <code>null</code> if there
-	 *   is no protocol adapter with the given id
-	 */
-	public static IProtocolAdapter findProtocolAdapter(String id) {
-		return MonitorPlugin.getInstance().getProtocolAdapter(id);
-	}
-	
+
 	/**
 	 * Returns an array of all known content filters.
 	 * <p>
-	 * A new array is returned on each call, so clients may store or modify the result.
+	 * Content filters are registered via the <code>contentFilters</code>
+	 * extension point in the <code>org.eclipse.wst.internet.monitor.core</code>
+	 * plug-in.
+	 * </p>
+	 * <p>
+	 * A new array is returned on each call; clients may safely store or modify the result.
 	 * </p>
 	 * 
-	 * @return a possibly-empty array of content filter instances {@link IContentFilter}
+	 * @return a possibly-empty array of content filter instances
 	 */
 	public static IContentFilter[] getContentFilters() {
 		return MonitorPlugin.getInstance().getContentFilters();
 	}
-	
+
 	/**
 	 * Returns the content filter with the given id, or <code>null</code>
 	 * if none. This convenience method searches the list of known
 	 * content filters ({@link #getContentFilters()}) for the one with a
-	 * matching id ({@link IContentFilter#getId()}). The id may not be null.
+	 * matching id ({@link IContentFilter#getId()})
 	 *
-	 * @param the content filter id
+	 * @param the content filter id; must not be <code>null</code>
 	 * @return the content filter instance, or <code>null</code> if there
 	 *   is no content filter with the given id
 	 */
 	public static IContentFilter findContentFilter(String id) {
-		return MonitorPlugin.getInstance().getContentFilter(id);
+		if (id == null)
+			throw new IllegalArgumentException();
+		return MonitorPlugin.getInstance().findContentFilter(id);
 	}
-	
+
 	/**
-	 * Add a monitor listener.
+	 * Adds a monitor listener.
 	 * Once registered, a listener starts receiving notification of 
 	 * changes to the monitors. The listener continues to receive
 	 * notifications until it is removed.
@@ -161,6 +109,8 @@
 	 * @see #removeMonitorListener(IMonitorListener)
 	 */
 	public static void addMonitorListener(IMonitorListener listener) {
+		if (listener == null)
+			throw new IllegalArgumentException();
 		manager.addMonitorListener(listener);
 	}
 
@@ -172,97 +122,26 @@
 	 * @see #addMonitorListener(IMonitorListener)
 	 */
 	public static void removeMonitorListener(IMonitorListener listener) {
+		if (listener == null)
+			throw new IllegalArgumentException();
 		manager.removeMonitorListener(listener);
 	}
 
 	/**
-	 * Returns an array of all known request instances.
+	 * Creates a new resend request from the given request.
 	 * <p>
-	 * A new array is returned on each call, so clients may store or modify the result.
+	 * [issue: This method seems to be HTTP-specific. It would be hard to
+	 * specify what it would mean for other protocols. It also violates the
+	 * premise that the monitor merely monitors traffic between client and
+	 * server. This method should be deleted.]
 	 * </p>
 	 * 
-	 * @return a possibly-empty array of request instances {@link IRequest}
-	 */
-	public static IRequest[] getRequests() {
-		List list = manager.getRequests();
-		IRequest[] r = new IRequest[list.size()];
-		list.toArray(r);
-		return r;
-	}
-	
-	/**
-	 * Remove all requests. This method clears all requests and their data
-	 * from the buffer and notifies the request listeners.
-	 */
-	public static void removeAllRequests() {
-		manager.removeAllRequests();
-	}
-	
-	/**
-	 * Add a request listener.
-	 * Once registered, a listener starts receiving notification of 
-	 * changes to the requests. The listener continues to receive
-	 * notifications until it is removed.
-	 * Has no effect if an identical listener is already registered.
-	 *
-	 * @param listener the request listener
-	 * @see #removeRequestListener(IRequestListener)
-	 */
-	public static void addRequestListener(IRequestListener listener) {
-		manager.addRequestListener(listener);
-	}
-
-	/**
-	 * Removes the given request listener. Has no
-	 * effect if the listener is not registered.
-	 * 
-	 * @param listener the listener
-	 * @see #addRequestListener(IRequestListener)
-	 */
-	public static void removeRequestListener(IRequestListener listener) {
-		manager.removeRequestListener(listener);
-	}
-	
-	/**
-	 * Convenience method to parse the given bytes into String form. The bytes
-	 * are parsed into a line delimited string. The byte array must not be null.
-	 * 
-	 * @param b a byte array
-	 * @return the string after the conversion
-	 */
-	public static String parse(byte[] b) {
-		if (b == null)
-			throw new IllegalArgumentException();
-
-		ByteArrayInputStream bin = new ByteArrayInputStream(b);
-		BufferedReader br = new BufferedReader(new InputStreamReader(bin));
-		StringBuffer sb = new StringBuffer();
-		try {
-			String s = br.readLine();
-			
-			while (s != null) {
-				sb.append(s);
-				s = br.readLine();
-				if (s != null)
-					sb.append(lineSeparator);
-			}
-		} catch (Exception e) {
-			Trace.trace(Trace.SEVERE, "Error parsing input", e);
-		}
-		
-		return sb.toString();
-	}
-
-	/**
-	 * Create and return an new IResendRequest from the specified request.
-	 * The request may not be null.
-	 * 
-	 * @param request the request that is to be resent
-	 * @return a new IResendRequest based on the specified request
+	 * @param request the request that is to be resent; may not be <code>null</code>
+	 * @return a new resend request
 	 */
 	public static IResendRequest createResendRequest(IRequest request) {
 		if (request == null)
 			throw new IllegalArgumentException();
-		return new ResendHTTPRequest(request);
+		return new ResendHTTPRequest(((Request)request).getMonitor(), request);
 	}
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/ProtocolAdapterDelegate.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/ProtocolAdapterDelegate.java
deleted file mode 100644
index 7b10e7c..0000000
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/ProtocolAdapterDelegate.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/**********************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- *    IBM - Initial API and implementation
- **********************************************************************/
-package org.eclipse.wst.internet.monitor.core;
-
-import java.io.IOException;
-import java.net.Socket;
-/**
- * A protocol adapter allows the monitor to support a new protocol between a client
- * and server, and manages the message passing between the two.
- * <p>
- * This abstract class is intended to be extended only by clients
- * to extend the <code>protocolAdapters</code> extension point.
- * </p>
- * 
- * @since 1.0
- */
-public abstract class ProtocolAdapterDelegate {
-	/**
-	 * Attaches the protocol adapter to the given monitor using the input and output socket.
-	 * The adapter is responsible for:
-	 *    * opening the input & output streams to pass information from the input socket
-	 *      (the client) to the output socket (server).
-	 *    * passing information from the output socket (server) back to the client.
-	 *    * creating and populating new org.eclipse.wst.internet.monitor.core.IRequest objects as necessary.
-	 *    * closing/cleanup on the input and output sockets.
-	 * 
-	 * @param monitor the monitor that uses this protocol adapter
-	 * @param in the input socket of the monitor client
-	 * @param out the output socket of the monitor server
-	 * @throws IOException if an exception occur when opening the streams of the input or 
-	 *         output sockets.   
-	 */
-	public abstract void connect(IMonitor monitor, Socket in, Socket out) throws IOException;
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/AcceptThread.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/AcceptThread.java
index 6f1eccb..efa7be6 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/AcceptThread.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/AcceptThread.java
@@ -28,7 +28,8 @@
 	
 	class ServerThread extends Thread {
 		/**
-		 * Actual running of the server proxy.
+		 * ServerThread accepts incoming connections and delegates to the protocol
+		 * adapter to deal with the connection.
 		 */
 	   public void run() {
 		   // create a new server socket
@@ -51,7 +52,8 @@
 				   Socket remoteSocket = new Socket(monitor.getRemoteHost(), monitor.getRemotePort());
 		
 				   // relay the call through
-				   ProtocolAdapter adapter = (ProtocolAdapter) monitor.getProtocolAdapter();
+				   String protocolId = monitor.getProtocol();
+				   ProtocolAdapter adapter = MonitorPlugin.getInstance().getProtocolAdapter(protocolId);
 				   adapter.parse(monitor, localSocket, remoteSocket);
 			   } catch (InterruptedIOException e) {
 			   	// do nothing
@@ -64,7 +66,7 @@
 	}
 
 	/**
-	 * ServerMonitorThread constructor comment.
+	 * AcceptThread constructor comment.
 	 */
 	public AcceptThread(IMonitor monitor) {
 		super();
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/IProtocolAdapter.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/IProtocolAdapter.java
new file mode 100644
index 0000000..1c7a7bf
--- /dev/null
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/IProtocolAdapter.java
@@ -0,0 +1,68 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.internet.monitor.core.internal;
+
+import org.eclipse.wst.internet.monitor.core.IMonitorWorkingCopy;
+import org.eclipse.wst.internet.monitor.core.MonitorCore;
+/**
+ * A protocol adapter enables a monitor to support a particular network
+ * protocol used to communicate between a client and server.
+ * <p>
+ * Protocol adapters are registered via the <code>protocolAdapaters</code>
+ * extension point in the <code>org.eclipse.wst.internet.monitor.core</code>
+ * plug-in. The global list of known protocol adapters is available via
+ * {@link MonitorCore.getProtocolAdapters()}. Standard protocol
+ * adapters for {@linkplain #HTTP_PROTOCOL_ID HTTP} and
+ * {@linkplain #TCPIP_PROTOCOL_ID TCP/IP} are built-in.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ * <p>
+ * [issue: Would it be fair to say that we're only talking about other protocols
+ * that are based on TCP/IP? IRequest does seem pretty TCP/IP specific.]
+ * </p>
+ * 
+ * @see IMonitorWorkingCopy#setProtocolAdapter(IProtocolAdapter)
+ * @since 1.0
+ */
+public interface IProtocolAdapter {
+	/**
+	 * Protocol adapter id (value {@value}) for TCP/IP.
+	 * The TCP/IP protocol adapter is standard.
+	 * 
+	 * @see MonitorCore#findProtocolAdapter(String)
+	 */
+	public static String TCPIP_PROTOCOL_ID = "TCP/IP";
+
+	/**
+	 * Protocol adapter id (value {@value}) for HTTP.
+	 * The HTTP protocol adapter is standard.
+	 * 
+	 * @see MonitorCore#findProtocolAdapter(String)
+	 */
+	public static String HTTP_PROTOCOL_ID = "HTTP";
+
+	/**
+	 * Returns the id of this adapter.
+	 * Each adapter has a distinct, fixed id. Ids are intended to be used
+	 * internally as keys; they are not intended to be shown to end users.
+	 * 
+	 * @return the element id
+	 */
+	public String getId();
+
+	/**
+	 * Returns the displayable (translated) name for this adapter.
+	 *
+	 * @return a displayable name
+	 */
+	public String getName();
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/Monitor.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/Monitor.java
index b191bc5..18eb78f 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/Monitor.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/Monitor.java
@@ -10,6 +10,12 @@
  **********************************************************************/
 package org.eclipse.wst.internet.monitor.core.internal;
 
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
 import org.eclipse.wst.internet.monitor.core.*;
 /**
  * 
@@ -20,15 +26,20 @@
 	private static final String MEMENTO_REMOTE_HOST = "remote-host";
 	private static final String MEMENTO_REMOTE_PORT = "remote-port";
 	private static final String MEMENTO_TYPE_ID = "type-id";
+	
+	private static final int ADD = 0;
+	private static final int CHANGE = 1;
 
 	protected String id;
 	protected String remoteHost;
 	protected int remotePort = 80;
 	protected int localPort = 80;
-	protected IProtocolAdapter type;
+	protected String protocolId;
 	
+	protected List requestListeners = new ArrayList(2);
+
 	public Monitor() {
-		type = MonitorPlugin.getInstance().getDefaultType();
+		protocolId = MonitorPlugin.getInstance().getDefaultType();
 	}
 	
 	/* (non-Javadoc)
@@ -62,18 +73,22 @@
 	/* (non-Javadoc)
 	 * @see org.eclipse.wst.internet.monitor.internal.IMonitor#isHTTPEnabled()
 	 */
-	public IProtocolAdapter getProtocolAdapter() {
-		return type;
+	public String getProtocol() {
+		return protocolId;
 	}
 
 	/* (non-Javadoc)
 	 * @see org.eclipse.wst.internet.monitor.internal.IMonitor#isRunning()
 	 */
 	public boolean isRunning() {
+		if (isWorkingCopy())
+			return false;
 		return MonitorManager.getInstance().isRunning(this);
 	}
 	
 	public void delete() {
+		if (isWorkingCopy())
+			return;
 		MonitorManager.getInstance().removeMonitor(this);
 	}
 
@@ -81,7 +96,7 @@
 		return false;
 	}
 	
-	public IMonitorWorkingCopy getWorkingCopy() {
+	public IMonitorWorkingCopy createWorkingCopy() {
 		return new MonitorWorkingCopy(this);
 	}
 	
@@ -90,12 +105,12 @@
 		remoteHost = monitor.getRemoteHost();
 		remotePort = monitor.getRemotePort();
 		localPort = monitor.getLocalPort();
-		type = monitor.getProtocolAdapter();
+		protocolId = monitor.getProtocol();
 	}
 	
 	protected void save(IMemento memento) {
 		memento.putString(MEMENTO_ID, id);
-		memento.putString(MEMENTO_TYPE_ID, type.getId());
+		memento.putString(MEMENTO_TYPE_ID, protocolId);
 		memento.putInteger(MEMENTO_LOCAL_PORT, localPort);
 		memento.putString(MEMENTO_REMOTE_HOST, remoteHost);
 		memento.putInteger(MEMENTO_REMOTE_PORT, remotePort);
@@ -103,7 +118,7 @@
 
 	protected void load(IMemento memento) {
 		id = memento.getString(MEMENTO_ID);
-		type = MonitorPlugin.getInstance().getProtocolAdapter(memento.getString(MEMENTO_TYPE_ID));
+		protocolId = memento.getString(MEMENTO_TYPE_ID);
 		Integer temp = memento.getInteger(MEMENTO_LOCAL_PORT);
 		if (temp != null)
 			localPort = temp.intValue();
@@ -112,4 +127,171 @@
 		if (temp != null)
 			remotePort = temp.intValue();
 	}
+	
+	/*
+	 * Starts the given monitor listening on its client port.
+	 */
+	public synchronized void start() throws CoreException {
+		if (isRunning())
+			return;
+		if (isWorkingCopy() || !MonitorManager.getInstance().exists(this))
+			throw new IllegalArgumentException();
+		
+		IStatus status = validate();
+		if (!status.isOK())
+			throw new CoreException(status);
+		
+		MonitorManager.getInstance().startMonitor(this);
+	}
+	
+	/*
+	 * Stops the given monitor and frees up all underlying operating 
+	 * system resources.
+	 */
+	public synchronized void stop() {
+		if (isWorkingCopy() || !MonitorManager.getInstance().exists(this))
+			throw new IllegalArgumentException();
+		if (!isRunning())
+			return;
+		MonitorManager.getInstance().stopMonitor(this);
+	}
+	
+	/*
+	 * Adds a request listener.
+	 */
+	public synchronized void addRequestListener(IRequestListener listener) {
+		if (listener == null)
+			throw new IllegalArgumentException();
+		if (!requestListeners.contains(listener))
+			requestListeners.add(listener);
+	}
+	
+	/*
+	 * Removes the given request listener. Has no
+	 * effect if the listener is not registered.
+	 */
+	public synchronized void removeRequestListener(IRequestListener listener) {
+		if (listener == null)
+			throw new IllegalArgumentException();
+		requestListeners.remove(listener);
+	}
+	
+	/**
+	 * Fire a request event.
+	 * @param rr
+	 * @param type
+	 */
+	protected void fireRequestEvent(IRequest rr, int type) {
+		int size = requestListeners.size();
+		IRequestListener[] xrl = MonitorPlugin.getInstance().getRequestListeners();
+		int size2 = xrl.length;
+		
+		IRequestListener[] rl = new IRequestListener[size + size2];
+		System.arraycopy(xrl, 0, rl, 0, size2);
+		for (int i = 0; i < size; i++)
+			rl[size2 + i] = (IRequestListener) requestListeners.get(i);
+
+		for (int i = 0; i < size + size2; i++) {
+			IRequestListener listener = rl[i];
+			if (type == ADD)
+				listener.requestAdded(rr);
+			else if (type == CHANGE)
+				listener.requestChanged(rr);
+		}
+	}
+	
+	/**
+	 * Add a new request response pair.
+	 */
+	public void addRequest(IRequest rr) {
+		fireRequestEvent(rr, ADD);
+	}
+
+	public void requestChanged(IRequest rr) {
+		fireRequestEvent(rr, CHANGE);
+	}
+	
+	public IStatus validate() {
+		if (localPort < 0)
+			return new Status(IStatus.ERROR, MonitorPlugin.PLUGIN_ID, 0, MonitorPlugin.getString("%errorInvalidLocalPort"), null);
+		
+		if (remotePort < 0)
+			return new Status(IStatus.ERROR, MonitorPlugin.PLUGIN_ID, 0, MonitorPlugin.getString("%errorInvalidRemotePort"), null);
+		
+		if (remoteHost == null || remoteHost.length() == 0 || !isValidHostname(remoteHost))
+			return new Status(IStatus.ERROR, MonitorPlugin.PLUGIN_ID, 0, MonitorPlugin.getString("%errorInvalidRemoteHost"), null);
+		
+		if (isLocalhost(remoteHost) && localPort == remotePort)
+			return new Status(IStatus.ERROR, MonitorPlugin.PLUGIN_ID, 0, MonitorPlugin.getString("%errorInvalidLocalPort"), null);
+	
+		return new Status(IStatus.OK, MonitorPlugin.PLUGIN_ID, 0, MonitorPlugin.getString("%monitorValid"), null);
+	}
+
+	protected static boolean isValidHostname(String host) {
+		if (host == null || host.trim().length() < 1)
+			return false;
+		
+		int length = host.length();
+		for (int i = 0; i < length; i++) {
+			char c = host.charAt(i);
+			if (!Character.isLetterOrDigit(c) && c != ':' && c != '.')
+				return false;
+		}
+		if (host.endsWith(":"))
+			return false;
+		return true;
+	}
+
+	protected static boolean isLocalhost(String host) {
+		if (host == null)
+			return false;
+		try {
+			if ("localhost".equals(host) || "127.0.0.1".equals(host))
+				return true;
+			InetAddress localHostaddr = InetAddress.getLocalHost();
+			if (localHostaddr.getHostName().equals(host))
+				return true;
+		} catch (Exception e) {
+			Trace.trace(Trace.WARNING, "Error checking for localhost", e);
+		}
+		return false;
+	}
+	
+	public String toString() {
+		return "Monitor [" + getId() + ", " + getProtocol() + ", " + getLocalPort() + ", "
+			+ getRemoteHost() + ", " + getRemotePort() + "]";
+	}
+	
+	public boolean equals(Object obj) {
+		if (!(obj instanceof Monitor))
+			return false;
+		
+		IMonitor m = (IMonitor) obj;
+		if (m.isWorkingCopy()) {
+			m = ((IMonitorWorkingCopy) m).getOriginal();
+			if (m == null)
+				return false;
+		}
+		if (id == null && m.getId() != null)
+			return false;
+		if (id != null && !id.equals(m.getId()))
+			return false;
+		
+		if (localPort != m.getLocalPort())
+			return false;
+		if (remotePort != m.getRemotePort())
+			return false;
+		
+		if (remoteHost == null && m.getRemoteHost() != null)
+			return false;
+		if (remoteHost != null && !remoteHost.equals(m.getRemoteHost()))
+			return false;
+		
+		if (protocolId == null && m.getProtocol() != null)
+			return false;
+		if (protocolId != null && !protocolId.equals(m.getProtocol()))
+			return false;
+		
+		return true;
+	}
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/MonitorManager.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/MonitorManager.java
index 2e87eba..29d55d0 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/MonitorManager.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/MonitorManager.java
@@ -17,7 +17,10 @@
 import java.util.List;
 import java.util.Map;
 
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.Status;
 import org.eclipse.wst.internet.monitor.core.*;
 /**
  * 
@@ -32,12 +35,7 @@
 	protected Map threads = new HashMap();
 	
 	protected List monitorListeners = new ArrayList();
-	
-	// requests
-	protected List requests = new ArrayList();
-	
-	protected List requestListeners = new ArrayList();
-	
+
 	private Preferences.IPropertyChangeListener pcl;
 	protected boolean ignorePreferenceChanges = false;
 	
@@ -78,7 +76,7 @@
 		return new ArrayList(monitors);
 	}
 
-	protected void addMonitor(IMonitor monitor) {
+	protected synchronized void addMonitor(IMonitor monitor) {
 		if (!monitors.contains(monitor))
 			monitors.add(monitor);
 		fireMonitorEvent(monitor, ADD);
@@ -89,12 +87,12 @@
 		return (threads.get(monitor) != null);
 	}
 
-	public void startMonitor(IMonitor monitor) throws Exception {
+	public void startMonitor(IMonitor monitor) throws CoreException {
 		if (!monitors.contains(monitor))
 			return;
 		
 		if (AcceptThread.isPortInUse(monitor.getLocalPort()))
-			throw new Exception(MonitorPlugin.getString("%errorPortInUse"));
+			throw new CoreException(new Status(IStatus.ERROR, MonitorPlugin.PLUGIN_ID, 0, MonitorPlugin.getString("%errorPortInUse"), null));
 		
 		AcceptThread thread = new AcceptThread(monitor);
 		thread.startServer();
@@ -112,7 +110,7 @@
 		}
 	}
 	
-	protected void removeMonitor(IMonitor monitor) {
+	protected synchronized void removeMonitor(IMonitor monitor) {
 		if (monitor.isRunning())
 			stopMonitor(monitor);
 		monitors.remove(monitor);
@@ -120,18 +118,23 @@
 		saveMonitors();
 	}
 	
-	protected void monitorChanged(IMonitor monitor) {
+	protected synchronized void monitorChanged(IMonitor monitor) {
 		fireMonitorEvent(monitor, CHANGE);
 		saveMonitors();
 	}
 	
+	protected boolean exists(IMonitor monitor) {
+		return (monitors.contains(monitor));
+	}
+	
 	/**
 	 * Add monitor listener.
 	 * 
 	 * @param listener
 	 */
-	public void addMonitorListener(IMonitorListener listener) {
-		monitorListeners.add(listener);
+	public synchronized void addMonitorListener(IMonitorListener listener) {
+		if (!monitorListeners.contains(listener))
+			monitorListeners.add(listener);
 	}
 
 	/**
@@ -139,8 +142,9 @@
 	 * 
 	 * @param listener
 	 */
-	public void removeMonitorListener(IMonitorListener listener) {
-		monitorListeners.remove(listener);
+	public synchronized void removeMonitorListener(IMonitorListener listener) {
+		if (monitorListeners.contains(listener))
+			monitorListeners.remove(listener);
 	}
 	
 	/**
@@ -162,96 +166,8 @@
 				listener.monitorRemoved(monitor);
 		}
 	}
-	
-	/**
-	 * Returns a list of the current requests.
-	 *
-	 * @return java.util.List
-	 */
-	public List getRequests() {
-		return requests;
-	}
-	
-	/**
-	 * Add a new request response pair.
-	 *
-	 * @param pair org.eclipse.tcpip.monitor.RequestResponse
-	 */
-	public void addRequest(IRequest rr) {
-		if (requests.contains(rr))
-			return;
 
-		requests.add(rr);
-		fireRequestEvent(rr, ADD);
-	}
-	
-	public void requestChanged(IRequest rr) {
-		fireRequestEvent(rr, CHANGE);
-	}
-	
-	public void removeRequest(IRequest rr) {
-		if (!requests.contains(rr))
-			return;
-
-		requests.remove(rr);
-		fireRequestEvent(rr, REMOVE);
-	}
-	
-	public void removeAllRequests() {
-		int size = requests.size();
-		IRequest[] rrs = new IRequest[size];
-		requests.toArray(rrs);
-		
-		for (int i = 0; i < size; i++) {
-			removeRequest(rrs[i]);
-		}
-	}
-	
-	/**
-	 * Add request listener.
-	 * 
-	 * @param listener
-	 */
-	public void addRequestListener(IRequestListener listener) {
-		requestListeners.add(listener);
-	}
-
-	/**
-	 * Remove request listener.
-	 * 
-	 * @param listener
-	 */
-	public void removeRequestListener(IRequestListener listener) {
-		requestListeners.remove(listener);
-	}
-
-	/**
-	 * Fire a request event.
-	 * @param rr
-	 * @param type
-	 */
-	protected void fireRequestEvent(IRequest rr, int type) {
-		int size = requestListeners.size();
-		IRequestListener[] xrl = MonitorPlugin.getInstance().getRequestListeners();
-		int size2 = xrl.length;
-		
-		IRequestListener[] rl = new IRequestListener[size + size2];
-		System.arraycopy(xrl, 0, rl, 0, size2);
-		for (int i = 0; i < size; i++)
-			rl[size2 + i] = (IRequestListener) requestListeners.get(i);
-
-		for (int i = 0; i < size + size2; i++) {
-			IRequestListener listener = rl[i];
-			if (type == ADD)
-				listener.requestAdded(rr);
-			else if (type == CHANGE)
-				listener.requestChanged(rr);
-			else if (type == REMOVE)
-				listener.requestRemoved(rr);
-		}
-	}
-	
-	protected void loadMonitors() {
+	protected synchronized void loadMonitors() {
 		Trace.trace(Trace.FINEST, "Loading monitors");
 		
 		monitors = new ArrayList();
@@ -277,7 +193,7 @@
 		}
 	}
 	
-	protected void saveMonitors() {
+	protected synchronized void saveMonitors() {
 		try {
 			ignorePreferenceChanges = true;
 			XMLMemento memento = XMLMemento.createWriteRoot("monitors");
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/MonitorPlugin.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/MonitorPlugin.java
index 370920f..fabdd47 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/MonitorPlugin.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/MonitorPlugin.java
@@ -14,7 +14,6 @@
 
 import org.eclipse.core.runtime.*;
 import org.eclipse.wst.internet.monitor.core.IContentFilter;
-import org.eclipse.wst.internet.monitor.core.IProtocolAdapter;
 import org.eclipse.wst.internet.monitor.core.IRequestListener;
 /**
  * The monitor core plugin.
@@ -61,21 +60,44 @@
 		}
 	}
 	
-	public IProtocolAdapter getDefaultType() {
-		return (ProtocolAdapter) protocolAdapters.get("HTTP");
+	public String getDefaultType() {
+		return "HTTP";
 	}
-	
-	public IProtocolAdapter getProtocolAdapter(String id) {
+
+	/**
+	 * Returns the protocol adapter with the given id, or <code>null</code>
+	 * if none. This convenience method searches the list of known
+	 * protocol adapters ({@link #getProtocolAdapters()}) for the one with a
+	 * matching id ({@link IProtocolAdater#getId()}).
+	 *
+	 * @param the protocol adapter id; must not be <code>null</code>
+	 * @return the protocol adapter instance, or <code>null</code> if there
+	 *   is no protocol adapter with the given id
+	 */
+	public ProtocolAdapter getProtocolAdapter(String id) {
 		return (ProtocolAdapter) protocolAdapters.get(id);
 	}
 
-	public IProtocolAdapter[] getProtocolAdapters() {
+	/**
+	 * Returns a list of all known protocol adapter instances.
+	 * <p>
+	 * Protocol adapters are registered via the <code>protocolAdapaters</code>
+	 * extension point in the <code>org.eclipse.wst.internet.monitor.core</code>
+	 * plug-in.
+	 * </p>
+	 * <p>
+	 * A new array is returned on each call; clients may safely store or modify the result.
+	 * </p>
+	 * 
+	 * @return a possibly-empty array of protocol adapter instances
+	 */
+	public ProtocolAdapter[] getProtocolAdapters() {
 		List list = new ArrayList();
 		Iterator iterator = protocolAdapters.values().iterator();
 		while (iterator.hasNext()) {
 			list.add(iterator.next());
 		}
-		IProtocolAdapter[] types = new IProtocolAdapter[list.size()];
+		ProtocolAdapter[] types = new ProtocolAdapter[list.size()];
 		list.toArray(types);
 		return types;
 	}
@@ -91,7 +113,7 @@
 		return cf;
 	}
 	
-	public IContentFilter getContentFilter(String id) {
+	public IContentFilter findContentFilter(String id) {
 		return (IContentFilter) contentFilters.get(id);
 	}
 	
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/MonitorWorkingCopy.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/MonitorWorkingCopy.java
index 460ef28..0be1856 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/MonitorWorkingCopy.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/MonitorWorkingCopy.java
@@ -27,7 +27,14 @@
 		this.monitor = monitor;
 		setInternal(monitor);
 	}
-	
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.wst.internet.monitor.internal.IMonitorWorkingCopy#getOriginal()
+	 */
+	public IMonitor getOriginal() {
+		return monitor;
+	}
+
 	/* (non-Javadoc)
 	 * @see org.eclipse.wst.internet.monitor.internal.IMonitorWorkingCopy#setRemoteHost(java.lang.String)
 	 */
@@ -59,19 +66,19 @@
 	/* (non-Javadoc)
 	 * @see org.eclipse.wst.internet.monitor.internal.IMonitorWorkingCopy#setProtocolAdapter(IProtocolAdapter)
 	 */
-	public void setProtocolAdapter(IProtocolAdapter protocolAdapter) {
-		type = protocolAdapter;
+	public void setProtocol(String protocolId2) {
+		protocolId = protocolId2;
 	}
 	
 	public boolean isWorkingCopy() {
 		return true;
 	}
 	
-	public IMonitorWorkingCopy getWorkingCopy() {
+	public IMonitorWorkingCopy createWorkingCopy() {
 		return this;
 	}
-	
-	public IMonitor save() {
+
+	public synchronized IMonitor save() {
 		MonitorManager mm = MonitorManager.getInstance();
 		if (monitor != null) {
 			//boolean restart = false;
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/ProtocolAdapter.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/ProtocolAdapter.java
index bf8da15..3c576f5 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/ProtocolAdapter.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/ProtocolAdapter.java
@@ -14,8 +14,6 @@
 import java.net.Socket;
 import org.eclipse.core.runtime.IConfigurationElement;
 import org.eclipse.wst.internet.monitor.core.IMonitor;
-import org.eclipse.wst.internet.monitor.core.IProtocolAdapter;
-import org.eclipse.wst.internet.monitor.core.ProtocolAdapterDelegate;
 /**
  * 
  */
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/ProtocolAdapterDelegate.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/ProtocolAdapterDelegate.java
new file mode 100644
index 0000000..4a6fb26
--- /dev/null
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/ProtocolAdapterDelegate.java
@@ -0,0 +1,82 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.internet.monitor.core.internal;
+
+import java.io.IOException;
+import java.net.Socket;
+import org.eclipse.wst.internet.monitor.core.IMonitor;
+import org.eclipse.wst.internet.monitor.core.IRequest;
+
+/**
+ * Abstract base class for protocol adapter delegates, which provide the
+ * implementation behind a particular protocol adapter.
+ * A protocol adapter watches the message traffic passing between client and
+ * server; it parses the messages and reports them in the form of 
+ * {@link IRequest} objects.
+ * <p>
+ * This abstract class is intended to be subclassed only by clients
+ * to extend the <code>protocolAdapters</code> extension point.
+ * The subclass must have a public 0-argument constructor, which will be used
+ * automatically to instantiate the delegate when required. 
+ * </p>
+ * <p>
+ * [issue: As implemented, there is one delegate instance per known protocol
+ * adapter. This means that if there are multiple monitor instances using the
+ * same protocol adapter (e.g., between different client-server pairs), then
+ * the single delegate instance has to juggle multiple monitor instances.
+ * This makes sense when the delegate instance does not require any instance
+ * state, which I'm not sure is the case here. It might be much better to spec
+ * one delegate instance per monitor instance, which would make it easy for
+ * each delegate instance to remember instance state.]
+ * [issue: The HTTP and TCP/IP delegate implementations create threads which
+ * shuffle info between sockets. If the monitor is changed or deleted, how do
+ * these threads go away? Methinks that delegates in general should be forced
+ * to implement disconnect(IMonitor) as well. This method would be called by the
+ * system when the monitor is changed or deleted, or when the plug-in is
+ * being shut down.]
+ * </p>
+ * 
+ * @since 1.0
+ */
+public abstract class ProtocolAdapterDelegate {
+	/**
+	 * Establishes an ongoing connection between client and server being
+	 * monitored by the given monitor. The <code>in</code> socket is associated
+	 * with the monitor's client. The <code>out</code> socket is associated with
+	 * the monitor's server. Different adapaters handle different network
+	 * protocols.
+	 * <p>
+	 * Subclasses must implement this method to achieve the following:
+	 * <ul>
+	 * <li>Client to server communication -
+	 * Opening an input stream on the <code>in</code> socket, opening an output
+	 * stream on the <code>out</code> socket, and establishing a mechanism that
+	 * will pass along all bytes received on the input stream to the output
+	 * stream.</li>
+	 * <li>Server to client communication - Opening an input stream on the
+	 * <code>out</code> socket, opening an output stream on the <code>in</code>
+	 * socket, and establishing a mechanism that will pass along all bytes
+	 * received on the input stream to the output stream.</li>
+	 * <li>Parsing the protocol-specific message traffic to create and report
+	 * request objects for each message passed between client and server.</li>
+	 * <li>Closing the input and output sockets and otherwise cleaning up
+	 * afterwards.</li>
+	 * </ul>
+	 * </p>
+	 * 
+	 * @param monitor the monitor that uses this protocol adapter
+	 * @param in the input socket of the monitor client
+	 * @param out the output socket of the monitor server
+	 * @throws IOException if an exception occur when opening the streams of the
+	 * input or output sockets
+	 */
+	public abstract void connect(IMonitor monitor, Socket in, Socket out) throws IOException;
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/Request.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/Request.java
index b483973..7fda818 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/Request.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/Request.java
@@ -16,13 +16,13 @@
 import java.util.Properties;
 
 import org.eclipse.core.runtime.Platform;
-import org.eclipse.wst.internet.monitor.core.IProtocolAdapter;
 import org.eclipse.wst.internet.monitor.core.IRequest;
 import org.eclipse.wst.internet.monitor.core.IResendRequest;
 /**
  * A single TCP/IP request/response pair.
  */
 public class Request implements IRequest {
+	protected Monitor monitor;
 	protected Date date;
 	protected long responseTime = -1;
 	protected int localPort;
@@ -32,29 +32,29 @@
 	protected byte[] response;
 	
 	protected String label;
-	protected IProtocolAdapter type;
+	protected String protocolId;
 
 	protected Properties properties;
 	
 	protected List resendRequests = new ArrayList();
 
-
 	/**
 	 * RequestResponse constructor comment.
 	 */
-	public Request(IProtocolAdapter type, int localPort, String remoteHost, int remotePort) {
+	public Request(Monitor monitor, String protocolId, int localPort, String remoteHost, int remotePort) {
 		super();
-		this.type = type;
+		this.monitor = monitor;
+		this.protocolId = protocolId;
 		this.localPort = localPort;
 		this.remoteHost = remoteHost;
 		this.remotePort = remotePort;
 		date = new Date();
 		properties = new Properties();
-		MonitorManager.getInstance().addRequest(this);
+		monitor.addRequest(this);
 	}
-	
-	public IProtocolAdapter getProtocolAdapter() {
-		return type;
+
+	public String getProtocol() {
+		return protocolId;
 	}
 
 	/**
@@ -185,7 +185,7 @@
 	
 		this.request = request;
 	
-		MonitorManager.getInstance().requestChanged(this);
+		monitor.requestChanged(this);
 	}
 
 	/**
@@ -201,7 +201,7 @@
 	
 		responseTime = System.currentTimeMillis() - date.getTime();
 	
-		MonitorManager.getInstance().requestChanged(this);
+		monitor.requestChanged(this);
 	}
 
 	/**
@@ -215,48 +215,27 @@
 			return;
 	
 		label = s;
-		MonitorManager.getInstance().requestChanged(this);
+		monitor.requestChanged(this);
 	}
 	
 	/**
 	 * 
 	 */
-	public void addProperty(String key, Object value) {
+	public void setProperty(String key, Object value) {
 		try {
 			if (properties.containsKey(key))
 				properties.remove(key);
-			properties.put(key, value);
+			if (value != null)
+				properties.put(key, value);
 		} catch (Exception e) {
 			Trace.trace(Trace.SEVERE, "Could not add property", e);
 		}
 	}
-	
+
 	/**
 	 * 
 	 */
-	public String getStringProperty(String key) {
-		try {
-			return (String) properties.get(key);
-		} catch (Exception e) {
-			return "";
-		}
-	}
-	
-	/**
-	 * 
-	 */
-	public Integer getIntegerProperty(String key) {
-		try {
-			return (Integer) properties.get(key);
-		} catch (Exception e) {
-			return null;
-		}
-	}
-	
-	/**
-	 * 
-	 */
-	public Object getObjectProperty(String key) {
+	public Object getProperty(String key) {
 		try {
 			return properties.get(key);
 		} catch (Exception e) {
@@ -264,8 +243,12 @@
 		}
 	}
 	
+	public Monitor getMonitor() {
+		return monitor;
+	}
+	
 	public void fireChangedEvent() {
-		MonitorManager.getInstance().requestChanged(this);
+		monitor.requestChanged(this);
 	}
 	
 	/* (non-Javadoc)
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/TCPIPProtocolAdapter.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/TCPIPProtocolAdapter.java
index b719157..ae8bf46 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/TCPIPProtocolAdapter.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/TCPIPProtocolAdapter.java
@@ -14,14 +14,12 @@
 import java.net.Socket;
 
 import org.eclipse.wst.internet.monitor.core.IMonitor;
-import org.eclipse.wst.internet.monitor.core.MonitorCore;
-import org.eclipse.wst.internet.monitor.core.ProtocolAdapterDelegate;
 /**
  * 
  */
 public class TCPIPProtocolAdapter extends ProtocolAdapterDelegate {
 	public void connect(IMonitor monitor, Socket in, Socket out) throws IOException {
-		Request request = new Request(MonitorCore.findProtocolAdapter("TCPIP"), monitor.getLocalPort(), monitor.getRemoteHost(), monitor.getRemotePort());
+		Request request = new Request((Monitor) monitor, IProtocolAdapter.TCPIP_PROTOCOL_ID, monitor.getLocalPort(), monitor.getRemoteHost(), monitor.getRemotePort());
 		Connection conn = new Connection(in, out);
 		DefaultThread requestThread = new DefaultThread(conn, request, in.getInputStream(), out.getOutputStream(), true);
 		requestThread.start();
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPConnection.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPConnection.java
index 6a208fb..08cf9c5 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPConnection.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPConnection.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.wst.internet.monitor.core.IMonitor;
 import org.eclipse.wst.internet.monitor.core.IRequest;
+import org.eclipse.wst.internet.monitor.core.internal.Monitor;
 import org.eclipse.wst.internet.monitor.core.internal.Trace;
 
 import java.util.List;
@@ -67,7 +68,7 @@
 	 */
 	public void addProperty(String key, Object value) {
 		IRequest pair = getRequestResponse(req);
-		pair.addProperty(key, value);
+		pair.setProperty(key, value);
 	}
 
 	/**
@@ -86,7 +87,7 @@
 	protected IRequest getRequestResponse(int i) {
 		synchronized (this) {
 			while (i >= calls.size()) {
-				IRequest rr = new HTTPRequest(monitor.getLocalPort(), monitor.getRemoteHost(), monitor.getRemotePort());
+				IRequest rr = new HTTPRequest((Monitor) monitor, monitor.getLocalPort(), monitor.getRemoteHost(), monitor.getRemotePort());
 				calls.add(rr);
 				return rr;
 			}
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPProtocolAdapter.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPProtocolAdapter.java
index 00b3b1d..820a8d9 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPProtocolAdapter.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPProtocolAdapter.java
@@ -14,8 +14,8 @@
 import java.net.Socket;
 
 import org.eclipse.wst.internet.monitor.core.IMonitor;
-import org.eclipse.wst.internet.monitor.core.ProtocolAdapterDelegate;
 import org.eclipse.wst.internet.monitor.core.internal.Connection;
+import org.eclipse.wst.internet.monitor.core.internal.ProtocolAdapterDelegate;
 /**
  * 
  */
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPRequest.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPRequest.java
index d9ffd37..d802c5c 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPRequest.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPRequest.java
@@ -10,7 +10,8 @@
  **********************************************************************/
 package org.eclipse.wst.internet.monitor.core.internal.http;
 
-import org.eclipse.wst.internet.monitor.core.MonitorCore;
+import org.eclipse.wst.internet.monitor.core.internal.IProtocolAdapter;
+import org.eclipse.wst.internet.monitor.core.internal.Monitor;
 import org.eclipse.wst.internet.monitor.core.internal.Request;
 /**
  * 
@@ -27,11 +28,11 @@
 	/**
 	 * HTTPRequestResponse constructor comment.
 	 */
-	public HTTPRequest(int localPort, String remoteHost, int remotePort) {
-		super(MonitorCore.findProtocolAdapter(MonitorCore.HTTP_PROTOCOL_ID), localPort, remoteHost, remotePort);
+	public HTTPRequest(Monitor monitor, int localPort, String remoteHost, int remotePort) {
+		super(monitor, IProtocolAdapter.HTTP_PROTOCOL_ID, localPort, remoteHost, remotePort);
 	}
-	
-	public byte[] getRequest(byte type2) {
+
+	public byte[] getRequest(int type2) {
 		if (type2 == ALL)
 			return request;
 		else if (type2 == TRANSPORT)
@@ -40,7 +41,7 @@
 			return getRequestContent();
 	}
 	
-	public byte[] getResponse(byte type2) {
+	public byte[] getResponse(int type2) {
 		if (type2 == ALL)
 			return response;
 		else if (type2 == TRANSPORT)
@@ -50,28 +51,28 @@
 	}
 	
 	protected byte[] getRequestHeader() {
-		Object obj = getObjectProperty(HTTP_REQUEST_HEADER);
+		Object obj = getProperty(HTTP_REQUEST_HEADER);
 		if (obj == null || !(obj instanceof byte[]))
 			return null;
 		return (byte[]) obj;
 	}
 	
 	protected byte[] getRequestContent() {
-		Object obj = getObjectProperty(HTTP_REQUEST_BODY);
+		Object obj = getProperty(HTTP_REQUEST_BODY);
 		if (obj == null || !(obj instanceof byte[]))
 			return null;
 		return (byte[]) obj;
 	}
 	
 	protected byte[] getResponseHeader() {
-		Object obj = getObjectProperty(HTTP_RESPONSE_HEADER);
+		Object obj = getProperty(HTTP_RESPONSE_HEADER);
 		if (obj == null || !(obj instanceof byte[]))
 			return null;
 		return (byte[]) obj;
 	}
 	
 	protected byte[] getResponseContent() {
-		Object obj = getObjectProperty(HTTP_RESPONSE_BODY);
+		Object obj = getProperty(HTTP_RESPONSE_BODY);
 		if (obj == null || !(obj instanceof byte[]))
 			return null;
 		return (byte[]) obj;
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPThread.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPThread.java
index 901cb84..bf93d62 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPThread.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/HTTPThread.java
@@ -13,6 +13,7 @@
 import java.io.*;
 import org.eclipse.wst.internet.monitor.core.IRequest;
 import org.eclipse.wst.internet.monitor.core.internal.Connection;
+import org.eclipse.wst.internet.monitor.core.internal.Request;
 import org.eclipse.wst.internet.monitor.core.internal.Trace;
 /**
  * Monitor server I/O thread.
@@ -446,7 +447,7 @@
 					if (isRequest && keepAlive)
 						waitForResponse();
 					
-					IRequest r = conn.getRequestResponse(true);
+					Request r = (Request) conn.getRequestResponse(true);
 					r.fireChangedEvent();
 
 					Trace.trace(Trace.PARSING, "Done HTTP request for " + this + " " + keepAlive);
@@ -589,20 +590,20 @@
 			byte[] b = rr.getRequest(IRequest.ALL);
 			byte[] h = new byte[b.length];
 			System.arraycopy(b, 0, h, 0, b.length);
-			rr.addProperty(HTTPRequest.HTTP_REQUEST_HEADER, h);
+			rr.setProperty(HTTPRequest.HTTP_REQUEST_HEADER, h);
 		} else {
 			byte[] b = rr.getResponse(IRequest.ALL);
 			byte[] h = new byte[b.length];
 			System.arraycopy(b, 0, h, 0, b.length);
-			rr.addProperty(HTTPRequest.HTTP_RESPONSE_HEADER, h);
+			rr.setProperty(HTTPRequest.HTTP_RESPONSE_HEADER, h);
 		}
 	}
 	
 	protected void setHTTPBody(byte[] b) {
 		IRequest rr = conn.getRequestResponse(isRequest);
 		if (isRequest)
-			rr.addProperty(HTTPRequest.HTTP_REQUEST_BODY, b);
+			rr.setProperty(HTTPRequest.HTTP_REQUEST_BODY, b);
 		else
-			rr.addProperty(HTTPRequest.HTTP_RESPONSE_BODY, b);
+			rr.setProperty(HTTPRequest.HTTP_RESPONSE_BODY, b);
 	}
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/ResendHTTPRequest.java b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/ResendHTTPRequest.java
index 98fc8a6..c714132 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/ResendHTTPRequest.java
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/internal/http/ResendHTTPRequest.java
@@ -17,6 +17,7 @@
 import org.eclipse.wst.internet.monitor.core.IRequest;
 import org.eclipse.wst.internet.monitor.core.IResendRequest;
 import org.eclipse.wst.internet.monitor.core.internal.Connection;
+import org.eclipse.wst.internet.monitor.core.internal.Monitor;
 import org.eclipse.wst.internet.monitor.core.internal.SocketWrapper;
 /**
  * Wraps an existing request to create an HTTP request that can be sent. The
@@ -36,11 +37,10 @@
 	 * 
 	 * @param req the request that is to be resent.
 	 */
-	public ResendHTTPRequest(IRequest req) {
-		super(req.getLocalPort(), req.getRemoteHost(), req.getRemotePort());
-		addProperty(HTTP_REQUEST_HEADER, req
-				.getObjectProperty(HTTP_REQUEST_HEADER));
-		addProperty(HTTP_REQUEST_BODY, req.getObjectProperty(HTTP_REQUEST_BODY));
+	public ResendHTTPRequest(Monitor monitor, IRequest req) {
+		super(monitor, req.getLocalPort(), req.getRemoteHost(), req.getRemotePort());
+		setProperty(HTTP_REQUEST_HEADER, req.getProperty(HTTP_REQUEST_HEADER));
+		setProperty(HTTP_REQUEST_BODY, req.getProperty(HTTP_REQUEST_BODY));
 		header = req.getRequest(TRANSPORT);
 		content = req.getRequest(CONTENT);
 		request = req.getRequest(ALL);
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/package.html b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/package.html
new file mode 100644
index 0000000..7fcc8ba
--- /dev/null
+++ b/plugins/org.eclipse.wst.internet.monitor.core/monitorcore/org/eclipse/wst/internet/monitor/core/package.html
@@ -0,0 +1,19 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+Provides core support for the internet monitor.
+<h2>
+Package Specification</h2>
+[<it>TBD - This is the best place to paint a high-level picture of what API is to be
+found in this package. Ideally, the reader would be able to form a high-level
+picture of what's there, and be able to quickly determine whether this is even
+relevant for what they're doing. E.g.: This package specifies the API related to the
+internet monitor.  This includes 
+area such as ... .  In addition, this API supplies various utility types such as
+....</it>]
+</body>
+</html>
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/plugin.properties b/plugins/org.eclipse.wst.internet.monitor.core/plugin.properties
index ec8d3af..bcba0f5 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/plugin.properties
+++ b/plugins/org.eclipse.wst.internet.monitor.core/plugin.properties
@@ -13,10 +13,15 @@
 
 # --------------- Errors ---------------
 errorPortInUse=The TCP/IP monitor could not start because the port is in use.
+errorInvalidLocalPort=The local port number is invalid.
+errorInvalidRemotePort=The remote port number is invalid.
+errorInvalidRemoteHost=The remote host name is invalid.
 
 extensionPointProtocolAdapters=Protocol Adapters
 extensionPointContentFilters=Content Filters
 extensionPointRequestListeners=Request Listeners
 
+monitorValid=The monitor is valid.
+
 HTTP=HTTP
 TCPIP=TCP/IP
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/plugin.xml b/plugins/org.eclipse.wst.internet.monitor.core/plugin.xml
index 214f354..8b254df 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/plugin.xml
+++ b/plugins/org.eclipse.wst.internet.monitor.core/plugin.xml
@@ -23,7 +23,7 @@
 
 <extension point="org.eclipse.wst.internet.monitor.core.protocolAdapters">
   <protocolAdapter
-    id="TCPIP"
+    id="TCP/IP"
     class="org.eclipse.wst.internet.monitor.core.internal.TCPIPProtocolAdapter"
     name="%TCPIP"/>
   <protocolAdapter
diff --git a/plugins/org.eclipse.wst.internet.monitor.core/schema/protocolAdapters.exsd b/plugins/org.eclipse.wst.internet.monitor.core/schema/protocolAdapters.exsd
index 0a770a7..1b86e47 100644
--- a/plugins/org.eclipse.wst.internet.monitor.core/schema/protocolAdapters.exsd
+++ b/plugins/org.eclipse.wst.internet.monitor.core/schema/protocolAdapters.exsd
@@ -58,11 +58,11 @@
          <attribute name="class" type="string" use="required">

             <annotation>

                <documentation>

-                  specifies the fully qualified name of the Java class that extends &lt;samp&gt;org.eclipse.wst.internet.monitor.core.ProtocolAdapterDelegate&lt;/samp&gt;
+                  specifies the fully qualified name of the Java class that extends &lt;samp&gt;org.eclipse.wst.internet.monitor.core.internal.ProtocolAdapterDelegate&lt;/samp&gt;
 Protocol adapter instances of this type will delegate to instances of this class.

                </documentation>

                <appInfo>

-                  <meta.attribute kind="java" basedOn="org.eclipse.wst.internet.monitor.core.ProtocolAdapterDelegate"/>

+                  <meta.attribute kind="java" basedOn="org.eclipse.wst.internet.monitor.core.internal.ProtocolAdapterDelegate"/>

                </appInfo>

             </annotation>

          </attribute>

@@ -101,7 +101,7 @@
          <meta.section type="apiInfo"/>

       </appInfo>

       <documentation>

-         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that extends the abstract class &lt;b&gt;org.eclipse.wst.internet.monitor.core.ProtocolAdapterDelegate&lt;/b&gt;.

+         Value of the attribute &lt;b&gt;class&lt;/b&gt; must be a fully qualified name of a Java class that extends the abstract class &lt;b&gt;org.eclipse.wst.internet.monitor.core.internal.ProtocolAdapterDelegate&lt;/b&gt;.

       </documentation>

    </annotation>

 

diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/ContentViewer.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/ContentViewer.java
index d2338eb..ef85d95 100644
--- a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/ContentViewer.java
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/ContentViewer.java
@@ -12,37 +12,123 @@
 
 import org.eclipse.swt.widgets.Composite;
 /**
- * Viewer interface for displaying request and response messages.
- * This abstract class is intended to be extended only by clients
+ * Editable viewer for displaying and editing requests and responses.
+ * <p>
+ * This abstract class is intended to be subclassed only by clients
  * to extend the <code>contentViewers</code> extension point.
+ * The subclass must have a public 0-argument constructor, which will be used
+ * automatically to instantiate the viewer when required.
+ * Once instantiated, {@link #init(Composite)} is called to create
+ * the viewer's controls. Then {@link #setContent(byte[])} is called,
+ * one or more times, to cause the viewer to display particular
+ * content. Finally, when the viewer is no longer needed, {@link #dispose()}
+ * is called to free up any resources tied up by the viewer.
+ * </p>
+ * <p>
+ * [issue: It's unclear how these content viewers are used.
+ * Is it just that the UI provides a list of available
+ * views for the user to make a manual selection from, regardless
+ * of the actual content of the message traffic?]
+ * </p>
+ * <p>
+ * [issue: Unless you have clear and pressing requirements for
+ * pluggable content viewers (i.e., besides the ones that you
+ * would be able to build in), I suggest you make 
+ * the <code>contentViewers</code> extension point and this
+ * class internal. You can always expose it later.]
+ * </p>
+ * <p>
+ * [issue: Every content viewer should have getEditable,
+ * setEditable, and getContent.
+ * Particular content viewer implementation must implement
+ * getContent, and decide whether instances are considered
+ * editable.]
+ * </p>
  * 
  * @since 1.0
  */
 public abstract class ContentViewer {
 	/**
-	 * Initializes the viewer so it can be used to display content. Requires the parent
-	 * Composite that the viewer will display its information in.
+	 * Creates a new content viewer instance.
+	 */
+	protected ContentViewer() {
+		// do nothing
+	}
+
+	/**
+	 * Creates the controls for this viewer as children of the given composite.
+	 * <p>
+	 * The default implementation of this method does nothing.
+	 * Subclasses should override this method.
+	 * </p>
 	 * 
 	 * @param parent the parent composite
 	 */
-	public void init(Composite parent) {
-		// do nothing
-	}
+	public abstract void init(Composite parent);
 
 	/**
-	 * Sets the content that the viewer should display. The parameter may be null if
-	 * no content should be displayed.
+	 * Sets the content that the viewer should display.
+	 * The parameter may be null if no content should be displayed.
+	 * <p>
+	 * The default implementation of this method does nothing.
+	 * Subclasses should override this method.
+	 * </p>
+	 * <p>
+	 * [issue: Since this is for displaying request-reponse messages,
+	 * why not pass an IRequest? The problem as it stands now is that
+	 * it is unclear from specs how content viewers relate to anything
+	 * else having to do with the monitor.]
+	 * </p>
 	 * 
-	 * @param b the content
+	 * @param b the content to display, or <code>null</code> to
+	 * display nothing
 	 */
-	public void setContent(byte[] b) {
-		// do nothing
-	}
+	public abstract void setContent(byte[] b);
 
 	/**
 	 * Disposes this viewer and any underlying resources such as a composite.
+	 * <p>
+	 * The default implementation of this method does nothing.
+	 * Subclasses should override this method to provide specialized cleanup.
+	 * </p>
+	 * <p>
+	 * [issue: The spec needs to be clarified as to who's expected to
+	 * do what. It's not clear when this is called. In general, the implementations
+	 * seem to assume that they can dispose of the parent
+	 * composite. This seems backwards, and wrong. I don't think
+	 * the viewer should assume that it's the only child of the
+	 * parent composite (even if it is).]
+	 * </p>
 	 */
 	public void dispose() {
 		// do nothing
 	}
+
+	/**
+	 * Set whether the current viewer is editable, that is, the user is able to
+	 * edit the content.
+	 * <p>
+	 * The default implementation of this method does nothing.
+	 * Subclasses should override this method to allows instances
+	 * to be made editable.
+	 * </p>
+	 * 
+	 * @param editable <code>true</code> if true the content can be edited,
+	 *    and <code>false</code> otherwise
+	 */
+	public void setEditable(boolean editable) {
+		// do nothing
+	}
+
+	/**
+	 * Get the content from the viewer. This is usually only interesting if the
+	 * content has changed.
+	 * <p>
+	 * The default implementation of this method does nothing and
+	 * returns null. Subclasses should override this method.
+	 * </p>
+	 * 
+	 * @return the content from the viewer, or <code>null</code> if none
+	 */
+	public abstract byte[] getContent();
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/EditableContentViewer.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/EditableContentViewer.java
deleted file mode 100644
index 194a96b..0000000
--- a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/EditableContentViewer.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/**********************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- *    IBM - Initial API and implementation
- **********************************************************************/
-package org.eclipse.wst.internet.monitor.ui;
-/**
- * Editable viewer for viewing and editing requests and responses.
- * This abstract class is intended to be extended only by clients
- * to extend the <code>contentFilters</code> extension point.
- * 
- * @see ContentViewer
- * @since 1.0
- */
-public abstract class EditableContentViewer extends ContentViewer {
-	/**
-	 * Set whether the current viewer is editable, that is, the user is able to
-	 * edit the content.
-	 * 
-	 * @param editable <code>true</code> if true the content can be edited,
-	 *    and <code>false</code> otherwise
-	 */
-	public void setEditable(boolean editable) {
-		// do nothing
-	}
-
-	/**
-	 * Get the content from the viewer. This is usually only interesting if the
-	 * content has changed.
-	 * 
-	 * @return the content from the viewer
-	 */
-	public byte[] getContent() {
-		return null;
-	}
-}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/MonitorUICore.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/MonitorUICore.java
new file mode 100644
index 0000000..f228883
--- /dev/null
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/MonitorUICore.java
@@ -0,0 +1,33 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *    IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.wst.internet.monitor.ui;
+
+import org.eclipse.wst.internet.monitor.core.IRequest;
+import org.eclipse.wst.internet.monitor.ui.internal.MonitorUIPlugin;
+/**
+ * Main class for access to the monitor UI.
+ * <p>
+ * This class provides all functionality through static members. It is not intended
+ * to be instantiated or subclassed.
+ * </p>
+ * 
+ * @since 1.0
+ */
+public final class MonitorUICore {
+	/**
+	 * Returns an array of the requests currently being displayed in the monitor.
+	 *
+	 * @return an array of requests
+	 */
+	public static IRequest[] getRequests() {
+		return MonitorUIPlugin.getInstance().getRequests();
+	}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorComposite.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorComposite.java
index eb7e2bf..ad1b707 100644
--- a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorComposite.java
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorComposite.java
@@ -143,7 +143,7 @@
 		edit.addSelectionListener(new SelectionAdapter() {
 			public void widgetSelected(SelectionEvent e) {
 				IMonitor monitor = (IMonitor) getSelection().get(0);
-				IMonitorWorkingCopy wc = monitor.getWorkingCopy();
+				IMonitorWorkingCopy wc = monitor.createWorkingCopy();
 				
 				MonitorDialog dialog = new MonitorDialog(getShell(), wc);
 				if (dialog.open() != Window.CANCEL) {
@@ -185,7 +185,7 @@
 				while (iterator.hasNext()) {
 					IMonitor monitor = (IMonitor) iterator.next();
 					try {
-						MonitorCore.startMonitor(monitor);
+						monitor.start();
 					} catch (CoreException ce) {
 						MessageDialog.openError(getShell(), MonitorUIPlugin.getResource("%errorDialogTitle"), ce.getStatus().getMessage());
 					} catch (Exception ce) {
@@ -205,7 +205,7 @@
 				while (iterator.hasNext()) {
 					IMonitor monitor = (IMonitor) iterator.next();
 					try {
-						MonitorCore.stopMonitor(monitor);
+						monitor.stop();
 					} catch (Exception ex) {
 						// ignore
 					}
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorDialog.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorDialog.java
index 1de67d7..969ec3e 100644
--- a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorDialog.java
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorDialog.java
@@ -10,9 +10,10 @@
  **********************************************************************/
 package org.eclipse.wst.internet.monitor.ui.internal;
 
-import java.net.InetAddress;
-
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
 import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.ErrorDialog;
 import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.*;
@@ -28,8 +29,8 @@
 import org.eclipse.swt.widgets.Text;
 import org.eclipse.ui.help.WorkbenchHelp;
 import org.eclipse.wst.internet.monitor.core.IMonitorWorkingCopy;
-import org.eclipse.wst.internet.monitor.core.IProtocolAdapter;
 import org.eclipse.wst.internet.monitor.core.MonitorCore;
+import org.eclipse.wst.internet.monitor.core.internal.IProtocolAdapter;
 /**
  * 
  */
@@ -39,7 +40,6 @@
 	
 	private Button okButton;
 	private Text monitorPort;
-	private Text remoteHostname;
 	private Text remotePort;
 	
 	interface StringModifyListener {
@@ -100,13 +100,13 @@
 		return text;
 	}
 	
-	protected Combo createTypeCombo(Composite comp, final IProtocolAdapter[] types, IProtocolAdapter sel, final TypeModifyListener listener) {
+	protected Combo createTypeCombo(Composite comp, final String[] types, String sel, final StringModifyListener listener) {
 		final Combo combo = new Combo(comp, SWT.DROP_DOWN | SWT.READ_ONLY);
 		int size = types.length;
 		String[] items = new String[size];
 		int index = -1;
 		for (int i = 0; i < size; i++) {
-			items[i] = types[i].getName();
+			items[i] = types[i];
 			if (types[i].equals(sel))
 				index = i;
 		}
@@ -158,7 +158,7 @@
 		group.setText(MonitorUIPlugin.getResource("%remoteGroup"));
 		
 		createLabel(group, MonitorUIPlugin.getResource("%remoteHost"));		
-		remoteHostname = createText(group, monitor.getRemoteHost(), new StringModifyListener() {
+		createText(group, monitor.getRemoteHost(), new StringModifyListener() {
 			public void valueChanged(String s) {
 				monitor.setRemoteHost(s);
 				validateFields();
@@ -178,9 +178,9 @@
 		});
 		
 		createLabel(group, MonitorUIPlugin.getResource("%parseType"));		
-		createTypeCombo(group, MonitorCore.getProtocolAdapters(), monitor.getProtocolAdapter(), new TypeModifyListener() {
-			public void valueChanged(IProtocolAdapter type) {
-				monitor.setProtocolAdapter(type);
+		createTypeCombo(group, new String[] {"TCP/IP","HTTP"}, monitor.getProtocol(), new StringModifyListener() {
+			public void valueChanged(String protocolId) {
+				monitor.setProtocol(protocolId);
 			}
 		});
 		
@@ -191,7 +191,12 @@
 	 * @see org.eclipse.jface.dialogs.Dialog#okPressed()
 	 */
 	protected void okPressed() {
-		monitor.save();
+		try {
+			monitor.save();
+		} catch (CoreException ce) {
+			ErrorDialog.openError(getShell(), MonitorUIPlugin.getResource("%errorDialogTitle"), ce.getLocalizedMessage(), ce.getStatus());
+			return;
+		}
 		super.okPressed();
 	}
 
@@ -214,59 +219,17 @@
 			return;
 		
 		boolean result = true;
-
-		String currHostname = remoteHostname.getText();
-		if (!isValidHostname(currHostname))
-			result = false;
-		
-		String currHostnamePort = remotePort.getText();
 		try {
-			Integer.parseInt(currHostnamePort);
-		} catch (Exception any) {
-			result = false;
-		}
-		
-		String currMonitorPort = monitorPort.getText();
-		try {
-			Integer.parseInt(currMonitorPort);
-		} catch (Exception any) {
-			result = false;
-		}
-		
-		if (result && isLocalhost(currHostname)) {
-			if (currHostnamePort.equals(currMonitorPort))
-				result = false;
-		}
-		setOKButtonEnabled(result);
-	}
-	
-	protected static boolean isValidHostname(String host) {
-		if (host == null || host.trim().length() < 1)
-			return false;
-		
-		int length = host.length();
-		for (int i = 0; i < length; i++) {
-			char c = host.charAt(i);
-			if (!Character.isLetterOrDigit(c) && c != ':' && c != '.')
-				return false;
-		}
-		if (host.endsWith(":"))
-			return false;
-		return true;
-	}
-
-	protected static boolean isLocalhost(String host) {
-		if (host == null)
-			return false;
-		try {
-			if ("localhost".equals(host) || "127.0.0.1".equals(host))
-				return true;
-			InetAddress localHostaddr = InetAddress.getLocalHost();
-			if (localHostaddr.getHostName().equals(host))
-				return true;
+			Integer.parseInt(remotePort.getText());
+			Integer.parseInt(monitorPort.getText());
 		} catch (Exception e) {
-			Trace.trace(Trace.WARNING, "Error checking for localhost", e);
+			result = false;
 		}
-		return false;
+		
+		IStatus status = monitor.validate();
+		if (!status.isOK())
+			result = false;
+		
+		setOKButtonEnabled(result);
 	}
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorPrefrencesDialog.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorPreferencesDialog.java
similarity index 93%
rename from plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorPrefrencesDialog.java
rename to plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorPreferencesDialog.java
index 1269ba5..5bf752e 100644
--- a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorPrefrencesDialog.java
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorPreferencesDialog.java
@@ -23,20 +23,20 @@
 /**
  * 
  */
-public class MonitorPrefrencesDialog extends Dialog {
+public class MonitorPreferencesDialog extends Dialog {
 	protected IMonitorWorkingCopy monitor;
 	protected boolean isEdit;
 
 	/**
 	 * @param parentShell
 	 */
-	public MonitorPrefrencesDialog(Shell parentShell, IMonitorWorkingCopy monitor) {
+	public MonitorPreferencesDialog(Shell parentShell, IMonitorWorkingCopy monitor) {
 		super(parentShell);
 		this.monitor = monitor;
 		isEdit = true;
 	}
 	
-	public MonitorPrefrencesDialog(Shell composite) {
+	public MonitorPreferencesDialog(Shell composite) {
 		super(composite);
 		isEdit=false;
 	}
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorTableLabelProvider.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorTableLabelProvider.java
index 8687122..32088ba 100644
--- a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorTableLabelProvider.java
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorTableLabelProvider.java
@@ -88,7 +88,7 @@
 		} else if (columnIndex == 1)
 			return monitor.getRemoteHost() + ":" + monitor.getRemotePort();
 		else if (columnIndex == 2)
-			return monitor.getProtocolAdapter().getName();
+			return monitor.getProtocol();
 		else if (columnIndex == 3)
 			return monitor.getLocalPort() + "";
 		else
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorUIPlugin.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorUIPlugin.java
index be5902b..7f7a3cc 100644
--- a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorUIPlugin.java
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/MonitorUIPlugin.java
@@ -10,9 +10,14 @@
  **********************************************************************/
 package org.eclipse.wst.internet.monitor.ui.internal;
 
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.InputStreamReader;
 import java.net.URL;
 import java.text.MessageFormat;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.eclipse.core.runtime.IAdapterFactory;
@@ -22,7 +27,13 @@
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.ui.IActionFilter;
 import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.wst.internet.monitor.core.IMonitor;
+import org.eclipse.wst.internet.monitor.core.IMonitorListener;
 import org.eclipse.wst.internet.monitor.core.IRequest;
+import org.eclipse.wst.internet.monitor.core.IRequestListener;
+import org.eclipse.wst.internet.monitor.core.MonitorCore;
+import org.eclipse.wst.internet.monitor.core.internal.Trace;
+import org.eclipse.wst.internet.monitor.ui.internal.view.MonitorView;
 import org.osgi.framework.BundleContext;
 /**
  * The TCP/IP monitor UI plugin.
@@ -33,6 +44,8 @@
 	private static MonitorUIPlugin singleton;
 
 	protected Map imageDescriptors = new HashMap();
+	
+	private static final String lineSeparator = System.getProperty("line.separator");
 
 	private static URL ICON_BASE_URL;
 	private static final String URL_CLCL = "clcl16/";
@@ -59,6 +72,36 @@
 
 	private static final String SHOW_VIEW_ON_ACTIVITY = "show-view";
 	private static final String SHOW_HEADER = "show-header";
+	
+	protected List requests = new ArrayList();
+	
+	protected IMonitorListener monitorListener = new IMonitorListener() {
+		public void monitorAdded(IMonitor monitor) {
+			monitor.addRequestListener(requestListener);
+		}
+
+		public void monitorChanged(IMonitor monitor) {
+			// ignore
+		}
+
+		public void monitorRemoved(IMonitor monitor) {
+			monitor.removeRequestListener(requestListener);
+		}
+	};
+
+	protected IRequestListener requestListener = new IRequestListener() {
+		public void requestAdded(IRequest request) {
+			addRequest(request);
+			
+			if (MonitorView.view != null)
+				MonitorView.view.doRequestAdded(request);
+		}
+
+		public void requestChanged(IRequest request) {
+			if (MonitorView.view != null)
+				MonitorView.view.doRequestChanged(request);
+		}
+	};
 
 	/**
 	 * MonitorUIPlugin constructor comment.
@@ -227,6 +270,30 @@
 		super.start(context);
 
 		getPreferenceStore().setDefault(MonitorUIPlugin.SHOW_VIEW_ON_ACTIVITY, true);
+		
+		MonitorCore.addMonitorListener(monitorListener);
+		
+		IMonitor[] monitors = MonitorCore.getMonitors();
+		if (monitors != null) {
+			int size = monitors.length;
+			for (int i = 0; i < size; i++) {
+				monitors[i].addRequestListener(requestListener);
+			}
+		}
+	}
+	
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		
+		IMonitor[] monitors = MonitorCore.getMonitors();
+		if (monitors != null) {
+			int size = monitors.length;
+			for (int i = 0; i < size; i++) {
+				monitors[i].removeRequestListener(requestListener);
+			}
+		}
+		
+		MonitorCore.removeMonitorListener(monitorListener);
 	}
 
 	public static boolean getDefaultShowOnActivityPreference() {
@@ -250,4 +317,54 @@
 		getInstance().getPreferenceStore().setValue(SHOW_HEADER, b);
 		getInstance().savePluginPreferences();
 	}
+	
+	/**
+	 * Convenience method to parse the given bytes into String form. The bytes
+	 * are parsed into a line delimited string. The byte array must not be null.
+	 * 
+	 * @param b a byte array
+	 * @return the string after the conversion
+	 */
+	public static String parse(byte[] b) {
+		if (b == null)
+			throw new IllegalArgumentException();
+
+		ByteArrayInputStream bin = new ByteArrayInputStream(b);
+		BufferedReader br = new BufferedReader(new InputStreamReader(bin));
+		StringBuffer sb = new StringBuffer();
+		try {
+			String s = br.readLine();
+			
+			while (s != null) {
+				sb.append(s);
+				s = br.readLine();
+				if (s != null)
+					sb.append(lineSeparator);
+			}
+		} catch (Exception e) {
+			Trace.trace(Trace.SEVERE, "Error parsing input", e);
+		}
+		
+		return sb.toString();
+	}
+	
+	public void addRequest(IRequest request) {
+		if (!requests.contains(request))
+			requests.add(request);
+	}
+
+	/**
+	 * Returns a list of the current requests.
+	 *
+	 * @return java.util.List
+	 */
+	public IRequest[] getRequests() {
+		IRequest[] r = new IRequest[requests.size()];
+		requests.toArray(r);
+		return r;
+	}
+	
+	public void clearRequests() {
+		requests = new ArrayList();
+	}
 }
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/SWTUtil.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/SWTUtil.java
index ef5fadd..9f7dfab 100644
--- a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/SWTUtil.java
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/SWTUtil.java
@@ -51,7 +51,6 @@
 			initializeDialogUnits(comp);
 		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING);
 		data.widthHint = getButtonWidthHint(b);
-		data.heightHint = Dialog.convertVerticalDLUsToPixels(fontMetrics, IDialogConstants.BUTTON_HEIGHT);
 		b.setLayoutData(data);
 		return b;
 	}
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/view/MonitorTreeContentProvider.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/view/MonitorTreeContentProvider.java
index b91ae83..f47c2f7 100644
--- a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/view/MonitorTreeContentProvider.java
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/view/MonitorTreeContentProvider.java
@@ -16,7 +16,7 @@
 import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.wst.internet.monitor.core.IRequest;
 import org.eclipse.wst.internet.monitor.core.IResendRequest;
-import org.eclipse.wst.internet.monitor.core.MonitorCore;
+import org.eclipse.wst.internet.monitor.ui.internal.MonitorUIPlugin;
 /**
  * Content provider for the monitor server view.
  */
@@ -71,7 +71,7 @@
 		if (element instanceof Integer) {
 			Integer in = (Integer) element;
 			List list = new ArrayList();
-			IRequest[] requests = MonitorCore.getRequests();
+			IRequest[] requests = MonitorUIPlugin.getInstance().getRequests();
 			if (requests != null) {
 				int size = requests.length;
 				for (int i = 0; i < size; i++) {
@@ -109,7 +109,7 @@
 	public Object[] getElements(Object element) {
 		if (ROOT.equals(element)) {
 			List list = new ArrayList();
-			IRequest[] requests = MonitorCore.getRequests();
+			IRequest[] requests = MonitorUIPlugin.getInstance().getRequests();
 			if (requests != null) {
 				int size = requests.length;
 				for (int i = 0; i < size; i++) {
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/view/MonitorView.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/view/MonitorView.java
index 758ad69..cde361a 100644
--- a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/view/MonitorView.java
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/view/MonitorView.java
@@ -54,7 +54,7 @@
 
 	protected IAction httpHeaderAction;
 	
-	protected static MonitorView view;
+	public static MonitorView view;
 	
 	protected IRequest currentRequest = null;
 	protected StructuredSelection currentSelection = null;
@@ -66,45 +66,30 @@
 		super();
 		view = this;
 	}
-	
-	protected void addListener() {
-		listener = new IRequestListener() {
-			public void requestAdded(final IRequest rr) {
-				Display.getDefault().asyncExec(new Runnable() {
-					public void run() {
-						if(!(rr instanceof IResendRequest))
-						{
-						  Integer in = new Integer(rr.getLocalPort());
-						  treeViewer.add(MonitorTreeContentProvider.ROOT, in);
-						  treeViewer.add(in, rr); 
-						  treeViewer.setSelection(new StructuredSelection(rr), true);
-						}
-					}
-				});
-			}
 
-			public void requestChanged(final IRequest rr) {
-				Display.getDefault().asyncExec(new Runnable() {
-					public void run() {
-						IStructuredSelection sel = (IStructuredSelection) treeViewer.getSelection();
-						
-						treeViewer.refresh(rr);
-						if (!sel.isEmpty())
-							treeViewer.setSelection(sel);
-					}
-				});
+	public void doRequestAdded(final IRequest rr) {
+		Display.getDefault().asyncExec(new Runnable() {
+			public void run() {
+				if (!(rr instanceof IResendRequest)) {
+				  Integer in = new Integer(rr.getLocalPort());
+				  treeViewer.add(MonitorTreeContentProvider.ROOT, in);
+				  treeViewer.add(in, rr); 
+				  treeViewer.setSelection(new StructuredSelection(rr), true);
+				}
 			}
+		});
+	}
 
-			public void requestRemoved(final IRequest rr) {
-				Display.getDefault().asyncExec(new Runnable() {
-					public void run() {
-						treeViewer.remove(rr);
-					}
-				});
+	public void doRequestChanged(final IRequest rr) {
+		Display.getDefault().asyncExec(new Runnable() {
+			public void run() {
+				IStructuredSelection sel = (IStructuredSelection) treeViewer.getSelection();
+				
+				treeViewer.refresh(rr);
+				if (!sel.isEmpty())
+					treeViewer.setSelection(sel);
 			}
-		};
-	
-		MonitorCore.addRequestListener(listener);
+		});
 	}
 
 	/**
@@ -373,7 +358,7 @@
 						String time = MonitorUIPlugin.getResource("%viewResponseTimeFormat", req.getResponseTime() + "");
 						label2.setText(MonitorUIPlugin.getResource("%viewResponseTime", time));
 					}
-					label3.setText(MonitorUIPlugin.getResource("%viewType", req.getProtocolAdapter().getName()));
+					label3.setText(MonitorUIPlugin.getResource("%viewType", req.getProtocol()));
 	
 					// request information
 					requestLabel.setText(MonitorUIPlugin.getResource("%viewRequest", "localhost:" + req.getLocalPort()));
@@ -398,7 +383,7 @@
 		});
 		treeViewer.expandToLevel(2);
 		
-        // Create a menu manager for a context menu.
+		// create a menu manager for a context menu
 		MenuManager menuManager = new MenuManager();
 		menuManager.setRemoveAllWhenShown(true);
 		menuManager.addMenuListener(new IMenuListener() {
@@ -407,16 +392,14 @@
 			}
 		});
 
-		// create the menu.
+		// create the menu
 		Menu menu = menuManager.createContextMenu(treeViewer.getControl());
 		treeViewer.getControl().setMenu(menu);
 		
-		// register the menu with the platform.
+		// register the menu with the platform
 		getSite().registerContextMenu(menuManager, treeViewer);
         
 		initializeActions();
-	
-		addListener();
 	}
 	
 	protected String getSizeString(byte[] a, byte[] b) {
@@ -433,7 +416,7 @@
 	public void dispose() {
 		super.dispose();
 		treeViewer = null;
-		MonitorCore.removeRequestListener(listener);
+		view = null;
 	}
 
 	/**
@@ -460,7 +443,7 @@
 	
 		IAction clearAction = new Action() {
 			public void run() {
-				MonitorCore.removeAllRequests();
+				MonitorUIPlugin.getInstance().clearRequests();
 			}
 		};
 		clearAction.setToolTipText(MonitorUIPlugin.getResource("%actionClearToolTip"));
@@ -487,7 +470,7 @@
 				IWorkbench workbench = PlatformUI.getWorkbench();
 				IWorkbenchWindow workbenchWindow = workbench.getActiveWorkbenchWindow();
 								
-				MonitorPrefrencesDialog monitorPrefDialog = new MonitorPrefrencesDialog(workbenchWindow.getShell());
+				MonitorPreferencesDialog monitorPrefDialog = new MonitorPreferencesDialog(workbenchWindow.getShell());
 				if (monitorPrefDialog.open() == Window.CANCEL)
 					return;
 			}
@@ -519,8 +502,6 @@
 				try {
 					IWorkbench workbench = MonitorUIPlugin.getInstance().getWorkbench();
 					IWorkbenchWindow workbenchWindow = workbench.getActiveWorkbenchWindow();
-					//if (workbenchWindow == null)
-					//	workbenchWindow = workbench.getWorkbenchWindows()[0];
 	
 					IWorkbenchPage page = workbenchWindow.getActivePage();
 	
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/view/SendModifiedMessageAction.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/view/SendModifiedMessageAction.java
index f1a2ec9..d0bf3bd 100644
--- a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/view/SendModifiedMessageAction.java
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/view/SendModifiedMessageAction.java
@@ -18,7 +18,6 @@
 import org.eclipse.wst.internet.monitor.core.IRequest;
 import org.eclipse.wst.internet.monitor.core.IResendRequest;
 import org.eclipse.wst.internet.monitor.ui.ContentViewer;
-import org.eclipse.wst.internet.monitor.ui.EditableContentViewer;
 import org.eclipse.wst.internet.monitor.ui.internal.viewers.HeaderViewer;
 /**
  * Send a modified message.
@@ -43,8 +42,7 @@
 				IResendRequest req = (IResendRequest) element;
 				ContentViewer curViewer = MonitorView.view.vm.getCurrentRequestViewer();
 				HeaderViewer curHeaderViewer = MonitorView.view.vm.getCurrentRequestHeaderViewer();
-				if (curViewer instanceof EditableContentViewer)
-					req.setRequest(((EditableContentViewer) curViewer).getContent(), IRequest.CONTENT);
+				req.setRequest(curViewer.getContent(), IRequest.CONTENT);
 				
 				if (curHeaderViewer != null)
 					req.setRequest(curHeaderViewer.getContent(), IRequest.TRANSPORT);
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/view/ViewerManager.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/view/ViewerManager.java
index b90fc3b..f1b3954 100644
--- a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/view/ViewerManager.java
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/view/ViewerManager.java
@@ -17,7 +17,6 @@
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.wst.internet.monitor.core.*;
 import org.eclipse.wst.internet.monitor.ui.ContentViewer;
-import org.eclipse.wst.internet.monitor.ui.EditableContentViewer;
 import org.eclipse.wst.internet.monitor.ui.internal.MonitorUIPlugin;
 import org.eclipse.wst.internet.monitor.ui.internal.Trace;
 import org.eclipse.wst.internet.monitor.ui.internal.viewers.ByteViewer;
@@ -95,20 +94,19 @@
 	}
 
 	public void setRequest(IRequest rr) {
-		// Maintain the state of the request and request header if they've been modified.
-		if (request instanceof IResendRequest
-				&& request.getResponse(IRequest.ALL) == null) {
-			if (reqViewer instanceof EditableContentViewer) {
-				IResendRequest resRequest = (IResendRequest) request;
-				EditableContentViewer editViewer = (EditableContentViewer) reqViewer;
-				byte[] content = editViewer.getContent();
-				if (content != null && !MonitorCore.parse(resRequest.getRequest(IRequest.CONTENT)).equals(MonitorCore.parse(content))) {
-					resRequest.setRequest(content, IRequest.CONTENT);
-				}
-				byte[] header = reqHeader.getContent();
-				if (header != null && !MonitorCore.parse(resRequest.getRequest(IRequest.TRANSPORT)).equals(MonitorCore.parse(header))) {
-					resRequest.setRequest(header, IRequest.TRANSPORT);
-				}
+		// maintain the state of the request and request header if they've been modified.
+		if (request instanceof IResendRequest && request.getResponse(IRequest.ALL) == null) {
+			IResendRequest resRequest = (IResendRequest) request;
+			//EditableContentViewer editViewer = (ContentViewer) reqViewer;
+			byte[] content = reqViewer.getContent();
+			byte[] b = resRequest.getRequest(IRequest.CONTENT);
+			if (content != null && b != null && !MonitorUIPlugin.parse(b).equals(MonitorUIPlugin.parse(content))) {
+				resRequest.setRequest(content, IRequest.CONTENT);
+			}
+			byte[] header = reqHeader.getContent();
+			b = resRequest.getRequest(IRequest.TRANSPORT);
+			if (header != null && b != null && !MonitorUIPlugin.parse(b).equals(MonitorUIPlugin.parse(header))) {
+				resRequest.setRequest(header, IRequest.TRANSPORT);
 			}
 		}
 		reqHeader.setRequestResponse(rr);
@@ -124,19 +122,16 @@
 		request = rr;
 		// Set the editor to editable if the request hasn't  been sent and the
 		// editor can be set as editable.
-		if (request instanceof IResendRequest
-				&& request.getResponse(IRequest.ALL) == null) {
+		if (request instanceof IResendRequest && request.getResponse(IRequest.ALL) == null) {
 			if (displayHeaderInf) {
 				reqHeader.setEditable(true);
 			}
-			if (reqViewer instanceof EditableContentViewer)
-				((EditableContentViewer) reqViewer).setEditable(true);
+			reqViewer.setEditable(true);
 		} else {
 			if (displayHeaderInf) {
 				reqHeader.setEditable(false);
 			}
-			if (reqViewer instanceof EditableContentViewer)
-				((EditableContentViewer) reqViewer).setEditable(false);
+			reqViewer.setEditable(false);
 		}
 	}
 
@@ -212,15 +207,12 @@
 		byte[] b = null;
 		if (request != null) {
 			b = filter(request.getRequest(IRequest.CONTENT));
-			// Set the editor to editable if the request hasn't  been sent and the
-			// editor can be set as editable.
-			if (request instanceof IResendRequest
-					&& request.getResponse(IRequest.TRANSPORT) == null) {
-				if (reqViewer instanceof EditableContentViewer)
-					((EditableContentViewer) reqViewer).setEditable(true);
+			// set the editor to editable if the request hasn't been sent and the
+			// editor can be set as editable
+			if (request instanceof IResendRequest && request.getResponse(IRequest.TRANSPORT) == null) {
+				reqViewer.setEditable(true);
 			} else {
-				if (reqViewer instanceof EditableContentViewer)
-					((EditableContentViewer) reqViewer).setEditable(false);
+				reqViewer.setEditable(false);
 			}
 		}
 		reqViewer.setContent(b);
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/viewers/ByteViewer.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/viewers/ByteViewer.java
index 26f6912..782972c 100644
--- a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/viewers/ByteViewer.java
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/viewers/ByteViewer.java
@@ -18,13 +18,13 @@
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Text;
 import org.eclipse.ui.help.WorkbenchHelp;
-import org.eclipse.wst.internet.monitor.core.MonitorCore;
-import org.eclipse.wst.internet.monitor.ui.EditableContentViewer;
+import org.eclipse.wst.internet.monitor.ui.ContentViewer;
 import org.eclipse.wst.internet.monitor.ui.internal.ContextIds;
+import org.eclipse.wst.internet.monitor.ui.internal.MonitorUIPlugin;
 /**
  * A basic byte viewer.
  */
-public class ByteViewer extends EditableContentViewer {
+public class ByteViewer extends ContentViewer {
 	protected Text text;
 	protected Composite comp;
 
@@ -41,7 +41,7 @@
 	public void setContent(byte[] b) {
 		String out = "";
 		if (b != null)
-			out = MonitorCore.parse(b);
+			out = MonitorUIPlugin.parse(b);
 
 		String lineSeparator = System.getProperty("line.separator");
 		int ls = lineSeparator.length();
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/viewers/HeaderViewer.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/viewers/HeaderViewer.java
index f161683..d75a90a 100644
--- a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/viewers/HeaderViewer.java
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/viewers/HeaderViewer.java
@@ -20,7 +20,6 @@
 import org.eclipse.swt.widgets.Text;
 import org.eclipse.ui.help.WorkbenchHelp;
 import org.eclipse.wst.internet.monitor.core.IRequest;
-import org.eclipse.wst.internet.monitor.core.MonitorCore;
 import org.eclipse.wst.internet.monitor.ui.internal.ContextIds;
 import org.eclipse.wst.internet.monitor.ui.internal.MonitorUIPlugin;
 /**
@@ -176,9 +175,13 @@
 		String out = "";
 		if (rr != null) {
 			if (msg == REQUEST_HEADER) {
-				out = MonitorCore.parse(rr.getRequest(IRequest.TRANSPORT));
+				byte[] b = rr.getRequest(IRequest.TRANSPORT);
+				if (b != null)
+					out = MonitorUIPlugin.parse(b);
 			} else if (msg == RESPONSE_HEADER) {
-				out = MonitorCore.parse(rr.getResponse(IRequest.TRANSPORT));
+				byte[] b = rr.getResponse(IRequest.TRANSPORT);
+				if (b != null)
+					out = MonitorUIPlugin.parse(b);
 			}
 		}
 		
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/viewers/ImageViewer.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/viewers/ImageViewer.java
index d07c136..5acc7f1 100644
--- a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/viewers/ImageViewer.java
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/viewers/ImageViewer.java
@@ -28,6 +28,8 @@
 	protected Composite rootComp;
 	protected Composite viewerComp;
 	protected Label messageLabel;
+	
+	protected byte[] content;
 
 	/* (non-Javadoc)
 	 * @see org.eclipse.wst.internet.monitor.ui.IContentViewer#init(Composite)
@@ -52,6 +54,7 @@
 	 * @see org.eclipse.wst.internet.monitor.ui.IContentViewer#setContent()
 	 */
 	public void setContent(byte[] b) {
+		content = b;
 		if (b == null || b.length == 0) {
 			messageLabel.setText("<" + MonitorUIPlugin.getResource("%imageViewInvalid") + ">");
 		} else {
@@ -84,6 +87,10 @@
 		viewerComp.layout(true);
 	}
 	
+	public byte[] getContent() {
+		return content;
+	}
+	
 	/* (non-Javadoc)
 	 * @see org.eclipse.wst.internet.monitor.ui.IContentViewer#dispose()
 	 */
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/viewers/XMLViewer.java b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/viewers/XMLViewer.java
index cedb8cd..36b4de9 100644
--- a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/viewers/XMLViewer.java
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/internal/viewers/XMLViewer.java
@@ -34,7 +34,6 @@
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Text;
 import org.eclipse.ui.help.WorkbenchHelp;
-import org.eclipse.wst.internet.monitor.core.MonitorCore;
 import org.eclipse.wst.internet.monitor.ui.ContentViewer;
 import org.eclipse.wst.internet.monitor.ui.internal.ContextIds;
 import org.eclipse.wst.internet.monitor.ui.internal.MonitorUIPlugin;
@@ -57,6 +56,8 @@
 	protected boolean setEncoding = false;
 	protected boolean missingEncoding = false;
 	protected String originalEncoding;
+	
+	protected byte[] content;
 
 	/* (non-Javadoc)
 	 * @see org.eclipse.wst.internet.monitor.ui.IContentViewer#dispose()
@@ -69,9 +70,10 @@
 	 * @see org.eclipse.wst.internet.monitor.ui.IContentViewer#setContent()
 	 */
 	public void setContent(byte[] b) {
+		content = b;
 		String out = "";		
 		if (b != null)
-			out = MonitorCore.parse(b);
+			out = MonitorUIPlugin.parse(b);
 				
 		String lineSeparator = System.getProperty("line.separator");
 		int ls = lineSeparator.length();
@@ -84,7 +86,7 @@
 		if (out_temp.indexOf("<?xml") < 0) 
 			xmlTagMissing = true;
 		
-		if (out.length() > 0) {		
+		if (out.length() > 0) {
 			byte[] b1 = createDocument(out);
 			String finalMsg = new String (b1);
 			if (finalMsg.startsWith("Invalid XML")) {
@@ -93,17 +95,13 @@
 				layout.topControl = messageLabel;
 				messageLabel.setVisible(true);
 				messageLabel.setText("<" + MonitorUIPlugin.getResource("%xmlViewInvalid") + ">");
-				
-			}
-			else if (xmlTagMissing && finalMsg.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")) {
+			} else if (xmlTagMissing && finalMsg.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")) {
 				int x = finalMsg.indexOf("\n") + 1;
 				String Msg = finalMsg.substring(x);
 				finalMsg = Msg;
 				
 				messageText.setText(finalMsg);
-			}
-			
-			else if (setEncoding) {
+			} else if (setEncoding) {
 				//change back to original Encoding
 				int begin = finalMsg.indexOf("UTF-8"); //location of opening "
 				int last = begin + 5;  //location of closing "
@@ -112,9 +110,7 @@
 				finalMsg = first_half + originalEncoding + second_half;	
 				
 				messageText.setText(finalMsg);
-			}
-			
-			else if (missingEncoding) {
+			} else if (missingEncoding) {
 				//remove encoding completely
 				int begin = finalMsg.indexOf("encoding=\"UTF-8\""); //location of opening "
 				int last = begin + 16;  //location of closing "
@@ -128,6 +124,10 @@
 			messageText.setText(out);
 	}
 	
+	public byte[] getContent() {
+		return content;
+	}
+	
 	/* (non-Javadoc)
 	 * @see org.eclipse.wst.internet.monitor.ui.IContentViewer#init(Composite)
 	 */
@@ -216,11 +216,9 @@
 			transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
 			transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
 			transformer.transform(source, result);            
-		}
-		catch (TransformerConfigurationException e) {
+		} catch (TransformerConfigurationException e) {
 			throw (IOException) (new IOException().initCause(e));
-		}
-		catch (TransformerException e) {
+		} catch (TransformerException e) {
 			throw (IOException) (new IOException().initCause(e));
 		}
 		return out.toByteArray();
diff --git a/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/package.html b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/package.html
new file mode 100644
index 0000000..47ce4e7
--- /dev/null
+++ b/plugins/org.eclipse.wst.internet.monitor.ui/monitorui/org/eclipse/wst/internet/monitor/ui/package.html
@@ -0,0 +1,19 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <title>Package-level Javadoc</title>
+</head>
+<body>
+Provides UI support for the internet monitor.
+<h2>
+Package Specification</h2>
+[<it>TBD - This is the best place to paint a high-level picture of what API is to be
+found in this package. Ideally, the reader would be able to form a high-level
+picture of what's there, and be able to quickly determine whether this is even
+relevant for what they're doing. E.g.: This package specifies the API related to the
+internet monitor.  This includes 
+area such as ... .  In addition, this API supplies various utility types such as
+....</it>]
+</body>
+</html>