Package org.jboss.soa.esb.listeners.config

Source Code of org.jboss.soa.esb.listeners.config.ConfigurationController

/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This 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 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.jboss.soa.esb.listeners.config;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javax.xml.transform.stream.StreamSource;

import org.apache.log4j.Logger;
import org.jboss.soa.esb.lifecycle.LifecycleResourceManager;
import org.jboss.soa.esb.listeners.LifecycleUtil;
import org.jboss.soa.esb.listeners.config.model.ModelAdapter;
import org.jboss.soa.esb.listeners.config.model.ModelParser;
import org.jboss.soa.esb.listeners.lifecycle.ManagedLifecycle;
import org.jboss.soa.esb.listeners.lifecycle.ManagedLifecycleController;
import org.jboss.soa.esb.listeners.lifecycle.ManagedLifecycleException;
import org.jboss.soa.esb.parameters.ParamRepositoryFactory;
import org.jboss.soa.esb.parameters.ParamRepositoryException;
import org.jboss.soa.esb.util.ClassUtil;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
* The controller monitors changes in the jbossesb configuration file call jbossesb.xml. When
* changes are detected it validates the XML, and when it passes validation it goes on and
* generates the jbossesb-listener.xml and jbossesb-gateway.xml.
*
* @author kstam
*
*/
public class ConfigurationController implements Runnable
{
  private static final int SLEEP_MILLIS       = 1000; // default interval between parameter reloads
        private static final int ENDED_MILLIS       = 20000; // default interval between parameter reloads
  private static final String JBOSSESB_XSD = "/jbossesb-1.0.1.xsd";
  private static final Logger mLogger = Logger.getLogger(ConfigurationController.class);
        private final Lock endedLock = new ReentrantLock() ;
        private final Condition endedChanged = endedLock.newCondition() ;
        private final Condition endRequested = endedLock.newCondition() ;
  private final String mConfigFileName;
  private final String mConfigName;
  private final String mValidationFileName;
  private final File mConfigDirectory;
        private final String mListenerConfigFile;
        private final String mGatewayConfigFile;
  private long mPreviousFileTimestamp;
  private boolean mIsEndRequested;
  private boolean ended;
    private ManagedLifecycleController controller ;

    /**
   * Start the Controller externally.
   * @param args - arg[0] - the parameter file name
   */
 
  public static void main(String[] args)
  {
    ConfigurationController configurationController = new ConfigurationController(args[0],null);
    configurationController.run();
  }
  /**
   * Construct a Configuration Manager from the named repository based
   * configuration. The default jbossesb-1.0.1.xsd will be used for validation.
   *
   * @param configFileName - Name of the configuration repository.
   *  
   */
  public ConfigurationController(String configFileName)
  {
    this(configFileName, null);
  }
  /**
   * Construct a Configuration Manager from the named repository based
   * configuration.
   *
   * @param configFileName - Name of the configuration repository.
   * @param validationFileName - Name of the file name used for validation (xsd or dtd).
   *  
   */
  public ConfigurationController(String configFileName, String validationFileName)
  {
    mConfigFileName = configFileName;
    File configFile = new File(configFileName);
    final String absolute = configFile.getAbsoluteFile().toURI().getPath() ;
    final int separator = absolute.indexOf(':') ;
    mConfigName = (separator >= 0 ? absolute.substring(separator+1) : absolute) ;
    File parent = configFile.getParentFile();
    mConfigDirectory = (null!=parent) ? parent : new File("");
                final File listenerConfigFile = new File(mConfigDirectory, Generator.ESB_CONFIG_XML_FILE) ;
                mListenerConfigFile = listenerConfigFile.getAbsolutePath() ;
                final File gatewayConfigFile = new File(mConfigDirectory, Generator.ESB_CONFIG_GATEWAY_XML_FILE) ;
                mGatewayConfigFile = gatewayConfigFile.getAbsolutePath() ;
    //Try to obtain a handle to the validation file (xsd)
    if (validationFileName==null) {
      mValidationFileName=JBOSSESB_XSD;
    } else {
      mValidationFileName = validationFileName;
    }

    processConfiguration() ;
  }

    protected String getListenerConfigFile() {
        return mListenerConfigFile;
    }

