org.taverna.server.master.localworker.RunDatabase.java Source code

Java tutorial

Introduction

Here is the source code for org.taverna.server.master.localworker.RunDatabase.java

Source

/*
 * Copyright (C) 2010-2011 The University of Manchester
 * 
 * See the file "LICENSE.txt" for license terms.
 */
package org.taverna.server.master.localworker;

import static java.lang.Integer.parseInt;
import static java.util.Arrays.asList;
import static java.util.UUID.randomUUID;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Required;
import org.taverna.server.master.exceptions.UnknownRunException;
import org.taverna.server.master.interfaces.Listener;
import org.taverna.server.master.interfaces.Policy;
import org.taverna.server.master.interfaces.RunStore;
import org.taverna.server.master.interfaces.TavernaRun;
import org.taverna.server.master.notification.NotificationEngine;
import org.taverna.server.master.utils.UsernamePrincipal;

/**
 * The main facade bean that interfaces to the database of runs.
 * 
 * @author Donal Fellows
 */
public class RunDatabase implements RunStore, RunDBSupport {
    private Log log = LogFactory.getLog("Taverna.Server.LocalWorker.RunDB");
    private RunDatabaseDAO dao;
    private List<CompletionNotifier> notifier = new ArrayList<CompletionNotifier>();
    private NotificationEngine notificationEngine;

    @Override
    public void setNotifier(CompletionNotifier n) {
        notifier = asList(n);
    }

    @Required
    @Override
    public void setNotificationEngine(NotificationEngine notificationEngine) {
        this.notificationEngine = notificationEngine;
    }

    @Required
    public void setDao(RunDatabaseDAO dao) {
        this.dao = dao;
    }

    @Override
    public void checkForFinishNow() {
        for (RemoteRunDelegate rrd : dao.getNotifiable())
            for (Listener l : rrd.getListeners())
                if (l.getName().equals("io")) {
                    try {
                        notifyFinished(rrd.id, l, rrd);
                    } catch (Exception e) {
                        log.warn("failed to do notification of completion", e);
                    }
                    break;
                }
    }

    @Override
    public void cleanNow() {
        try {
            dao.doClean();
        } catch (Exception e) {
            log.warn("failure during deletion of expired runs", e);
        }
    }

    @Override
    public int countRuns() {
        return dao.countRuns();
    }

    @Override
    public void flushToDisk(RemoteRunDelegate run) {
        try {
            dao.flushToDisk(run);
        } catch (IOException e) {
            throw new RuntimeException("unexpected problem when persisting run record in database", e);
        }
    }

    @Override
    public RemoteRunDelegate pickArbitraryRun() throws Exception {
        return dao.pickArbitraryRun();
    }

    @Override
    public List<String> listRunNames() {
        return dao.listRunNames();
    }

    @Override
    public TavernaRun getRun(UsernamePrincipal user, Policy p, String uuid) throws UnknownRunException {
        TavernaRun run = dao.get(uuid);
        if (run != null && (user == null || p.permitAccess(user, run)))
            return run;
        throw new UnknownRunException();
    }

    @Override
    public TavernaRun getRun(String uuid) throws UnknownRunException {
        TavernaRun run = dao.get(uuid);
        if (run != null)
            return run;
        throw new UnknownRunException();
    }

    @Override
    public Map<String, TavernaRun> listRuns(UsernamePrincipal user, Policy p) {
        return dao.listRuns(user, p);
    }

    private void logLength(String message, Object obj) {
        if (!log.isDebugEnabled())
            return;
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(obj);
            oos.close();
            log.debug(message + ": " + baos.size());
        } catch (Exception e) {
            log.warn("oops", e);
        }
    }

    @Override
    public String registerRun(TavernaRun run) {
        if (!(run instanceof RemoteRunDelegate))
            throw new IllegalArgumentException("run must be created by localworker package");
        RemoteRunDelegate rrd = (RemoteRunDelegate) run;
        if (rrd.id == null)
            rrd.id = randomUUID().toString();
        logLength("RemoteRunDelegate serialized length", rrd);
        try {
            dao.persistRun(rrd);
        } catch (IOException e) {
            throw new RuntimeException("unexpected problem when persisting run record in database", e);
        }
        return rrd.getId();
    }

    @Override
    public void unregisterRun(String uuid) {
        try {
            dao.unpersistRun(uuid);
        } catch (RuntimeException e) {
            log.debug("problem persisting the deletion of the run " + uuid, e);
        }
    }

    /**
     * Process the event that a run has finished.
     * 
     * @param name
     *            The name of the run.
     * @param io
     *            The io listener of the run (used to get information about the
     *            run).
     * @param run
     *            The handle to the run.
     * @throws Exception
     *             If anything goes wrong.
     */
    private void notifyFinished(String name, Listener io, RemoteRunDelegate run) throws Exception {
        if (notifier == null)
            return;
        String to = io.getProperty("notificationAddress");
        int code;
        try {
            code = parseInt(io.getProperty("exitcode"));
        } catch (NumberFormatException nfe) {
            // Ignore; not much we can do here...
            return;
        }

        for (CompletionNotifier n : notifier)
            notificationEngine.dispatchMessage(run, to, n.makeMessageSubject(name, run, code),
                    n.makeCompletionMessage(name, run, code));
    }
}