diff --git a/build.xml b/build.xml
index b3bdecfbb..67995e4cf 100644
--- a/build.xml
+++ b/build.xml
@@ -412,14 +412,19 @@ Output
+
-
+
+
-
+
+
+
+
@@ -445,25 +450,40 @@ Output
>
+
+
+
-
+
+
+
+
+
+
+
-
+
+
+
+
+
+
-
+
+
diff --git a/src/contrib/org/apache/http/contrib/conn/TalkativeSocketFactory.java b/src/contrib/org/apache/http/contrib/conn/TalkativeSocketFactory.java
new file mode 100644
index 000000000..2bc98367b
--- /dev/null
+++ b/src/contrib/org/apache/http/contrib/conn/TalkativeSocketFactory.java
@@ -0,0 +1,335 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+
+package org.apache.http.contrib.conn;
+
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.IOException;
+import java.io.FilterInputStream;
+import java.io.FilterOutputStream;
+import java.net.Socket;
+import java.net.InetAddress;
+
+import org.apache.http.params.HttpParams;
+import org.apache.http.conn.SocketFactory;
+import org.apache.http.conn.PlainSocketFactory;
+
+
+/**
+ * A factory for sockets that debug-print the transmitted data.
+ *
+ * @author Roland Weber
+ *
+ *
+ *
+ * @version $Revision$ $Date$
+ *
+ * @since 4.0
+ */
+public class TalkativeSocketFactory implements SocketFactory {
+
+ /** Where to print the debug output to. */
+ private final PrintStream debugStream;
+
+
+ /**
+ * Creates a new talkative socket factory.
+ *
+ * @param ps where to print the debug output to
+ */
+ public TalkativeSocketFactory(PrintStream ps) {
+
+ if (ps == null) {
+ throw new IllegalArgumentException
+ ("Print stream must not be null.");
+ }
+ debugStream = ps;
+ }
+
+
+ /**
+ * Creates a new talkative socket.
+ *
+ * @return the talkative socket
+ */
+ public Socket createSocket() {
+
+ return new TalkativeSocket();
+ }
+
+
+ // non-javadoc, see interface org.apache.http.conn.SocketFactory
+ public Socket connectSocket(Socket sock, String host, int port,
+ InetAddress localAddress, int localPort,
+ HttpParams params)
+ throws IOException {
+
+ // just delegate the call to the default
+ return PlainSocketFactory.getSocketFactory().connectSocket
+ (sock, host, port, localAddress, localPort, params);
+ }
+
+
+ /**
+ * Prepares a byte for debug printing.
+ *
+ * @param sb the string buffer to append to
+ * @param data the byte to append. For consistency with
+ * java.io streams, the byte is passed as int.
+ */
+ public final static void appendByte(StringBuffer sb, int data) {
+
+ if (data < 32) {
+ switch (data) {
+ case 10: sb.append("[\\n]"); break;
+ case 13: sb.append("[\\r]"); break;
+ default: sb.append("[0x")
+ .append(Integer.toHexString(data)).append("]");
+ }
+ } else if (data > 127) {
+ sb.append("[0x")
+ .append(Integer.toHexString(data)).append("]");
+ } else {
+ sb.append((char) data);
+ }
+ } // appendByte
+
+
+ /**
+ * A talkative socket.
+ * That's a plain socket that creates talkative
+ * input and output streams.
+ */
+ public class TalkativeSocket extends Socket {
+
+ protected InputStream talkativeInput;
+ protected OutputStream talkativeOutput;
+
+ // default constructor only
+
+ public InputStream getInputStream() throws IOException {
+ if (talkativeInput == null) {
+ debugStream.println(">>>> (wrapping input stream)");
+ talkativeInput = new TalkativeInputStream
+ (super.getInputStream(), debugStream);
+ }
+ return talkativeInput;
+ }
+
+ public OutputStream getOutputStream() throws IOException {
+ if (talkativeOutput == null) {
+ debugStream.println(">>>> (wrapping output stream)");
+ talkativeOutput = new TalkativeOutputStream
+ (super.getOutputStream(), debugStream);
+ }
+ return talkativeOutput;
+ }
+
+
+ public String toString() {
+ return "Talkative" + super.toString();
+ }
+
+ } // class TalkativeSocket
+
+
+ /**
+ * Output stream that debug-prints the written data.
+ *
+ * @author Roland Weber
+ */
+ public static class TalkativeOutputStream extends FilterOutputStream {
+
+ /** Where to debug-print to. */
+ private final PrintStream debug;
+
+ private static final String PREFIX_STRING = ">> ";
+ private static final int PREFIX_LENGTH = PREFIX_STRING.length();
+
+ /**
+ * A string buffer for building debug output.
+ * The prefix will never change.
+ */
+ private final StringBuffer buffer;
+
+
+ /**
+ * Creates a new talkative output stream.
+ *
+ * @param out the underlying output stream
+ * @param ps the print stream for debug output
+ */
+ public TalkativeOutputStream(OutputStream out, PrintStream ps) {
+ super(out);
+ if (ps == null) {
+ throw new IllegalArgumentException
+ ("Print stream must not be null.");
+ }
+ debug = ps;
+ buffer = new StringBuffer(128);
+ buffer.append(PREFIX_STRING);
+ }
+
+ public void close() throws IOException {
+ debug.println(">>>> close");
+ super.close();
+ }
+
+ public void flush() throws IOException {
+ debug.println(">>>> flush");
+ super.flush();
+ }
+
+ public void write(byte[] b) throws IOException {
+ buffer.setLength(PREFIX_LENGTH);
+ for (int i=0; iRoland Weber
+ */
+ public static class TalkativeInputStream extends FilterInputStream {
+
+ /** Where to debug-print to. */
+ private final PrintStream debug;
+
+ private static final String PREFIX_STRING = "<< ";
+ private static final int PREFIX_LENGTH = PREFIX_STRING.length();
+
+ /**
+ * A string buffer for building debug output.
+ * The prefix will never change.
+ */
+ private final StringBuffer buffer;
+
+
+ /**
+ * Creates a new talkative input stream.
+ *
+ * @param in the underlying input stream
+ * @param ps the print stream for debug output
+ */
+ public TalkativeInputStream(InputStream in, PrintStream ps) {
+ super(in);
+ if (ps == null) {
+ throw new IllegalArgumentException
+ ("Print stream must not be null.");
+ }
+ debug = ps;
+ buffer = new StringBuffer(128);
+ buffer.append(PREFIX_STRING);
+ }
+
+
+ public void close() throws IOException {
+ debug.println("<<<< close");
+ super.close();
+ }
+
+ public long skip(long n) throws IOException {
+ long skipped = super.skip(n);
+
+ debug.print("<<<< skip ");
+ debug.println(skipped);
+
+ return skipped;
+ }
+
+ public int read() throws IOException {
+ int data = super.read();
+ if (data < 0)
+ debug.print("<<<< EOF");
+ else
+ {
+ buffer.setLength(PREFIX_LENGTH);
+ appendByte(buffer, data);
+ debug.println(buffer);
+ }
+ return data;
+ }
+
+ public int read(byte[] b) throws IOException {
+ int length = super.read(b);
+
+ buffer.setLength(PREFIX_LENGTH);
+ for (int i=0; i.
+ *
+ */
+
+package org.apache.http.examples.conn;
+
+
+import org.apache.http.HttpHost;
+import org.apache.http.Header;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpVersion;
+import org.apache.http.message.BasicHttpRequest;
+import org.apache.http.params.HttpParams;
+import org.apache.http.params.HttpProtocolParams;
+import org.apache.http.impl.DefaultHttpParams;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpExecutionContext;
+
+import org.apache.http.conn.Scheme;
+import org.apache.http.conn.SocketFactory;
+import org.apache.http.conn.PlainSocketFactory;
+import org.apache.http.conn.UnmanagedClientConnection;
+import org.apache.http.conn.SocketConnectionOperator;
+import org.apache.http.conn.impl.DefaultClientConnection;
+import org.apache.http.conn.impl.DefaultSocketConnectionOperator;
+
+
+
+/**
+ * How to open a direct connection using
+ * {@link SocketConnectionOperator SocketConnectionOperator}.
+ * This exemplifies the opening of the connection only.
+ * The subsequent message exchange should not be used as a template.
+ *
+ * @author Roland Weber
+ *
+ *
+ *
+ * @version $Revision$ $Date$
+ *
+ * @since 4.0
+ */
+public class OperatorConnectDirect {
+
+ /**
+ * The default parameters.
+ * Instantiated in {@link #setup setup}.
+ */
+ private static HttpParams defaultParameters = null;
+
+
+ /**
+ * Main entry point to this example.
+ *
+ * @param args ignored
+ */
+ public final static void main(String[] args)
+ throws Exception {
+
+ final HttpHost target = new HttpHost("jakarta.apache.org", 80, "http");
+
+ setup(); // some general setup
+
+ // one operator can be used for many connections
+ SocketConnectionOperator scop = createOperator();
+ UnmanagedClientConnection conn = createConnection();
+
+ HttpRequest req = createRequest(target);
+ HttpContext ctx = createContext();
+
+ System.out.println("opening connection to " + target);
+ scop.openConnection(conn, target, ctx, getParams());
+
+ System.out.println("sending request");
+ conn.sendRequestHeader(req);
+ // there is no request entity
+ conn.flush();
+
+ System.out.println("receiving response header");
+ HttpResponse rsp = conn.receiveResponseHeader(getParams());
+
+ System.out.println("----------------------------------------");
+ System.out.println(rsp.getStatusLine());
+ Header[] headers = rsp.getAllHeaders();
+ for (int i=0; i