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 015package org.apache.tapestry5.internal.services; 016 017import static org.apache.tapestry5.commons.util.CollectionFactory.newConcurrentMap; 018 019import java.util.Map; 020 021import org.apache.tapestry5.commons.ObjectLocator; 022import org.apache.tapestry5.services.ApplicationStateContribution; 023import org.apache.tapestry5.services.ApplicationStateCreator; 024import org.apache.tapestry5.services.ApplicationStateManager; 025import org.apache.tapestry5.services.ApplicationStatePersistenceStrategy; 026import org.apache.tapestry5.services.ApplicationStatePersistenceStrategySource; 027 028public 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 T getIfExists() 064 { 065 return strategy.getIfExists(ssoClass); 066 } 067 } 068 069 /** 070 * The map will be extended periodically as new ASOs, not in the configuration, are encountered. 071 * Thut is is thread 072 * safe. 073 */ 074 private final Map<Class, ApplicationStateAdapter> classToAdapter = newConcurrentMap(); 075 076 private final ApplicationStatePersistenceStrategySource source; 077 078 private final ObjectLocator locator; 079 080 @SuppressWarnings("unchecked") 081 public ApplicationStateManagerImpl(Map<Class, ApplicationStateContribution> configuration, 082 ApplicationStatePersistenceStrategySource source, ObjectLocator locator) 083 { 084 this.source = source; 085 this.locator = locator; 086 087 for (Class asoClass : configuration.keySet()) 088 { 089 ApplicationStateContribution contribution = configuration.get(asoClass); 090 091 ApplicationStateAdapter adapter = newAdapter(asoClass, contribution.getStrategy(), 092 contribution.getCreator()); 093 094 classToAdapter.put(asoClass, adapter); 095 } 096 097 } 098 099 @SuppressWarnings("unchecked") 100 private <T> ApplicationStateAdapter<T> newAdapter(final Class<T> ssoClass, String strategyName, 101 ApplicationStateCreator<T> creator) 102 { 103 if (creator == null) 104 { 105 creator = new ApplicationStateCreator<T>() 106 { 107 public T create() 108 { 109 return locator.autobuild("Instantiating instance of SSO class " 110 + ssoClass.getName(), ssoClass); 111 } 112 }; 113 } 114 115 ApplicationStatePersistenceStrategy strategy = source.get(strategyName); 116 117 return new ApplicationStateAdapter(ssoClass, strategy, creator); 118 } 119 120 @SuppressWarnings("unchecked") 121 private <T> ApplicationStateAdapter<T> getAdapter(Class<T> ssoClass) 122 { 123 ApplicationStateAdapter<T> result = classToAdapter.get(ssoClass); 124 125 // Not found is completely OK, we'll define it on the fly. 126 127 if (result == null) 128 { 129 result = newAdapter(ssoClass, DEFAULT_STRATEGY, null); 130 classToAdapter.put(ssoClass, result); 131 } 132 133 return result; 134 } 135 136 public <T> T get(Class<T> ssoClass) 137 { 138 return getAdapter(ssoClass).getOrCreate(); 139 } 140 141 public <T> T getIfExists(Class<T> ssoClass) 142 { 143 return getAdapter(ssoClass).getIfExists(); 144 } 145 146 public <T> void set(Class<T> ssoClass, T sso) 147 { 148 getAdapter(ssoClass).set(sso); 149 } 150 151 public <T> boolean exists(Class<T> ssoClass) 152 { 153 return getAdapter(ssoClass).exists(); 154 } 155 156}