View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.server;
20  
21  import java.io.IOException;
22  import java.io.InterruptedIOException;
23  import java.io.PrintWriter;
24  import java.util.Formatter;
25  import java.util.Locale;
26  
27  import javax.servlet.ServletResponse;
28  
29  import org.eclipse.jetty.io.EofException;
30  import org.eclipse.jetty.io.RuntimeIOException;
31  import org.eclipse.jetty.util.log.Log;
32  import org.eclipse.jetty.util.log.Logger;
33  
34  
35  /* ------------------------------------------------------------ */
36  /** Specialized PrintWriter for servlet Responses
37   * <p>An instance of ResponseWriter is the {@link PrintWriter} subclass returned by {@link Response#getWriter()}.
38   * It differs from the standard {@link PrintWriter} in that:<ul>
39   * <li>It does not support autoflush</li>
40   * <li>The default Locale for {@link #format(String, Object...)} is the locale obtained by {@link ServletResponse#getLocale()}</li>
41   * <li>If a write or print method is called while {@link #checkError()}  returns true, then a {@link RuntimeIOException} is thrown to stop needless iterations.</li>
42   * <li>The writer may be reopen to allow for recycling</li>
43   * </ul>
44   * 
45   */
46  public class ResponseWriter extends PrintWriter
47  {
48      private static final Logger LOG = Log.getLogger(ResponseWriter.class);
49      private final static String __lineSeparator = System.getProperty("line.separator");
50      private final static String __trueln = "true"+__lineSeparator;
51      private final static String __falseln = "false"+__lineSeparator;
52      
53      private final HttpWriter _httpWriter;
54      private final Locale _locale;
55      private final String _encoding;
56      private IOException _ioException;
57      private boolean _isClosed = false;
58      private Formatter _formatter;
59  
60      public ResponseWriter(HttpWriter httpWriter,Locale locale,String encoding)
61      {
62          super(httpWriter,false);
63          _httpWriter=httpWriter;
64          _locale=locale;
65          _encoding=encoding;
66      }
67  
68      public boolean isFor(Locale locale, String encoding)
69      {
70          if (_locale==null && locale!=null)
71              return false;
72          if (_encoding==null && encoding!=null)
73              return false;
74          return _encoding.equalsIgnoreCase(encoding) && _locale.equals(locale);
75      }
76  
77      protected void reopen()
78      {
79          synchronized (lock)
80          {
81              _isClosed=false;
82              clearError();
83              out=_httpWriter;
84          }
85      }
86  
87      @Override
88      protected void clearError()
89      {
90          synchronized (lock)
91          {
92              _ioException=null;
93              super.clearError();
94          }
95      }
96      
97      @Override
98      public boolean checkError()
99      {
100         synchronized (lock)
101         {
102             return _ioException!=null || super.checkError();
103         }
104     }
105     
106     private void setError(Throwable th)
107     {
108         super.setError();
109 
110         if (th instanceof IOException)
111             _ioException=(IOException)th;
112         else
113         {
114             _ioException=new IOException(String.valueOf(th));
115             _ioException.initCause(th);
116         }
117 
118         if (LOG.isDebugEnabled())
119             LOG.debug(th);
120     }
121 
122 
123     @Override
124     protected void setError()
125     {
126         setError(new IOException());
127     }
128 
129     /** Check to make sure that the stream has not been closed */
130     private void isOpen() throws IOException
131     {       
132         if (_ioException!=null)
133             throw new RuntimeIOException(_ioException); 
134         
135         if (_isClosed)
136             throw new EofException("Stream closed");
137     }
138 
139     @Override
140     public void flush()
141     {
142         try
143         {
144             synchronized (lock)
145             {
146                 isOpen();
147                 out.flush();
148             }
149         }
150         catch (IOException ex)
151         {
152             setError(ex);
153         }
154     }
155 
156     @Override
157     public void close()
158     {
159         try
160         {
161             synchronized (lock)
162             {
163                 out.close();
164                 _isClosed = true;
165             }
166         }
167         catch (IOException ex)
168         {
169             setError(ex);
170         }
171     }
172 
173     @Override
174     public void write(int c)
175     {
176         try
177         {
178             synchronized (lock)
179             {
180                 isOpen();
181                 out.write(c);
182             }
183         }
184         catch (InterruptedIOException ex)
185         {
186             LOG.debug(ex);
187             Thread.currentThread().interrupt();
188         }
189         catch (IOException ex)
190         {
191             setError(ex);
192         }
193     }
194     
195     @Override
196     public void write(char buf[], int off, int len)
197     {
198         try
199         {
200             synchronized (lock)
201             {
202                 isOpen();
203                 out.write(buf,off,len);
204             }
205         }
206         catch (InterruptedIOException ex)
207         {
208             LOG.debug(ex);
209             Thread.currentThread().interrupt();
210         }
211         catch (IOException ex)
212         {
213             setError(ex);
214         }
215     }
216 
217     @Override
218     public void write(char buf[])
219     { 
220         this.write(buf,0,buf.length);
221     }
222 
223     @Override
224     public void write(String s, int off, int len)
225     {
226         try
227         {
228             synchronized (lock)
229             {
230                 isOpen();
231                 out.write(s,off,len);
232             }
233         }
234         catch (InterruptedIOException ex)
235         {
236             LOG.debug(ex);
237             Thread.currentThread().interrupt();
238         }
239         catch (IOException ex)
240         {
241             setError(ex);
242         }
243     }
244 
245     @Override
246     public void write(String s)
247     {
248         this.write(s,0,s.length());
249     }
250 
251     @Override
252     public void print(boolean b)
253     {
254         this.write(b?"true":"false");
255     }
256     
257     @Override
258     public void print(char c)
259     {
260         this.write(c);
261     }
262 
263     @Override
264     public void print(int i)
265     {
266         this.write(String.valueOf(i));
267     }
268 
269     @Override
270     public void print(long l)
271     {
272         this.write(String.valueOf(l));
273     }
274 
275     @Override
276     public void print(float f)
277     {
278         this.write(String.valueOf(f));
279     }
280 
281     @Override
282     public void print(double d)
283     {
284         this.write(String.valueOf(d));
285     }
286 
287     @Override
288     public void print(char s[])
289     {
290         this.write(s);
291     }
292 
293     @Override
294     public void print(String s)
295     {
296         if (s == null)
297             s = "null";
298         this.write(s);
299     }
300 
301     @Override
302     public void print(Object obj)
303     {
304         this.write(String.valueOf(obj));
305     }
306 
307     @Override
308     public void println()
309     {
310         try
311         {
312             synchronized (lock)
313             {
314                 isOpen();
315                 out.write(__lineSeparator);
316             }
317         }
318         catch (InterruptedIOException ex)
319         {
320             LOG.debug(ex);
321             Thread.currentThread().interrupt();
322         }
323         catch (IOException ex)
324         {
325             setError(ex);
326         }
327     }
328 
329     @Override
330     public void println(boolean b)
331     {
332         println(b?__trueln:__falseln);
333     }
334 
335     @Override
336     public void println(char c)
337     {
338         try
339         {
340             synchronized (lock)
341             {
342                 isOpen();
343                 out.write(c);
344             }
345         }
346         catch (InterruptedIOException ex)
347         {
348             LOG.debug(ex);
349             Thread.currentThread().interrupt();
350         }
351         catch (IOException ex)
352         {
353             setError(ex);
354         }
355     }
356 
357     @Override
358     public void println(int x)
359     {
360         this.println(String.valueOf(x));
361     }
362 
363     @Override
364     public void println(long x)
365     {
366         this.println(String.valueOf(x));
367     }
368     
369     @Override
370     public void println(float x)
371     {
372         this.println(String.valueOf(x));
373     }
374 
375     @Override
376     public void println(double x)
377     {
378         this.println(String.valueOf(x));
379     }
380 
381     @Override
382     public void println(char s[])
383     {
384         try
385         {
386             synchronized (lock)
387             {
388                 isOpen();
389                 out.write(s,0,s.length);
390                 out.write(__lineSeparator);
391             }
392         }
393         catch (InterruptedIOException ex)
394         {
395             LOG.debug(ex);
396             Thread.currentThread().interrupt();
397         }
398         catch (IOException ex)
399         {
400             setError(ex);
401         }
402     }
403 
404     @Override
405     public void println(String s)
406     {
407         if (s == null)
408             s = "null";
409         
410         try
411         {
412             synchronized (lock)
413             {
414                 isOpen();
415                 out.write(s,0,s.length());
416                 out.write(__lineSeparator);
417             }
418         }
419         catch (InterruptedIOException ex)
420         {
421             LOG.debug(ex);
422             Thread.currentThread().interrupt();
423         }
424         catch (IOException ex)
425         {
426             setError(ex);
427         }
428     }
429 
430     @Override
431     public void println(Object x)
432     {
433         this.println(String.valueOf(x));
434     }
435 
436     @Override
437     public PrintWriter printf(String format, Object... args)
438     {
439         return format(_locale,format,args);
440     }
441 
442     @Override
443     public PrintWriter printf(Locale l, String format, Object... args)
444     {
445         return format(l,format,args);
446     }
447 
448     @Override
449     public PrintWriter format(String format, Object... args)
450     {
451         return format(_locale,format,args);
452     }
453 
454     @Override
455     public PrintWriter format(Locale l, String format, Object... args)
456     { 
457         try 
458         {
459             synchronized (lock) 
460             {
461                 isOpen();
462                 if ((_formatter == null) || (_formatter.locale() != l))
463                     _formatter = new Formatter(this, l);
464                 _formatter.format(l, format, args);
465             }
466         } 
467         catch (InterruptedIOException ex)
468         {
469             LOG.debug(ex);
470             Thread.currentThread().interrupt();
471         }
472         catch (IOException ex)
473         {
474             setError(ex);
475         }
476         return this;
477     }
478 
479     
480     
481 }