/******************************************************************************* * Copyright (c) 2015 IBH SYSTEMS GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBH SYSTEMS GmbH - initial API and implementation *******************************************************************************/ package org.eclipse.packagedrone.repo.channel.apm.aspect; import java.util.concurrent.Callable; import org.eclipse.packagedrone.repo.utils.ThrowingRunnable; import org.eclipse.packagedrone.utils.Exceptions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Guard { private final static Logger logger = LoggerFactory.getLogger ( Guard.class ); private final ThreadLocal<Integer> state = ThreadLocal.withInitial ( () -> 0 ); private final Runnable guardRunner; public Guard ( final Runnable guardRunner ) { this.guardRunner = guardRunner; } public void guarded ( final ThrowingRunnable action ) { guarded ( () -> { action.run (); return null; } ); } public <T> T guarded ( final Callable<T> action ) { final boolean first = push (); logger.trace ( "run guarded - first: {}", first ); try { final T result = Exceptions.wrapException ( action ); if ( first ) { logger.debug ( "execute guard runner" ); // only call if the action was successful and it was the first level this.guardRunner.run (); } return result; } finally { pop (); } } private boolean push () { final int level = this.state.get (); this.state.set ( level + 1 ); return level == 0; } private void pop () { this.state.set ( this.state.get () - 1 ); } }