1 /*
2  * JBoss, Home of Professional Open Source.
3  * Copyright 2014 Red Hat, Inc., and individual contributors
4  * as indicated by the @author tags.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  */

18
19 package io.undertow.servlet.spec;
20
21 import java.io.OutputStream;
22 import java.io.PrintWriter;
23 import java.lang.reflect.Field;
24 import java.security.AccessController;
25 import java.security.PrivilegedAction;
26 import java.util.Locale;
27
28 import sun.misc.Unsafe;
29
30 /**
31  * @author Stuart Douglas
32  */

33 public final class ServletPrintWriterDelegate extends PrintWriter {
34     private ServletPrintWriterDelegate() {
35         super((OutputStream) null);
36     }
37
38     private static final sun.misc.Unsafe UNSAFE;
39
40     static {
41         UNSAFE = getUnsafe();
42     }
43
44     public static ServletPrintWriterDelegate newInstance(final ServletPrintWriter servletPrintWriter) {
45         final ServletPrintWriterDelegate delegate;
46         if (System.getSecurityManager() == null) {
47             try {
48                 delegate = (ServletPrintWriterDelegate) UNSAFE.allocateInstance(ServletPrintWriterDelegate.class);
49             } catch (InstantiationException e) {
50                 throw new RuntimeException(e);
51             }
52         } else {
53             delegate = AccessController.doPrivileged(new PrivilegedAction<ServletPrintWriterDelegate>() {
54                 @Override
55                 public ServletPrintWriterDelegate run() {
56                     try {
57                         return  (ServletPrintWriterDelegate) UNSAFE.allocateInstance(ServletPrintWriterDelegate.class);
58                     } catch (InstantiationException e) {
59                         throw new RuntimeException(e);
60                     }
61                 }
62             });
63         }
64         delegate.setServletPrintWriter(servletPrintWriter);
65         return delegate;
66     }
67
68     private ServletPrintWriter servletPrintWriter;
69
70     public void setServletPrintWriter(final ServletPrintWriter servletPrintWriter) {
71         this.servletPrintWriter = servletPrintWriter;
72     }
73
74     @Override
75     public void flush() {
76         servletPrintWriter.flush();
77     }
78
79     @Override
80     public void close() {
81         servletPrintWriter.close();
82     }
83
84     @Override
85     public boolean checkError() {
86         return servletPrintWriter.checkError();
87     }
88
89     @Override
90     public void write(final int c) {
91         servletPrintWriter.write(c);
92     }
93
94     @Override
95     public void write(final char[] buf, final int off, final int len) {
96         servletPrintWriter.write(buf, off, len);
97     }
98
99     @Override
100     public void write(final char[] buf) {
101         servletPrintWriter.write(buf);
102     }
103
104     @Override
105     public void write(final String s, final int off, final int len) {
106         servletPrintWriter.write(s, off, len);
107     }
108
109     @Override
110     public void write(final String s) {
111         servletPrintWriter.write(s == null ? "null" : s);
112     }
113
114     @Override
115     public void print(final boolean b) {
116         servletPrintWriter.print(b);
117     }
118
119     @Override
120     public void print(final char c) {
121         servletPrintWriter.print(c);
122     }
123
124     @Override
125     public void print(final int i) {
126         servletPrintWriter.print(i);
127     }
128
129     @Override
130     public void print(final long l) {
131         servletPrintWriter.print(l);
132     }
133
134     @Override
135     public void print(final float f) {
136         servletPrintWriter.print(f);
137     }
138
139     @Override
140     public void print(final double d) {
141         servletPrintWriter.print(d);
142     }
143
144     @Override
145     public void print(final char[] s) {
146         servletPrintWriter.print(s);
147     }
148
149     @Override
150     public void print(final String s) {
151         servletPrintWriter.print(s);
152     }
153
154     @Override
155     public void print(final Object obj) {
156         servletPrintWriter.print(obj);
157     }
158
159     @Override
160     public void println() {
161         servletPrintWriter.println();
162     }
163
164     @Override
165     public void println(final boolean x) {
166         servletPrintWriter.println(x);
167     }
168
169     @Override
170     public void println(final char x) {
171         servletPrintWriter.println(x);
172     }
173
174     @Override
175     public void println(final int x) {
176         servletPrintWriter.println(x);
177     }
178
179     @Override
180     public void println(final long x) {
181         servletPrintWriter.println(x);
182     }
183
184     @Override
185     public void println(final float x) {
186         servletPrintWriter.println(x);
187     }
188
189     @Override
190     public void println(final double x) {
191         servletPrintWriter.println(x);
192     }
193
194     @Override
195     public void println(final char[] x) {
196         servletPrintWriter.println(x);
197     }
198
199     @Override
200     public void println(final String x) {
201         servletPrintWriter.println(x);
202     }
203
204     @Override
205     public void println(final Object x) {
206         servletPrintWriter.println(x);
207     }
208
209     @Override
210     public PrintWriter printf(final String format, final Object... args) {
211         servletPrintWriter.printf(format, args);
212         return this;
213     }
214
215     @Override
216     public PrintWriter printf(final Locale l, final String format, final Object... args) {
217         servletPrintWriter.printf(l, format, args);
218         return this;
219     }
220
221     @Override
222     public PrintWriter format(final String format, final Object... args) {
223         servletPrintWriter.format(format, args);
224         return this;
225     }
226
227     @Override
228     public PrintWriter format(final Locale l, final String format, final Object... args) {
229         servletPrintWriter.format(l, format, args);
230         return this;
231     }
232
233     @Override
234     public PrintWriter append(final CharSequence csq) {
235         servletPrintWriter.append(csq);
236         return this;
237     }
238
239     @Override
240     public PrintWriter append(final CharSequence csq, final int start, final int end) {
241         servletPrintWriter.append(csq, start, end);
242         return this;
243     }
244
245     @Override
246     public PrintWriter append(final char c) {
247         servletPrintWriter.append(c);
248         return this;
249     }
250
251     private static Unsafe getUnsafe() {
252         if (System.getSecurityManager() != null) {
253             return AccessController.doPrivileged(new PrivilegedAction<Unsafe>() {
254                 public Unsafe run() {
255                     return getUnsafe0();
256                 }
257             });
258         }
259         return getUnsafe0();
260     }
261
262     private static Unsafe getUnsafe0()  {
263         try {
264             Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
265             theUnsafe.setAccessible(true);
266             return (Unsafe) theUnsafe.get(null);
267         } catch (Throwable t) {
268             throw new RuntimeException("JDK did not allow accessing unsafe", t);
269         }
270     }
271 }
272