1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.apksig.util; 18 19 import java.io.IOException; 20 import java.nio.ByteBuffer; 21 22 /** 23 * Abstract representation of a source of data. 24 * 25 * <p>This abstraction serves three purposes: 26 * <ul> 27 * <li>Transparent handling of different types of sources, such as {@code byte[]}, 28 * {@link java.nio.ByteBuffer}, {@link java.io.RandomAccessFile}, memory-mapped file.</li> 29 * <li>Support sources larger than 2 GB. If all sources were smaller than 2 GB, {@code ByteBuffer} 30 * may have worked as the unifying abstraction.</li> 31 * <li>Support sources which do not fit into logical memory as a contiguous region.</li> 32 * </ul> 33 * 34 * <p>There are following ways to obtain a chunk of data from the data source: 35 * <ul> 36 * <li>Stream the chunk's data into a {@link DataSink} using 37 * {@link #feed(long, long, DataSink) feed}. This is best suited for scenarios where there is no 38 * need to have the chunk's data accessible at the same time, for example, when computing the 39 * digest of the chunk. If you need to keep the chunk's data around after {@code feed} 40 * completes, you must create a copy during {@code feed}. However, in that case the following 41 * methods of obtaining the chunk's data may be more appropriate.</li> 42 * <li>Obtain a {@link ByteBuffer} containing the chunk's data using 43 * {@link #getByteBuffer(long, int) getByteBuffer}. Depending on the data source, the chunk's 44 * data may or may not be copied by this operation. This is best suited for scenarios where 45 * you need to access the chunk's data in arbitrary order, but don't need to modify the data and 46 * thus don't require a copy of the data.</li> 47 * <li>Copy the chunk's data to a {@link ByteBuffer} using 48 * {@link #copyTo(long, int, ByteBuffer) copyTo}. This is best suited for scenarios where 49 * you require a copy of the chunk's data, such as to when you need to modify the data. 50 * </li> 51 * </ul> 52 */ 53 public interface DataSource { 54 55 /** 56 * Returns the amount of data (in bytes) contained in this data source. 57 */ size()58 long size(); 59 60 /** 61 * Feeds the specified chunk from this data source into the provided sink. 62 * 63 * @param offset index (in bytes) at which the chunk starts inside data source 64 * @param size size (in bytes) of the chunk 65 * 66 * @throws IndexOutOfBoundsException if {@code offset} or {@code size} is negative, or if 67 * {@code offset + size} is greater than {@link #size()}. 68 */ feed(long offset, long size, DataSink sink)69 void feed(long offset, long size, DataSink sink) throws IOException; 70 71 /** 72 * Returns a buffer holding the contents of the specified chunk of data from this data source. 73 * Changes to the data source are not guaranteed to be reflected in the returned buffer. 74 * Similarly, changes in the buffer are not guaranteed to be reflected in the data source. 75 * 76 * <p>The returned buffer's position is {@code 0}, and the buffer's limit and capacity is 77 * {@code size}. 78 * 79 * @param offset index (in bytes) at which the chunk starts inside data source 80 * @param size size (in bytes) of the chunk 81 * 82 * @throws IndexOutOfBoundsException if {@code offset} or {@code size} is negative, or if 83 * {@code offset + size} is greater than {@link #size()}. 84 */ getByteBuffer(long offset, int size)85 ByteBuffer getByteBuffer(long offset, int size) throws IOException; 86 87 /** 88 * Copies the specified chunk from this data source into the provided destination buffer, 89 * advancing the destination buffer's position by {@code size}. 90 * 91 * @param offset index (in bytes) at which the chunk starts inside data source 92 * @param size size (in bytes) of the chunk 93 * 94 * @throws IndexOutOfBoundsException if {@code offset} or {@code size} is negative, or if 95 * {@code offset + size} is greater than {@link #size()}. 96 */ copyTo(long offset, int size, ByteBuffer dest)97 void copyTo(long offset, int size, ByteBuffer dest) throws IOException; 98 99 /** 100 * Returns a data source representing the specified region of data of this data source. Changes 101 * to data represented by this data source will also be visible in the returned data source. 102 * 103 * @param offset index (in bytes) at which the region starts inside data source 104 * @param size size (in bytes) of the region 105 * 106 * @throws IndexOutOfBoundsException if {@code offset} or {@code size} is negative, or if 107 * {@code offset + size} is greater than {@link #size()}. 108 */ slice(long offset, long size)109 DataSource slice(long offset, long size); 110 } 111