    001    // Copyright 2006, 2007, 2008, 2009, 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
    015    package org.apache.tapestry5.ioc.internal.util;
    016
    017    /**
    018     * Logic for handling one shot semantics for classes; classes that include a method (or methods) that "locks down" the
    019     * instance, to prevent it from being used again in the future.
    020     */
    021    public class OneShotLock extends LockSupport
    022    {
    023        private boolean lock;
    024
    025        /**
    026         * Checks to see if the lock has been set (via {@link #lock()}).
    027         *
    028         * @throws IllegalStateException
    029         *         if the lock is set
    030         */
    031        public void check()
    032        {
    033            try
    034            {
    035                acquireReadLock();
    036
    037                innerCheck();
    038            } finally
    039            {
    040                releaseReadLock();
    041            }
    042        }
    043
    044        private void innerCheck()
    045        {
    046            if (lock)
    047            {
    048                // The depth to find the caller of the check() or lock() method varies between JDKs.
    049
    050                StackTraceElement[] elements = Thread.currentThread().getStackTrace();
    051
    052                int i = 0;
    053                while (!elements[i].getMethodName().equals("innerCheck"))
    054                {
    055                    i++;
    056                }
    057
    058                throw new IllegalStateException(UtilMessages.oneShotLock(elements[i + 2]));
    059            }
    060        }
    061
    062        /**
    063         * Checks the lock, then sets it.
    064         */
    065        public void lock()
    066        {
    067            try
    068            {
    069                takeWriteLock();
    070
    071                innerCheck();
    072
    073                lock = true;
    074            } finally
    075            {
    076                releaseWriteLock();
    077            }
    078        }
    079    }