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 int read(byte[] buffer, int off, int len) throws IOException { 061 final int count = super.read(buffer, off, len); 062 if (count < 0) { 063 return -1; 064 } 065 final int lastIndex = off + count - 1; 066 if (lastIndex >= 0) { 067 byte lastByte = buffer[lastIndex]; 068 if (lastByte == matchLast) { 069 /* look ahead */ 070 super.mark(1); 071 int nextC = super.read(); 072 if (nextC < 0) { 073 /* matchLast is the last byte - cut it away and do not reset */ 074 return count - 1; 075 } else { 076 super.reset(); 077 } 078 } 079 } 080 return count; 081 } 082 083 @Override 084 public boolean markSupported() { 085 /* we do not want callers to mess with mark() and reset() because we use it ourselves */ 086 return false; 087 } 088 089 @Override 090 public synchronized long skip(long n) { 091 throw new UnsupportedOperationException(); 092 } 093 094 @Override 095 public synchronized void mark(int readlimit) { 096 throw new UnsupportedOperationException(); 097 } 098 099 @Override 100 public synchronized void reset() { 101 throw new UnsupportedOperationException(); 102 } 103 104}