1 8 package org.apache.avalon.excalibur.lang; 9 10 import java.util.HashMap ; 11 import java.util.Map ; 12 import java.util.Iterator ; 13 import java.util.ArrayList ; 14 15 46 public final class LayeredThreadContext 47 { 48 private final static RuntimePermission c_setThreadContextPermission = 50 new RuntimePermission ( "LayeredThreadContext.setThreadContext" ); 51 52 private final static RuntimePermission c_pushPermission = 54 new RuntimePermission ( "LayeredThreadContext.push" ); 55 56 private final static InheritableThreadLocal c_context = new CloningInheritableThreadLocal(); 57 58 private final ThreadContextAccessor m_accessor = new InnerThreadContextAccessor(); 60 61 private final ThreadContextPolicy m_policy; 63 64 private final ArrayList m_layers = new ArrayList (); 66 67 72 public static LayeredThreadContext getThreadContext() 73 { 74 return (LayeredThreadContext)c_context.get(); 75 } 76 77 86 public static void setThreadContext( final LayeredThreadContext threadContext ) 87 throws SecurityException 88 { 89 final SecurityManager securityManager = System.getSecurityManager(); 90 if( null != securityManager ) 91 { 92 securityManager.checkPermission( c_setThreadContextPermission ); 93 } 94 95 final LayeredThreadContext oldThreadContext = (LayeredThreadContext)c_context.get(); 96 if( null != oldThreadContext ) oldThreadContext.deactivate(); 97 98 c_context.set( threadContext ); 99 if( null != threadContext ) 100 { 101 threadContext.activate(); 102 } 103 } 104 105 109 public LayeredThreadContext( final ThreadContextPolicy policy ) 110 { 111 if( null == policy ) 112 { 113 throw new NullPointerException ( "policy property is null" ); 114 } 115 116 m_policy = policy; 117 } 118 119 130 public synchronized void pop( final Object key ) 131 throws IllegalArgumentException 132 { 133 final int size = m_layers.size(); 134 final int top = size - 1; 135 for( int i = top; i >= 0; i-- ) 136 { 137 final Layer layer = (Layer)m_layers.get( i ); 138 if( layer.matchesKey( key ) ) 139 { 140 for( int j = top; j >= i; j-- ) 141 { 142 m_layers.remove( j ); 143 } 144 return; 145 } 146 } 147 148 throw new IllegalArgumentException ( "Unknown key " + key ); 149 } 150 151 161 public synchronized void push( final Object key, final Map map, final boolean isDivider ) 162 throws SecurityException , IllegalArgumentException 163 { 164 final SecurityManager securityManager = System.getSecurityManager(); 165 if( null != securityManager ) 166 { 167 securityManager.checkPermission( c_pushPermission ); 168 } 169 170 final Map data = new HashMap (); 171 172 final Iterator keys = map.keySet().iterator(); 173 while( keys.hasNext() ) 174 { 175 final Object keyValue = keys.next(); 176 final Object value = map.get( keyValue ); 177 final String keyString = keyValue.toString(); 178 179 m_policy.verifyKeyValue( keyString, value ); 180 data.put( keyString, value ); 181 } 182 183 m_layers.add( new Layer( key, data, isDivider ) ); 184 } 185 186 192 protected synchronized Object contextGet( final String key ) 193 { 194 final int size = m_layers.size(); 195 final int top = size - 1; 196 for( int i = top; i >= 0; i-- ) 197 { 198 final Layer layer = (Layer)m_layers.get( i ); 199 if( layer.containsKey( key ) ) 200 { 201 return layer.get( key ); 202 } 203 204 if( layer.isDivider() ) break; 206 } 207 208 return null; 209 } 210 211 217 protected synchronized boolean contextContainsKey( final String key ) 218 { 219 final int size = m_layers.size(); 220 final int top = size - 1; 221 for( int i = top; i >= 0; i-- ) 222 { 223 final Layer layer = (Layer)m_layers.get( i ); 224 if( layer.containsKey( key ) ) 225 { 226 return true; 227 } 228 229 if( layer.isDivider() ) break; 231 } 232 233 return false; 234 } 235 236 241 protected synchronized LayeredThreadContext duplicate() 242 { 243 final LayeredThreadContext context = new LayeredThreadContext( m_policy ); 244 245 final int size = m_layers.size(); 246 for( int i = 0; i < size; i++ ) 247 { 248 final Layer layer = (Layer)m_layers.get( i ); 249 250 context.m_layers.add( layer ); 252 } 253 254 return context; 255 } 256 257 260 private void activate() 261 { 262 m_policy.activate( m_accessor ); 263 } 264 265 268 private void deactivate() 269 { 270 m_policy.deactivate( m_accessor ); 271 } 272 273 276 private static class CloningInheritableThreadLocal extends InheritableThreadLocal 277 { 278 protected Object childValue( final Object parentValue ) 279 { 280 final LayeredThreadContext context = (LayeredThreadContext)parentValue; 281 return context.duplicate(); 282 } 283 } 284 285 288 private class InnerThreadContextAccessor implements ThreadContextAccessor 289 { 290 public boolean containsKey( final String key ) 291 { 292 return contextContainsKey( key ); 293 } 294 295 public Object get( final String key ) 296 { 297 return contextGet( key ); 298 } 299 } 300 } 301 | Popular Tags |