/** * Constructs an instance with arbitrary {@link DataSource} and {@link DataSink} instances for * reading and writing the cache. One use of this constructor is to allow data to be transformed * before it is written to disk. * * @param cache The cache. * @param upstream A {@link DataSource} for reading data not in the cache. * @param cacheReadDataSource A {@link DataSource} for reading data from the cache. * @param cacheWriteDataSink A {@link DataSink} for writing data to the cache. If null, cache is * accessed read-only. * @param flags A combination of {@link #FLAG_BLOCK_ON_CACHE}, {@link #FLAG_IGNORE_CACHE_ON_ERROR} * and {@link #FLAG_IGNORE_CACHE_FOR_UNSET_LENGTH_REQUESTS}, or 0. * @param eventListener An optional {@link EventListener} to receive events. */ public CacheDataSource(Cache cache, DataSource upstream, DataSource cacheReadDataSource, DataSink cacheWriteDataSink, @Flags int flags, @Nullable EventListener eventListener) { this.cache = cache; this.cacheReadDataSource = cacheReadDataSource; this.blockOnCache = (flags & FLAG_BLOCK_ON_CACHE) != 0; this.ignoreCacheOnError = (flags & FLAG_IGNORE_CACHE_ON_ERROR) != 0; this.ignoreCacheForUnsetLengthRequests = (flags & FLAG_IGNORE_CACHE_FOR_UNSET_LENGTH_REQUESTS) != 0; this.upstreamDataSource = upstream; if (cacheWriteDataSink != null) { this.cacheWriteDataSource = new TeeDataSource(upstream, cacheWriteDataSink); } else { this.cacheWriteDataSource = null; } this.eventListener = eventListener; }
/** * Constructs an instance with arbitrary {@link DataSource} and {@link DataSink} instances for * reading and writing the cache. One use of this constructor is to allow data to be transformed * before it is written to disk. * * @param cache The cache. * @param upstream A {@link DataSource} for reading data not in the cache. * @param cacheReadDataSource A {@link DataSource} for reading data from the cache. * @param cacheWriteDataSink A {@link DataSink} for writing data to the cache. If null, cache is * accessed read-only. * @param flags A combination of {@link #FLAG_BLOCK_ON_CACHE} and {@link * #FLAG_IGNORE_CACHE_ON_ERROR} or 0. * @param eventListener An optional {@link EventListener} to receive events. */ public CacheDataSource(Cache cache, DataSource upstream, DataSource cacheReadDataSource, DataSink cacheWriteDataSink, @Flags int flags, @Nullable EventListener eventListener) { this.cache = cache; this.cacheReadDataSource = cacheReadDataSource; this.blockOnCache = (flags & FLAG_BLOCK_ON_CACHE) != 0; this.ignoreCacheOnError = (flags & FLAG_IGNORE_CACHE_ON_ERROR) != 0; this.ignoreCacheForUnsetLengthRequests = (flags & FLAG_IGNORE_CACHE_FOR_UNSET_LENGTH_REQUESTS) != 0; this.upstreamDataSource = upstream; if (cacheWriteDataSink != null) { this.cacheWriteDataSource = new TeeDataSource(upstream, cacheWriteDataSink); } else { this.cacheWriteDataSource = null; } this.eventListener = eventListener; }
/** * Constructs an instance with arbitrary {@link DataSource} and {@link DataSink} instances for * reading and writing the cache. One use of this constructor is to allow data to be transformed * before it is written to disk. * * @param cache The cache. * @param upstream A {@link DataSource} for reading data not in the cache. * @param cacheReadDataSource A {@link DataSource} for reading data from the cache. * @param cacheWriteDataSink A {@link DataSink} for writing data to the cache. * @param flags A combination of {@link #FLAG_BLOCK_ON_CACHE}, {@link #FLAG_IGNORE_CACHE_ON_ERROR} * and {@link #FLAG_CACHE_UNBOUNDED_REQUESTS} or 0. * @param eventListener An optional {@link EventListener} to receive events. */ public CacheDataSource(Cache cache, DataSource upstream, DataSource cacheReadDataSource, DataSink cacheWriteDataSink, @Flags int flags, EventListener eventListener) { this.cache = cache; this.cacheReadDataSource = cacheReadDataSource; this.blockOnCache = (flags & FLAG_BLOCK_ON_CACHE) != 0; this.ignoreCacheOnError = (flags & FLAG_IGNORE_CACHE_ON_ERROR) != 0; this.bypassUnboundedRequests = (flags & FLAG_CACHE_UNBOUNDED_REQUESTS) == 0; this.upstreamDataSource = upstream; if (cacheWriteDataSink != null) { this.cacheWriteDataSource = new TeeDataSource(upstream, cacheWriteDataSink); } else { this.cacheWriteDataSource = null; } this.eventListener = eventListener; }
/** * Returns a new {@link CacheDataSource} instance. If {@code offline} is true, it can only read * data from the cache. */ public CacheDataSource buildCacheDataSource(boolean offline) { DataSource cacheReadDataSource = cacheReadDataSourceFactory != null ? cacheReadDataSourceFactory.createDataSource() : new FileDataSource(); if (offline) { return new CacheDataSource(cache, DummyDataSource.INSTANCE, cacheReadDataSource, null, CacheDataSource.FLAG_BLOCK_ON_CACHE, null); } else { DataSink cacheWriteDataSink = cacheWriteDataSinkFactory != null ? cacheWriteDataSinkFactory.createDataSink() : new CacheDataSink(cache, CacheDataSource.DEFAULT_MAX_CACHE_FILE_SIZE); DataSource upstream = upstreamDataSourceFactory.createDataSource(); upstream = priorityTaskManager == null ? upstream : new PriorityDataSource(upstream, priorityTaskManager, C.PRIORITY_DOWNLOAD); return new CacheDataSource(cache, upstream, cacheReadDataSource, cacheWriteDataSink, CacheDataSource.FLAG_BLOCK_ON_CACHE, null); } }
private static CacheDataSource buildCacheDataSource(Context context, DataSource upstreamSource, boolean useAesEncryption) throws CacheException { File cacheDir = context.getExternalCacheDir(); Cache cache = new SimpleCache(new File(cacheDir, EXO_CACHE_DIR), new NoOpCacheEvictor()); emptyCache(cache); // Source and cipher final String secretKey = "testKey:12345678"; DataSource file = new FileDataSource(); DataSource cacheReadDataSource = useAesEncryption ? new AesCipherDataSource(Util.getUtf8Bytes(secretKey), file) : file; // Sink and cipher CacheDataSink cacheSink = new CacheDataSink(cache, EXO_CACHE_MAX_FILESIZE); byte[] scratch = new byte[3897]; DataSink cacheWriteDataSink = useAesEncryption ? new AesCipherDataSink(Util.getUtf8Bytes(secretKey), cacheSink, scratch) : cacheSink; return new CacheDataSource(cache, upstreamSource, cacheReadDataSource, cacheWriteDataSink, CacheDataSource.FLAG_BLOCK_ON_CACHE, null); // eventListener }
/** * @see CacheDataSource#CacheDataSource(Cache, DataSource, DataSource, DataSink, int, * EventListener) */ public CacheDataSourceFactory(Cache cache, Factory upstreamFactory, Factory cacheReadDataSourceFactory, DataSink.Factory cacheWriteDataSinkFactory, @CacheDataSource.Flags int flags, EventListener eventListener) { this.cache = cache; this.upstreamFactory = upstreamFactory; this.cacheReadDataSourceFactory = cacheReadDataSourceFactory; this.cacheWriteDataSinkFactory = cacheWriteDataSinkFactory; this.flags = flags; this.eventListener = eventListener; }
/** * @see CacheDataSource#CacheDataSource(Cache, DataSource, DataSource, DataSink, int, * EventListener) */ public CacheDataSourceFactory(Cache cache, Factory upstreamFactory, Factory cacheReadDataSourceFactory, DataSink.Factory cacheWriteDataSinkFactory, int flags, EventListener eventListener) { this.cache = cache; this.upstreamFactory = upstreamFactory; this.cacheReadDataSourceFactory = cacheReadDataSourceFactory; this.cacheWriteDataSinkFactory = cacheWriteDataSinkFactory; this.flags = flags; this.eventListener = eventListener; }
/** * @param cache Cache instance to be used to store downloaded data. * @param upstreamDataSourceFactory A {@link Factory} for downloading data. * @param cacheReadDataSourceFactory A {@link Factory} for reading data from the cache. * If null, null is passed to {@link Downloader} constructor. * @param cacheWriteDataSinkFactory A {@link DataSink.Factory} for writing data to the cache. If * null, null is passed to {@link Downloader} constructor. * @param priorityTaskManager If one is given then the download priority is set lower than * loading. If null, null is passed to {@link Downloader} constructor. */ public DownloaderConstructorHelper(Cache cache, Factory upstreamDataSourceFactory, @Nullable Factory cacheReadDataSourceFactory, @Nullable DataSink.Factory cacheWriteDataSinkFactory, @Nullable PriorityTaskManager priorityTaskManager) { Assertions.checkNotNull(upstreamDataSourceFactory); this.cache = cache; this.upstreamDataSourceFactory = upstreamDataSourceFactory; this.cacheReadDataSourceFactory = cacheReadDataSourceFactory; this.cacheWriteDataSinkFactory = cacheWriteDataSinkFactory; this.priorityTaskManager = priorityTaskManager; }
@Override public DataSink createDataSink() { return new CacheDataSink(cache, maxCacheFileSize, bufferSize); }
@Override public DataSink createDataSink() { return new CacheDataSink(cache, maxCacheFileSize); }
/** * Create an instance whose {@code write} methods have the side effect of overwriting the input * {@code data}. Use this constructor for maximum efficiency in the case that there is no * requirement for the input data arrays to remain unchanged. * * @param secretKey The key data. * @param wrappedDataSink The wrapped {@link DataSink}. */ public AesCipherDataSink(byte[] secretKey, DataSink wrappedDataSink) { this(secretKey, wrappedDataSink, null); }
/** * Create an instance whose {@code write} methods are free of side effects. Use this constructor * when the input data arrays are required to remain unchanged. * * @param secretKey The key data. * @param wrappedDataSink The wrapped {@link DataSink}. * @param scratch Scratch space. Data is decrypted into this array before being written to the * wrapped {@link DataSink}. It should be of appropriate size for the expected writes. If a * write is larger than the size of this array the write will still succeed, but multiple * cipher calls will be required to complete the operation. */ public AesCipherDataSink(byte[] secretKey, DataSink wrappedDataSink, byte[] scratch) { this.wrappedDataSink = wrappedDataSink; this.secretKey = secretKey; this.scratch = scratch; }