org.eclipse.ecr.automation.OperationContext.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ecr.automation.OperationContext.java

Source

/*
 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     bstefanescu
 */
package org.eclipse.ecr.automation;

import java.security.Principal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.ecr.core.api.CoreSession;
import org.eclipse.ecr.runtime.api.Framework;
import org.eclipse.ecr.runtime.transaction.TransactionHelper;

/**
 * An operation context. Holds context objects, a context parameters map and a
 * list of operations to run.
 * <p>
 * Context objects are:
 * <ul>
 * <li>The Operation Chain Input - optional. It will be used as the input for
 * the first operation in the chain. If input is null then only VOID methods in
 * the first operation will be matched.
 * <li>A Core Session - which is optional and should be provided by the caller.
 * (either at creation time as a constructor argument, either using the
 * {@link #setCoreSession(CoreSession)} method. When running the operation chain
 * in asynchronous mode another session will be created by preserving the
 * current session credentials.
 * </ul>
 * <p>
 * Each entry in the operation list contains the ID of the operation to be run
 * and a map of operation parameters to use when initializing the operation.
 * <p>
 * The context parameters map can be filled with contextual information by the
 * caller. Each operation will be able to access the contextual data at runtime
 * and to update it if needed.
 *
 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
 */
public class OperationContext extends HashMap<String, Object> {

    private static final Log log = LogFactory.getLog(OperationContext.class);

    private static final long serialVersionUID = 2944230823597903715L;

    /**
     * Whether to save the session at the end of the chain execution. The
     * default is true.
     */
    protected boolean commit = true;

    protected final transient List<CleanupHandler> cleanupHandlers;

    /**
     * Each stack use a key the type of the objects in the stack: document,
     * documents, blob or blobs
     */
    protected final transient Map<String, List<Object>> stacks;

    /**
     * A logins stack manage multiple logins and sessions in a single chain
     * execution
     */
    protected transient LoginStack loginStack;

    /**
     * The execution input that will be updated after an operation run with the
     * operation output
     */
    protected Object input;

    /**
     * A list of trace messages useful to use in exception details.
     */
    protected List<String> trace;

    public OperationContext() {
        this(null);
    }

    public OperationContext(CoreSession session) {
        stacks = new HashMap<String, List<Object>>();
        cleanupHandlers = new ArrayList<CleanupHandler>();
        loginStack = new LoginStack(session);
        trace = new ArrayList<String>();
    }

    public void setCoreSession(CoreSession session) {
        this.loginStack.setSession(session);
    }

    public void setCommit(boolean commit) {
        this.commit = commit;
    }

    public boolean isCommit() {
        return commit;
    }

    public CoreSession getCoreSession() {
        return loginStack.getSession();
    }

    public LoginStack getLoginStack() {
        return loginStack;
    }

    public Principal getPrincipal() {
        CoreSession session = loginStack.getSession();
        return session != null ? session.getPrincipal() : null;
    }

    public void setInput(Object input) {
        this.input = input;
    }

    public Object getInput() {
        return input;
    }

    public Object peek(String type) {
        List<Object> stack = stacks.get(type);
        if (stack == null) {
            return null;
        }
        return stack.isEmpty() ? null : stack.get(stack.size() - 1);
    }

    public void push(String type, Object obj) {
        List<Object> stack = stacks.get(type);
        if (stack == null) {
            stack = new ArrayList<Object>();
            stacks.put(type, stack);
        }
        stack.add(obj);
    }

    public Object pop(String type) {
        List<Object> stack = stacks.get(type);
        if (stack == null) {
            return null;
        }
        return stack.isEmpty() ? null : stack.remove(stack.size() - 1);
    }

    public Object pull(String type) {
        List<Object> stack = stacks.get(type);
        if (stack == null) {
            return null;
        }
        return stack.isEmpty() ? null : stack.remove(0);
    }

    public <T> T getAdapter(Class<T> type) {
        if (type.isAssignableFrom(getClass())) {
            return type.cast(this);
        } else if (type.isAssignableFrom(CoreSession.class)) {
            return type.cast(getCoreSession());
        } else if (type.isAssignableFrom(Principal.class)) {
            return type.cast(getPrincipal());
        } else { // try nuxeo services
            try {
                return Framework.getService(type);
            } catch (Exception e) {
                throw new RuntimeException("Failed to lookup service: " + type, e);
            }
        }
    }

    public void addTrace(String trace) {
        this.trace.add(trace);
    }

    public List<String> getTrace() {
        return trace;
    }

    public String getFormattedTrace() {
        String crlf = System.getProperty("line.separator");
        StringBuilder buf = new StringBuilder();
        for (String t : trace) {
            buf.append("> ").append(t).append(crlf);
        }
        return buf.toString();
    }

    public void addCleanupHandler(CleanupHandler handler) {
        cleanupHandlers.add(handler);
    }

    public void removeCleanupHandler(CleanupHandler handler) {
        cleanupHandlers.remove(handler);
    }

    public void dispose() throws OperationException {
        trace.clear();
        loginStack.clear();
        for (CleanupHandler handler : cleanupHandlers) {
            try {
                handler.cleanup();
            } catch (Exception e) {
                log.error(e, e);
            }
        }
    }

    /**
     * Set the rollback mark on the current tx. This will cause the transaction to rollback.
     * Also this is setting the session commit flag on false
     */
    public void setRollback() {
        setCommit(false);
        TransactionHelper.setTransactionRollbackOnly();
    }
}