View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.geronimo.javamail.store.imap.connection;
19  
20  import java.io.ByteArrayOutputStream;
21  
22  /**
23   * Simple extension to the ByteArrayOutputStream to allow inspection
24   * of the data while it is being accumulated.
25   */
26  public class IMAPResponseBuffer extends ByteArrayOutputStream {
27  
28      public IMAPResponseBuffer() {
29          super();
30      }
31  
32  
33      /**
34       * Read a character from the byte array output stream buffer
35       * at the give position.
36       *
37       * @param index  The requested index.
38       *
39       * @return The byte at the target index, or -1 if the index is out of
40       *         bounds.
41       */
42      public int read(int index) {
43          if (index >= size()) {
44              return -1;
45          }
46          return buf[index];
47      }
48  
49      /**
50       * Read a buffer of data from the output stream's accumulator
51       * buffer.  This will copy the data into a target byte arrain.
52       *
53       * @param buffer The target byte array for returning the data.
54       * @param offset The offset of the source data within the output stream buffer.
55       * @param length The desired length.
56       *
57       * @return The count of bytes transferred into the buffer.
58       */
59      public int read(byte[] buffer, int offset, int length) {
60  
61          int available = size() - offset;
62          length = Math.min(length, available);
63          // nothing to return?   quit now.
64          if (length <= 0) {
65              return 0;
66          }
67          System.arraycopy(buf, offset, buffer, 0, length);
68          return length;
69      }
70  
71      /**
72       * Search backwards through the buffer for a given byte.
73       *
74       * @param target The search character.
75       *
76       * @return The index relative to the buffer start of the given byte.
77       *         Returns -1 if not found.
78       */
79      public int lastIndex(byte target) {
80          for (int i = size() - 1; i > 0; i--) {
81              if (buf[i] == target) {
82                  return i;
83              }
84          }
85          return -1;
86      }
87  
88  
89      /**
90       * Return the last byte written to the output stream.  Returns
91       * -1 if the stream is empty.
92       *
93       * @return The last byte written (or -1 if the stream is empty).
94       */
95      public int lastByte() {
96          if (size() > 0) {
97              return buf[size() - 1];
98          }
99          return -1;
100     }
101 
102 
103     /**
104      * Retrieve an IMAP literal length value from the buffer.  We
105      * have a literal length value IFF the last characters written
106      * to the buffer have the form "{nnnn}".  This returns the
107      * integer value of the info inside the curly braces.  Returns -1
108      * if a valid literal length is not found.
109      *
110      * @return A literal length value, or -1 if we don't have a literal
111      *         signature at the end.
112      */
113     public int getLiteralLength() {
114         // was the last byte before the line break the close of the literal length?
115         if (lastByte() == '}') {
116             // locate the length start
117             int literalStart = lastIndex((byte)'{');
118             // no matching start, this can't be a literal.
119             if (literalStart == -1) {
120                 return -1;
121             }
122 
123             String lenString = new String(buf, literalStart + 1, size() - (literalStart + 2));
124             try {
125                 return Integer.parseInt(lenString);
126             } catch (NumberFormatException e) {
127                 e.printStackTrace(); 
128             }
129         }
130         // not a literal
131         return -1;
132     }
133 }
134