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.*; 021 022 public class DefaultExecutionContext extends ExecutionContext { 023 /** 024 * The source of recipes and existing objects. 025 */ 026 private Repository repository; 027 028 /** 029 * Before each recipe is executed it is pushed on the stack. The 030 * stack is used to detect circular dependencies and so a recipe can 031 * access the caller recipe (e.g. UnsetPropertiesRecipe returns a 032 * map of the caller's unset properties) 033 */ 034 private final LinkedList<Recipe> stack = new LinkedList<Recipe>(); 035 036 /** 037 * The unresolved references by name. 038 */ 039 private final SortedMap<String, List<Reference>> unresolvedRefs = new TreeMap<String, List<Reference>>(); 040 041 public DefaultExecutionContext() { 042 this(new DefaultRepository()); 043 } 044 045 public DefaultExecutionContext(Repository repository) { 046 if (repository == null) throw new NullPointerException("repository is null"); 047 this.repository = repository; 048 } 049 050 public void push(Recipe recipe) { 051 if (stack.contains(recipe)) { 052 ArrayList<Recipe> circularity = new ArrayList<Recipe>(stack.subList(stack.indexOf(recipe), stack.size())); 053 054 // remove anonymous nodes from circularity list 055 for (Iterator<Recipe> iterator = circularity.iterator(); iterator.hasNext();) { 056 Recipe item = iterator.next(); 057 if (item != recipe && item.getName() == null) { 058 iterator.remove(); 059 } 060 } 061 062 // add ending node to list so a full circuit is shown 063 circularity.add(recipe); 064 065 throw new CircularDependencyException(circularity); 066 } 067 stack.add(recipe); 068 } 069 070 public Recipe pop() { 071 return stack.removeLast(); 072 } 073 074 public LinkedList<Recipe> getStack() { 075 return new LinkedList<Recipe>(stack); 076 } 077 078 public Repository getRepository() { 079 return repository; 080 } 081 082 public void setRepository(Repository repository) { 083 if (repository == null) throw new NullPointerException("repository is null"); 084 this.repository = repository; 085 } 086 087 public boolean containsObject(String name) { 088 boolean contains = repository.contains(name); 089 return contains; 090 } 091 092 public Object getObject(String name) { 093 Object object = repository.get(name); 094 return object; 095 } 096 097 public void addObject(String name, Object object) { 098 repository.add(name, object); 099 100 // set any pending references 101 List<Reference> list = unresolvedRefs.remove(name); 102 if (list != null) { 103 for (Reference Reference : list) { 104 Reference.set(object); 105 } 106 } 107 } 108 109 public void addReference(Reference reference) { 110 Object value = repository.get(reference.getName()); 111 if (value != null && !(value instanceof Recipe)) { 112 reference.set(value); 113 } else { 114 List<Reference> list = unresolvedRefs.get(reference.getName()); 115 if (list == null) { 116 list = new ArrayList<Reference>(); 117 unresolvedRefs.put(reference.getName(), list); 118 } 119 list.add(reference); 120 } 121 } 122 123 public SortedMap<String, List<Reference>> getUnresolvedRefs() { 124 return unresolvedRefs; 125 } 126 127 public ClassLoader getClassLoader() { 128 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 129 if (classLoader == null) classLoader = getClass().getClassLoader(); 130 return classLoader; 131 } 132 }