Package org.openbp.server

Source Code of org.openbp.server.ProcessServer

/*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*   limitations under the License.
*/
package org.openbp.server;

import java.util.Iterator;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.openbp.common.application.Application;
import org.openbp.common.generic.msgcontainer.MsgItem;
import org.openbp.common.generic.msgcontainer.StandardMsgContainer;
import org.openbp.common.logger.LogUtil;
import org.openbp.core.CoreModule;
import org.openbp.core.OpenBPException;
import org.openbp.core.engine.EngineException;
import org.openbp.core.model.Model;
import org.openbp.core.remote.ClientConnectionInfo;
import org.openbp.server.context.TokenContextService;
import org.openbp.server.engine.Engine;
import org.openbp.server.engine.EngineRunner;
import org.openbp.server.engine.debugger.Debugger;
import org.openbp.server.remote.RemoteConnectorServer;
import org.openbp.server.scheduler.ProcessScheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

/**
* This class is the main anchor point of an OpenBP server.
* It performs all server startup and shutdown tasks.
* Note that you must call the {@link #initialize} method before you can request any services from the server.
*
* @author Heiko Erhardt
*/
@Service("processServer")
public class ProcessServer extends CoreModule
    implements ApplicationContextAware
{
  // Components configured by Spring

  /** Classpath name of the server's properties resource or null */
  private String propertiesResourceName = "OpenBP-Server.properties";

  @Autowired
  private ProcessFacade processFacade;

  @Autowired
  private Engine engine;

  @Autowired
  private EngineRunner engineRunner;

  @Autowired
  private TokenContextService tokenContextService;

  @Autowired
  private Debugger debugger;

  @Autowired(required=false)
  private ProcessScheduler processScheduler;

  @Autowired @Qualifier("exportedService")
  private List<Object> services;

  private ClientConnectionInfo connectionInfo;

  private RemoteConnectorServer remoteConnectorServer;

  /** Spring application context if the process server was instantiated by the Spring framework */
  private ApplicationContext applicationContext;

  private volatile boolean initialized;
  private volatile boolean initializing;

  /**
   * Constructor to be used by the Spring framework only, class needs to be autowired.
   * You might also use the {@link ProcessServerFactory} for construction.
   */
  public ProcessServer()
  {
  }

  /**
   * Initializes the server.
   * Call this method before requesting any services from the core.
     * This method will also be called from the IoC container that supports the JSR 250 @PostConstruct annotation.
   *
   * @throws OpenBPException On severe error
   */
  @PostConstruct
  public synchronized void initialize()
  {
    if (! initialized && ! initializing)
    {
      synchronized(this)
      {
        if (! initialized && ! initializing)
        {
          try
          {
            // To prevent endless recursion by calling initialize() from within some getters below
            initializing = true;

            determineRootDir();
            if (propertiesResourceName != null)
            {
              Application.registerPropertyResource(propertiesResourceName, 80, false);
            }

            // Perform the core initialization
            super.initialize();

            // Reads all models
            initModels();

            // Initialize the remote services
            initRemoting();

            // Initialize the engine
            tokenContextService.initialize();
            if (debugger != null)
            {
              debugger.initialize();
            }
            if (getEngineRunner() != null)
            {
              getEngineRunner().initialize();
            }

            initialized = true;
          }
          finally
          {
            initializing = false;
          }
        }
      }
    }
  }

  /**
   * Initializes the model manager.
   *
   * @throws OpenBPException On error
   */
  private void initModels()
  {
    LogUtil.info(getClass(), "Loading models...");

    // Read all models
    getModelMgr().readModels();

    // Initialize the models
    getModelMgr().initializeModels();

    // Print any errors to stderr
    StandardMsgContainer msgContainer = getModelMgr().getMsgContainer();
    for (Iterator it = msgContainer.getMsgs(); it.hasNext();)
    {
      MsgItem msgItem = (MsgItem) it.next();
      LogUtil.error(getClass(), msgItem.getFormattedMsgWithSource());
    }
    msgContainer.clearMsgs();

    LogUtil.info(getClass(), "Model load complete.");
  }

  /**
   * Registers the services and start up the RMI registry.
   *
   * @throws OpenBPException On error
   */
  private void initRemoting()
  {
    if (services == null)
    {
      // No services to publish
      return;
    }

    try
    {
      // Determine remote connection properties
      if (connectionInfo == null)
      {
        // Load connection info from properties file if not specified in the Spring config file
        connectionInfo = new ClientConnectionInfo();
        connectionInfo.loadFromProperties();
      }

      // Make the remote connector known to the RMI registry
      if (connectionInfo.isEnabled())
      {
        remoteConnectorServer = new RemoteConnectorServer();

        for (Iterator it = services.iterator(); it.hasNext();)
        {
          remoteConnectorServer.registerService(it.next());
        }

        remoteConnectorServer.setConnectionInfo(connectionInfo);
        remoteConnectorServer.bindToRegistry();
      }
    }
    catch (Exception e)
    {
      throw new EngineException("Initialization", "Error initializing services.", e);
    }
  }

  /**
   * Performs shutdown of the process server using a 60 second timeout.
   *
   * Calls shutdownModel for each loaded model.
   */
  @PreDestroy
  public boolean shutdown()
  {
    return shutdown(60000L);
  }

  /**
   * Performs shutdown of the process server.
   * Before the server shutdown, the engine runner (if present) will be shut down (see {@link EngineRunner#waitForStop}).
   * Also calls {@link Model#shutdownModel} for each loaded model.
   * The method will ignore any exception, however, they will be logged.
   *
   * @param timeoutMS Timeout in milliseconds for the engine runner shutdown.
   * If this value is 0, the method will just check if everything has completed, but will not wait for any processes.
   * If this value is -1, no timeout will apply (i. e. the method will definately wait
   * until all context executions have finished).
   * @return true if no context is currently executing and there were no exceptions during shutdown,
   * false if either the engine runner shutdown timeout has elapsed or there have been exceptions during the shutdown.
   */
  public boolean shutdown(long timeoutMS)
  {
    boolean ret = true;

    if (initialized)
    {
      synchronized (this)
      {
        if (initialized)
        {
          LogUtil.info(getClass(), "Shutting down the OpenBP engine...");

          try
          {
            if (getEngineRunner() != null)
            {
              ret = getEngineRunner().waitForStop(timeoutMS);
              getEngineRunner().shutdown();
            }
            if (debugger != null)
            {
              debugger.shutdown();
            }
            tokenContextService.shutdown();

            if (remoteConnectorServer != null)
            {
              try
              {
                remoteConnectorServer.unbindFromRegistry();
              }
              catch (Exception e)
              {
                // Ignore errors when unbinding, we are shutting down anyway
                // We also don't log this one.
                ret = false;
              }
              remoteConnectorServer = null;
            }

            // Shutdown all models
            for (Iterator it = getModelMgr().getModels().iterator(); it.hasNext();)
            {
              Model model = (Model) it.next();
              try
              {
                model.shutdownModel();
              }
              catch (Exception e)
              {
                LogUtil.error(getClass(), "Error during shutdown of model $0", model.getQualifier(), e);
                ret = false;
              }
            }

            super.shutdown();
          }
          catch (Exception e)
          {
            LogUtil.error(getClass(), "Error during OpenBP engine shutdown.", e);
            ret = false;
          }
          finally
          {
            LogUtil.info(getClass(), "OpenBP engine shutdown complete.");

            initialized = false;
          }
        }
      }
    }

    return ret;
  }

  /**
     * Implementation of the ApplicationContextAware interface.
     * See org.springframework.context.ApplicationContextAware.
     * Called by the Spring framework after bean construction.
   *
   * @param applicationContext Spring application context the process server was instantiated by the Spring framework
   */
  public void setApplicationContext(ApplicationContext applicationContext)
  {
    this.applicationContext = applicationContext;
  }

  /**
   * Gets the spring application context if the process server was instantiated by the Spring framework.
   */
  public ApplicationContext getApplicationContext()
  {
    return applicationContext;
  }

  /**
   * Sets the classpath name of the server's properties resource.
   * @param propertiesResourceName Resource name or null (default: "OpenBP-Server.properties")
   */
  public void setPropertiesResourceName(String propertiesResourceName)
  {
    this.propertiesResourceName = propertiesResourceName;
  }

  /**
   * Gets the process facade.
   */
  public ProcessFacade getProcessFacade()
  {
    initialize();
    return processFacade;
  }

  /**
   * Sets the process facade.
   */
  public void setProcessFacade(ProcessFacade processFacade)
  {
    this.processFacade = processFacade;
  }

  /**
   * Gets the engine.
   */
  public Engine getEngine()
  {
    initialize();
    return engine;
  }

  /**
   * Sets the engine.
   */
  public void setEngine(Engine engine)
  {
    this.engine = engine;
  }

  /**
   * Gets the engine runner.
   */
  public EngineRunner getEngineRunner()
  {
    initialize();
    return engineRunner;
  }

  /**
   * Sets the engine runner.
   */
  public void setEngineRunner(EngineRunner engineRunner)
  {
    this.engineRunner = engineRunner;
  }

  /**
   * Gets the token context service.
   */
  public TokenContextService getTokenContextService()
  {
    initialize();
    return tokenContextService;
  }

  /**
   * Sets the token context service.
   */
  public void setTokenContextService(TokenContextService tokenContextService)
  {
    this.tokenContextService = tokenContextService;
  }

  /**
   * Gets the process scheduler.
   */
  public ProcessScheduler getProcessScheduler()
  {
    initialize();
    return processScheduler;
  }

  /**
   * Sets the process scheduler.
   */
  public void setProcessScheduler(ProcessScheduler processScheduler)
  {
    this.processScheduler = processScheduler;
  }

  /**
   * Sets the list of service implementations.
   */
  public void setServices(List services)
  {
    this.services = services;
  }

  /**
   * Sets the connection info.
   */
  public void setConnectionInfo(ClientConnectionInfo connectionInfo)
  {
    this.connectionInfo = connectionInfo;
  }
}
TOP

Related Classes of org.openbp.server.ProcessServer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.