001/*
002 * ====================================================================
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *   http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied.  See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 * ====================================================================
020 *
021 * This software consists of voluntary contributions made by many
022 * individuals on behalf of the Apache Software Foundation.  For more
023 * information on the Apache Software Foundation, please see
024 * <http://www.apache.org/>.
025 *
026 */
027package org.apache.http.impl.conn;
028
029import java.io.ByteArrayInputStream;
030import java.io.IOException;
031import java.io.InputStream;
032
033import org.apache.commons.logging.Log;
034import org.apache.http.annotation.Contract;
035import org.apache.http.annotation.ThreadingBehavior;
036import org.apache.http.util.Args;
037
038/**
039 * Logs data to the wire LOG.
040 * TODO: make package private. Should not be part of the public API.
041 *
042 * @since 4.0
043 */
044@Contract(threading = ThreadingBehavior.IMMUTABLE)
045public class Wire {
046
047    private final Log log;
048    private final String id;
049
050    /**
051     * @since 4.3
052     */
053    public Wire(final Log log, final String id) {
054        this.log = log;
055        this.id = id;
056    }
057
058    public Wire(final Log log) {
059        this(log, "");
060    }
061
062    private void wire(final String header, final InputStream instream)
063      throws IOException {
064        final StringBuilder buffer = new StringBuilder();
065        int ch;
066        while ((ch = instream.read()) != -1) {
067            if (ch == 13) {
068                buffer.append("[\\r]");
069            } else if (ch == 10) {
070                    buffer.append("[\\n]\"");
071                    buffer.insert(0, "\"");
072                    buffer.insert(0, header);
073                    log.debug(id + " " + buffer.toString());
074                    buffer.setLength(0);
075            } else if ((ch < 32) || (ch > 127)) {
076                buffer.append("[0x");
077                buffer.append(Integer.toHexString(ch));
078                buffer.append("]");
079            } else {
080                buffer.append((char) ch);
081            }
082        }
083        if (buffer.length() > 0) {
084            buffer.append('\"');
085            buffer.insert(0, '\"');
086            buffer.insert(0, header);
087            log.debug(id + " " + buffer.toString());
088        }
089    }
090
091
092    public boolean enabled() {
093        return log.isDebugEnabled();
094    }
095
096    public void output(final InputStream outstream)
097      throws IOException {
098        Args.notNull(outstream, "Output");
099        wire(">> ", outstream);
100    }
101
102    public void input(final InputStream instream)
103      throws IOException {
104        Args.notNull(instream, "Input");
105        wire("<< ", instream);
106    }
107
108    public void output(final byte[] b, final int off, final int len)
109      throws IOException {
110        Args.notNull(b, "Output");
111        wire(">> ", new ByteArrayInputStream(b, off, len));
112    }
113
114    public void input(final byte[] b, final int off, final int len)
115      throws IOException {
116        Args.notNull(b, "Input");
117        wire("<< ", new ByteArrayInputStream(b, off, len));
118    }
119
120    public void output(final byte[] b)
121      throws IOException {
122        Args.notNull(b, "Output");
123        wire(">> ", new ByteArrayInputStream(b));
124    }
125
126    public void input(final byte[] b)
127      throws IOException {
128        Args.notNull(b, "Input");
129        wire("<< ", new ByteArrayInputStream(b));
130    }
131
132    public void output(final int b)
133      throws IOException {
134        output(new byte[] {(byte) b});
135    }
136
137    public void input(final int b)
138      throws IOException {
139        input(new byte[] {(byte) b});
140    }
141
142    public void output(final String s)
143      throws IOException {
144        Args.notNull(s, "Output");
145        output(s.getBytes());
146    }
147
148    public void input(final String s)
149      throws IOException {
150        Args.notNull(s, "Input");
151        input(s.getBytes());
152    }
153}