View Javadoc

1   /***
2    * Redistribution and use of this software and associated documentation
3    * ("Software"), with or without modification, are permitted provided
4    * that the following conditions are met:
5    *
6    * 1. Redistributions of source code must retain copyright
7    *    statements and notices.  Redistributions must also contain a
8    *    copy of this document.
9    *
10   * 2. Redistributions in binary form must reproduce the
11   *    above copyright notice, this list of conditions and the
12   *    following disclaimer in the documentation and/or other
13   *    materials provided with the distribution.
14   *
15   * 3. The name "Exolab" must not be used to endorse or promote
16   *    products derived from this Software without prior written
17   *    permission of Exoffice Technologies.  For written permission,
18   *    please contact info@exolab.org.
19   *
20   * 4. Products derived from this Software may not be called "Exolab"
21   *    nor may "Exolab" appear in their names without prior written
22   *    permission of Exoffice Technologies. Exolab is a registered
23   *    trademark of Exoffice Technologies.
24   *
25   * 5. Due credit should be given to the Exolab Project
26   *    (http://www.exolab.org/).
27   *
28   * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29   * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
32   * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39   * OF THE POSSIBILITY OF SUCH DAMAGE.
40   *
41   * Copyright 2004-2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42   *
43   * $Id: HTTPOutputStream.java,v 1.2 2005/04/04 15:08:53 tanderson Exp $
44   */
45  package org.exolab.jms.net.http;
46  
47  import java.io.IOException;
48  import java.io.OutputStream;
49  import java.net.HttpURLConnection;
50  import java.net.URL;
51  import java.net.URLConnection;
52  
53  import org.apache.commons.logging.Log;
54  import org.apache.commons.logging.LogFactory;
55  
56  
57  /***
58   * Writes to an {@link URLConnection}.
59   *
60   * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
61   * @version $Revision: 1.2 $ $Date: 2005/04/04 15:08:53 $
62   */
63  class HTTPOutputStream extends OutputStream {
64  
65      /***
66       * The connection identifier.
67       */
68      private final String _id;
69  
70      /***
71       * The tunnel servlet URL.
72       */
73      private final URL _url;
74  
75      /***
76       * The connection information.
77       */
78      private final HTTPRequestInfo _info;
79  
80      /***
81       * The local data buffer.
82       */
83      private final byte[] _data;
84  
85      /***
86       * The current index into <code>_data</code>.
87       */
88      private int _index;
89  
90      /***
91       * The logger.
92       */
93      private static final Log _log = LogFactory.getLog(HTTPOutputStream.class);
94  
95  
96      /***
97       * Construct a new <code>HTTPOutputStream</code>.
98       *
99       * @param id   the connection identifier
100      * @param url  the URL to connect to
101      * @param size the size of the buffer
102      * @param info the connection information
103      */
104     public HTTPOutputStream(String id, URL url, int size, HTTPRequestInfo info) {
105         _id = id;
106         _url = url;
107         _data = new byte[size];
108         _info = info;
109     }
110 
111     /***
112      * Flushes this output stream and forces any buffered output bytes to be
113      * written out.
114      *
115      * @throws IOException if an I/O error occurs
116      */
117     public void flush() throws IOException {
118         while (_index > 0) {
119             doWrite();
120         }
121     }
122 
123     /***
124      * Writes length bytes from the specified byte array starting at offset to
125      * this output stream.
126      *
127      * @param buffer the data to write
128      * @param offset the start offset in the data
129      * @param length the number of bytes to write
130      * @throws IOException if an I/O error occurs
131      */
132     public void write(byte[] buffer, int offset, int length)
133             throws IOException {
134 
135         int space = _data.length - _index;
136         if (space >= length) {
137             // got enough space, so copy it to the buffer
138             System.arraycopy(buffer, offset, _data, _index, length);
139             _index += length;
140         } else {
141             flush();
142             doWrite(buffer, offset, length);
143         }
144     }
145 
146     /***
147      * Writes the specified byte to this output stream.
148      *
149      * @param value the byte value
150      * @throws IOException if an I/O error occurs
151      */
152     public void write(int value) throws IOException {
153         while (_index >= _data.length) {
154             flush();
155         }
156         _data[_index++] = (byte) value;
157     }
158 
159     /***
160      * Writes from the local data buffer to the underlying connection.
161      *
162      * @throws IOException if an I/O error occurs
163      */
164     private void doWrite() throws IOException {
165         try {
166             doWrite(_data, 0, _index);
167             _index = 0;
168         } catch (IOException exception) {
169             _log.debug(exception, exception);
170             throw exception;
171         }
172     }
173 
174     /***
175      * Writes length bytes from the specified byte array starting at offset to
176      * the underlying connection.
177      *
178      * @param buffer the data to write
179      * @param offset the start offset in the data
180      * @param length the number of bytes to write
181      * @throws IOException if an I/O error occurs
182      */
183     private void doWrite(byte[] buffer, int offset, int length)
184             throws IOException {
185 
186         HttpURLConnection connection =
187                 TunnelHelper.create(_url, _id, "write", _info);
188         connection.setDoOutput(true);
189         OutputStream out = connection.getOutputStream();
190         out.write(buffer, offset, length);
191         out.close();
192         if (_log.isDebugEnabled()) {
193             _log.debug("doWrite(length=" + length + "), [id=" + _id + "]");
194         }
195 
196         if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
197             throw new IOException(connection.getResponseCode() + " "
198                                   + connection.getResponseMessage());
199         }
200 
201     }
202 
203 }