📄 dimedelimitedinputstream.java
字号:
streamInError = new IOException(Messages.getMessage ("attach.DimeStreamError1", "" + (recordLength - bytesRead))); throw streamInError; } if (!ME) { streamInError = new IOException(Messages.getMessage( "attach.DimeStreamError0")); throw streamInError; } //in theory the last chunk of data should also have been padded, but lets be tolerant of that. dataPadLength = 0; } else if (bytesRead >= recordLength) { //get rid of pading. try { dataPadLength -= readPad(dataPadLength); } catch (IOException e) { //in theory the last chunk of data should also have been padded, but lets be tolerant of that. if (!ME) throw e; else { dataPadLength = 0; streamInError = null; } } } if (bytesRead >= recordLength && ME) { finalClose(); } return totalbytesread >= 0 ? totalbytesread : -1; } void readHeader(boolean isChunk) throws IOException { bytesRead = 0; //How many bytes of the record have been read. if (isChunk) { if (!moreChunks) throw new RuntimeException( Messages.getMessage("attach.DimeStreamError2")); dataPadLength -= readPad(dataPadLength); //Just incase it was left over. } byte[] header = new byte[12]; if (header.length != readFromStream(header)) { streamInError = new IOException(Messages.getMessage( "attach.DimeStreamError3", "" + header.length)); throw streamInError; } //VERSION byte version = (byte) ((header[0] >>> 3) & 0x1f); if (version > DimeMultiPart.CURRENT_VERSION) { streamInError = new IOException(Messages.getMessage("attach.DimeStreamError4", "" + version, "" + DimeMultiPart.CURRENT_VERSION)); throw streamInError; } //B, E, C MB = 0 != (0x4 & header[0]); ME = 0 != (0x2 & header[0]); moreChunks = 0 != (0x1 & header[0]); //TYPE_T if (!isChunk) tnf = DimeTypeNameFormat.parseByte((byte) ((header[1] >>> 4) & (byte) 0xf)); //OPTIONS_LENGTH int optionsLength = ((((int) header[2]) << 8) & 0xff00) | ((int) header[3]); //ID_LENGTH int idLength = ((((int) header[4]) << 8) & 0xff00) | ((int) header[5]); //TYPE_LENGTH int typeLength = ((((int) header[6]) << 8) & 0xff00) | ((int) header[7]); //DATA_LENGTH recordLength = ((((long) header[8]) << 24) & 0xff000000L) | ((((long) header[9]) << 16) & 0xff0000L) | ((((long) header[10]) << 8) & 0xff00L) | ((long) header[11] & 0xffL); //OPTIONS + PADDING if (0 != optionsLength) { byte[] optBytes = new byte[optionsLength]; if (optionsLength != readFromStream(optBytes)) { streamInError = new IOException(Messages.getMessage( "attach.DimeStreamError5", "" + optionsLength)); throw streamInError; } optBytes = null; //Yup throw it away, don't know anything about options. int pad = DimeBodyPart.dimePadding(optionsLength); if (pad != readFromStream(header, 0, pad)) { streamInError = new IOException( Messages.getMessage("attach.DimeStreamError7")); throw streamInError; } } // ID + PADDING if (0 < idLength) { byte[] idBytes = new byte[ idLength]; if (idLength != readFromStream(idBytes)) { streamInError = new IOException( Messages.getMessage("attach.DimeStreamError8")); throw streamInError; } if (idLength != 0 && !isChunk) { id = new String(idBytes); } int pad = DimeBodyPart.dimePadding(idLength); if (pad != readFromStream(header, 0, pad)) { streamInError = new IOException(Messages.getMessage( "attach.DimeStreamError9")); throw streamInError; } } //TYPE + PADDING if (0 < typeLength) { byte[] typeBytes = new byte[typeLength]; if (typeLength != readFromStream(typeBytes)) { streamInError = new IOException(Messages.getMessage( "attach.DimeStreamError10")); throw streamInError; } if (typeLength != 0 && !isChunk) { type = new String(typeBytes); } int pad = DimeBodyPart.dimePadding(typeLength); if (pad != readFromStream(header, 0, pad)) { streamInError = new IOException(Messages.getMessage( "attach.DimeStreamError11")); throw streamInError; } } log.debug("MB:" + MB + ", ME:" + ME + ", CF:" + moreChunks + "Option length:" + optionsLength + ", ID length:" + idLength + ", typeLength:" + typeLength + ", TYPE_T:" + tnf); log.debug("id:\"" + id + "\""); log.debug("type:\"" + type + "\""); log.debug("recordlength:\"" + recordLength + "\""); dataPadLength = DimeBodyPart.dimePadding(recordLength); } /** * Read from the delimited stream. * @param b is the array to read into. Read as much as possible * into the size of this array. * @return the number of bytes read. -1 if endof stream * @throws IOException if data could not be read from the stream */ public int read(byte[] b) throws IOException { return read(b, 0, b.length); } // fixme: this seems a bit inefficient /** * Read from the boundary delimited stream. * * @return the byte read, or -1 if endof stream * @throws IOException if there was an error reading the data */ public int read() throws IOException { byte[] b = new byte[1]; int read = read(b, 0, 1); if (read < 0) return -1; // fixme: should we also check for read != 1? return (b[0] & 0xff); // convert byte value to a positive int } /** * Closes the stream. * <p> * This will take care of flushing any remaining data to the strea. * <p> * Multiple calls to this method will result in the stream being closed once * and then all subsequent calls being ignored. * * @throws IOException if the stream could not be closed */ public void close() throws IOException { synchronized(this){ if (closed) return; closed = true; //mark it closed. } log.debug(Messages.getMessage("bStreamClosed", "" + streamNo)); if (bytesRead < recordLength || moreChunks) { //We need get this off the stream. //Easy way to flush through the stream; byte[] readrest = new byte[1024 * 16]; int bread = 0; do { bread = _read(readrest, 0, readrest.length);//should also close the orginal stream. } while (bread > -1); } dataPadLength -= readPad(dataPadLength); } // fixme: if mark is not supported, do we throw an exception here? /** * Mark the stream. * This is not supported. */ public void mark(int readlimit) {//do nothing } public void reset() throws IOException { streamInError = new IOException(Messages.getMessage( "attach.bounday.mns")); throw streamInError; } public boolean markSupported() { return false; } public synchronized int available() throws IOException { if (null != streamInError) throw streamInError; int chunkAvail = (int) Math.min((long) Integer.MAX_VALUE, recordLength - bytesRead); int streamAvail = 0; try { streamAvail = is.available(); } catch (IOException e) { streamInError = e; throw e; } if (chunkAvail == 0 && moreChunks && (12 + dataPadLength) <= streamAvail) { dataPadLength -= readPad(dataPadLength); readHeader(true); return available(); } return Math.min(streamAvail, chunkAvail); } protected void finalClose() throws IOException { try{ theEnd = true; if(null != is) is.close(); }finally{ is= null; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -