001package org.apache.maven; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.util.LinkedList; 023import java.util.Map; 024 025import com.google.common.collect.Maps; 026import com.google.inject.Key; 027import com.google.inject.OutOfScopeException; 028import com.google.inject.Provider; 029import com.google.inject.Scope; 030import com.google.inject.util.Providers; 031 032public class SessionScope 033 implements Scope 034{ 035 private static final Provider<Object> SEEDED_KEY_PROVIDER = new Provider<Object>() 036 { 037 public Object get() 038 { 039 throw new IllegalStateException(); 040 } 041 }; 042 043 private static final class ScopeState 044 { 045 public final Map<Key<?>, Provider<?>> seeded = Maps.newHashMap(); 046 047 public final Map<Key<?>, Object> provided = Maps.newHashMap(); 048 } 049 050 private final ThreadLocal<LinkedList<ScopeState>> values = new ThreadLocal<LinkedList<ScopeState>>(); 051 052 public void enter() 053 { 054 LinkedList<ScopeState> stack = values.get(); 055 if ( stack == null ) 056 { 057 stack = new LinkedList<ScopeState>(); 058 values.set( stack ); 059 } 060 stack.addFirst( new ScopeState() ); 061 } 062 063 private ScopeState getScopeState() 064 { 065 LinkedList<ScopeState> stack = values.get(); 066 if ( stack == null || stack.isEmpty() ) 067 { 068 throw new IllegalStateException(); 069 } 070 return stack.getFirst(); 071 } 072 073 public void exit() 074 { 075 final LinkedList<ScopeState> stack = values.get(); 076 if ( stack == null || stack.isEmpty() ) 077 { 078 throw new IllegalStateException(); 079 } 080 stack.removeFirst(); 081 if ( stack.isEmpty() ) 082 { 083 values.remove(); 084 } 085 } 086 087 public <T> void seed( Class<T> clazz, Provider<T> value ) 088 { 089 getScopeState().seeded.put( Key.get( clazz ), value ); 090 } 091 092 public <T> void seed( Class<T> clazz, final T value ) 093 { 094 getScopeState().seeded.put( Key.get( clazz ), Providers.of( value ) ); 095 } 096 097 public <T> Provider<T> scope( final Key<T> key, final Provider<T> unscoped ) 098 { 099 return new Provider<T>() 100 { 101 @SuppressWarnings( "unchecked" ) 102 public T get() 103 { 104 LinkedList<ScopeState> stack = values.get(); 105 if ( stack == null || stack.isEmpty() ) 106 { 107 throw new OutOfScopeException( "Cannot access " + key + " outside of a scoping block" ); 108 } 109 110 ScopeState state = stack.getFirst(); 111 112 Provider<?> seeded = state.seeded.get( key ); 113 114 if ( seeded != null ) 115 { 116 return (T) seeded.get(); 117 } 118 119 T provided = (T) state.provided.get( key ); 120 if ( provided == null && unscoped != null ) 121 { 122 provided = unscoped.get(); 123 state.provided.put( key, provided ); 124 } 125 126 return provided; 127 } 128 }; 129 } 130 131 @SuppressWarnings( { "unchecked" } ) 132 public static <T> Provider<T> seededKeyProvider() 133 { 134 return (Provider<T>) SEEDED_KEY_PROVIDER; 135 } 136}