    protected String getGatewayConfigFile() {
        return mGatewayConfigFile;
    }

    /**
     * Thread that observes the configuration (file). If the configuration is updated it is
     * validated and new set jbossesb-listener.xml and jbossesb-gateway.xml is created for the
     * current server.
     */
   public void run()
  {
    mLogger.info("Configuration Controller instance started.");
    try {
      if (mConfigFileName!=null) {
                                do {
          processConfiguration() ;
        } while(!waitForRequestedEnd(SLEEP_MILLIS)) ;
                                stopController() ;
      } else {
        mLogger.fatal("The name of the configuran file was null: " + mConfigFileName);
      }
    } finally {
            LifecycleResourceManager.getSingleton().cleanupAllResources() ;
      mLogger.info("Exiting Config Controller...");
      setEnded(true) ;
    }
  }

  /**
   * Has the controller instance ended.
   * @return True if this controller instance has ended, otherwise false..
   */
  public boolean hasEnded() {
            endedLock.lock() ;
            try
            {
    return ended ;
            }
            finally
            {
                endedLock.unlock() ;
            }
  }
       
        /**
         * Set the ended flag.
         * @param ended The value of the ended flag.
         */
        private void setEnded(final boolean ended)
        {
            endedLock.lock() ;
            try
            {
                this.ended = ended ;
                endedChanged.signalAll() ;
            }
            finally
            {
                endedLock.unlock() ;
            }
        }
       
        /**
         * Wait until the ended flag has been set.
         * @return true if the ended flag has been set, false otherwise
         */
        public boolean waitUntilEnded()
        {
            return waitUntilEnded(ENDED_MILLIS) ;
        }
       
        /**
         * Wait until the ended flag has been set.
         * @param maxDelay The maximum time to wait for the flag to be set.
         * @return true if the ended flag has been set, false otherwise
         */
        public boolean waitUntilEnded(final long maxDelay)
        {
            final long endTime = System.currentTimeMillis() + maxDelay ;
            endedLock.lock() ;
            try
            {
                try
                {
                    while (!ended)
                    {
                        final long delay = endTime - System.currentTimeMillis() ;
                        if ((delay <= 0) || !endedChanged.await(delay, TimeUnit.MILLISECONDS))
                        {
                            break ;
                        }
                    }
                }
                catch (final InterruptedException ie) {} // ignore
               
                return ended ;
            }
            finally
            {
                endedLock.unlock() ;
            }
        }
       
        /**
         * Wait for a request to end.
         * @param maxDelay The maximum time to wait in milliseconds.
         */
        public boolean waitForRequestedEnd(final long maxDelay)
        {
            final long endTime = System.currentTimeMillis() + maxDelay ;
            endedLock.lock() ;
            try
            {
                try
                {
                    while (!mIsEndRequested)
                    {
                        final long delay = endTime - System.currentTimeMillis() ;
                        if ((delay <= 0) || !endRequested.await(delay, TimeUnit.MILLISECONDS))
                        {
                            break ;
                        }
                    }
                }
                catch (final InterruptedException ie) {} // ignore
               
                return mIsEndRequested ;
            }
            finally
            {
                endedLock.unlock() ;
            }
        }
 
  /**
   * To request the end of processing.
   */
  public void requestEnd()
    {
        endedLock.lock() ;
        try
        {
            mIsEndRequested = true;
            endRequested.signalAll() ;
        }
        finally
        {
            endedLock.unlock() ;
        }
  }
 
