View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  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,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.shared.util.io;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.io.PushbackInputStream;
24  
25  /**
26   * NOTE: Copy of org.apache.abdera.i18n.text.io.DynamicPushbackInputStream
27   * 
28   * PushbackInputStream implementation that performs dynamic resizing of the unread buffer
29   */
30  public class DynamicPushbackInputStream extends PushbackInputStream
31  {
32  
33      private final int origsize;
34  
35      public DynamicPushbackInputStream(InputStream in)
36      {
37          super(in);
38          this.origsize = 1;
39      }
40  
41      public DynamicPushbackInputStream(InputStream in, int initialSize)
42      {
43          super(in, initialSize);
44          this.origsize = initialSize;
45      }
46  
47      /**
48       * Clear the buffer
49       */
50      public int clear()
51      {
52          int m = buf.length;
53          buf = new byte[origsize];
54          pos = origsize;
55          return m;
56      }
57  
58      /**
59       * Shrink the buffer. This will reclaim currently unused space in the buffer, reducing memory but potentially
60       * increasing the cost of resizing the buffer
61       */
62      public int shrink()
63      {
64          byte[] old = buf;
65          if (pos == 0)
66          {
67              return 0; // nothing to do
68          }
69          int n = old.length - pos;
70          int m;
71          int p;
72          int s;
73          int l;
74          if (n < origsize)
75          {
76              buf = new byte[origsize];
77              p = pos;
78              s = origsize - n;
79              l = old.length - p;
80              m = old.length - origsize;
81              pos = s;
82          }
83          else
84          {
85              buf = new byte[n];
86              p = pos;
87              s = 0;
88              l = n;
89              m = old.length - l;
90              pos = 0;
91          }
92          System.arraycopy(old, p, buf, s, l);
93          return m;
94      }
95  
96      private void resize(int len)
97      {
98          byte[] old = buf;
99          buf = new byte[old.length + len];
100         System.arraycopy(old, 0, buf, len, old.length);
101     }
102 
103     public void unread(byte[] b, int off, int len) throws IOException
104     {
105         if (len > pos && pos + len > buf.length)
106         {
107             resize(len - pos);
108             pos += len - pos;
109         }
110         super.unread(b, off, len);
111     }
112 
113     public void unread(int b) throws IOException
114     {
115         if (pos == 0)
116         {
117             resize(1);
118             pos++;
119         }
120         super.unread(b);
121     }
122 
123     public int read() throws IOException
124     {
125         int m = super.read();
126         if (pos >= buf.length && buf.length > origsize)
127         {
128             shrink();
129         }
130         return m;
131     }
132 
133     public int read(byte[] b, int off, int len) throws IOException
134     {
135         this.available(); // workaround for a problem in PushbackInputStream, without this, the amount of bytes read
136                           // from some streams will be incorrect
137         int r = super.read(b, off, len);
138         if (pos >= buf.length && buf.length > origsize)
139         {
140             shrink();
141         }
142         return r;
143     }
144 
145     public long skip(long n) throws IOException
146     {
147         long r = super.skip(n);
148         if (pos >= buf.length && buf.length > origsize)
149         {
150             shrink();
151         }
152         return r;
153     }
154 }