    001// Copyright 2009, 2011, 2012 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.ioc.internal.services;
    016
    017import org.apache.tapestry5.ioc.ObjectCreator;
    018import org.apache.tapestry5.ioc.internal.util.LockSupport;
    019
    020/**
    021 * An {@link org.apache.tapestry5.ioc.ObjectCreator} that delegates to another
    022 * {@link org.apache.tapestry5.ioc.ObjectCreator} and caches the result.
    023 */
    024public class CachingObjectCreator<T> extends LockSupport implements ObjectCreator<T>
    025{
    026    private boolean cached;
    027
    028    private T cachedValue;
    029
    030    private ObjectCreator<T> delegate;
    031
    032    public CachingObjectCreator(ObjectCreator<T> delegate)
    033    {
    034        this.delegate = delegate;
    035    }
    036
    037    @Override
    038    public T createObject()
    039    {
    040        try
    041        {
    042            acquireReadLock();
    043
    044            if (!cached)
    045            {
    046                cacheValueFromDelegate();
    047            }
    048
    049            return cachedValue;
    050        } finally
    051        {
    052            releaseReadLock();
    053        }
    054    }
    055
    056    private void cacheValueFromDelegate()
    057    {
    058        try
    059        {
    060            upgradeReadLockToWriteLock();
    061
    062            if (!cached)
    063            {
    064                cachedValue = delegate.createObject();
    065                cached = true;
    066                delegate = null;
    067            }
    068        } finally
    069        {
    070            downgradeWriteLockToReadLock();
    071        }
    072    }
    073}