/*
* Copyright (C) 2008 Laurent Caillette
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.novelang.testing;
import java.security.Permission;
import static com.google.common.base.Preconditions.checkState;
import org.novelang.logger.Logger;
import org.novelang.logger.LoggerFactory;
/**
* Traps calls to {@link System#exit(int)} by installing some hacky {@code SecurityManager}.
* This class is thread-unsafe and installs a {@code SecurityManager} allowing everything
* (except JVM termination).
*
* @author Laurent Caillette
*/
public class NoSystemExit {
private static final Logger LOGGER = LoggerFactory.getLogger( NoSystemExit.class ) ;
public static final NoSystemExit INSTANCE = new NoSystemExit() ;
/**
* Synchronize access on every field on this object.
*/
private final Object lock = new Object() ;
private SecurityManager previous = null ;
private boolean installed = false ;
public void install() {
synchronized( lock ) {
checkState( ! installed, "Alread installed" ) ;
this.previous = System.getSecurityManager() ;
final SecurityManager securityManager = new NoExitSecurityManager() ;
System.setSecurityManager( securityManager ) ;
installed = true ;
}
}
public void uninstall() {
synchronized( lock ) {
checkState( installed, "Not installed" ) ;
System.setSecurityManager( previous ) ;
installed = false ;
}
}
public static class ExitTrappedException extends SecurityException { }
private static class NoExitSecurityManager extends SecurityManager {
@Override
public void checkPermission( final Permission permission ) {
final String permissionName = permission.getName() ;
if( permissionName.startsWith( "exitVM" ) ) {
LOGGER.debug( "Checking permission " + permissionName ) ;
throw new ExitTrappedException() ;
}
}
}
}