001/**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one or more
004 * contributor license agreements.  See the NOTICE file distributed with
005 * this work for additional information regarding copyright ownership.
006 * The ASF licenses this file to You under the Apache License, Version 2.0
007 * (the "License"); you may not use this file except in compliance with
008 * the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing, software
013 *  distributed under the License is distributed on an "AS IS" BASIS,
014 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 *  See the License for the specific language governing permissions and
016 *  limitations under the License.
017 */
018package org.apache.xbean.recipe;
019
020import java.util.LinkedList;
021import java.util.List;
022import java.util.Map;
023
024public abstract class ExecutionContext {
025    private static final ThreadLocal<ExecutionContext> context = new ThreadLocal<ExecutionContext>();
026
027    public static boolean isContextSet() {
028        return context.get() != null;
029    }
030
031    public static ExecutionContext getContext() {
032        ExecutionContext executionContext = context.get();
033        if (executionContext == null) {
034            throw new IllegalStateException("Execution context has not been set");
035        }
036        return executionContext;
037    }
038
039    public static ExecutionContext setContext(ExecutionContext newContext) {
040        ExecutionContext oldContext = context.get();
041        context.set(newContext);
042        return oldContext;
043    }
044
045    /**
046     * Adds a recipe to the top of the execution stack.  If the recipe is already on
047     * the stack, a CircularDependencyException is thrown.
048     * @param recipe the recipe to add to the stack
049     * @throws CircularDependencyException if the recipe is already on the stack
050     */
051    public abstract void push(Recipe recipe) throws CircularDependencyException;
052
053    /**
054     * Removes the top recipe from the execution stack.
055     * @return the top recipe on the stack
056     */
057    public abstract Recipe pop();
058
059    /**
060     * Gets a snapshot of the current execution stack.  The returned list is
061     * a snapshot so any modification of the returned list does not modify
062     * the stack contained in this object.
063     * @return a snapshot of the current execution stack
064     */
065    public abstract LinkedList<Recipe> getStack();
066
067    /**
068     * Does this context contain a object with the specified name.
069     *
070     * @param name the unique name of the object instance
071     * @return true if this context contain a object with the specified name
072     */
073    public abstract boolean containsObject(String name);
074
075    /**
076     * Gets the object or recipe with the specified name from the repository.
077     *
078     * @param name the unique name of the object instance
079     * @return the object instance, a recipe to build the object or null
080     */
081    public abstract Object getObject(String name);
082
083    /**
084     * Add an object to the repository.
085     *
086     * @param name the unique name of the object instance
087     * @param object the object instance
088     * @throws ConstructionException if another object instance is already registered with the name
089     */
090    public abstract void addObject(String name, Object object);
091
092    /**
093     * Adds a reference to an object to this context.  If an object is already registered under
094     * the referenced name, the reference will immedately be set.  Otherwise, the reference will be set
095     * when an object is added with the referenced name.
096     *
097     * @param reference the reference to set
098     */
099    public abstract void addReference(Reference reference);
100
101    /**
102     * Gets the unresolved references by name.
103     *
104     * @return the unresolved references by name
105     */
106    public abstract Map<String, List<Reference>> getUnresolvedRefs();
107
108    /**
109     * Gets the class loader used for loading of all classes during the
110     * life of this execution context
111     * @return the class loader for loading classes in this context
112     */
113    public abstract ClassLoader getClassLoader();
114}