    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.ioc.internal.util.CollectionFactory.newConcurrentMap;
    018
    019import java.util.Map;
    020
    021import org.apache.tapestry5.ioc.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
    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}