001 // Copyright 2007, 2008, 2010 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry5.internal.services;
016
017 import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newConcurrentMap;
018
019 import java.util.Map;
020
021 import org.apache.tapestry5.ioc.ObjectLocator;
022 import org.apache.tapestry5.services.ApplicationStateContribution;
023 import org.apache.tapestry5.services.ApplicationStateCreator;
024 import org.apache.tapestry5.services.ApplicationStateManager;
025 import org.apache.tapestry5.services.ApplicationStatePersistenceStrategy;
026 import org.apache.tapestry5.services.ApplicationStatePersistenceStrategySource;
027
028 public class ApplicationStateManagerImpl implements ApplicationStateManager
029 {
030 static final String DEFAULT_STRATEGY = "session";
031
032 static class ApplicationStateAdapter<T>
033 {
034 private final Class<T> ssoClass;
035
036 private final ApplicationStatePersistenceStrategy strategy;
037
038 private final ApplicationStateCreator<T> creator;
039
040 ApplicationStateAdapter(Class<T> ssoClass, ApplicationStatePersistenceStrategy strategy,
041 ApplicationStateCreator<T> creator)
042 {
043 this.ssoClass = ssoClass;
044 this.strategy = strategy;
045 this.creator = creator;
046 }
047
048 T getOrCreate()
049 {
050 return strategy.get(ssoClass, creator);
051 }
052
053 void set(T sso)
054 {
055 strategy.set(ssoClass, sso);
056 }
057
058 boolean exists()
059 {
060 return strategy.exists(ssoClass);
061 }
062 }
063
064 /**
065 * The map will be extended periodically as new ASOs, not in the configuration, are encountered.
066 * Thut is is thread
067 * safe.
068 */
069 private final Map<Class, ApplicationStateAdapter> classToAdapter = newConcurrentMap();
070
071 private final ApplicationStatePersistenceStrategySource source;
072
073 private final ObjectLocator locator;
074
075 @SuppressWarnings("unchecked")
076 public ApplicationStateManagerImpl(Map<Class, ApplicationStateContribution> configuration,
077 ApplicationStatePersistenceStrategySource source, ObjectLocator locator)
078 {
079 this.source = source;
080 this.locator = locator;
081
082 for (Class asoClass : configuration.keySet())
083 {
084 ApplicationStateContribution contribution = configuration.get(asoClass);
085
086 ApplicationStateAdapter adapter = newAdapter(asoClass, contribution.getStrategy(),
087 contribution.getCreator());
088
089 classToAdapter.put(asoClass, adapter);
090 }
091
092 }
093
094 @SuppressWarnings("unchecked")
095 private <T> ApplicationStateAdapter<T> newAdapter(final Class<T> ssoClass, String strategyName,
096 ApplicationStateCreator<T> creator)
097 {
098 if (creator == null)
099 {
100 creator = new ApplicationStateCreator<T>()
101 {
102 public T create()
103 {
104 return locator.autobuild("Instantiating instance of SSO class "
105 + ssoClass.getName(), ssoClass);
106 }
107 };
108 }
109
110 ApplicationStatePersistenceStrategy strategy = source.get(strategyName);
111
112 return new ApplicationStateAdapter(ssoClass, strategy, creator);
113 }
114
115 @SuppressWarnings("unchecked")
116 private <T> ApplicationStateAdapter<T> getAdapter(Class<T> ssoClass)
117 {
118 ApplicationStateAdapter<T> result = classToAdapter.get(ssoClass);
119
120 // Not found is completely OK, we'll define it on the fly.
121
122 if (result == null)
123 {
124 result = newAdapter(ssoClass, DEFAULT_STRATEGY, null);
125 classToAdapter.put(ssoClass, result);
126 }
127
128 return result;
129 }
130
131 public <T> T get(Class<T> ssoClass)
132 {
133 return getAdapter(ssoClass).getOrCreate();
134 }
135
136 public <T> T getIfExists(Class<T> ssoClass)
137 {
138 ApplicationStateAdapter<T> adapter = getAdapter(ssoClass);
139
140 return adapter.exists() ? adapter.getOrCreate() : null;
141 }
142
143 public <T> void set(Class<T> ssoClass, T sso)
144 {
145 getAdapter(ssoClass).set(sso);
146 }
147
148 public <T> boolean exists(Class<T> ssoClass)
149 {
150 return getAdapter(ssoClass).exists();
151 }
152
153 }