Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
PersistenceBrokerThreadMapping |
|
| 4.75;4.75 |
1 | package org.apache.ojb.broker.core; | |
2 | ||
3 | /* Copyright 2003-2005 The Apache Software Foundation | |
4 | * | |
5 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | * you may not use this file except in compliance with the License. | |
7 | * You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, software | |
12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | * See the License for the specific language governing permissions and | |
15 | * limitations under the License. | |
16 | */ | |
17 | ||
18 | import java.util.Collection; | |
19 | import java.util.HashMap; | |
20 | import java.util.HashSet; | |
21 | import java.util.Iterator; | |
22 | import java.util.WeakHashMap; | |
23 | ||
24 | import org.apache.ojb.broker.PBFactoryException; | |
25 | import org.apache.ojb.broker.PBKey; | |
26 | import org.apache.ojb.broker.PersistenceBrokerException; | |
27 | import org.apache.ojb.broker.PersistenceBrokerInternal; | |
28 | ||
29 | /** | |
30 | * Helper class that tracks correspondence between PersistenceBroker instances | |
31 | * and threads. The main task that this class solves is: to get current | |
32 | * PersistenceBroker for the given thread. For internal use only. | |
33 | * | |
34 | * @author Oleg Nitz | |
35 | * @version $Id: PersistenceBrokerThreadMapping.java,v 1.1 2007-08-24 22:17:35 ewestfal Exp $ | |
36 | */ | |
37 | public class PersistenceBrokerThreadMapping | |
38 | { | |
39 | /** | |
40 | * A Collection of all HashMaps added to the <CODE>ThreadLocal currentBrokerMap</CODE> that are still -alive-. | |
41 | * If all the PersistenceBrokers are always correctly closed, the Collection should remain empty. | |
42 | * The Collection is iterated trough when calling the <CODE>shutdown()</CODE> method and all the maps that are | |
43 | * still alive will be cleared. | |
44 | */ | |
45 | private static Collection loadedHMs = new HashSet(); | |
46 | ||
47 | /** | |
48 | * The hashmap that maps PBKeys to current brokers for the thread | |
49 | */ | |
50 | private static ThreadLocal currentBrokerMap = new ThreadLocal(); | |
51 | ||
52 | /** | |
53 | * Mark a PersistenceBroker as preferred choice for current Thread | |
54 | * | |
55 | * @param key The PBKey the broker is associated to | |
56 | * @param broker The PersistenceBroker to mark as current | |
57 | */ | |
58 | public static void setCurrentPersistenceBroker(PBKey key, PersistenceBrokerInternal broker) | |
59 | throws PBFactoryException | |
60 | { | |
61 | HashMap map = (HashMap) currentBrokerMap.get(); | |
62 | WeakHashMap set = null; | |
63 | if(map == null) | |
64 | { | |
65 | map = new HashMap(); | |
66 | currentBrokerMap.set(map); | |
67 | ||
68 | loadedHMs.add(map); | |
69 | } | |
70 | else | |
71 | { | |
72 | set = (WeakHashMap) map.get(key); | |
73 | } | |
74 | ||
75 | if(set == null) | |
76 | { | |
77 | // We emulate weak HashSet using WeakHashMap | |
78 | set = new WeakHashMap(); | |
79 | map.put(key, set); | |
80 | } | |
81 | set.put(broker, null); | |
82 | } | |
83 | ||
84 | /** | |
85 | * Unmark a PersistenceBroker as preferred choice for current Thread | |
86 | * | |
87 | * @param key The PBKey the broker is associated to | |
88 | * @param broker The PersistenceBroker to unmark | |
89 | */ | |
90 | public static void unsetCurrentPersistenceBroker(PBKey key, PersistenceBrokerInternal broker) | |
91 | throws PBFactoryException | |
92 | { | |
93 | HashMap map = (HashMap) currentBrokerMap.get(); | |
94 | WeakHashMap set = null; | |
95 | if(map != null) | |
96 | { | |
97 | set = (WeakHashMap) map.get(key); | |
98 | if(set != null) | |
99 | { | |
100 | set.remove(broker); | |
101 | if(set.isEmpty()) | |
102 | { | |
103 | map.remove(key); | |
104 | } | |
105 | } | |
106 | if(map.isEmpty()) | |
107 | { | |
108 | currentBrokerMap.set(null); | |
109 | loadedHMs.remove(map); | |
110 | } | |
111 | } | |
112 | } | |
113 | ||
114 | /** | |
115 | * Return the current open {@link org.apache.ojb.broker.PersistenceBroker} | |
116 | * instance for the given {@link org.apache.ojb.broker.PBKey}, if any. | |
117 | * | |
118 | * @param key | |
119 | * @return null if no open {@link org.apache.ojb.broker.PersistenceBroker} found. | |
120 | */ | |
121 | public static PersistenceBrokerInternal currentPersistenceBroker(PBKey key) | |
122 | throws PBFactoryException, PersistenceBrokerException | |
123 | { | |
124 | HashMap map = (HashMap) currentBrokerMap.get(); | |
125 | WeakHashMap set; | |
126 | PersistenceBrokerInternal broker = null; | |
127 | ||
128 | if(map == null) | |
129 | { | |
130 | return null; | |
131 | } | |
132 | ||
133 | set = (WeakHashMap) map.get(key); | |
134 | if(set == null) | |
135 | { | |
136 | return null; | |
137 | } | |
138 | ||
139 | // seek for an open broker, preferably in transaction | |
140 | for(Iterator it = set.keySet().iterator(); it.hasNext();) | |
141 | { | |
142 | PersistenceBrokerInternal tmp = (PersistenceBrokerInternal) it.next(); | |
143 | if(tmp == null || tmp.isClosed()) | |
144 | { | |
145 | it.remove(); | |
146 | continue; | |
147 | } | |
148 | broker = tmp; | |
149 | if(tmp.isInTransaction()) | |
150 | { | |
151 | break; // the best choice found | |
152 | } | |
153 | } | |
154 | return broker; | |
155 | } | |
156 | ||
157 | /** | |
158 | * Clean up static fields and any registered ThreadLocal contents to grant a clean | |
159 | * shutdown/reload of OJB within re/hot-deployable applications. | |
160 | */ | |
161 | public static void shutdown() | |
162 | { | |
163 | for(Iterator it = loadedHMs.iterator(); it.hasNext();) | |
164 | { | |
165 | ((HashMap) it.next()).clear(); | |
166 | } | |
167 | loadedHMs.clear(); | |
168 | loadedHMs = null; | |
169 | currentBrokerMap = null; | |
170 | } | |
171 | } |