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