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    }