All Downloads are FREE. Search and download functionalities are using the official Maven repository.

uk.org.retep.kernel.bootstrap.Bootstrap Maven / Gradle / Ivy

/*
 * 

Copyright (c) 1998-2009, Peter T Mount
* All rights reserved.

* *

* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU 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 . *

* *

* GNU GENERAL PUBLIC LICENSE - CLASSPATH EXCEPTION *

* *

* Linking this library statically or dynamically with other modules * is making a combined work based on this library. Thus, the terms * and conditions of the GNU General Public License cover the whole * combination. *

* *

* As a special exception, the copyright holders of this library give * you permission to link this library with independent modules to * produce an executable, regardless of the license terms of these * independent modules, and to copy and distribute the resulting * executable under terms of your choice, provided that you also meet, * for each linked independent module, the terms and conditions of the * license of that module. *

* *

* An independent module is a module which is either not derived from or based * on this library, or a module who's classes extend those within this library * as part of the implementation of the library. *

* *

* If you modify this library, you may extend this exception to your version * of the library, but you are not obligated to do so. If you do not wish to * do so, delete this exception statement from your version. *

*/ package uk.org.retep.kernel.bootstrap; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.ServiceLoader; import java.util.Set; import java.util.concurrent.BlockingDeque; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; import uk.org.retep.kernel.module.Module; import uk.org.retep.kernel.module.ModuleEvent; /** * The bootstrap class run by the native launchers. * *

* It runs in the system class loader so cannot have any dependencies * outside of it's own jar other than the standard classes. *

* *

* It manages the configuration of the system classloaders, terracotta integration * and the initialisation of the Kernel itself. *

* * @author peter */ public class Bootstrap { private static final Bootstrap instance = new Bootstrap(); private ClassLoader classLoader; private String applicationName; private List arguments = new ArrayList(); private Thread bootStrapThread; private File homeDirectory; private Date applicationStartDate; private Set modules; private BlockingDeque> eventQueue; public static Bootstrap getInstance() { return instance; } private Bootstrap() { } /** * Used by JNI to set the application name * @param applicationName */ public void setApplicationName( final String applicationName ) { this.applicationName = applicationName; // TODO check to see if this is true as the native launcher now does this... // On Linux and Darwin, applicationName is just that, but on Win32 // when run from inside Cygwin it's the full path to the .exe so // we have to do an inline StringUtils.basename() in that case if( File.separatorChar == '\\' ) { final int i = applicationName.lastIndexOf( '\\' ); if( i > -1 ) { this.applicationName = applicationName.substring( i + 1 ); } } } /** * Used by JNI to add a command line argument * @param arg command line argument */ public void addArgument( final String arg ) { arguments.add( arg ); } /** * Used by JNI to determine if we are restarting the application. * @return true if we are restarting */ public boolean isRestart() { return false; } /** * Used by JNI - starts up the actual kernel */ public void bootstrap() { try { final long startTime = System.currentTimeMillis(); applicationStartDate = new Date( startTime ); if( bootStrapThread == null ) { bootStrapThread = Thread.currentThread(); } else { throw new SecurityException( "Only the BootStrap Thread may call this method" ); } eventQueue = new LinkedBlockingDeque>(); createClassLoader(); createModules(); startModules(); runEventQueue(); } catch( Throwable t ) { t.printStackTrace(); System.exit( 1 ); } } private void runEventQueue() throws InterruptedException { while( true ) { final ModuleEvent event = eventQueue.poll( 1L, TimeUnit.SECONDS ); if( event != null ) { relayEvent( event ); } } } private void relayEvent( final ModuleEvent event ) { for( Module module : modules ) { try { module.handleModuleEvent( event ); } catch( Throwable t ) { t.printStackTrace(); } } } private URL getJarURL( final Class clazz ) throws MalformedURLException { URL classURL = clazz.getResource( clazz.getSimpleName() + ".class" ); if( classURL == null ) { return null; } String path = classURL.toString(); int i = path.indexOf( '!' ); if( i > -1 ) { path = path.substring( 0, i ); } if( path.startsWith( "jar:" ) ) { path = path.substring( 4 ); } return new URL( path ); } private File getJarFile( final Class clazz ) { try { URL jarURL = getJarURL( clazz ); if( jarURL != null ) { return new File( jarURL.getPath() ).getAbsoluteFile(); } return null; } catch( MalformedURLException ex ) { ex.printStackTrace(); return null; } } private void createClassLoader() throws MalformedURLException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { // The jar is under bin (i.e. home/bin/app.jar) so this returns // a File representing bin. final File binDir = getJarFile( getClass() ).getParentFile(); // Now resolve home. If binDir is called MacOS then home is Resources // otherwise its .. // FIXME this is going to be in the binary homeDirectory = binDir.getParentFile(); if( "MacOS".equals( binDir.getName() ) ) { // For OSX home is the Resources directory homeDirectory = new File( homeDirectory, "Resources" ); } // Now according to the layout check commons then app specific jars // and add to the List. final File libDir = new File( homeDirectory, "lib" ); final String clusterName = System.getProperty( "retep.cluster.name", applicationName ); classLoader = KernelClassLoader.create( applicationName, clusterName, libDir, Thread.currentThread().getContextClassLoader() ); Thread.currentThread().setContextClassLoader( classLoader ); } private void createModules() throws Exception { // Load the modules and add to the set. This defines the deployment order modules = new HashSet(); final ServiceLoader sl = ServiceLoader.load( Module.class, classLoader ); for( Module module : sl ) { modules.add( module ); } // FIXME the binary knows this already final File configDirectory = new File( homeDirectory, "etc" ); // Point dataDirectory to data/appName or data/common final File data1Dir = new File( homeDirectory, "data" ); File data2Dir = new File( data1Dir, applicationName ); File data3Dir = new File( data1Dir, "common" ); final File dataDirectory = data2Dir.exists() ? data2Dir : data3Dir; // Now create them for( Module module : modules ) { module.setApplicationName( applicationName ); module.setApplicationStartDate( applicationStartDate ); module.setArguments( arguments ); module.setClassLoader( classLoader ); module.setConfigDirectory( configDirectory ); module.setDataDirectory( dataDirectory ); module.setEventDeque( eventQueue ); module.setHomeDirectory( homeDirectory ); } } private void startModules() throws Throwable { for( Module module : modules ) { module.start(); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy