1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.catalina.connector;
18
19 import java.io.IOException;
20 import java.nio.ByteBuffer;
21
22 import javax.servlet.ServletOutputStream;
23 import javax.servlet.WriteListener;
24
25 import org.apache.tomcat.util.res.StringManager;
26
27 /**
28 * Coyote implementation of the servlet output stream.
29 *
30 * @author Costin Manolache
31 * @author Remy Maucherat
32 */
33 public class CoyoteOutputStream extends ServletOutputStream {
34
35 protected static final StringManager sm = StringManager.getManager(CoyoteOutputStream.class);
36
37
38 // ----------------------------------------------------- Instance Variables
39
40 protected OutputBuffer ob;
41
42
43 // ----------------------------------------------------------- Constructors
44
45
46 protected CoyoteOutputStream(OutputBuffer ob) {
47 this.ob = ob;
48 }
49
50
51 // --------------------------------------------------------- Public Methods
52
53
54 /**
55 * Prevent cloning the facade.
56 */
57 @Override
58 protected Object clone() throws CloneNotSupportedException {
59 throw new CloneNotSupportedException();
60 }
61
62
63 // -------------------------------------------------------- Package Methods
64
65
66 /**
67 * Clear facade.
68 */
69 void clear() {
70 ob = null;
71 }
72
73
74 // --------------------------------------------------- OutputStream Methods
75
76
77 @Override
78 public void write(int i) throws IOException {
79 boolean nonBlocking = checkNonBlockingWrite();
80 ob.writeByte(i);
81 if (nonBlocking) {
82 checkRegisterForWrite();
83 }
84 }
85
86
87 @Override
88 public void write(byte[] b) throws IOException {
89 write(b, 0, b.length);
90 }
91
92
93 @Override
94 public void write(byte[] b, int off, int len) throws IOException {
95 boolean nonBlocking = checkNonBlockingWrite();
96 ob.write(b, off, len);
97 if (nonBlocking) {
98 checkRegisterForWrite();
99 }
100 }
101
102
103 public void write(ByteBuffer from) throws IOException {
104 boolean nonBlocking = checkNonBlockingWrite();
105 ob.write(from);
106 if (nonBlocking) {
107 checkRegisterForWrite();
108 }
109 }
110
111
112 /**
113 * Will send the buffer to the client.
114 */
115 @Override
116 public void flush() throws IOException {
117 boolean nonBlocking = checkNonBlockingWrite();
118 ob.flush();
119 if (nonBlocking) {
120 checkRegisterForWrite();
121 }
122 }
123
124
125 /**
126 * Checks for concurrent writes which are not permitted. This object has no
127 * state information so the call chain is
128 * CoyoteOutputStream->OutputBuffer->CoyoteResponse.
129 *
130 * @return <code>true</code> if this OutputStream is currently in
131 * non-blocking mode.
132 */
133 private boolean checkNonBlockingWrite() {
134 boolean nonBlocking = !ob.isBlocking();
135 if (nonBlocking && !ob.isReady()) {
136 throw new IllegalStateException(sm.getString("coyoteOutputStream.nbNotready"));
137 }
138 return nonBlocking;
139 }
140
141
142 /**
143 * Checks to see if there is data left in the Coyote output buffers (NOT the
144 * servlet output buffer) and if so registers the associated socket for
145 * write so the buffers will be emptied. The container will take care of
146 * this. As far as the app is concerned, there is a non-blocking write in
147 * progress. It doesn't have visibility of whether the data is buffered in
148 * the socket buffer or the Coyote buffers.
149 */
150 private void checkRegisterForWrite() {
151 ob.checkRegisterForWrite();
152 }
153
154
155 @Override
156 public void close() throws IOException {
157 ob.close();
158 }
159
160 @Override
161 public boolean isReady() {
162 return ob.isReady();
163 }
164
165
166 @Override
167 public void setWriteListener(WriteListener listener) {
168 ob.setWriteListener(listener);
169 }
170 }
171
172