001    // Copyright 2006, 2007, 2008, 2009 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
022    {
023        private boolean lock;
024    
025        /**
026         * Checks to see if the lock has been set (via {@link #lock()}).
027         *
028         * @throws IllegalStateException if the lock is set
029         */
030        public synchronized void check()
031        {
032            innerCheck();
033        }
034    
035        private void innerCheck()
036        {
037            if (lock)
038            {
039                // The depth to find the caller of the check() or lock() method varies between JDKs.
040    
041    
042                StackTraceElement[] elements = Thread.currentThread().getStackTrace();
043    
044                int i = 0;
045                while (!elements[i].getMethodName().equals("innerCheck"))
046                    i++;
047    
048                throw new IllegalStateException(UtilMessages.oneShotLock(elements[i + 2]));
049            }
050        }
051    
052        /**
053         * Checks the lock, then sets it.
054         */
055        public synchronized void lock()
056        {
057            innerCheck();
058    
059            lock = true;
060        }
061    }