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

at.spardat.xma.boot.comp.AppManager Maven / Gradle / Ivy

There is a newer version: 1.16.0
Show newest version
/*******************************************************************************
 * Copyright (c) 2003, 2007 s IT Solutions AT Spardat 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:
 *     s IT Solutions AT Spardat GmbH - initial API and implementation
 *******************************************************************************/

package at.spardat.xma.boot.comp;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Properties;

import at.spardat.xma.boot.Statics;
import at.spardat.xma.boot.cache.VersionNumber;
import at.spardat.xma.boot.comp.data.XMAComponent;
import at.spardat.xma.boot.comp.data.XMAResource;
import at.spardat.xma.boot.component.IComponent;
import at.spardat.xma.boot.component.IComponentHelper;
import at.spardat.xma.boot.component.IRtXMASessionClient;
import at.spardat.xma.boot.exc.BRLoginException;
import at.spardat.xma.boot.exc.BRTCodes;
import at.spardat.xma.boot.exc.BootRuntimeException;
import at.spardat.xma.boot.logger.LogLevel;
import at.spardat.xma.boot.logger.Logger;
import at.spardat.xma.boot.transport.CommunicationException;
import at.spardat.xma.boot.transport.HostnameVerifierImpl;
import at.spardat.xma.boot.transport.Transport;
import at.spardat.xma.boot.transport.XMA_URI;
import at.spardat.xma.boot.util.Util;
import at.spardat.xma.boot.fdm.FastDevelopmentLoader;

/**
 * The AppManager is responsible for handling the application-context and classloaders
 * for xma-components that it also invokes.
 *
 * @author s3595 Chris Sch?fer (CGS)
 * @version $Id: AppManager.java 5899 2010-06-08 14:27:34Z gub $
 *
 */
public class AppManager  {

    /** singleton */
    private static AppManager instance_;

    /** logger */
    private Logger log_;

    /**
     * running applications.
     * contains an AppContainerfor each running application.
     */
    private Hashtable apps_;

    /** configuration properties */
    private Properties props;

    /** loads and checks application descriptions */
    private AppLoader loader;

    /** loads components in fast development mode */
    private FastDevelopmentLoader fdmLoader;

    /** if 'boot.transport.hostname.accept' is set, checks in getComponent() if the host is to accept */
    private HostnameVerifierImpl hostNameAccepter;

    /** if 'boot.transport.hostname.block' is set, checks in getComponent() if the host is to block */
    private HostnameVerifierImpl hostNameBlocker;

    /** constructor */
    public AppManager( Properties pnew ) {
       props      = pnew;
       log_       = Logger.getLogger( "boot.appManager"); //$NON-NLS-1$
       apps_      = new Hashtable(10);

       String acceptHosts = props.getProperty(Statics.CFG_PROP_HOSTNAMEACCEPT);
       if(acceptHosts != null && acceptHosts.length() > 0)
           hostNameAccepter = new HostnameVerifierImpl (acceptHosts);
       String blockHosts = props.getProperty(Statics.CFG_PROP_HOSTNAMEBLOCK);
       if(blockHosts != null && blockHosts.length() > 0)
           hostNameBlocker = new HostnameVerifierImpl (blockHosts);
    }

    /** initialisation */
    public static synchronized AppManager initialize( Properties pnew ) {
         // if(instance_ == null )
           instance_ = new AppManager( pnew );
       return instance_ ;
    }

    /** get instance */
    public static AppManager getInstance( ) {
        if(instance_ == null)
          throw new IllegalStateException( "Application Manager not initialized"); //$NON-NLS-1$
        else
          return instance_;
    }

    /**
     * prepare, and instantiate a component.
     * 
* {@link at.spardat.xma.boot.Launcher#launch} * * @throws Exception unrecoverable exception. */ public IComponent getComponent( String component) throws Exception { return getComponent(component,new Properties()); } /** * prepare, and instantiate a component. *
* {@link at.spardat.xma.boot.Launcher#launch} * * @throws Exception unrecoverable exception. */ public IComponent getComponent(String component, Properties properties) throws Exception { XMA_URI uri = new XMA_URI(component); if(!acceptXMA_URI(uri)){ throw new BootRuntimeException(BRTCodes.getText(BRTCodes.COMPONENT_NOT_ACCEPTED), component /*uri.getComponent()*/,uri.getServer()).setCode(BRTCodes.COMPONENT_NOT_ACCEPTED); } String appname = uri.getApplication(); AppContainer appC = (AppContainer)apps_.get(appname); /* if this is the first component for this application, * prepare the application and session */ if( appC == null ) { appC = initializeApplication(uri,properties) ; } /* * if this component is accessed the first time during this application start, * load the components resources into the classloader, and register it as running. */ XMAComponent cmp = appC.getApp().getComponent( uri.getComponent() ); if(cmp==null) throw new BootRuntimeException(BRTCodes.getText(BRTCodes.COMPONENT_NOT_FOUND), uri.getComponent()).setCode(BRTCodes.COMPONENT_NOT_FOUND); if( !appC.isRunningCmp(cmp) ) { boolean fdm = "true".equalsIgnoreCase(props.getProperty("boot.fdm")) && uri.getServer().equals("localhost"); if(fdm) { if(fdmLoader==null) { fdmLoader = new FastDevelopmentLoader(props); } fdmLoader.loadComponent(cmp); appC.getCcl().addURL(cmp.getFdmUrl()); } /* load resources for this component */ loader.loadResources( uri, cmp.getRes(), appC.getServerVers(), fdm ); /* the classloader needs all component resources for a component to run, * but only once. */ ArrayList array = getComponentUrls( uri, cmp, XMAResource.TypeID.TYPE_JAR); for (int i = 0; i < array.size(); i++) { appC.getCcl().addURL( (URL)array.get(i) ); } // add the native libs, too appC.getCcl().addNativeLibs(getComponentUrls(uri,cmp,XMAResource.TypeID.TYPE_NATIVELIB)); appC.addRunningCmp(cmp); } /* * load the component from the application classloader */ Class c = appC.getCcl().loadClass( cmp.getImplPackage_() + Statics.strClient + cmp.getName_() ); Class sessionClass = appC.getCcl().loadClass( "at.spardat.xma.session.XMASessionClient" ); //$NON-NLS-1$ Constructor ccons = c.getConstructor(new Class[]{ sessionClass }); Object rtc = ccons.newInstance( new Object[] { appC.getSession() } ); IComponentHelper compHelper = loader.getCompHelper(); cmp.addInstance(compHelper.castToIComponent(rtc)); return compHelper.castToIComponent(rtc); } /** * This method tests if the given host is in the BootRuntime properties: * 'boot.transport.hostname.accept' * 'boot.transport.hostname.block' * The entries in the two properties are seperated by '|' or ';' and every entry may contain one wildcard character ('*'). * If 'boot.transport.hostname.accept' is empty then every host is accepted, otherwise the given host has to match an entry of this property. * Even an accepted host can be blocked by an entry in 'boot.transport.hostname.block'. * A hostname is also local DNS resoled to its IP adress, so you can also allow or block hosts by IP adresses. * If a host is not acceptable then a BootRuntimeException is thrown. * * This method is in package scope to be used by AppManagerTest. * * @param uri * @throws BootRuntimeException * @since version_number * @author s3460 */ boolean acceptXMA_URI(XMA_URI uri){ String host = uri.getServer(); if(hostNameAccepter != null && !hostNameAccepter.verify(host)){ log_.log(LogLevel.WARNING, "The host \"{0}\" is not accepted as it is not configured in \"{1}\" having value : {2}", new Object[]{host, Statics.CFG_PROP_HOSTNAMEACCEPT, props.getProperty(Statics.CFG_PROP_HOSTNAMEACCEPT)}); return false; } if(hostNameBlocker != null && hostNameBlocker.verify(host)){ log_.log(LogLevel.WARNING, "The host \"{0}\" is blocked as it is configured in \"{1}\" having value: {2}", new Object[]{host, Statics.CFG_PROP_HOSTNAMEBLOCK, props.getProperty(Statics.CFG_PROP_HOSTNAMEBLOCK)}); return false; } return true; } /** * prepare, and start a component. *
* {@link at.spardat.xma.boot.Launcher#launch} * * @throws Exception unrecoverable exception. */ public Properties launch( String component, Properties input) throws Exception { Properties output = new Properties(); Object rtc = getComponent(component,input); output = loader.getCompHelper().launch(rtc,input); return output; } /** * cleanup components and application resources. * logout from application, if this component is the last one for this application. * * @param rtc the terminating component */ public void endComponent(IComponent rtc) { AppContainer appC = loader.getCompHelper().getRTSession(rtc).getAppContainer(); String strClassName = rtc.getClass().getName(); String strCmpName = strClassName.substring(strClassName.lastIndexOf('.')+1); XMAComponent cmp = appC.getRunningCmp( strCmpName); cmp.remInstance(rtc); if( cmp.instanceCount() == 0 ) { XMAComponent cmpT = appC.remRunningCmp(strCmpName); log_.log(LogLevel.FINE, "removed component: {0}", cmpT.getName_()); //$NON-NLS-1$ } if( appC.runningCmp() == 0 ) { appC.getSession().logout(); apps_.remove( appC.getApp().getName_() ); } } /** * prepare urls for the classloader for this component. * * @return ArrayList array of component resource urls */ private ArrayList getComponentUrls( XMA_URI uri, XMAComponent cmp, String type) throws Exception { ArrayList array = new ArrayList(10); // for each resource for (Iterator iter = cmp.getRes().values().iterator(); iter.hasNext();) { XMAResource res = (XMAResource) iter.next(); AppLoader.urlLocalToArray(res,array,type); } return array; } static class DigestServer { byte[] hash; VersionNumber version; } private DigestServer getDigestServer(XMA_URI uri) throws CommunicationException { DigestServer digestServer = new DigestServer(); uri.setComponent(null); uri.setResource("session"); uri.addParameter("operation","checkVersion"); try{ byte[] answer = Transport.getTransport().callServerEvent(null,uri,new byte[0]); if(answer.length<16) throw new RuntimeException("server digest to short: "+new String(answer)); digestServer.hash = new byte[16]; System.arraycopy(answer,0,digestServer.hash,0,16); if(answer.length>16) { try { digestServer.version=VersionNumber.parse("_"+new String(answer,16,answer.length-16,"US-ASCII")+"."); } catch (UnsupportedEncodingException uee) { throw new RuntimeException("Encodung US-ASCII not supported ",uee); } } if(digestServer.version==null) { digestServer.version=new VersionNumber(0,0,0); } return digestServer; } catch (CommunicationException e) { Transport.getTransport().logProxyInfo(LogLevel.WARNING); throw e; } } /** * compare to application descriptor hash codes */ private boolean compare( byte[] a, byte[] b ) { if( a==null || b==null || a.length != b.length) { return false; } for( int i=0; i DetailException auspacken und weiterwerfen. appC.setSession(session); /* login */ boolean loggedIn=false; try { loggedIn=session.login(properties); } catch (AbstractMethodError ame) { //compatibility with runtime before 1.7.0 loggedIn=session.login(); } if(!loggedIn) { log_.log( LogLevel.WARNING, "(server) login failed" ); //$NON-NLS-1$ throw new BRLoginException("login failed"); } /* add to list of running applications */ apps_.put( uri.getApplication(), appC ); /* mark application as used today (for cache cleanup only)*/ loader.markApplicationUsed( appC.getApp().getApplicationDescrURI() ); return appC; } /** * Loads the given application from the cache and updates it from the server * if neccessary. * @param uri of the application * @return AppContainer containing the loaded application description * @throws CommunicationException if the application hash can not be loaded from the server * @throws BootRuntimeException if the download of the application resources failed twice */ public AppContainer loadAndUpdateApplication(XMA_URI uri) throws CommunicationException, BootRuntimeException { AppContainer appC = null; if( loader == null) loader = new AppLoader( props ); DigestServer digest = getDigestServer(uri.getApplicationURI()); /* load the application */ try { appC = loader.loadApplication( uri.getApplicationURI(), digest.hash, digest.version ); } catch (Exception exc) { // download failed -> clear cache and retry log_.log(LogLevel.WARNING,"application loading failed: ",exc); log_.log(LogLevel.WARNING,"retrying loading of application ..."); try { Util util = Util.getInstance(); String dirName = util.urlToPath(uri.getApplicationURI().getHTTP_URI()).toString(); File dir = new File(loader.getFileCache().getBaseDir(),dirName); util.removeApplicationRecursive( dir, log_ ); appC = loader.loadApplication(uri,digest.hash, digest.version); } catch (Exception e2) { log_.log(LogLevel.SEVERE,"application loading failed twice: ",e2); throw new BootRuntimeException(BRTCodes.getText(BRTCodes.VERSION_UPDATE_ERROR) ).setCode(BRTCodes.VERSION_UPDATE_ERROR).setShowToEndUser(true); } } return appC; } /** * Returns the classloader used for loading SWT classes. * This method just calls {@link AppLoader#getSwtClassLoader()} * @return the swtClassloader or null if no AppLoader or no swtClassloader allready exists. */ public CCLoader getSWTClassLoader() { return loader!=null?loader.getSwtClassLoader():null; } /** * Returns the ComponentHelper used for SWT-dependent methods. * This method just calls {@link AppLoader#getCompHelper()} * @return the ComponentHelper or null if no AppLoader or no ComponentHelper allready exists. */ public IComponentHelper getCompHelper() { return loader!=null?loader.getCompHelper():null; } }// class




© 2015 - 2024 Weber Informatics LLC | Privacy Policy