    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}