org.paxle.core.data.impl.DataPipe.java Source code

Java tutorial

Introduction

Here is the source code for org.paxle.core.data.impl.DataPipe.java

Source

/**
 * This file is part of the Paxle project.
 * Visit http://www.paxle.net for more information.
 * Copyright 2007-2010 the original author or authors.
 *
 * Licensed under the terms of the Common Public License 1.0 ("CPL 1.0").
 * Any use, reproduction or distribution of this program constitutes the recipient's acceptance of this agreement.
 * The full license text is available under http://www.opensource.org/licenses/cpl1.0.txt
 * or in the file LICENSE.txt in the root directory of the Paxle distribution.
 *
 * Unless required by applicable law or agreed to in writing, this software is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 */

package org.paxle.core.data.impl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.paxle.core.data.IDataConsumer;
import org.paxle.core.data.IDataProvider;
import org.paxle.core.data.IDataSink;
import org.paxle.core.data.IDataSource;

/**
 * This pipe acts as {@link IDataConsumer data-consumer} and {@link IDataProvider data-provider}
 * and just copies data from a {@link IDataSource data-source} to a {@link IDataSink data-sink}
 */
public class DataPipe<Data> extends Thread implements IDataProvider<Data>, IDataConsumer<Data> {

    private IDataSink<Data> sink = null;
    private IDataSource<Data> source = null;

    /**
     * for logging
     */
    private Log logger = LogFactory.getLog(this.getClass());

    /**
     * Indicates that the current thread was stopped through a call
     * to {@link #terminate()}
     */
    private boolean stopped = false;

    public DataPipe() {
        this.start();
    }

    /**
     * @see IDataProvider#setDataSink(IDataSink)
     */
    public synchronized void setDataSink(IDataSink<Data> dataSink) {
        if (dataSink == null)
            throw new NullPointerException("The data-sink is null.");
        if (this.sink != null)
            throw new IllegalStateException("The data-sink was already set.");
        this.sink = dataSink;
        this.notify();
    }

    /**
     * @see IDataConsumer#setDataSource(IDataSource)
     */
    public synchronized void setDataSource(IDataSource<Data> dataSource) {
        if (dataSource == null)
            throw new NullPointerException("The data-source is null.");
        if (this.source != null)
            throw new IllegalStateException("The data-source was already set.");
        this.source = dataSource;
        this.notify();
    }

    /**
     * Function to terminate the {@link DataPipe} thread.
     * @throws InterruptedException 
     */
    public void terminate() throws InterruptedException {
        // setting stop flag
        this.stopped = true;

        // interrupt thread if required
        this.interrupt();

        // wait for termination
        this.join(200);
    }

    /**
     * @see Thread#run()
     */
    @Override
    public void run() {
        try {
            synchronized (this) {
                while ((this.sink == null) || (this.source == null))
                    this.wait();
            }

            while (!this.stopped && !this.isInterrupted()) {
                Data data = this.source.getData();
                this.sink.putData(data);
            }
        } catch (Exception e) {
            if (!(e instanceof InterruptedException)) {
                this.logger.error(String.format("%s: Unexpected '%s' while copying data.", this.getName(),
                        e.getClass().getName()), e);
            } else {
                this.logger.info("Thread stopped successfully.");
            }
        }
    }

}