Skip to content
This repository was archived by the owner on Aug 17, 2018. It is now read-only.

Commit e585bc7

Browse files
author
Dongbin Nie
committed
svn path=/trunk/; revision=1430
1 parent 5d09915 commit e585bc7

1 file changed

Lines changed: 100 additions & 26 deletions

File tree

impl/src/main/java/org/apache/jasper/runtime/JspWriterImpl.java

Lines changed: 100 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -90,13 +90,20 @@
9090
*
9191
* @author Anil K. Vijendran
9292
* @author Kin-man Chung
93+
* @author Dongbin Nie
9394
*/
9495
public class JspWriterImpl extends JspWriter {
96+
97+
private static final int MAX_BUFFER_SIZE = Integer.getInteger(
98+
"org.apache.jasper.runtime.JspWriterImpl.MAX_THREAD_LOCAL_BUFFER_SIZE",
99+
32 * 1024);
100+
101+
private static final ThreadLocal<CharBufferThreadLocalPool>
102+
charBufferPools = new ThreadLocal<CharBufferThreadLocalPool>();
95103

96104
private Writer out;
97105
private ServletResponse response;
98-
private char cb[];
99-
private int nextChar;
106+
private CharBuffer buf;
100107
private boolean flushed = false;
101108
private boolean closed = false;
102109
protected boolean implementsByteWriter = true;
@@ -131,8 +138,7 @@ public JspWriterImpl(ServletResponse response, int sz,
131138
if (sz < 0)
132139
throw new IllegalArgumentException("Buffer size <= 0");
133140
this.response = response;
134-
cb = sz == 0 ? null : new char[sz];
135-
nextChar = 0;
141+
allocateCharBuffer();
136142
// START OF IASRI 4641975/6172992
137143
try {
138144
response.setBufferSize(sz);
@@ -144,11 +150,9 @@ public JspWriterImpl(ServletResponse response, int sz,
144150

145151
void init( ServletResponse response, int sz, boolean autoFlush ) {
146152
this.response= response;
147-
if( sz > 0 && ( cb == null || sz > cb.length ) )
148-
cb=new char[sz];
149-
nextChar = 0;
150153
this.autoFlush=autoFlush;
151154
this.bufferSize=sz;
155+
allocateCharBuffer();
152156
// START OF IASRI 4641975/6172992
153157
try {
154158
response.setBufferSize(sz);
@@ -165,7 +169,7 @@ void recycle() {
165169
closed = false;
166170
out = null;
167171
byteOut = null;
168-
nextChar = 0;
172+
releaseCharBuffer();
169173
response = null;
170174
}
171175

@@ -179,11 +183,11 @@ protected final void flushBuffer() throws IOException {
179183
return;
180184
flushed = true;
181185
ensureOpen();
182-
if (nextChar == 0)
186+
if (buf.pos == buf.offset)
183187
return;
184188
initOut();
185-
out.write(cb, 0, nextChar);
186-
nextChar = 0;
189+
out.write(buf.buf, buf.offset, buf.pos - buf.offset);
190+
buf.pos = buf.offset;
187191
}
188192

189193
private void initOut() throws IOException {
@@ -217,15 +221,16 @@ public final void clear() throws IOException {
217221
throw new IOException(
218222
getLocalizeMessage("jsp.error.attempt_to_clear_flushed_buffer"));
219223
ensureOpen();
220-
nextChar = 0;
224+
if (buf != null)
225+
buf.pos = buf.offset;
221226
}
222227

223228
public void clearBuffer() throws IOException {
224229
if (bufferSize == 0)
225230
throw new IllegalStateException(
226231
getLocalizeMessage("jsp.error.ise_on_clear"));
227232
ensureOpen();
228-
nextChar = 0;
233+
buf.pos = buf.offset;
229234
}
230235

231236
private final void bufferOverflow() throws IOException {
@@ -273,7 +278,7 @@ public void close() throws IOException {
273278
* @return the number of bytes unused in the buffer
274279
*/
275280
public int getRemaining() {
276-
return bufferSize - nextChar;
281+
return buf == null ? 0 : buf.lim - buf.pos;
277282
}
278283

279284
/** check to make sure that the stream has not been closed */
@@ -347,12 +352,12 @@ public void write(int c) throws IOException {
347352
out.write(c);
348353
}
349354
else {
350-
if (nextChar >= bufferSize)
355+
if (getRemaining() == 0)
351356
if (autoFlush)
352357
flushBuffer();
353358
else
354359
bufferOverflow();
355-
cb[nextChar++] = (char) c;
360+
buf.buf[buf.pos++] = (char) c;
356361
}
357362
}
358363

@@ -412,11 +417,11 @@ public void write(char cbuf[], int off, int len)
412417

413418
int b = off, t = off + len;
414419
while (b < t) {
415-
int d = min(bufferSize - nextChar, t - b);
416-
System.arraycopy(cbuf, b, cb, nextChar, d);
420+
int d = min(getRemaining(), t - b);
421+
System.arraycopy(cbuf, b, buf.buf, buf.pos, d);
417422
b += d;
418-
nextChar += d;
419-
if (nextChar >= bufferSize)
423+
buf.pos += d;
424+
if (getRemaining() == 0)
420425
if (autoFlush)
421426
flushBuffer();
422427
else
@@ -449,11 +454,11 @@ public void write(String s, int off, int len) throws IOException {
449454
}
450455
int b = off, t = off + len;
451456
while (b < t) {
452-
int d = min(bufferSize - nextChar, t - b);
453-
s.getChars(b, b + d, cb, nextChar);
457+
int d = min(getRemaining(), t - b);
458+
s.getChars(b, b + d, buf.buf, buf.pos);
454459
b += d;
455-
nextChar += d;
456-
if (nextChar >= bufferSize)
460+
buf.pos += d;
461+
if (getRemaining() == 0)
457462
if (autoFlush)
458463
flushBuffer();
459464
else
@@ -718,11 +723,80 @@ public void println(Object x) throws IOException {
718723

719724
// START PWC 6512276
720725
public boolean hasData() {
721-
if (bufferSize != 0 && nextChar != 0) {
726+
if (bufferSize != 0 && buf.pos != buf.offset) {
722727
return true;
723728
}
724729

725730
return false;
726731
}
727732
// END PWC 6512276
733+
734+
private void allocateCharBuffer() {
735+
if (bufferSize == 0) return;
736+
737+
if (bufferSize > MAX_BUFFER_SIZE) {
738+
buf = new CharBuffer(new char[bufferSize], 0, bufferSize);
739+
} else {
740+
buf = getCharBufferThreadLocalPool().allocate(bufferSize);
741+
}
742+
}
743+
744+
private void releaseCharBuffer() {
745+
if (buf == null) return;
746+
747+
if ((buf.lim - buf.offset) <= MAX_BUFFER_SIZE) {
748+
getCharBufferThreadLocalPool().release(buf);
749+
}
750+
buf = null;
751+
}
752+
753+
private CharBufferThreadLocalPool getCharBufferThreadLocalPool() {
754+
CharBufferThreadLocalPool pool = charBufferPools.get();
755+
if (pool == null) {
756+
pool = new CharBufferThreadLocalPool();
757+
charBufferPools.set(pool);
758+
}
759+
return pool;
760+
}
761+
762+
private static class CharBuffer {
763+
char[] buf;
764+
int offset;
765+
int pos;
766+
int lim;
767+
768+
CharBuffer(char[] buffer, int offset, int length) {
769+
this.buf = buffer;
770+
this.offset = offset;
771+
this.pos = offset;
772+
this.lim = offset + length;
773+
}
774+
}
775+
776+
private static class CharBufferThreadLocalPool {
777+
private char[] pool;
778+
private int pos;
779+
780+
public CharBuffer allocate(int size) {
781+
if (remaining() < size) {
782+
pool = new char[MAX_BUFFER_SIZE];
783+
pos = 0;
784+
}
785+
786+
CharBuffer allocated = new CharBuffer(pool, pos, size);
787+
pos += size;
788+
789+
return allocated;
790+
}
791+
792+
public void release(CharBuffer buffer) {
793+
if (buffer.buf == pool && buffer.lim == pos) {
794+
pos = buffer.offset;
795+
}
796+
}
797+
798+
public int remaining() {
799+
return pool == null ? 0 : pool.length - pos;
800+
}
801+
}
728802
}

0 commit comments

Comments
 (0)