KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > webflow > definition > registry > FlowDefinitionRegistryImpl


1 /*
2  * Copyright 2002-2006 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.springframework.webflow.definition.registry;
17
18 import java.util.Iterator JavaDoc;
19 import java.util.LinkedList JavaDoc;
20 import java.util.Map JavaDoc;
21 import java.util.TreeMap JavaDoc;
22
23 import org.springframework.core.style.ToStringCreator;
24 import org.springframework.util.Assert;
25 import org.springframework.webflow.definition.FlowDefinition;
26
27 /**
28  * A generic registry implementation for housing one or more flow definitions.
29  * <p>
30  * This registry may be refreshed at runtime to "hot reload" refreshable flow
31  * definitions.
32  *
33  * @author Keith Donald
34  */

35 public class FlowDefinitionRegistryImpl implements FlowDefinitionRegistry {
36
37     /**
38      * The map of loaded Flow definitions maintained in this registry.
39      */

40     private Map JavaDoc flowDefinitions = new TreeMap JavaDoc();
41
42     /**
43      * An optional parent flow definition registry.
44      */

45     private FlowDefinitionRegistry parent;
46     
47     // implementing FlowDefinitionRegistryMBean
48

49     public String JavaDoc[] getFlowDefinitionIds() {
50         return (String JavaDoc[])flowDefinitions.keySet().toArray(new String JavaDoc[flowDefinitions.size()]);
51     }
52
53     public int getFlowDefinitionCount() {
54         return flowDefinitions.size();
55     }
56
57     public boolean containsFlowDefinition(String JavaDoc id) {
58         Assert.hasText(id, "The flow id is required");
59         return flowDefinitions.get(id) != null;
60     }
61
62     public void refresh() throws FlowDefinitionConstructionException {
63         ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
64         try {
65             // workaround for JMX
66
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
67             LinkedList JavaDoc needsReindexing = new LinkedList JavaDoc();
68             Iterator JavaDoc it = flowDefinitions.entrySet().iterator();
69             while (it.hasNext()) {
70                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc)it.next();
71                 String JavaDoc key = (String JavaDoc)entry.getKey();
72                 FlowDefinitionHolder holder = (FlowDefinitionHolder)entry.getValue();
73                 holder.refresh();
74                 if (!holder.getFlowDefinitionId().equals(key)) {
75                     needsReindexing.add(new Indexed(key, holder));
76                 }
77             }
78             it = needsReindexing.iterator();
79             while (it.hasNext()) {
80                 Indexed indexed = (Indexed)it.next();
81                 reindex(indexed.holder, indexed.key);
82             }
83         }
84         finally {
85             Thread.currentThread().setContextClassLoader(loader);
86         }
87     }
88
89     public void refresh(String JavaDoc flowId)
90             throws NoSuchFlowDefinitionException, FlowDefinitionConstructionException {
91         ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
92         try {
93             // workaround for JMX
94
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
95             FlowDefinitionHolder holder = getFlowDefinitionHolder(flowId);
96             holder.refresh();
97             if (!holder.getFlowDefinitionId().equals(flowId)) {
98                 reindex(holder, flowId);
99             }
100         }
101         finally {
102             Thread.currentThread().setContextClassLoader(loader);
103         }
104     }
105     
106     // implementing FlowDefinitionLocator
107

108     public FlowDefinition getFlowDefinition(String JavaDoc id)
109             throws NoSuchFlowDefinitionException, FlowDefinitionConstructionException {
110         Assert.hasText(id,
111                 "Unable to load a flow definition: no flow id was provided. Please provide a valid flow identifier.");
112         try {
113             return getFlowDefinitionHolder(id).getFlowDefinition();
114         }
115         catch (NoSuchFlowDefinitionException e) {
116             if (parent != null) {
117                 // try parent
118
return parent.getFlowDefinition(id);
119             }
120             throw e;
121         }
122     }
123     
124     // implementing FlowDefinitionRegistry
125

126     public void setParent(FlowDefinitionRegistry parent) {
127         this.parent = parent;
128     }
129     
130     public FlowDefinition[] getFlowDefinitions() throws FlowDefinitionConstructionException {
131         FlowDefinition[] flows = new FlowDefinition[flowDefinitions.size()];
132         Iterator JavaDoc it = flowDefinitions.values().iterator();
133         int i = 0;
134         while (it.hasNext()) {
135             FlowDefinitionHolder holder = (FlowDefinitionHolder)it.next();
136             flows[i] = holder.getFlowDefinition();
137             i++;
138         }
139         return flows;
140     }
141
142     public void registerFlowDefinition(FlowDefinitionHolder flowHolder) {
143         Assert.notNull(flowHolder, "The flow definition holder to register is required");
144         index(flowHolder);
145     }
146
147     /**
148      * Remove identified flow definition from this registry. If the given
149      * id is not known in this registry, nothing will happen.
150      * @param id the flow definition id
151      */

152     public void removeFlowDefinition(String JavaDoc id) {
153         Assert.hasText(id, "The flow id is required");
154         flowDefinitions.remove(id);
155     }
156     
157     // internal helpers
158

159     /**
160      * Reindex given flow definition.
161      * @param holder the holder holding the flow definition to reindex
162      * @param oldId the id that was previously assigned to given flow definition
163      */

164     private void reindex(FlowDefinitionHolder holder, String JavaDoc oldId) {
165         flowDefinitions.remove(oldId);
166         index(holder);
167     }
168
169     /**
170      * Index given flow definition.
171      * @param holder the holder holding the flow definition to index
172      */

173     private void index(FlowDefinitionHolder holder) {
174         Assert.hasText(holder.getFlowDefinitionId(), "The flow holder to index must return a non-blank flow id");
175         flowDefinitions.put(holder.getFlowDefinitionId(), holder);
176     }
177
178     /**
179      * Returns the identified flow definition holder. Throws an exception
180      * if it cannot be found.
181      */

182     private FlowDefinitionHolder getFlowDefinitionHolder(String JavaDoc id) throws NoSuchFlowDefinitionException {
183         FlowDefinitionHolder flowHolder = (FlowDefinitionHolder)flowDefinitions.get(id);
184         if (flowHolder == null) {
185             throw new NoSuchFlowDefinitionException(id, getFlowDefinitionIds());
186         }
187         return flowHolder;
188     }
189
190     /**
191      * Simple value object that holds the key for an indexed flow definition
192      * holder in this registry. Used to support reindexing on a refresh.
193      *
194      * @author Keith Donald
195      */

196     private static class Indexed {
197         
198         private String JavaDoc key;
199
200         private FlowDefinitionHolder holder;
201
202         public Indexed(String JavaDoc key, FlowDefinitionHolder holder) {
203             this.key = key;
204             this.holder = holder;
205         }
206     }
207
208     public String JavaDoc toString() {
209         return new ToStringCreator(this).append("flowDefinitions", flowDefinitions).append("parent", parent).toString();
210     }
211 }
Popular Tags