001/* 002 * Copyright 2017 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.workspaces.cmis; 017 018import java.io.FilterInputStream; 019import java.io.IOException; 020import java.io.InputStream; 021import java.math.BigInteger; 022 023import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException; 024 025/** 026 * Copied from openCMIS Server Development Guide 027 * 028 */ 029public class CmisContentRangeInputStream extends FilterInputStream 030{ 031 private static final int BUFFER_SIZE = 4096; 032 033 private long _offset; 034 private long _length; 035 private long _remaining; 036 037 /** 038 * create a RangeInputStream 039 * @param stream stream 040 * @param offset offset 041 * @param length length 042 */ 043 public CmisContentRangeInputStream(InputStream stream, BigInteger offset, BigInteger length) 044 { 045 super(stream); 046 047 this._offset = offset != null ? offset.longValue() : 0; 048 this._length = length != null ? length.longValue() : Long.MAX_VALUE; 049 050 this._remaining = this._length; 051 052 if (this._offset > 0) 053 { 054 skipBytes(); 055 } 056 } 057 058 private void skipBytes() 059 { 060 long remainingSkipBytes = _offset; 061 062 try 063 { 064 while (remainingSkipBytes > 0) 065 { 066 long skipped = super.skip(remainingSkipBytes); 067 remainingSkipBytes -= skipped; 068 069 if (skipped == 0) 070 { 071 // stream might not support skipping 072 skipBytesByReading(remainingSkipBytes); 073 break; 074 } 075 } 076 } 077 catch (IOException e) 078 { 079 throw new CmisRuntimeException("Skipping the stream failed!", e); 080 } 081 } 082 083 private void skipBytesByReading(long remainingSkipBytes) 084 { 085 long usedRemainingSkipBytes = remainingSkipBytes; 086 try 087 { 088 final byte[] buffer = new byte[BUFFER_SIZE]; 089 while (usedRemainingSkipBytes > 0) 090 { 091 long skipped = super.read(buffer, 0, (int) Math.min(buffer.length, usedRemainingSkipBytes)); 092 if (skipped == -1) 093 { 094 break; 095 } 096 097 usedRemainingSkipBytes -= skipped; 098 } 099 } 100 catch (IOException e) 101 { 102 throw new CmisRuntimeException("Reading the stream failed!", e); 103 } 104 } 105 106 @Override 107 public boolean markSupported() 108 { 109 return false; 110 } 111 112 @Override 113 public long skip(long n) throws IOException 114 { 115 if (_remaining <= 0) 116 { 117 return 0; 118 } 119 120 long skipped = super.skip(n); 121 _remaining -= skipped; 122 123 return skipped; 124 } 125 126 @Override 127 public int available() throws IOException 128 { 129 if (_remaining <= 0) 130 { 131 return 0; 132 } 133 134 int avail = super.available(); 135 136 if (_remaining < avail) 137 { 138 return (int) _remaining; 139 } 140 141 return avail; 142 } 143 144 @Override 145 public int read() throws IOException 146 { 147 if (_remaining <= 0) 148 { 149 return -1; 150 } 151 152 _remaining--; 153 154 return super.read(); 155 } 156 157 @Override 158 public int read(byte[] b, int off, int len) throws IOException 159 { 160 if (_remaining <= 0) 161 { 162 return -1; 163 } 164 165 int readBytes = super.read(b, off, (int) Math.min(len, _remaining)); 166 if (readBytes == -1) 167 { 168 return -1; 169 } 170 171 _remaining -= readBytes; 172 173 return readBytes; 174 } 175 176 @Override 177 public int read(byte[] b) throws IOException 178 { 179 return read(b, 0, b.length); 180 } 181}