  /**
   * Process the configuration.
   */
  private void processConfiguration()
  {
    if (isReloadNeeded()) {
      try {
        StreamSource validationInputSource=null;
        InputStream validationInputStream = ClassUtil.getResourceAsStream(mValidationFileName, getClass());
        //if this fails try using the
        if (validationInputStream==null) {
          File validationFile = new File(mValidationFileName);
          mLogger.debug("Validation file " + mValidationFileName + " exists?:" + validationFile.exists());
          try {
            validationInputStream = new FileInputStream(validationFile);
          } catch (FileNotFoundException e) {
            mLogger.error(e.getMessage(),e);
            throw new IllegalStateException("ESB validation file [" + (new File(mValidationFileName)).getAbsolutePath() + "] not found.", e);
          }
        }
        if (validationInputStream==null) {
          mLogger.warn("Could not obtain validation file " + mValidationFileName);
        } else {
          mLogger.debug("Reading validation info from " + mValidationFileName);
          validationInputSource = new StreamSource(validationInputStream);
        }
       
        mLogger.info("loading configuration..");
        String configXml = ParamRepositoryFactory.getInstance().get(mConfigFileName);
        mLogger.debug("Start validation on configXml=" + configXml);
        if (ModelParser.getParser().validate(new StringReader(configXml))) {
          mLogger.debug("Configuration file " + mConfigFileName + " passed validation. Starting " +
              " the generation process of the jbossesb-listener.xml and the jbossesb-gateway.xml.");
          Generator generator = new Generator(new ByteArrayInputStream(configXml.getBytes()));
          generator.generate(mConfigDirectory);

                    mLogger.info("Parameter reload completed.");
                    stopController() ;

                    // TODO: Get rid of generating config files to disk.  It's nuts.  Use in memory stream buffers!!
                    controller = startController(generator.getModel());
        }
      } catch (Exception e) {
        mLogger.error("The current versions of the jbossesb-listener.xml and/or"
                + " jbossesb-gateway.xml are kept in place until the error is resolved: "
                +  e.getMessage(), e);
      }
    }
  }
 
  public ManagedLifecycleController startController(final ModelAdapter configModel)
      throws ParamRepositoryException, SAXException, ManagedLifecycleException, ConfigurationException
  {
      LifecycleResourceManager.getSingleton().associateDeployment(mConfigName) ;
            return startController(configModel, LifecycleUtil.getConfigTree(mListenerConfigFile), LifecycleUtil.getConfigTree(mGatewayConfigFile)) ;
  }

    public static ManagedLifecycleController startController(ModelAdapter configModel, ConfigTree listenerConfig, ConfigTree gatewayConfig) throws ParamRepositoryException, SAXException, ManagedLifecycleException, ConfigurationException {
        final List<ManagedLifecycle> instances = LifecycleUtil.getListeners(listenerConfig);
        instances.addAll(LifecycleUtil.getGateways(gatewayConfig));

        ManagedLifecycleController lifecycleController = new ManagedLifecycleController(instances);

        try {
            lifecycleController.start();

            // In parallel, create a map of the contract publication info...
            ServicePublisher.addServicePublishers(lifecycleController, configModel.getServicePublishers());
        } catch (final ManagedLifecycleException mle) {
            lifecycleController = null;
            mLogger.error("Unexpected exception starting controller", mle);
        }

        return lifecycleController;
    }

    /**
   * Check the file timestamp and return true when it changes. In other
   * words this only works for files for now.
   *
   * @return true if the file timestamp changed.
   */
  private boolean isReloadNeeded()
  {
    File configFile = new File(mConfigFileName);
    if (configFile.exists()) {
      long currentFileTimestamp = configFile.lastModified();
      if (mPreviousFileTimestamp==0 || currentFileTimestamp > mPreviousFileTimestamp) {
        if (mLogger.isDebugEnabled()) {
          mLogger.debug("The previous timestamp on the file was: " + new Date(mPreviousFileTimestamp)
            + " the new timestamp on the file is: " + new Date(currentFileTimestamp));
        }
        mPreviousFileTimestamp = currentFileTimestamp;
        return true;
      }
    } else {
      mLogger.error("The configuration file " + configFile + " could not be found.");
    }
    return false;
  }
       
        /**
         * Stop the controller if it is active.
         */
        private void stopController()
        {
            stopController(controller);
            LifecycleResourceManager.getSingleton().disassociateDeployment(mConfigFileName) ;
            controller = null ;
        }

    /**
     * Stop the controller if it is active.
     */
    public static void stopController(ManagedLifecycleController lifecycleController) {
        if (lifecycleController != null)
        {
            try
            {
                ServicePublisher.removeServicePublishers(lifecycleController);
                lifecycleController.stop();
            }
            catch (final ManagedLifecycleException mle)
            {
                mLogger.error("Unexpected exception stopping controller", mle) ;
            }
        }
    }
}
TOP

Related Classes of org.jboss.soa.esb.listeners.config.ConfigurationController

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.