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     */
018    package org.apache.xbean.recipe;
019    
020    import java.util.LinkedList;
021    import java.util.List;
022    import java.util.Map;
023    
024    public 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    }