    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    }