From 61220f8af5b845282a9cc19a2ee30a0ca00ba81b Mon Sep 17 00:00:00 2001 From: Roland Weber Date: Fri, 5 Jan 2007 11:32:17 +0000 Subject: [PATCH] new connection interfaces, step 4 - first example, plus a debug contrib git-svn-id: https://svn.apache.org/repos/asf/jakarta/httpcomponents/httpclient/trunk@492988 13f79535-47bb-0310-9956-ffa450edef68 --- build.xml | 30 +- .../contrib/conn/TalkativeSocketFactory.java | 335 ++++++++++++++++++ .../examples/conn/OperatorConnectDirect.java | 192 ++++++++++ 3 files changed, 552 insertions(+), 5 deletions(-) create mode 100644 src/contrib/org/apache/http/contrib/conn/TalkativeSocketFactory.java create mode 100644 src/examples/org/apache/http/examples/conn/OperatorConnectDirect.java 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