/**
* Copyright 2016 StreamSets Inc.
*
* Licensed under the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.streamsets.pipeline.lib.io.fileref;
import com.streamsets.pipeline.api.FileRef;
import com.streamsets.pipeline.api.Stage;
import com.streamsets.pipeline.api.impl.Utils;
import com.streamsets.pipeline.lib.hashing.HashingUtil;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;
/**
* An AbstractFileRef to accommodate the common logic used by the implementations of {@link FileRef}
*
*/
public abstract class AbstractFileRef extends FileRef {
private final boolean createMetrics;
private final long totalSizeInBytes;
private final double rateLimit;
private final boolean verifyChecksum;
private final String checksum;
private final HashingUtil.HashType checksumAlgorithm;
private final Set<Class<? extends AutoCloseable>> supportedStreamClasses;
/**
* @param bufferSize The buffer size that can be used by the input stream.
* @param createMetrics if the metrics are needed
* @param totalSizeInBytes the file size, can be null, if {@link #createMetrics} is false
*/
public AbstractFileRef(
Set<Class<? extends AutoCloseable>> supportedStreamClasses,
int bufferSize,
boolean createMetrics,
long totalSizeInBytes,
double rateLimit,
boolean verifyChecksum,
String checksum,
HashingUtil.HashType checksumAlgorithm
) {
super(bufferSize);
Utils.checkNotNull(supportedStreamClasses, "supportedStreamClasses");
Utils.checkArgument(
supportedStreamClasses.contains(InputStream.class),
Utils.format("Input Stream should be at least supported by the File Ref {}", this.getClass().getName())
);
this.supportedStreamClasses = supportedStreamClasses;
this.createMetrics = createMetrics;
this.totalSizeInBytes = totalSizeInBytes;
this.rateLimit = rateLimit;
this.verifyChecksum = verifyChecksum;
this.checksum = checksum;
this.checksumAlgorithm = checksumAlgorithm;
}
@Override
@SuppressWarnings("unchecked")
public <T extends AutoCloseable> Set<Class<T>> getSupportedStreamClasses() {
return (Set)supportedStreamClasses;
}
@Override
@SuppressWarnings("unchecked")
public <T extends AutoCloseable> T createInputStream(Stage.Context context, Class<T> streamClassType) throws IOException {
Utils.checkArgument(
supportedStreamClasses.contains(streamClassType),
Utils.format("Stream class {} not supported for {}.", streamClassType, this.getClass().getName())
);
T stream = createInputStream(streamClassType);
stream = (createMetrics)?(T)new MetricEnabledWrapperStream<>(toString(), totalSizeInBytes, context, stream) : stream;
stream = (rateLimit > 0)? (T)new RateLimitingWrapperStream<>(stream, totalSizeInBytes, rateLimit) : stream;
return (verifyChecksum)?(T)new VerifyChecksumWrapperStream<>(stream, checksum, checksumAlgorithm) : stream;
}
/**
* Creates the Stream instance based on the stream class type.
* @param streamClassType the stream class type
* @param <T> Stream Implementation of {@link AutoCloseable}
* @return the stream
* @throws IOException if there are issues in creating the stream.
*/
protected abstract <T extends AutoCloseable> T createInputStream(Class<T> streamClassType) throws IOException ;
/**
* Abstract File Ref Builder
* @param <F> {@link FileRef}
* @param <B> {@link Builder}
*/
public static abstract class Builder<F extends AbstractFileRef, B extends Builder<F, B>> {
protected int bufferSize = Integer.MAX_VALUE;
protected boolean createMetrics = true;
protected long totalSizeInBytes;
protected boolean verifyChecksum = false;
protected double rateLimit = -1;
protected String checksum;
protected HashingUtil.HashType checksumAlgorithm;
@SuppressWarnings("unchecked")
public B bufferSize(int bufferSize) {
this.bufferSize = (bufferSize == -1)? Integer.MAX_VALUE : bufferSize;
return (B) this;
}
@SuppressWarnings("unchecked")
public B createMetrics(boolean createMetrics) {
this.createMetrics = createMetrics;
return (B)this;
}
public B rateLimit(double rateLimit) {
this.rateLimit = rateLimit;
return (B)this;
}
@SuppressWarnings("unchecked")
public B verifyChecksum(boolean verifyChecksum) {
this.verifyChecksum = verifyChecksum;
return (B)this;
}
@SuppressWarnings("unchecked")
public B totalSizeInBytes(long totalSizeInBytes) {
this.totalSizeInBytes = totalSizeInBytes;
return (B)this;
}
@SuppressWarnings("unchecked")
public B checksum(String checksum) {
Utils.checkArgument(verifyChecksum, "Verify Checksum should be true");
Utils.checkNotNull(checksum, checksum);
this.checksum = checksum;
return (B)this;
}
@SuppressWarnings("unchecked")
public B checksumAlgorithm(HashingUtil.HashType checksumAlgorithm) {
Utils.checkArgument(verifyChecksum, "Verify Checksum should be true");
Utils.checkNotNull(checksumAlgorithm, "checksumAlgorithm");
this.checksumAlgorithm = checksumAlgorithm;
return (B)this;
}
public abstract F build();
}
}