History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/net/httpserver/ChunkedOutputStream.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/net/httpserver/ChunkedOutputStream.java+163−0
@@ -0,0 +1,163 @@
1/*
2 * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.net.httpserver;
27
28import java.io.*;
29import java.net.*;
30import com.sun.net.httpserver.*;
31import com.sun.net.httpserver.spi.*;
32
33/**
34 * a class which allows the caller to write an arbitrary
35 * number of bytes to an underlying stream.
36 * normal close() does not close the underlying stream
37 *
38 * This class is buffered.
39 *
40 * Each chunk is written in one go as :-
41 * abcd\r\nxxxxxxxxxxxxxx\r\n
42 *
43 * abcd is the chunk-size, and xxx is the chunk data
44 * If the length is less than 4 chars (in size) then the buffer
45 * is written with an offset.
46 * Final chunk is:
47 * 0\r\n\r\n
48 */
49
50class ChunkedOutputStream extends FilterOutputStream
51{
52 private boolean closed = false;
53 /* max. amount of user data per chunk */
54 final static int CHUNK_SIZE = 4096;
55 /* allow 4 bytes for chunk-size plus 4 for CRLFs */
56 final static int OFFSET = 6; /* initial <=4 bytes for len + CRLF */
57 private int pos = OFFSET;
58 private int count = 0;
59 private byte[] buf = new byte [CHUNK_SIZE+OFFSET+2];
60 ExchangeImpl t;
61
62 ChunkedOutputStream (ExchangeImpl t, OutputStream src) {
63 super (src);
64 this.t = t;
65 }
66
67 public void write (int b) throws IOException {
68 if (closed) {
69 throw new StreamClosedException ();
70 }
71 buf [pos++] = (byte)b;
72 count ++;
73 if (count == CHUNK_SIZE) {
74 writeChunk();
75 }
76 assert count < CHUNK_SIZE;
77 }
78
79 public void write (byte[]b, int off, int len) throws IOException {
80 if (closed) {
81 throw new StreamClosedException ();
82 }
83 int remain = CHUNK_SIZE - count;
84 if (len > remain) {
85 System.arraycopy (b,off,buf,pos,remain);
86 count = CHUNK_SIZE;
87 writeChunk();
88 len -= remain;
89 off += remain;
90 while (len >= CHUNK_SIZE) {
91 System.arraycopy (b,off,buf,OFFSET,CHUNK_SIZE);
92 len -= CHUNK_SIZE;
93 off += CHUNK_SIZE;
94 count = CHUNK_SIZE;
95 writeChunk();
96 }
97 }
98 if (len > 0) {
99 System.arraycopy (b,off,buf,pos,len);
100 count += len;
101 pos += len;
102 }
103 if (count == CHUNK_SIZE) {
104 writeChunk();
105 }
106 }
107
108 /**
109 * write out a chunk , and reset the pointers
110 * chunk does not have to be CHUNK_SIZE bytes
111 * count must == number of user bytes (<= CHUNK_SIZE)
112 */
113 private void writeChunk () throws IOException {
114 char[] c = Integer.toHexString (count).toCharArray();
115 int clen = c.length;
116 int startByte = 4 - clen;
117 int i;
118 for (i=0; i<clen; i++) {
119 buf[startByte+i] = (byte)c[i];
120 }
121 buf[startByte + (i++)] = '\r';
122 buf[startByte + (i++)] = '\n';
123 buf[startByte + (i++) + count] = '\r';
124 buf[startByte + (i++) + count] = '\n';
125 out.write (buf, startByte, i+count);
126 count = 0;
127 pos = OFFSET;
128 }
129
130 public void close () throws IOException {
131 if (closed) {
132 return;
133 }
134 flush();
135 try {
136 /* write an empty chunk */
137 writeChunk();
138 out.flush();
139 LeftOverInputStream is = t.getOriginalInputStream();
140 if (!is.isClosed()) {
141 is.close();
142 }
143 /* some clients close the connection before empty chunk is sent */
144 } catch (IOException e) {
145
146 } finally {
147 closed = true;
148 }
149
150 WriteFinishedEvent e = new WriteFinishedEvent (t);
151 t.getHttpContext().getServerImpl().addEvent (e);
152 }
153
154 public void flush () throws IOException {
155 if (closed) {
156 throw new StreamClosedException ();
157 }
158 if (count > 0) {
159 writeChunk();
160 }
161 out.flush();
162 }
163}