biz.c24.io.spring.batch.reader.source.FileSource.java Source code

Java tutorial

Introduction

Here is the source code for biz.c24.io.spring.batch.reader.source.FileSource.java

Source

/*
 * Copyright 2012 C24 Technologies.
 * 
 * Licensed 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 biz.c24.io.spring.batch.reader.source;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.StepExecution;
import org.springframework.core.io.Resource;

import biz.c24.io.spring.util.C24Utils;

/**
 * An implementation of SplittingReaderSource which extracts its data from uncompressed files.
 * Expects to be told the path of the file to write to by the supplied Resource or, 
 * if not specified, a property called input.file in the job parameters
 * (as populated by Spring Batch's org.springframework.batch.admin.integration.FileToJobLaunchRequestAdapter)
 * 
 * @author Andrew Elmore
 */
public class FileSource implements SplittingReaderSource {

    private static final Logger LOG = LoggerFactory.getLogger(FileSource.class);

    private SplittingReader reader = null;

    private String name;

    private Resource resource = null;

    private String encoding = C24Utils.DEFAULT_FILE_ENCODING;

    private boolean consistentLineTerminators = true;

    /**
     * How many lines at the start of the file should we skip?
     */
    private int skipLines = 0;

    /*
     * (non-Javadoc)
     * @see biz.c24.io.spring.batch.reader.source.SplittingReaderSource#getName()
     */
    public String getName() {
        return name;
    }

    /* (non-Javadoc)
     * @see biz.c24.spring.batch.BufferedReaderSource#initialise(org.springframework.batch.core.StepExecution)
     */
    public void initialise(StepExecution stepExecution) {

        try {
            // Get an InputStream and a name for where we're reading from
            // Use the Resource if supplied

            InputStream source = null;
            if (resource != null) {
                name = resource.getFilename();
                source = resource.getInputStream();
            } else {

                // If no resource supplied, fallback to a Job parameter called input.file
                name = stepExecution.getJobParameters().getString("input.file");

                // Remove any leading file:// if it exists
                if (name.startsWith("file://")) {
                    name = name.substring("file://".length());
                }

                source = new FileInputStream(name);
            }

            // Prime the reader
            LOG.debug("Opening {} with encoding {}", name, getEncoding());
            reader = new SplittingReader(new InputStreamReader(source, getEncoding()), consistentLineTerminators);
            if (skipLines > 0) {
                for (int i = 0; i < skipLines && reader.ready(); i++) {
                    // Skip the line
                    reader.readLine();
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /* (non-Javadoc)
     * @see biz.c24.spring.batch.BufferedReaderSource#close()
     */
    public void close() {
        if (reader != null) {
            try {
                reader.close();
                // Spring Batch lifecycle will ensure that this doesn't happen while 
                // someone is still trying to read (ie calling getReader and risking an NPE)
                reader = null;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /* (non-Javadoc)
     * @see biz.c24.spring.batch.BufferedReaderSource#getReader()
     */
    public SplittingReader getReader() {
        try {
            if (reader != null && reader.ready()) {
                return reader;
            } else {
                return null;
            }
        } catch (IOException e) {
            // Stream has been closed beneath our feet. Nothing to read.
            return null;
        }
    }

    @Override
    public SplittingReader getNextReader() {
        SplittingReader retVal = reader;
        reader = null;
        return retVal;
    }

    @Override
    public boolean useMultipleThreadsPerReader() {
        return true;
    }

    @Override
    public void discard(SplittingReader reader) throws IOException {
        if (this.reader == reader) {
            reader.close();
            this.reader = null;
        }

    }

    /**
     * How many lines will be skipped at the start of the file before the Reader is handed to callers?
     * @return the number of lines to skip at the start of the file
     */
    public int getSkipLines() {
        return skipLines;
    }

    /**
     * How many lines should be skipped at the start of the file before the Reader is handed to callers?
     * @param skipLines
     */
    public void setSkipLines(int skipLines) {
        this.skipLines = skipLines;
    }

    /**
     * The resource we acquire InputStreams from
     * @return the resource that we'll read from
     */
    public Resource getResource() {
        return resource;
    }

    /**
     * Set the resource we acquire InputStreams from
     */
    public void setResource(Resource resource) {
        this.resource = resource;
    }

    /**
     * Returns the encoding we are using when reading the file.
     * @return the encoding being used to read the file
     */
    public String getEncoding() {
        return encoding;
    }

    /**
     * Sets the encoding to use to read the file
     * @param encoding the encoding the use
     */
    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    /**
     * Do we expect all lines in our input to use the same line terminator?
     * @return
     */
    public boolean isConsistentLineTerminators() {
        return consistentLineTerminators;
    }

    /**
     * If we know that all lines within the file use the same line terminator, we can provide a hint to the 
     * SplittingReader to optimise its data extraction
     * 
     * @param consistentLineTerminators Set to true if all lines use the same line terminator for a speed boost during splitting
     */
    public void setConsistentLineTerminators(boolean consistentLineTerminators) {
        this.consistentLineTerminators = consistentLineTerminators;
    }

}