org.smartdeveloperhub.harvesters.it.frontend.publisher.DynamicPublisher.java Source code

Java tutorial

Introduction

Here is the source code for org.smartdeveloperhub.harvesters.it.frontend.publisher.DynamicPublisher.java

Source

/**
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   This file is part of the Smart Developer Hub Project:
 *     http://www.smartdeveloperhub.org/
 *
 *   Center for Open Middleware
 *     http://www.centeropenmiddleware.com/
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   Copyright (C) 2015-2016 Center for Open Middleware.
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   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.
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 *   Artifact    : org.smartdeveloperhub.harvesters.it.frontend:it-frontend-core:0.1.0
 *   Bundle      : it-frontend-core-0.1.0.jar
 * #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
 */
package org.smartdeveloperhub.harvesters.it.frontend.publisher;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.ldp4j.application.session.WriteSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.smartdeveloperhub.harvesters.it.frontend.BackendController;
import org.smartdeveloperhub.harvesters.it.notification.CollectorConfiguration;
import org.smartdeveloperhub.harvesters.it.notification.NotificationManager;

import com.google.common.base.Function;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;

final class DynamicPublisher implements Publisher {

    private final class PublicationTerminationHandler implements FutureCallback<Boolean> {
        @Override
        public void onSuccess(final Boolean result) {
            DynamicPublisher.this.publishingCompleted.countDown();
            if (result) {
                LOGGER.info("Initial publication completed. Started notification handling...");
            } else {
                DynamicPublisher.this.manager.shutdown();
                LOGGER.warn("Initial publication failed. Notification handling aborted.");
            }
        }

        @Override
        public void onFailure(final Throwable t) {
            DynamicPublisher.this.publishingCompleted.countDown();
            LOGGER.error("Publication failed", t);
        }
    }

    private final class PublicationTerminationAggregator implements Function<List<Boolean>, Boolean> {
        @Override
        public Boolean apply(final List<Boolean> terminations) {
            for (final boolean completed : terminations) {
                if (!completed) {
                    return false;
                }
            }
            return true;
        }
    }

    private static final Logger LOGGER = LoggerFactory.getLogger(DynamicPublisher.class);

    private final ListeningExecutorService pool;

    private final NotificationManager manager;

    private final CountDownLatch publishingCompleted;

    private final BackendController controller;

    DynamicPublisher(final BackendController controller, final List<CollectorConfiguration> config) {
        this.controller = controller;
        this.pool = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10,
                new ThreadFactoryBuilder().setNameFormat("Publisher-thread-%d").build()));
        this.publishingCompleted = new CountDownLatch(1);
        this.manager = NotificationManager.newInstance(config,
                new PublishingNotificationListener(this.publishingCompleted, controller.getTarget()));
    }

    void awaitPublicationCompletion() throws InterruptedException {
        this.publishingCompleted.await();
    }

    @Override
    public void initialize(final WriteSession session) throws IOException {
        LOGGER.info("Publishing IT Harvester Resource...");
        PublisherHelper.publishHarvester(session, this.controller.getTarget(), this.controller.getProjects());
        LOGGER.info("Published IT Harvester Resource");
    }

    @Override
    public void start() {
        LOGGER.info("Starting publisher...");
        try {
            LOGGER.info("Starting notification manager...");
            this.manager.start();
            LOGGER.info("Started notification manager. Starting initial publication...");

            // Queue the publisher tasks...
            @SuppressWarnings("unchecked")
            final ListenableFuture<List<Boolean>> terminations = Futures.<Boolean>allAsList(
                    submitTask(new ProjectContentPublisherTask(this.controller)),
                    submitTask(new ContributorPublisherTask(this.controller)),
                    submitTask(new CommitPublisherTask(this.controller)));

            // Combine their result
            final ListenableFuture<Boolean> aggregatedTermination = Futures.transform(terminations,
                    new PublicationTerminationAggregator(), this.pool);

            // ... and take an action
            Futures.addCallback(aggregatedTermination, new PublicationTerminationHandler(), this.pool);
        } catch (final IOException e) {
            LOGGER.error("Could not start notification manager. Full stacktrace follows:", e);
        } finally {
            LOGGER.info("Publisher started.");
        }
    }

    @Override
    public void stop() {
        LOGGER.info("Finishing publisher...");
        shutdownPool();
        this.manager.shutdown();
        LOGGER.info("Publisher finished.");
    }

    private ListenableFuture<Boolean> submitTask(final PublisherTask task) {
        return this.pool.submit(task);
    }

    private void shutdownPool() {
        this.pool.shutdown();
        boolean interrupted = false;
        while (!this.pool.isTerminated() && !interrupted) {
            try {
                this.pool.awaitTermination(1000, TimeUnit.MILLISECONDS);
            } catch (final InterruptedException e) {
                Thread.currentThread().interrupt();
                interrupted = true;
            }
        }
    }

}