All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.amazonaws.services.kinesis.multilang.LineReaderTask Maven / Gradle / Ivy

/*
 * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Amazon Software License (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 * http://aws.amazon.com/asl/
 *
 * or in the "license" file accompanying this file. This file 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.amazonaws.services.kinesis.multilang;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.Callable;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * This abstract class captures the process of reading from an input stream. Three methods must be provided for
 * implementations to work.
 * 
    *
  1. {@link #handleLine(String)}
  2. *
  3. {@link #returnAfterEndOfInput()}
  4. *
  5. {@link #returnAfterException(Exception)}
  6. *
* * @param */ abstract class LineReaderTask implements Callable { private static final Log LOG = LogFactory.getLog(LineReaderTask.class); private BufferedReader reader; private String description; private String shardId; LineReaderTask() { } /** * Reads lines off the input stream until a return value is set, or an exception is encountered, or the end of the * input stream is reached. Will call the appropriate methods in each case. This is the shared piece of logic * between any tasks that need to read from a child process's STDOUT or STDERR. */ @Override public T call() throws Exception { String nextLine = null; try { LOG.info("Starting: " + description); while ((nextLine = reader.readLine()) != null) { HandleLineResult result = handleLine(nextLine); if (result.hasReturnValue()) { return result.returnValue(); } } } catch (IOException e) { return returnAfterException(e); } LOG.info("Stopping: " + description); return returnAfterEndOfInput(); } /** * Handle a line read from the input stream. The return value indicates whether the enclosing read-loop should * return from the {@link #call()} function by having a value, indicating that value should be returned immediately * without reading further, or not having a value, indicating that more lines of input need to be read before * returning. * * @param line A line read from the input stream. * @return HandleLineResult which may or may not have a has return value, indicating to return or not return yet * respectively. */ protected abstract HandleLineResult handleLine(String line); /** * This method will be called if there is an error while reading from the input stream. The return value of this * method will be returned as the result of this Callable unless an Exception is thrown. If an Exception is thrown * then that exception will be thrown by the Callable. * * @param e An exception that occurred while reading from the input stream. * @return What to return. */ protected abstract T returnAfterException(Exception e) throws Exception; /** * This method will be called once the end of the input stream is reached. The return value of this method will be * returned as the result of this Callable. Implementations of this method are welcome to throw a runtime exception * to indicate that the task was unsuccessful. * * @return What to return. */ protected abstract T returnAfterEndOfInput(); /** * Allows subclasses to provide more detailed logs. Specifically, this allows the drain tasks and GetNextMessageTask * to log which shard they're working on. * * @return The shard id */ public String getShardId() { return this.shardId; } /** * The description should be a string explaining what this particular LineReader class does. * * @return The description. */ public String getDescription() { return this.description; } /** * The result of a call to {@link LineReaderTask#handleLine(String)}. Allows implementations of that method to * indicate whether a particular invocation of that method produced a return for this task or not. If a return value * doesn't exist the {@link #call()} method will continue to the next line. * * @param */ protected class HandleLineResult { private boolean hasReturnValue; private V returnValue; HandleLineResult() { this.hasReturnValue = false; } HandleLineResult(V returnValue) { this.hasReturnValue = true; this.returnValue = returnValue; } boolean hasReturnValue() { return this.hasReturnValue; } V returnValue() { if (hasReturnValue()) { return this.returnValue; } else { throw new RuntimeException("There was no value to return."); } } } /** * An initialization method allows us to delay setting the attributes of this class. Some of the attributes, stream * and shardId, are not known to the {@link MultiLangRecordProcessorFactory} when it constructs a * {@link MultiLangRecordProcessor} but are later determined when * {@link MultiLangRecordProcessor#initialize(String)} is called. So we follow a pattern where the attributes are * set inside this method instead of the constructor so that this object will be initialized when all its attributes * are known to the record processor. * * @param stream * @param shardId * @param description * @return */ protected LineReaderTask initialize(InputStream stream, String shardId, String description) { return this.initialize(new BufferedReader(new InputStreamReader(stream)), shardId, description); } /** * @param reader * @param shardId * @param description * @return */ protected LineReaderTask initialize(BufferedReader reader, String shardId, String description) { this.reader = reader; this.shardId = shardId; this.description = description; return this; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy