Java tutorial
/* * Copyright (c) 2001-2011 Convertigo SA. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero 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/>. * * $URL$ * $Author$ * $Revision$ * $Date$ */ package com.twinsoft.convertigo.engine; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Constructor; import java.security.Provider; import java.security.Security; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; import javax.servlet.http.HttpServletRequest; import javax.swing.event.EventListenerList; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.auth.AuthPolicy; import org.apache.commons.lang3.StringUtils; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import com.twinsoft.api.SessionManager; import com.twinsoft.convertigo.beans.core.DatabaseObject; import com.twinsoft.convertigo.beans.core.Project; import com.twinsoft.convertigo.beans.core.RequestableObject; import com.twinsoft.convertigo.beans.core.Transaction; import com.twinsoft.convertigo.engine.EnginePropertiesManager.PropertyName; import com.twinsoft.convertigo.engine.cache.CacheManager; import com.twinsoft.convertigo.engine.enums.Parameter; import com.twinsoft.convertigo.engine.externalbrowser.ExternalBrowserManager; import com.twinsoft.convertigo.engine.providers.couchdb.CouchDbManager; import com.twinsoft.convertigo.engine.providers.sapjco.SapJcoDestinationDataProvider; import com.twinsoft.convertigo.engine.requesters.HttpSessionListener; import com.twinsoft.convertigo.engine.requesters.Requester; import com.twinsoft.convertigo.engine.scheduler.SchedulerManager; import com.twinsoft.convertigo.engine.util.CachedIntrospector; import com.twinsoft.convertigo.engine.util.Crypto2; import com.twinsoft.convertigo.engine.util.FileUtils; import com.twinsoft.convertigo.engine.util.GenericUtils; import com.twinsoft.convertigo.engine.util.HttpUtils; import com.twinsoft.convertigo.engine.util.LogWrapper; import com.twinsoft.convertigo.engine.util.XMLUtils; import com.twinsoft.tas.ApplicationException; import com.twinsoft.tas.Authentication; import com.twinsoft.tas.KeyManager; import com.twinsoft.tas.ParsingException; import com.twinsoft.util.Log; import com.twinsoft.util.TWSKey; public class Engine { public static final String JVM_PROPERTY_USER_WORKSPACE = "convertigo.cems.user_workspace_path"; public static final String JVM_PROPERTY_GLOBAL_SYMBOLS_FILE = "convertigo.cems.global_symbols_file"; public static final String JVM_PROPERTY_GLOBAL_SYMBOLS_FILE_COMPATIBILITY = "convertigo_global_symbols"; public static String USER_WORKSPACE_PATH = System.getProperty(JVM_PROPERTY_USER_WORKSPACE, System.getProperty("user.home") + "/convertigo"); public static String PROJECTS_PATH = ""; public static String CERTIFICATES_PATH = ""; public static String LOG_PATH = ""; public static String XSL_PATH = ""; public static String DTD_PATH = ""; public static String TEMPLATES_PATH = ""; public static String WEBAPP_PATH = ""; public static String CACHE_PATH = ""; public static String CONFIGURATION_PATH = ""; static { // Do not forget to retrieve the canonical paths, i.e. the path // where ".." and "." are resolved to unique paths. try { USER_WORKSPACE_PATH = new File(USER_WORKSPACE_PATH).getCanonicalPath(); } catch (IOException e) { } } /** * This is the application reference. */ public static Engine theApp; public static AuthenticatedSessionManager authenticatedSessionManager; /** * Defines if application is started. */ public static boolean isStarted = false; /** * Defines if application is started. */ public static boolean isStartFailed = false; /** * Defines if application is Service Oriented. */ public static boolean isSOA = false; /** * Defines if that Convertigo is a Studio. */ private static boolean bStudioMode = false; /** * The database objects manager. */ public DatabaseObjectsManager databaseObjectsManager; /** * The SQL connections manager. */ public JdbcConnectionManager sqlConnectionManager; /** * The files manager */ public FilePropertyManager filePropertyManager; /** * The TracePlayer manager */ public TracePlayerManager tracePlayerManager; /** * The context manager. */ public ContextManager contextManager; /** * The thread manager. */ public ThreadManager threadManager; /** * The security token manager. */ public SecurityTokenManager securityTokenManager; /** * The cache manager. */ public CacheManager cacheManager; /** * The usage monitor. */ public UsageMonitor usageMonitor; /** * The billing manager */ public BillingManager billingManager; /** * The proxy manager */ public ProxyManager proxyManager; /** * The external browser manager */ public ExternalBrowserManager externalBrowserManager; /** * The external browser manager */ public SchemaManager schemaManager; /** * The resource compressor manager for minification */ public MinificationManager minificationManager; /** * The plugins manager */ public PluginsManager pluginsManager; /** * The CouchDb manager */ public CouchDbManager couchDbManager; /** * The REST api manager */ public RestApiManager restApiManager; /** * Loggers */ public static Logger logConvertigo; public static Logger logEngine; public static Logger logBillers; public static Logger logAdmin; public static Logger logBeans; public static Logger logContext; public static Logger logEmulators; public static Logger logUser; public static Logger logContextManager; public static Logger logCacheManager; public static Logger logTracePlayerManager; public static Logger logDatabaseObjectManager; public static Logger logJobManager; public static Logger logCertificateManager; public static Logger logProxyManager; public static Logger logUsageMonitor; public static Logger logStatistics; public static Logger logScheduler; public static Logger logSiteClipper; public static Logger logExternalBrowser; public static Logger logAudit; public static Logger logDevices; public static Logger logCouchDbManager; public static Logger logSecurityTokenManager; /** * The Log object for the application. */ @Deprecated public static LogWrapper log; /** * Defines the cloud customer_name. */ final public static String cloud_customer_name; /** * The engine start/stop date. */ public static long startStopDate; /** * The scheduler for running jobs. */ public SchedulerManager schedulerManager; /** * The event manager for dispatching events. */ public EventManager eventManager; public HttpClient httpClient; public CloseableHttpClient httpClient4; public RsaManager rsaManager; static { try { Engine.authenticatedSessionManager = new AuthenticatedSessionManager(); Engine.authenticatedSessionManager.init(); } catch (EngineException e) { e.printStackTrace(); } cloud_customer_name = System.getProperty("convertigo.cloud.customer_name"); AuthPolicy.registerAuthScheme(AuthPolicy.NTLM, com.jivesoftware.authHelper.customescheme.ntlm2.CustomNTLM2Scheme.class); } private static boolean bInitPathsDone = false; public static void initPaths(String webappPath) throws IOException { if (bInitPathsDone) return; // Create/update the user workspace if needed File userWorkspaceDirectory = new File(Engine.USER_WORKSPACE_PATH); File defaultUserWorkspaceDirectory = new File(webappPath + "/WEB-INF/default_user_workspace"); System.out.println("Updating the user workspace from '" + defaultUserWorkspaceDirectory.toString() + "' to '" + Engine.USER_WORKSPACE_PATH + "'"); try { FileUtils.mergeDirectories(defaultUserWorkspaceDirectory, userWorkspaceDirectory); } catch (Exception e) { System.out.println("Error while updating the user workspace"); e.printStackTrace(); } if (Engine.PROJECTS_PATH.length() == 0) { Engine.PROJECTS_PATH = new File(Engine.USER_WORKSPACE_PATH + "/projects").getCanonicalPath(); } Engine.CACHE_PATH = new File(Engine.USER_WORKSPACE_PATH + "/cache").getCanonicalPath(); Engine.CONFIGURATION_PATH = new File(Engine.USER_WORKSPACE_PATH + "/configuration").getCanonicalPath(); Engine.CERTIFICATES_PATH = new File(Engine.USER_WORKSPACE_PATH + "/certificates").getCanonicalPath(); Engine.WEBAPP_PATH = new File(webappPath).getCanonicalPath(); Engine.XSL_PATH = new File(Engine.WEBAPP_PATH + "/xsl").getCanonicalPath(); Engine.DTD_PATH = new File(Engine.WEBAPP_PATH + "/dtd").getCanonicalPath(); Engine.TEMPLATES_PATH = new File(Engine.WEBAPP_PATH + "/templates").getCanonicalPath(); bInitPathsDone = true; } public static synchronized void start() throws EngineException { if (Engine.theApp == null) { System.out.println("Starting Convertigo Enterprise Mobility Server"); // If the engine has been stopped by the admin, we must reload // properties EnginePropertiesManager.loadProperties(); boolean bProjectsDataCompatibilityMode = Boolean.parseBoolean( EnginePropertiesManager.getProperty(PropertyName.PROJECTS_DATA_COMPATIBILITY_MODE)); if (bProjectsDataCompatibilityMode) { System.out.println("Projects data compatibility mode required"); try { Engine.PROJECTS_PATH = new File(Engine.WEBAPP_PATH + "/projects").getCanonicalPath(); File projectsDir = new File(Engine.PROJECTS_PATH); projectsDir.mkdir(); } catch (IOException e) { throw new EngineException("Unable to update projects path for compatibility mode", e); } } isStarted = false; isStartFailed = false; RequestableObject.nbCurrentWorkerThreads = 0; Engine.startStopDate = System.currentTimeMillis(); System.out.println("Creating/updating loggers"); String logFile = EnginePropertiesManager.getProperty(PropertyName.LOG4J_APPENDER_CEMSAPPENDER_FILE); System.out.println("Log file: " + logFile); // Main loggers Engine.logConvertigo = Logger.getLogger("cems"); Engine.logEngine = Logger.getLogger("cems.Engine"); Engine.logAdmin = Logger.getLogger("cems.Admin"); Engine.logBeans = Logger.getLogger("cems.Beans"); Engine.logBillers = Logger.getLogger("cems.Billers"); Engine.logEmulators = Logger.getLogger("cems.Emulators"); Engine.logContext = Logger.getLogger("cems.Context"); Engine.logUser = Logger.getLogger("cems.Context.User"); Engine.logUsageMonitor = Logger.getLogger("cems.UsageMonitor"); Engine.logStatistics = Logger.getLogger("cems.Statistics"); Engine.logScheduler = Logger.getLogger("cems.Scheduler"); Engine.logSiteClipper = Logger.getLogger("cems.SiteClipper"); /** #3437 : Disabled ExternalBrowser feature because it's not terminated Engine.logExternalBrowser = Logger.getLogger("cems.ExternalBrowser"); */ Engine.logAudit = Logger.getLogger("cems.Context.Audit"); // Managers Engine.logContextManager = Logger.getLogger("cems.ContextManager"); Engine.logCacheManager = Logger.getLogger("cems.CacheManager"); Engine.logTracePlayerManager = Logger.getLogger("cems.TracePlayerManager"); Engine.logJobManager = Logger.getLogger("cems.JobManager"); Engine.logCertificateManager = Logger.getLogger("cems.CertificateManager"); Engine.logDatabaseObjectManager = Logger.getLogger("cems.DatabaseObjectManager"); Engine.logProxyManager = Logger.getLogger("cems.ProxyManager"); Engine.logDevices = Logger.getLogger("cems.Devices"); Engine.logCouchDbManager = Logger.getLogger("cems.CouchDbManager"); Engine.logSecurityTokenManager = Logger.getLogger("cems.SecurityTokenManager"); // Logger for compatibility issues Engine.log = new LogWrapper(Engine.logConvertigo); LogWrapper.initWrapper(Engine.logEmulators); try { Engine.logEngine.info("==========================================================="); Engine.logEngine.info("Web app home: " + Engine.WEBAPP_PATH); Engine.logEngine.info("User workspace: " + Engine.USER_WORKSPACE_PATH); Engine.logEngine.info("Configuration path: " + Engine.CONFIGURATION_PATH); Engine.logEngine.info("Projects path: " + Engine.PROJECTS_PATH); if (bProjectsDataCompatibilityMode) { Engine.logEngine.warn("Projects data compatibility mode required"); } Engine.logEngine.info("Log: " + Engine.LOG_PATH); if (cloud_customer_name != null) { Engine.logEngine.info("Cloud customer: " + cloud_customer_name); } // Check environment and native dependencies if (!isStudioMode()) { StartupDiagnostics.run(); } // Initializing the engine Engine.theApp = new Engine(); CachedIntrospector.prefetchDatabaseObjectsAsync(); try { Engine.theApp.usageMonitor = new UsageMonitor(); Engine.theApp.usageMonitor.init(); Thread vulture = new Thread(Engine.theApp.usageMonitor); vulture.setName("UsageMonitor"); vulture.setDaemon(true); vulture.start(); } catch (Exception e) { Engine.logEngine.error("Unable to launch the usage monitor.", e); } Engine.theApp.eventManager = new EventManager(); Engine.theApp.eventManager.init(); Engine.theApp.databaseObjectsManager = new DatabaseObjectsManager(); Engine.theApp.databaseObjectsManager.init(); Engine.theApp.sqlConnectionManager = new JdbcConnectionManager(); Engine.theApp.sqlConnectionManager.init(); Engine.theApp.filePropertyManager = new FilePropertyManager(); Engine.theApp.filePropertyManager.init(); try { Engine.theApp.proxyManager = new ProxyManager(); Engine.theApp.proxyManager.init(); } catch (Exception e) { Engine.logEngine.error("Unable to launch the proxy manager.", e); } try { Engine.theApp.billingManager = new BillingManager(); Engine.theApp.billingManager.init(); } catch (Exception e) { Engine.logEngine.error("Unable to launch the billing manager.", e); } // Initialization of the trace player try { Engine.theApp.tracePlayerManager = new TracePlayerManager(); Engine.theApp.tracePlayerManager.init(); } catch (Exception e) { Engine.logEngine.error("Unable to run the trace player.", e); } try { Engine.theApp.minificationManager = new MinificationManager(); Engine.theApp.minificationManager.init(); } catch (Exception e) { Engine.logEngine.error("Unable to run the minification manager.", e); } try { Engine.theApp.couchDbManager = new CouchDbManager(); Engine.theApp.couchDbManager.init(); } catch (Exception e) { Engine.logEngine.error("Unable to run the couchDbProxy manager.", e); } try { Engine.theApp.pluginsManager = new PluginsManager(); Engine.theApp.pluginsManager.init(); } catch (Exception e) { Engine.logEngine.error("Unable to run the plugins manager.", e); } try { Engine.theApp.restApiManager = RestApiManager.getInstance(); Engine.theApp.restApiManager.init(); } catch (Exception e) { Engine.logEngine.error("Unable to run the rest api manager.", e); } Engine.logEngine.info("Current working directory is '" + System.getProperty("user.dir") + "'."); // Creating the Carioca Authentication objects Engine.logEngine.debug("Creating the Carioca Authentication objects"); String cariocaUserName = EnginePropertiesManager .getProperty(PropertyName.CARIOCA_DEFAULT_USER_NAME); String cariocaPassword = EnginePropertiesManager .getProperty(PropertyName.CARIOCA_DEFAULT_USER_PASSWORD); Engine.theApp.authentications = new HashMap<String, Authentication>(); // Initialization of the default TAS properties try { KeyManager.log = new LogWrapper(Engine.logEngine); Authentication auth = Engine.theApp.getAuthenticationObject("", null); auth.login(cariocaUserName, cariocaPassword); } catch (Exception e) { Engine.logEngine.error("The authentication to Carioca has failed (user name: \"" + cariocaUserName + "\", user password: \"" + cariocaPassword + "\").", e); } // TODO : retrieve SOA flag from KeyManager isSOA = true; // Creation of the session manager Engine.theApp.sessionManager = new SessionManager(); Engine.theApp.sessionManager.setLog(new LogWrapper(Engine.logEngine)); Engine.theApp.sessionManager.setProductCode(SessionManager.CONVERTIGO); String s = EnginePropertiesManager.getProperty(PropertyName.CONNECTORS_MONITORING); Engine.theApp.setMonitored(s.equalsIgnoreCase("true")); // Create Projects directory if needed File projectsDirFile = new File(Engine.PROJECTS_PATH); try { if (!projectsDirFile.exists()) projectsDirFile.mkdirs(); } catch (Exception e) { Engine.logEngine.error("An error occured while creating projects directory.", e); } // Starts projects migration process MigrationManager.performProjectsMigration(); // Security providers registration try { File dir = new File(Engine.CERTIFICATES_PATH); String[] files = dir.list(new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith((".pkcs11")); } }); if (files != null && files.length > 0) { Engine.logEngine.info("Registering security providers..."); try { Class<?> sunPKCS11Class = Class.forName("sun.security.pkcs11.SunPKCS11"); String file; for (int i = 0; i < files.length; i++) { file = Engine.CERTIFICATES_PATH + "/" + files[i]; try { Constructor<?> constructor = sunPKCS11Class .getConstructor(new Class[] { String.class }); Provider provider = (Provider) constructor.newInstance(new Object[] { file }); Security.addProvider(provider); Engine.logEngine.info("Provider '" + provider.getName() + "' has been successfully registered."); } catch (Exception e) { Engine.logEngine.error("Unable to register security provider from file: " + file + " . Please check that the implementation library is in the Java lib path."); } } } catch (ClassNotFoundException e) { Engine.logEngine.error( "Unable to find sun.security.pkcs11.SunPKCS11 class! PKCS#11 authentication won't be available. You must use JVM 1.5 or higher in order to use PKCS#11 authentication."); } } Provider[] providers = Security.getProviders(); String sProviders = ""; for (int i = 0; i < providers.length; i++) { sProviders += providers[i].getName() + ", "; } Engine.logEngine.debug("Registered providers: " + sProviders); } catch (Exception e) { Engine.logEngine.error("Unable to register security providers.", e); } // Launch the cache manager try { String cacheManagerClassName = EnginePropertiesManager .getProperty(PropertyName.CACHE_MANAGER_CLASS); Engine.logEngine.debug("Cache manager class: " + cacheManagerClassName); Engine.theApp.cacheManager = (CacheManager) Class.forName(cacheManagerClassName).newInstance(); Engine.theApp.cacheManager.init(); Thread vulture = new Thread(Engine.theApp.cacheManager); Engine.theApp.cacheManager.executionThread = vulture; vulture.setName("CacheManager"); vulture.setDaemon(true); vulture.start(); } catch (Exception e) { Engine.logEngine.error("Unable to launch the cache manager.", e); } // Launch the thread manager try { Engine.theApp.threadManager = new ThreadManager(); Engine.theApp.threadManager.init(); Thread vulture = new Thread(Engine.theApp.threadManager); Engine.theApp.threadManager.executionThread = vulture; vulture.setName("ThreadManager"); vulture.setDaemon(true); vulture.start(); } catch (Exception e) { Engine.theApp.threadManager = null; Engine.logEngine.error("Unable to launch the thread manager.", e); } // Launch the context manager try { Engine.theApp.contextManager = new ContextManager(); Engine.theApp.contextManager.init(); Thread vulture = new Thread(Engine.theApp.contextManager); Engine.theApp.contextManager.executionThread = vulture; vulture.setName("ContextManager"); vulture.setDaemon(true); vulture.start(); } catch (Exception e) { Engine.theApp.contextManager = null; Engine.logEngine.error("Unable to launch the context manager.", e); } // Launch the security token manager Engine.theApp.securityTokenManager = new SecurityTokenManager(); Engine.theApp.securityTokenManager.init(); // Initialize the HttpClient try { Engine.logEngine.debug("HttpClient initializing..."); Engine.theApp.httpClient = HttpUtils.makeHttpClient3(true); Engine.theApp.httpClient4 = HttpUtils.makeHttpClient4(true); Engine.logEngine.debug("HttpClient initialized!"); } catch (Exception e) { Engine.logEngine.error("Unable to initialize the HttpClient.", e); } // Initialization of the schedule manager Engine.theApp.schedulerManager = new SchedulerManager(true); // Initialization of the RSA manager Engine.theApp.rsaManager = new RsaManager(); Engine.theApp.rsaManager.init(); // Initialization of the External Browser manager /** #3437 : Disabled ExternalBrowser feature because it's not terminated Engine.theApp.externalBrowserManager = new ExternalBrowserManager(); Engine.theApp.externalBrowserManager.init(); */ // Initialization of the Schema manager Engine.theApp.schemaManager = new SchemaManager(); Engine.theApp.schemaManager.init(); // XUL initialization String xulrunner_url = System.getProperty("org.eclipse.swt.browser.XULRunnerPath"); if (xulrunner_url == null || xulrunner_url.equals("")) { xulrunner_url = EnginePropertiesManager.getProperty(PropertyName.XULRUNNER_URL); } File f = new File(xulrunner_url); if (f.exists()) { xulrunner_url = f.getAbsolutePath(); Engine.logEngine .debug("initMozillaSWT: org.eclipse.swt.browser.XULRunnerPath=" + xulrunner_url); System.setProperty("org.eclipse.swt.browser.XULRunnerPath", xulrunner_url); } else { Engine.logEngine.error("Error in initMozillaSWT: " + xulrunner_url + " doesn't exist, fix it with xulrunner.url"); } if (Engine.isEngineMode() && Engine.isLinux() && "true".equals(EnginePropertiesManager.getProperty(PropertyName.LINUX_LAUNCH_XVNC))) { Engine.logEngine .debug("initMozillaSWT: org.eclipse.swt.browser.XULRunnerPath=" + xulrunner_url); final String display = System.getenv("DISPLAY"); if (display != null) { try { String port = System.getProperty("xvnc.port"); if (port == null) { port = "" + (Integer.parseInt(display.replaceAll(".*:(\\d*)", "$1")) + 5900); System.setProperty("xvnc.port", port); } Engine.logEngine.debug("Xvnc should listen on " + port + " port"); } catch (Exception e) { } try { File vncDir = new File(Engine.WEBAPP_PATH + "/WEB-INF/xvnc"); File Xvnc = new File(vncDir, "/Xvnc"); File fonts = new File(vncDir, "/fonts"); File wm = new File(vncDir, "/matchbox-window-manager"); if (vncDir.exists() && Xvnc.exists() && fonts.exists() && wm.exists()) { for (File file : GenericUtils.<File>asList(Xvnc, wm)) { new ProcessBuilder("/bin/chmod", "u+x", file.getAbsolutePath()).start() .waitFor(); } String depth = EnginePropertiesManager.getProperty(PropertyName.LINUX_XVNC_DEPTH); String geometry = EnginePropertiesManager .getProperty(PropertyName.LINUX_XVNC_GEOMETRY); Engine.logEngine .debug("Xvnc will use depth " + depth + " and geometry " + geometry); Process pr_xvnc = new ProcessBuilder(Xvnc.getAbsolutePath(), display, "-fp", fonts.getAbsolutePath(), "-depth", depth, "-geometry", geometry).start(); Thread.sleep(500); try { int exit = pr_xvnc.exitValue(); InputStream err = pr_xvnc.getErrorStream(); byte[] buf = new byte[err.available()]; err.read(buf); Engine.logEngine.debug("Xvnc failed to run with exit code " + exit + " and this error : <<" + new String(buf, "UTF-8") + ">>"); } catch (Exception e) { new ProcessBuilder(wm.getAbsolutePath()).start(); Engine.logEngine.debug("Xvnc successfully started !"); } } else { Engine.logEngine.info( vncDir.getAbsolutePath() + " not found or incomplet, cannot start Xvnc"); } } catch (Exception e) { Engine.logEngine.info("failed to launch Xvnc (maybe already launched", e); } } else Engine.logEngine .warn("Trying to start Xvnc on Linux without DISPLAY environment variable !"); } // SAP provider registration try { SapJcoDestinationDataProvider.init(); Engine.logEngine.debug("SAP destination provider successfully registered"); } catch (Throwable e) { Engine.logEngine.error("Error while registering SAP destination provider", e); } isStarted = true; Engine.logEngine.info("Convertigo engine started"); } catch (Throwable e) { isStartFailed = true; Engine.logEngine.error("Unable to successfully start the engine.", e); } } else { Engine.logEngine.info("Convertigo engine already started"); } } public static synchronized void stop() throws EngineException { if (Engine.theApp != null) { if (!MigrationManager.isMigrationFinished()) throw new EngineException("Migration process of projects is still running."); try { Engine.logEngine.info("Stopping the engine"); // Temporary reset the start/stop date in order to unlink the requestable's // running thread engine ID. Engine.startStopDate = 0; if (Engine.theApp.contextManager != null) { Engine.logEngine.info("Removing all contexts"); Engine.theApp.contextManager.destroy(); } Engine.logEngine.info("Resetting statistics"); EngineStatistics.reset(); if (Engine.theApp.usageMonitor != null) { Engine.logEngine.info("Removing the usage monitor"); Engine.theApp.usageMonitor.destroy(); } if (Engine.theApp.sqlConnectionManager != null) { Engine.logEngine.info("Removing the SQL connections manager"); Engine.theApp.sqlConnectionManager.destroy(); } if (Engine.theApp.filePropertyManager != null) { Engine.logEngine.info("Removing the file property manager"); Engine.theApp.filePropertyManager.destroy(); } if (Engine.theApp.billingManager != null) { Engine.logEngine.info("Removing the billing manager"); Engine.theApp.billingManager.destroy(); } if (Engine.theApp.tracePlayerManager != null) { Engine.logEngine.info("Removing the TracePlayer manager"); Engine.theApp.tracePlayerManager.destroy(); } if (Engine.theApp.cacheManager != null) { Engine.logEngine.info("Removing the cache manager"); Engine.theApp.cacheManager.destroy(); } if (Engine.theApp.proxyManager != null) { Engine.logEngine.info("Removing the proxy manager"); Engine.theApp.proxyManager.destroy(); } if (Engine.theApp.minificationManager != null) { Engine.logEngine.info("Removing the minification manager"); Engine.theApp.minificationManager.destroy(); } if (Engine.theApp.couchDbManager != null) { Engine.logEngine.info("Removing the couchdb manager"); Engine.theApp.couchDbManager.destroy(); } if (Engine.theApp.rsaManager != null) { Engine.logEngine.info("Removing the rsa manager"); Engine.theApp.rsaManager.destroy(); } if (Engine.theApp.externalBrowserManager != null) { Engine.logEngine.info("Removing the external browser manager"); Engine.theApp.externalBrowserManager.destroy(); } if (Engine.theApp.schemaManager != null) { Engine.logEngine.info("Removing the schema manager"); Engine.theApp.schemaManager.destroy(); } if (Engine.theApp.pluginsManager != null) { Engine.logEngine.info("Removing the plugins manager"); Engine.theApp.pluginsManager.destroy(); } if (Engine.theApp.restApiManager != null) { Engine.logEngine.info("Removing the rest api manager"); Engine.theApp.restApiManager.destroy(); } // Closing the session manager if (Engine.theApp.sessionManager != null) { Engine.logEngine.info("Closing the session manager"); Engine.theApp.sessionManager.removeAllSessions(); Engine.theApp.sessionManager = null; } Engine.logEngine.info("Resetting the key manager"); KeyManager.reset(); if (Engine.theApp.schedulerManager != null) { Engine.logEngine.info("Removing the scheduler manager"); Engine.theApp.schedulerManager.destroy(); } if (Engine.theApp.databaseObjectsManager != null) { Engine.logEngine.info("Removing the database objects manager"); Engine.theApp.databaseObjectsManager.destroy(); } if (Engine.theApp.threadManager != null) { Engine.logEngine.info("Removing the thread manager"); Engine.theApp.threadManager.destroy(); } if (Engine.theApp.securityTokenManager != null) { Engine.logEngine.info("Removing the security token manager"); Engine.theApp.securityTokenManager.destroy(); } Engine.logEngine.info("Unregistering the SAP destination provider"); try { SapJcoDestinationDataProvider.destroy(); } catch (Throwable e) { Engine.logEngine.error("Error while unregistering SAP destination provider", e); } HttpSessionListener.removeAllSession(); Engine.logEngine.info("The Convertigo Engine has been successfully stopped."); } finally { Engine.startStopDate = System.currentTimeMillis(); if (Engine.theApp.eventManager != null) { Engine.logEngine.info("Removing the event manager"); Engine.theApp.eventManager.destroy(); } Engine.theApp.eventManager = null; isStarted = false; RequestableObject.nbCurrentWorkerThreads = 0; EnginePropertiesManager.unload(); Engine.theApp = null; System.gc(); } } else { Engine.logEngine.info("Convertigo engine already stopped"); } } /** * The Carioca authentication objects map. */ public Map<String, Authentication> authentications = null; /** * The session manager for Javelin sessions. */ public SessionManager sessionManager; private boolean bMonitored = false; public ConnectorsMonitor connectorsMonitor; public void setMonitored(boolean bMonitored) { if (bMonitored != this.bMonitored) { this.bMonitored = bMonitored; if (bMonitored) { if (connectorsMonitor == null) connectorsMonitor = new ConnectorsMonitor(); connectorsMonitor.setVisible(true); sessionManager.setMonitorFrame(connectorsMonitor); sessionManager.setMonitor(true); // TODO: ajouter tous les connecteurs dj chargs dans les // contextes } else if (connectorsMonitor != null) { connectorsMonitor.setVisible(false); } } } public boolean isMonitored() { return bMonitored; } /** * Constructs a new Engine object. */ public Engine() { Engine.logEngine.info("==========================================================="); Engine.logEngine.info(" Convertigo Enterprise Mobility Server " + com.twinsoft.convertigo.engine.Version.fullProductVersion); Engine.logEngine.info(" engine " + Version.version); Engine.logEngine.info(" beans " + com.twinsoft.convertigo.beans.Version.version); Engine.logEngine.info("==========================================================="); Engine.logEngine.info("Start date: " + (new Date(startStopDate)).toString()); Engine.logEngine.info("Class loader: " + getClass().getClassLoader()); Engine.logEngine.info("Java Runtime " + System.getProperty("java.version") + " (classes: " + System.getProperty("java.class.version") + ", vendor: " + System.getProperty("java.vendor") + ")"); try { Engine.logEngine.info("Java XML engine: " + org.apache.xerces.impl.Version.getVersion()); } catch (Throwable e) { Engine.logEngine.warn("Unable to detect the XML engine"); } try { Engine.logEngine.info("Java XSL engine: " + org.apache.xalan.Version.getVersion()); } catch (Throwable e) { Engine.logEngine.warn("Unable to detect the XSL engine"); } // Enumeration of the properties try { Engine.logEngine.debug( EnginePropertiesManager.getPropertiesAsString("System properties", System.getProperties())); } catch (Exception e) { Engine.logEngine.error("Unable to retrieve the sorted system properties list.", e); } // Enumeration of the properties try { Engine.logEngine.debug(EnginePropertiesManager.getPropertiesAsString("Engine properties", null)); } catch (Exception e) { Engine.logEngine.error("Unable to retrieve the sorted engine properties list.", e); } } public Authentication getAuthenticationObject(String tasVirtualServer, String authName) throws ParsingException, com.twinsoft.tas.SQLException, ApplicationException { String name = (tasVirtualServer.equals("") ? "carioca" : tasVirtualServer) + "_" + authName; Authentication auth = (Authentication) authentications.get(name); if (auth == null) { Properties tasProperties = new Properties(); tasProperties.put("tasRoot", EnginePropertiesManager.getProperty(EnginePropertiesManager.PropertyName.CARIOCA_URL)); tasProperties.put("tasLoginPage", "login.asp"); tasProperties.put("tasServerScriptsDirectory", "Java"); tasProperties.put("tasVirtualServer", tasVirtualServer); auth = new Authentication(tasProperties); authentications.put(name, auth); Engine.logEngine.debug("Creation of the Authentication object for the Carioca virtual server \"" + (tasVirtualServer.equals("") ? "carioca" : tasVirtualServer) + "\"."); } else { Engine.logEngine.debug("Retrieving the Authentication object for the Carioca virtual server \"" + (tasVirtualServer.equals("") ? "carioca" : tasVirtualServer) + "\"."); } return auth; } public static ObjectsProvider objectsProvider = null; public static void setObjectsProvider(ObjectsProvider objectsProvider) { Engine.objectsProvider = objectsProvider; } /** * Retrieves the XML document according to the given context. * * @param requester * the calling requester. * @param context * the request context. * * @return the generated XML document. */ public Document getDocument(Requester requester, Context context) throws EngineException { Document outputDom = null; String t = context.statistics.start(EngineStatistics.GET_DOCUMENT); try { Engine.logContext.trace("Engine.getDocument: started"); // Are we in the studio context? if (isStudioMode()) { Engine.logContext.debug("The requested object will be processed in the studio context."); } // Checking whether the asynchronous mode has been requested. if ((context.isAsync) && (JobManager.jobExists(context.contextID))) { Engine.logContext .debug("The requested object is working and is asynchronous; requesting job status..."); HttpServletRequest request = (HttpServletRequest) requester.inputData; if (request.getParameter(Parameter.Abort.getName()) != null) { Engine.logContext.debug("Job abortion has been required"); return JobManager.abortJob(context.contextID); } return JobManager.getJobStatus(context.contextID); } // Loading project if (context.projectName == null) throw new EngineException("The project name has been specified!"); // Checking whether the asynchronous mode has been requested. if ((context.isAsync) && (JobManager.jobExists(context.contextID))) { Engine.logContext .debug("The requested object is working and is asynchronous; requesting job status..."); HttpServletRequest request = (HttpServletRequest) requester.inputData; if (request.getParameter(Parameter.Abort.getName()) != null) { Engine.logContext.debug("Job abortion has been required"); return JobManager.abortJob(context.contextID); } return JobManager.getJobStatus(context.contextID); } // Loading project if (context.projectName == null) throw new EngineException("The project name has been specified!"); Project currentProject; if (isStudioMode()) { if (objectsProvider == null) { throw new EngineException( "Is the Projects view opened in the Studio? Failed to load: " + context.projectName); } currentProject = objectsProvider.getProject(context.projectName); if (currentProject == null) { throw new EngineException( "No project has been opened in the Studio. A project should be opened in the Studio in order that the Convertigo engine can work."); } else if (!currentProject.getName().equalsIgnoreCase(context.projectName)) { throw new EngineException("The requested project (\"" + context.projectName + "\") does not match with the opened project (\"" + currentProject.getName() + "\") in the Studio.\nYou cannot make a request on a different project than the one opened in the Studio."); } Engine.logContext.debug("Using project from Studio"); context.project = currentProject; } else { if ((context.project == null) || (context.isNewSession)) { Engine.logEngine.debug("New project requested: '" + context.projectName + "'"); context.project = Engine.theApp.databaseObjectsManager.getProjectByName(context.projectName); Engine.logContext.debug("Project loaded: " + context.project.getName()); } } context.project.checkSymbols(); String corsOrigin = context.project.getCorsOrigin(); if (StringUtils.isNotBlank(corsOrigin)) { context.setResponseHeader("Access-Control-Allow-Origin", corsOrigin); } // Loading sequence if (context.sequenceName != null) { context.loadSequence(); } else { // Loading connector context.loadConnector(); // Loading transaction // Load default transaction if no overidden transaction is // provided if (context.transactionName == null) { context.requestedObject = context.getConnector().getDefaultTransaction(); context.transaction = (Transaction) context.requestedObject; context.transactionName = context.requestedObject.getName(); Engine.logContext.debug("Default transaction loaded: " + context.transactionName); } // Try to load overriden transaction else { context.requestedObject = context.getConnector().getTransactionByName(context.transactionName); context.transaction = (Transaction) context.requestedObject; if (context.requestedObject == null) { throw new EngineException("Unknown transaction \"" + context.transactionName + "\""); } Engine.logContext.debug("Transaction loaded: " + context.requestedObject.getName()); } context.transaction.checkSymbols(); if (context.getConnector().isTasAuthenticationRequired()) { if (context.tasSessionKey == null) { throw new EngineException( "A Carioca authentication is required in order to process the transaction."); } else { // Checking VIC information if needed if (context.isRequestFromVic) { Engine.logContext.debug("[Engine.getDocument()] Checking VIC session key"); String s = Crypto2.decodeFromHexString(context.tasSessionKey); int i = s.indexOf(','); if (i == -1) throw new EngineException("Unable to decrypt the VIC session key (reason: #1)!"); try { long t0 = Long.parseLong(s.substring(0, i)); Engine.logContext.debug("[VIC key check] t0=" + t0); long t1 = System.currentTimeMillis(); Engine.logContext.debug("[VIC key check] t1=" + t1); long d = Math.abs(t1 - t0); Engine.logContext.debug("[VIC key check] d=" + d); String user = s.substring(i + 1); Engine.logContext.debug("[VIC key check] user: " + user); long deltaT = 1000 * 60 * 10; if (d > deltaT) throw new EngineException("The VIC session key has expired."); if (!user.equals(context.tasUserName)) throw new EngineException("Wrong user name!"); } catch (NumberFormatException e) { throw new EngineException("Unable to decrypt the VIC session key (reason: #2)!"); } Engine.logContext.debug("[VIC key check] VIC session key OK"); } // Checking Carioca session key else if (context.isTrustedRequest) { if (!context.tasSessionKeyVerified) { Engine.logContext.debug("[Engine.getDocument()] Checking Carioca session key"); TWSKey twsKey = new TWSKey(); twsKey.CreateKey(1); int cariocaSessionKeyLifeTime = 60; try { cariocaSessionKeyLifeTime = Integer .parseInt(EnginePropertiesManager.getProperty( EnginePropertiesManager.PropertyName.CARIOCA_SESSION_KEY_LIFE_TIME)); } catch (NumberFormatException e) { Engine.logContext.warn( "The Carioca session key life time value is not valid (not a number)! Setting default to 60s."); } Engine.logContext.debug("Carioca session key lifetime: " + cariocaSessionKeyLifeTime + " second(s)"); String result = checkCariocaSessionKey(context, context.tasSessionKey, context.tasServiceCode, 0, cariocaSessionKeyLifeTime); if (result != null) throw new EngineException(result); Engine.logContext.debug("[ContextManager] Carioca session key OK"); context.tasSessionKeyVerified = true; } } } } } // Check requestable accessibility requester.checkAccessibility(); // Check requestable access policy requester.checkSecuredConnection(); // Check authenticated context requirement requester.checkAuthenticatedContext(); requester.checkParentContext(); RequestableObject requestedObject = context.requestedObject; String contextResponseExpiryDate = (String) context.get(Parameter.ResponseExpiryDate.getName()); String oldResponseExpiryDate = null; if (contextResponseExpiryDate != null) { oldResponseExpiryDate = requestedObject.getResponseExpiryDate(); requestedObject.setResponseExpiryDate(contextResponseExpiryDate); context.remove(Parameter.ResponseExpiryDate.getName()); } try { if (context.isAsync) { outputDom = JobManager.addJob(cacheManager, requestedObject, requester, context); } else { outputDom = cacheManager.getDocument(requester, context); } } finally { if (oldResponseExpiryDate != null) { requestedObject.setResponseExpiryDate(oldResponseExpiryDate); } } Element documentElement = outputDom.getDocumentElement(); documentElement.setAttribute("version", Version.fullProductVersion); documentElement.setAttribute("context", context.name); documentElement.setAttribute("contextId", context.contextID); DatabaseObject lastDetectedObject = (DatabaseObject) context.lastDetectedObject; if (lastDetectedObject != null) { documentElement.setAttribute("screenclass", lastDetectedObject.getName()); // TODO : // documentElement.setAttribute(lastDetectedObject.getClass().getName().toLowerCase(), // lastDetectedObject.getName()); } context.documentSignatureSent = System.currentTimeMillis(); documentElement.setAttribute("signature", Long.toString(context.documentSignatureSent)); // Add the user reference if any if (context.userReference != null) { documentElement.setAttribute("userReference", context.userReference); } fireDocumentGenerated(new RequestableEngineEvent(outputDom, context.projectName, context.sequenceName, context.connectorName)); } catch (EngineException e) { String message = "[Engine.getDocument()] Context ID#" + context.contextID + " - Unable to build the XML document."; message += "\n[" + e.getClass().getName() + "] " + e.getMessage(); if (System.getProperty("java.specification.version").compareTo("1.4") >= 0) { Throwable eCause = e; while ((eCause = eCause.getCause()) != null) { if (!(eCause instanceof ConvertigoException)) { message += "\n" + Log.getStackTrace(eCause); } else { message += "\n[" + eCause.getClass().getName() + "] " + eCause.getMessage(); } } } Engine.logContext.error(message); // Just re-throw the exception throw (EngineException) e; } catch (Throwable e) { Engine.logEngine.error("Context ID#" + context.contextID + " - An unexpected error has occured while building the XML document.", e); throw new EngineException("An unexpected error has occured while building the XML document." + "Please contact Convertigo support, providing the following information:", e); } finally { if (context.requestedObject != null) { Engine.logContext.debug("Requested object is billable: " + context.requestedObject.isBillable()); if (context.requestedObject.isBillable()) { // Fix regression for Teamlog's billing abortion! // In case of exception thrown, outputDom is Null so use // context.outputDocument! if (context.outputDocument == null) { Engine.logContext.warn("Billing aborted because the generated XML document is null"); } else { String billingClassName = context.getConnector().getBillingClassName(); try { Engine.logContext.debug("Billing class name required: " + billingClassName); AbstractBiller biller = (AbstractBiller) Class.forName(billingClassName).newInstance(); Engine.logContext.debug("Executing the biller"); biller.insertBilling(context); } catch (Throwable e) { Engine.logContext.warn("Unable to execute the biller (the billing is thus ignored): [" + e.getClass().getName() + "] " + e.getMessage()); } } } } context.statistics.stop(t); if (context.requestedObject != null) { try { Engine.theApp.billingManager.insertBilling(context); } catch (Exception e) { Engine.logContext.warn("Unable to insert billing ticket (the billing is thus ignored): [" + e.getClass().getName() + "] " + e.getMessage()); } } Engine.logContext.trace("Engine.getDocument: finished"); } XMLUtils.logXml(outputDom, Engine.logContext, "Generated XML"); return outputDom; } public String checkCariocaSessionKey(Context context, String sKey, String sServiceCode, long idUser, int iDelta) { String sSplit = null; if (sKey == null) return "Carioca session key is null!"; sSplit = Crypto2.decodeFromHexString(sKey); if (sSplit == null) return "Unable to decode the Carioca session key!"; long d; long i; String v; StringTokenizer strtok = new StringTokenizer(sSplit, ";"); if (strtok.hasMoreTokens()) { d = Long.valueOf(strtok.nextToken()).longValue(); Engine.logContext.debug("Engine.checkCariocaSessionKey() d=" + d); long c = System.currentTimeMillis(); Engine.logContext.debug("Engine.checkCariocaSessionKey() c=" + c); if (strtok.hasMoreTokens()) { i = Long.valueOf(strtok.nextToken()).longValue(); Engine.logContext.debug("Engine.checkCariocaSessionKey() i=" + i); if (strtok.hasMoreTokens()) { v = strtok.nextToken(); Engine.logContext.debug("Engine.checkCariocaSessionKey() v=" + v); if (v.equals("#")) v = new String(""); // time expired // if ((d > System.currentTimeMillis()) || // (System.currentTimeMillis() > (d+(iDelta*1000)))) Engine.logContext.debug("Engine.checkCariocaSessionKey() Math.abs(c - d)=" + Math.abs(c - d)); if (Math.abs(c - d) > iDelta * 1000) return "The Carioca session key has expired!"; // check service service if (sServiceCode.compareTo(v) != 0) return "The service code does not match! (expected service code: " + sServiceCode + ")"; if ((idUser != 0) && (idUser != i)) return "The user id does not match!"; return null; } } } return "Wrong Carioca session key format"; } public Document getErrorDocument(Throwable e, Requester requester, Context context) throws Exception { // Generate the XML document for error Document document = buildErrorDocument(e, requester, context); context.outputDocument = document; fireDocumentGenerated(new RequestableEngineEvent(context.outputDocument, context.projectName, context.sequenceName, context.connectorName)); return document; } public static Document buildErrorDocument(Throwable e, Requester requester, Context context) throws Exception { boolean bHide = EnginePropertiesManager.getProperty(PropertyName.HIDING_ERROR_INFORMATION).equals("true"); return ConvertigoError.get(e).buildErrorDocument(requester, context, bHide); } public static String getExceptionSchema() { String exceptionSchema = ""; exceptionSchema += " <xsd:complexType name=\"ConvertigoError\">\n"; exceptionSchema += " <xsd:sequence>\n"; exceptionSchema += " <xsd:element name=\"context\" type=\"p_ns:ConvertigoErrorContext\" />\n"; exceptionSchema += " <xsd:element name=\"exception\" type=\"xsd:string\" />\n"; exceptionSchema += " <xsd:element name=\"message\" type=\"xsd:string\" />\n"; exceptionSchema += " <xsd:element name=\"stacktrace\" type=\"xsd:string\" />\n"; exceptionSchema += " </xsd:sequence>\n"; exceptionSchema += " </xsd:complexType>\n"; exceptionSchema += " <xsd:complexType name=\"ConvertigoErrorContext\">\n"; exceptionSchema += " <xsd:sequence>\n"; exceptionSchema += " <xsd:element name=\"variable\" maxOccurs=\"unbounded\" minOccurs=\"0\" type=\"p_ns:ConvertigoErrorContextVariable\" />\n"; exceptionSchema += " </xsd:sequence>\n"; exceptionSchema += " </xsd:complexType>\n"; exceptionSchema += " <xsd:complexType name=\"ConvertigoErrorContextVariable\">\n"; exceptionSchema += " <xsd:attribute name=\"name\" type=\"xsd:string\" />\n"; exceptionSchema += " <xsd:attribute name=\"value\" type=\"xsd:string\" />\n"; exceptionSchema += " </xsd:complexType>\n"; return exceptionSchema; } public static String getArrayOfSchema(String schemaType) { String arraySchema = ""; arraySchema += "<xsd:complexType name=\"ArrayOf_" + schemaType.replaceAll(":", "_") + "\">\n"; arraySchema += " <xsd:complexContent>\n"; arraySchema += " <xsd:restriction base=\"soapenc:Array\">\n"; arraySchema += " <xsd:attribute ref=\"soapenc:arrayType\" wsdl:arrayType=\"" + schemaType + "[]\"/>\n"; arraySchema += " </xsd:restriction>\n"; arraySchema += " </xsd:complexContent>\n"; arraySchema += "</xsd:complexType>\n"; return arraySchema; } private EventListenerList migrationListeners = new EventListenerList(); public void addMigrationListener(MigrationListener migrationListener) { migrationListeners.add(MigrationListener.class, migrationListener); } public void removeMigrationListener(MigrationListener migrationListener) { migrationListeners.remove(MigrationListener.class, migrationListener); } public void fireProjectMigrated(EngineEvent engineEvent) { // Guaranteed to return a non-null array Object[] listeners = migrationListeners.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == MigrationListener.class) { ((MigrationListener) listeners[i + 1]).projectMigrated(engineEvent); } } } public void fireMigrationFinished(EngineEvent engineEvent) { // Guaranteed to return a non-null array Object[] listeners = migrationListeners.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == MigrationListener.class) { ((MigrationListener) listeners[i + 1]).migrationFinished(engineEvent); } } } private EventListenerList engineListeners = new EventListenerList(); public void addEngineListener(EngineListener engineListener) { engineListeners.add(EngineListener.class, engineListener); } public void removeEngineListener(EngineListener engineListener) { engineListeners.remove(EngineListener.class, engineListener); } public void fireBlocksChanged(EngineEvent engineEvent) { // Guaranteed to return a non-null array Object[] listeners = engineListeners.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == EngineListener.class) { ((EngineListener) listeners[i + 1]).blocksChanged(engineEvent); } } } public void fireObjectDetected(EngineEvent engineEvent) { // Guaranteed to return a non-null array Object[] listeners = engineListeners.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == EngineListener.class) { ((EngineListener) listeners[i + 1]).objectDetected(engineEvent); } } } public void fireDocumentGenerated(EngineEvent engineEvent) { // Guaranteed to return a non-null array Object[] listeners = engineListeners.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == EngineListener.class) { ((EngineListener) listeners[i + 1]).documentGenerated(engineEvent); } } } public void fireStepReached(EngineEvent engineEvent) { // Guaranteed to return a non-null array Object[] listeners = engineListeners.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == EngineListener.class) { ((EngineListener) listeners[i + 1]).stepReached(engineEvent); } } } public void fireTransactionStarted(EngineEvent engineEvent) { // Guaranteed to return a non-null array Object[] listeners = engineListeners.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == EngineListener.class) { ((EngineListener) listeners[i + 1]).transactionStarted(engineEvent); } } } public void fireTransactionFinished(EngineEvent engineEvent) { // Guaranteed to return a non-null array Object[] listeners = engineListeners.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == EngineListener.class) { ((EngineListener) listeners[i + 1]).transactionFinished(engineEvent); } } } public void fireSequenceStarted(EngineEvent engineEvent) { // Guaranteed to return a non-null array Object[] listeners = engineListeners.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == EngineListener.class) { ((EngineListener) listeners[i + 1]).sequenceStarted(engineEvent); } } } public void fireSequenceFinished(EngineEvent engineEvent) { // Guaranteed to return a non-null array Object[] listeners = engineListeners.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == EngineListener.class) { ((EngineListener) listeners[i + 1]).sequenceFinished(engineEvent); } } } public static boolean isCloudMode() { return cloud_customer_name != null; } public static boolean isEngineMode() { return !Engine.isStudioMode(); } public static boolean isStudioMode() { return bStudioMode; } public static void setStudioMode() { Engine.bStudioMode = true; } public static boolean isLinux() { return System.getProperty("os.name").indexOf("Linux") != -1; } }