View Javadoc

1   // ========================================================================
2   // Copyright (c) 2008-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  
14  package org.eclipse.jetty.server;
15  
16  import java.io.IOException;
17  import java.io.Writer;
18  
19  import javax.servlet.ServletOutputStream;
20  
21  import org.eclipse.jetty.http.AbstractGenerator;
22  import org.eclipse.jetty.http.Generator;
23  import org.eclipse.jetty.io.Buffer;
24  import org.eclipse.jetty.io.ByteArrayBuffer;
25  import org.eclipse.jetty.io.EofException;
26  import org.eclipse.jetty.util.ByteArrayOutputStream2;
27  
28  /** Output.
29   * 
30   * <p>
31   * Implements  {@link javax.servlet.ServletOutputStream} from the <code>javax.servlet</code> package.   
32   * </p>
33   * A {@link ServletOutputStream} implementation that writes content
34   * to a {@link AbstractGenerator}.   The class is designed to be reused
35   * and can be reopened after a close.
36   */
37  public class HttpOutput extends ServletOutputStream 
38  {
39      protected final AbstractGenerator _generator;
40      protected final long _maxIdleTime;
41      protected final ByteArrayBuffer _buf = new ByteArrayBuffer(AbstractGenerator.NO_BYTES);
42      private boolean _closed;
43      
44      // These are held here for reuse by Writer
45      String _characterEncoding;
46      Writer _converter;
47      char[] _chars;
48      ByteArrayOutputStream2 _bytes;
49      
50  
51      /* ------------------------------------------------------------ */
52      public HttpOutput(AbstractGenerator generator, long maxIdleTime)
53      {
54          _generator=generator;
55          _maxIdleTime=maxIdleTime;
56      }
57  
58      /* ------------------------------------------------------------ */
59      public boolean isWritten()
60      {
61          return _generator.getContentWritten()>0;
62      }
63      
64      /* ------------------------------------------------------------ */
65      /*
66       * @see java.io.OutputStream#close()
67       */
68      @Override
69      public void close() throws IOException
70      {
71          _closed=true;
72      }
73      
74      /* ------------------------------------------------------------ */
75      public boolean isClosed()
76      {
77          return _closed;
78      }
79      
80      /* ------------------------------------------------------------ */
81      public void reopen()
82      {
83          _closed=false;
84      }
85      
86      /* ------------------------------------------------------------ */
87      @Override
88      public void flush() throws IOException
89      {
90          _generator.flush(_maxIdleTime);
91      }
92  
93      /* ------------------------------------------------------------ */
94      @Override
95      public void write(byte[] b, int off, int len) throws IOException
96      {
97          write(new ByteArrayBuffer(b,off,len));
98      }
99  
100     /* ------------------------------------------------------------ */
101     /*
102      * @see java.io.OutputStream#write(byte[])
103      */
104     @Override
105     public void write(byte[] b) throws IOException
106     {
107         write(new ByteArrayBuffer(b));
108     }
109 
110     /* ------------------------------------------------------------ */
111     /*
112      * @see java.io.OutputStream#write(int)
113      */
114     @Override
115     public void write(int b) throws IOException
116     {
117         if (_closed)
118             throw new IOException("Closed");
119         if (!_generator.isOpen())
120             throw new EofException();
121         
122         // Block until we can add _content.
123         while (_generator.isBufferFull())
124         {
125             _generator.blockForOutput(_maxIdleTime);
126             if (_closed)
127                 throw new IOException("Closed");
128             if (!_generator.isOpen())
129                 throw new EofException();
130         }
131 
132         // Add the _content
133         if (_generator.addContent((byte)b))
134             // Buffers are full so flush.
135             flush();
136        
137         if (_generator.isAllContentWritten())
138         {
139             flush();
140             close();
141         }
142     }
143 
144     /* ------------------------------------------------------------ */
145     private void write(Buffer buffer) throws IOException
146     {
147         if (_closed)
148             throw new IOException("Closed");
149         if (!_generator.isOpen())
150             throw new EofException();
151         
152         // Block until we can add _content.
153         while (_generator.isBufferFull())
154         {
155             _generator.blockForOutput(_maxIdleTime);
156             if (_closed)
157                 throw new IOException("Closed");
158             if (!_generator.isOpen())
159                 throw new EofException();
160         }
161 
162         // Add the _content
163         _generator.addContent(buffer, Generator.MORE);
164 
165         // Have to flush and complete headers?
166         
167         if (_generator.isAllContentWritten())
168         {
169             flush();
170             close();
171         } 
172         else if (_generator.isBufferFull())
173             flush();
174 
175         // Block until our buffer is free
176         while (buffer.length() > 0 && _generator.isOpen())
177         {
178             _generator.blockForOutput(_maxIdleTime);
179         }
180     }
181 
182     /* ------------------------------------------------------------ */
183     /* 
184      * @see javax.servlet.ServletOutputStream#print(java.lang.String)
185      */
186     @Override
187     public void print(String s) throws IOException
188     {
189         write(s.getBytes());
190     }
191 }