Tue, 09 Apr 2013 14:51:13 +0100
8010393: Update JAX-WS RI to 2.2.9-b12941
Reviewed-by: alanb, erikj
Contributed-by: miroslav.kos@oracle.com, martin.grebac@oracle.com
ohair@286 | 1 | /* |
alanb@368 | 2 | * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. |
ohair@286 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
ohair@286 | 4 | * |
ohair@286 | 5 | * This code is free software; you can redistribute it and/or modify it |
ohair@286 | 6 | * under the terms of the GNU General Public License version 2 only, as |
ohair@286 | 7 | * published by the Free Software Foundation. Oracle designates this |
ohair@286 | 8 | * particular file as subject to the "Classpath" exception as provided |
ohair@286 | 9 | * by Oracle in the LICENSE file that accompanied this code. |
ohair@286 | 10 | * |
ohair@286 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
ohair@286 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
ohair@286 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
ohair@286 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
ohair@286 | 15 | * accompanied this code). |
ohair@286 | 16 | * |
ohair@286 | 17 | * You should have received a copy of the GNU General Public License version |
ohair@286 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
ohair@286 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
ohair@286 | 20 | * |
ohair@286 | 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
ohair@286 | 22 | * or visit www.oracle.com if you need additional information or have any |
ohair@286 | 23 | * questions. |
ohair@286 | 24 | */ |
ohair@286 | 25 | |
ohair@286 | 26 | /* |
ohair@286 | 27 | * @(#)UUDecoderStream.java 1.8 02/07/08 |
ohair@286 | 28 | */ |
ohair@286 | 29 | |
ohair@286 | 30 | |
ohair@286 | 31 | |
ohair@286 | 32 | package com.sun.xml.internal.messaging.saaj.packaging.mime.util; |
ohair@286 | 33 | |
ohair@286 | 34 | import java.io.*; |
ohair@286 | 35 | |
ohair@286 | 36 | /** |
ohair@286 | 37 | * This class implements a UUDecoder. It is implemented as |
ohair@286 | 38 | * a FilterInputStream, so one can just wrap this class around |
ohair@286 | 39 | * any input stream and read bytes from this filter. The decoding |
ohair@286 | 40 | * is done as the bytes are read out. |
ohair@286 | 41 | * |
ohair@286 | 42 | * @author John Mani |
ohair@286 | 43 | * @author Bill Shannon |
ohair@286 | 44 | */ |
ohair@286 | 45 | |
ohair@286 | 46 | public class UUDecoderStream extends FilterInputStream { |
ohair@286 | 47 | private String name; |
ohair@286 | 48 | private int mode; |
ohair@286 | 49 | |
ohair@286 | 50 | private byte[] buffer; // cache of decoded bytes |
ohair@286 | 51 | private int bufsize = 0; // size of the cache |
ohair@286 | 52 | private int index = 0; // index into the cache |
ohair@286 | 53 | private boolean gotPrefix = false; |
ohair@286 | 54 | private boolean gotEnd = false; |
ohair@286 | 55 | private LineInputStream lin; |
ohair@286 | 56 | |
ohair@286 | 57 | /** |
ohair@286 | 58 | * Create a UUdecoder that decodes the specified input stream |
ohair@286 | 59 | * @param in the input stream |
ohair@286 | 60 | */ |
ohair@286 | 61 | public UUDecoderStream(InputStream in) { |
ohair@286 | 62 | super(in); |
ohair@286 | 63 | lin = new LineInputStream(in); |
ohair@286 | 64 | buffer = new byte[45]; // max decoded chars in a line = 45 |
ohair@286 | 65 | } |
ohair@286 | 66 | |
ohair@286 | 67 | /** |
ohair@286 | 68 | * Read the next decoded byte from this input stream. The byte |
ohair@286 | 69 | * is returned as an <code>int</code> in the range <code>0</code> |
ohair@286 | 70 | * to <code>255</code>. If no byte is available because the end of |
ohair@286 | 71 | * the stream has been reached, the value <code>-1</code> is returned. |
ohair@286 | 72 | * This method blocks until input data is available, the end of the |
ohair@286 | 73 | * stream is detected, or an exception is thrown. |
ohair@286 | 74 | * |
ohair@286 | 75 | * @return next byte of data, or <code>-1</code> if the end of |
ohair@286 | 76 | * stream is reached. |
ohair@286 | 77 | * @exception IOException if an I/O error occurs. |
ohair@286 | 78 | * @see java.io.FilterInputStream#in |
ohair@286 | 79 | */ |
ohair@286 | 80 | |
ohair@286 | 81 | public int read() throws IOException { |
ohair@286 | 82 | if (index >= bufsize) { |
ohair@286 | 83 | readPrefix(); |
ohair@286 | 84 | if (!decode()) |
ohair@286 | 85 | return -1; |
ohair@286 | 86 | index = 0; // reset index into buffer |
ohair@286 | 87 | } |
ohair@286 | 88 | return buffer[index++] & 0xff; // return lower byte |
ohair@286 | 89 | } |
ohair@286 | 90 | |
ohair@286 | 91 | public int read(byte[] buf, int off, int len) throws IOException { |
ohair@286 | 92 | int i, c; |
ohair@286 | 93 | for (i = 0; i < len; i++) { |
ohair@286 | 94 | if ((c = read()) == -1) { |
ohair@286 | 95 | if (i == 0) // At end of stream, so we should |
ohair@286 | 96 | i = -1; // return -1, NOT 0. |
ohair@286 | 97 | break; |
ohair@286 | 98 | } |
ohair@286 | 99 | buf[off+i] = (byte)c; |
ohair@286 | 100 | } |
ohair@286 | 101 | return i; |
ohair@286 | 102 | } |
ohair@286 | 103 | |
ohair@286 | 104 | public boolean markSupported() { |
ohair@286 | 105 | return false; |
ohair@286 | 106 | } |
ohair@286 | 107 | |
ohair@286 | 108 | public int available() throws IOException { |
ohair@286 | 109 | // This is only an estimate, since in.available() |
ohair@286 | 110 | // might include CRLFs too .. |
ohair@286 | 111 | return ((in.available() * 3)/4 + (bufsize-index)); |
ohair@286 | 112 | } |
ohair@286 | 113 | |
ohair@286 | 114 | /** |
ohair@286 | 115 | * Get the "name" field from the prefix. This is meant to |
ohair@286 | 116 | * be the pathname of the decoded file |
ohair@286 | 117 | * |
ohair@286 | 118 | * @return name of decoded file |
ohair@286 | 119 | * @exception IOException if an I/O error occurs. |
ohair@286 | 120 | */ |
ohair@286 | 121 | public String getName() throws IOException { |
ohair@286 | 122 | readPrefix(); |
ohair@286 | 123 | return name; |
ohair@286 | 124 | } |
ohair@286 | 125 | |
ohair@286 | 126 | /** |
ohair@286 | 127 | * Get the "mode" field from the prefix. This is the permission |
ohair@286 | 128 | * mode of the source file. |
ohair@286 | 129 | * |
ohair@286 | 130 | * @return permission mode of source file |
ohair@286 | 131 | * @exception IOException if an I/O error occurs. |
ohair@286 | 132 | */ |
ohair@286 | 133 | public int getMode() throws IOException { |
ohair@286 | 134 | readPrefix(); |
ohair@286 | 135 | return mode; |
ohair@286 | 136 | } |
ohair@286 | 137 | |
ohair@286 | 138 | /** |
ohair@286 | 139 | * UUencoded streams start off with the line: |
ohair@286 | 140 | * "begin <mode> <filename>" |
ohair@286 | 141 | * Search for this prefix and gobble it up. |
ohair@286 | 142 | */ |
ohair@286 | 143 | private void readPrefix() throws IOException { |
ohair@286 | 144 | if (gotPrefix) // got the prefix |
ohair@286 | 145 | return; |
ohair@286 | 146 | |
ohair@286 | 147 | String s; |
ohair@286 | 148 | for (;;) { |
ohair@286 | 149 | // read till we get the prefix: "begin MODE FILENAME" |
ohair@286 | 150 | s = lin.readLine(); // NOTE: readLine consumes CRLF pairs too |
ohair@286 | 151 | if (s == null) |
ohair@286 | 152 | throw new IOException("UUDecoder error: No Begin"); |
ohair@286 | 153 | if (s.regionMatches(true, 0, "begin", 0, 5)) { |
ohair@286 | 154 | try { |
ohair@286 | 155 | mode = Integer.parseInt(s.substring(6,9)); |
ohair@286 | 156 | } catch (NumberFormatException ex) { |
ohair@286 | 157 | throw new IOException("UUDecoder error: " + ex.toString()); |
ohair@286 | 158 | } |
ohair@286 | 159 | name = s.substring(10); |
ohair@286 | 160 | gotPrefix = true; |
ohair@286 | 161 | return; |
ohair@286 | 162 | } |
ohair@286 | 163 | } |
ohair@286 | 164 | } |
ohair@286 | 165 | |
ohair@286 | 166 | private boolean decode() throws IOException { |
ohair@286 | 167 | |
ohair@286 | 168 | if (gotEnd) |
ohair@286 | 169 | return false; |
ohair@286 | 170 | bufsize = 0; |
ohair@286 | 171 | String line; |
ohair@286 | 172 | do { |
ohair@286 | 173 | line = lin.readLine(); |
ohair@286 | 174 | |
ohair@286 | 175 | /* |
ohair@286 | 176 | * Improperly encoded data sometimes omits the zero length |
ohair@286 | 177 | * line that starts with a space character, we detect the |
ohair@286 | 178 | * following "end" line here. |
ohair@286 | 179 | */ |
ohair@286 | 180 | if (line == null) |
ohair@286 | 181 | throw new IOException("Missing End"); |
ohair@286 | 182 | if (line.regionMatches(true, 0, "end", 0, 3)) { |
ohair@286 | 183 | gotEnd = true; |
ohair@286 | 184 | return false; |
ohair@286 | 185 | } |
ohair@286 | 186 | } while (line.length() == 0); |
ohair@286 | 187 | int count = line.charAt(0); |
ohair@286 | 188 | if (count < ' ') |
ohair@286 | 189 | throw new IOException("Buffer format error"); |
ohair@286 | 190 | |
ohair@286 | 191 | /* |
ohair@286 | 192 | * The first character in a line is the number of original (not |
ohair@286 | 193 | * the encoded atoms) characters in the line. Note that all the |
ohair@286 | 194 | * code below has to handle the <SPACE> character that indicates |
ohair@286 | 195 | * end of encoded stream. |
ohair@286 | 196 | */ |
ohair@286 | 197 | count = (count - ' ') & 0x3f; |
ohair@286 | 198 | |
ohair@286 | 199 | if (count == 0) { |
ohair@286 | 200 | line = lin.readLine(); |
ohair@286 | 201 | if (line == null || !line.regionMatches(true, 0, "end", 0, 3)) |
ohair@286 | 202 | throw new IOException("Missing End"); |
ohair@286 | 203 | gotEnd = true; |
ohair@286 | 204 | return false; |
ohair@286 | 205 | } |
ohair@286 | 206 | |
ohair@286 | 207 | int need = ((count * 8)+5)/6; |
ohair@286 | 208 | //System.out.println("count " + count + ", need " + need + ", len " + line.length()); |
ohair@286 | 209 | if (line.length() < need + 1) |
ohair@286 | 210 | throw new IOException("Short buffer error"); |
ohair@286 | 211 | |
ohair@286 | 212 | int i = 1; |
ohair@286 | 213 | byte a, b; |
ohair@286 | 214 | /* |
ohair@286 | 215 | * A correct uuencoder always encodes 3 characters at a time, even |
ohair@286 | 216 | * if there aren't 3 characters left. But since some people out |
ohair@286 | 217 | * there have broken uuencoders we handle the case where they |
ohair@286 | 218 | * don't include these "unnecessary" characters. |
ohair@286 | 219 | */ |
ohair@286 | 220 | while (bufsize < count) { |
ohair@286 | 221 | // continue decoding until we get 'count' decoded chars |
ohair@286 | 222 | a = (byte)((line.charAt(i++) - ' ') & 0x3f); |
ohair@286 | 223 | b = (byte)((line.charAt(i++) - ' ') & 0x3f); |
ohair@286 | 224 | buffer[bufsize++] = (byte)(((a << 2) & 0xfc) | ((b >>> 4) & 3)); |
ohair@286 | 225 | |
ohair@286 | 226 | if (bufsize < count) { |
ohair@286 | 227 | a = b; |
ohair@286 | 228 | b = (byte)((line.charAt(i++) - ' ') & 0x3f); |
ohair@286 | 229 | buffer[bufsize++] = |
ohair@286 | 230 | (byte)(((a << 4) & 0xf0) | ((b >>> 2) & 0xf)); |
ohair@286 | 231 | } |
ohair@286 | 232 | |
ohair@286 | 233 | if (bufsize < count) { |
ohair@286 | 234 | a = b; |
ohair@286 | 235 | b = (byte)((line.charAt(i++) - ' ') & 0x3f); |
ohair@286 | 236 | buffer[bufsize++] = (byte)(((a << 6) & 0xc0) | (b & 0x3f)); |
ohair@286 | 237 | } |
ohair@286 | 238 | } |
ohair@286 | 239 | return true; |
ohair@286 | 240 | } |
ohair@286 | 241 | |
ohair@286 | 242 | /*** begin TEST program ***** |
ohair@286 | 243 | public static void main(String argv[]) throws Exception { |
ohair@286 | 244 | FileInputStream infile = new FileInputStream(argv[0]); |
ohair@286 | 245 | UUDecoderStream decoder = new UUDecoderStream(infile); |
ohair@286 | 246 | int c; |
ohair@286 | 247 | |
ohair@286 | 248 | try { |
ohair@286 | 249 | while ((c = decoder.read()) != -1) |
ohair@286 | 250 | System.out.write(c); |
ohair@286 | 251 | System.out.flush(); |
ohair@286 | 252 | } catch (Exception e) { |
ohair@286 | 253 | e.printStackTrace(); |
ohair@286 | 254 | } |
ohair@286 | 255 | } |
ohair@286 | 256 | **** end TEST program ****/ |
ohair@286 | 257 | } |