001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.util; 018 019import java.io.BufferedInputStream; 020import java.io.IOException; 021import java.io.InputStream; 022 023/** 024 * An {@link InputStream} that skips the last byte of the underlying delegate {@link InputStream} if the last byte is 025 * equal to the given {@code matchLast} value. 026 */ 027public class SkipLastByteInputStream extends BufferedInputStream { 028 029 private final byte matchLast; 030 031 public SkipLastByteInputStream(InputStream delegate, byte matchLast) { 032 super(delegate); 033 this.matchLast = matchLast; 034 } 035 036 public SkipLastByteInputStream(InputStream delegate, int size, byte matchLast) { 037 super(delegate, size); 038 this.matchLast = matchLast; 039 } 040 041 @Override 042 public int read() throws IOException { 043 int c = super.read(); 044 if (c < 0) { 045 return -1; 046 } else if (c == matchLast) { 047 /* look ahead */ 048 super.mark(1); 049 int nextC = super.read(); 050 if (nextC < 0) { 051 /* matchLast is the last byte */ 052 return -1; 053 } 054 super.reset(); 055 } 056 return c; 057 } 058 059 @Override 060 public void close() throws IOException { 061 super.close(); 062 } 063 064 @Override 065 public int read(byte[] buffer, int off, int len) throws IOException { 066 final int count = super.read(buffer, off, len); 067 if (count < 0) { 068 return -1; 069 } 070 final int lastIndex = off + count - 1; 071 if (lastIndex >= 0) { 072 byte lastByte = buffer[lastIndex]; 073 if (lastByte == matchLast) { 074 /* look ahead */ 075 super.mark(1); 076 int nextC = super.read(); 077 if (nextC < 0) { 078 /* matchLast is the last byte - cut it away and do not reset */ 079 return count - 1; 080 } else { 081 super.reset(); 082 } 083 } 084 } 085 return count; 086 } 087 088 @Override 089 public boolean markSupported() { 090 /* we do not want callers to mess with mark() and reset() because we use it ourselves */ 091 return false; 092 } 093 094 @Override 095 public synchronized long skip(long n) { 096 throw new UnsupportedOperationException(); 097 } 098 099 @Override 100 public synchronized void mark(int readlimit) { 101 throw new UnsupportedOperationException(); 102 } 103 104 @Override 105 public synchronized void reset() { 106 throw new UnsupportedOperationException(); 107 } 108 109}