Package de.iritgo.aktera.core.container

Source Code of de.iritgo.aktera.core.container.KeelContainer

/**
* This file is part of the Iritgo/Aktera Framework.
*
* Copyright (C) 2005-2011 Iritgo Technologies.
* Copyright (C) 2003-2005 BueroByte GbR.
*
* Iritgo licenses this file to You 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 de.iritgo.aktera.core.container;


import de.iritgo.aktera.util.string.SuperString;
import de.iritgo.simplelife.string.StringTools;
import org.apache.avalon.excalibur.logger.LoggerManager;
import org.apache.avalon.fortress.impl.DefaultContainer;
import org.apache.avalon.fortress.util.ContextManagerConstants;
import org.apache.avalon.fortress.util.OverridableContext;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.logger.LogKitLogger;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Vector;


/**
* This is the top-level container for Keel Framework services. This is
* instantiated by the KeelServer class.
*
* @version        $Revision: 1.2 $        $Date: 2006/10/02 00:15:52 $
* @author Shash Chatterjee
* Created on Oct 17, 2002
*/
public class KeelContainer extends DefaultContainer implements Container
{
  private static Container defaultContainer;

  private Configuration m_configuration;

  private KeelServiceableDelegate svcDelegate;

  private AbstractApplicationContext springApplicationContext;

  private String[] springFileConfigLocations;

  private String[] springClasspathConfigLocations;

  private String[] hibernateConfigLocations;

  private List<Runnable> shutdownHandlers = new LinkedList<Runnable>();

  private LoggerManager loggerManager;

  private Configuration logConfig;

  public Object getService(String role, String hint, Context ctx) throws ServiceException
  {
    return svcDelegate.getService(role, hint, ctx);
  }

  public Object getService(String role, String hint) throws ServiceException
  {
    return svcDelegate.getService(role, hint);
  }

  public Object getService(String role) throws ServiceException
  {
    return svcDelegate.getService(role);
  }

  public Configuration getSysConfig()
  {
    return m_configuration;
  }

  public void release(Object obj)
  {
    if (obj != null)
    {
      synchronized (svcDelegate)
      {
        svcDelegate.releaseService(obj);
      }
    }
  }

  /**
   * @deprecated Use release(Object obj) instead
   */
  public void release(String role, Object obj)
  {
    synchronized (svcDelegate)
    {
      svcDelegate.releaseService(obj);
    }
  }

  /**
   * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
   */
  public void contextualize(Context context) throws ContextException
  {
    //The context passed here is read-only....
    //Wrap it in a writable context we can make read-only later
    super.contextualize(new OverridableContext(context));

    if (defaultContainer == null)
    {
      defaultContainer = this;
    }

    springFileConfigLocations = (String[]) context.get("keel.config.spring.file");
    springClasspathConfigLocations = (String[]) context.get("keel.config.spring.classpath");
    hibernateConfigLocations = (String[]) context.get("keel.config.hibernate");
    loggerManager = (LoggerManager) context.get("keel.loggerManager");
    logConfig = (Configuration) context.get("keel.config.log");
  }

  /**
   * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
   */
  public void configure(Configuration config) throws ConfigurationException
  {
    m_configuration = null;

    Configuration newConfig = handleConditionalConfigs(config);

    try
    {
      super.configure(newConfig);
      m_configuration = newConfig;
    }
    catch (ConfigurationException ce)
    {
      System.err.println("Configuration Exception:");
      ce.printStackTrace(System.err);
      throw ce;
    }

    System.err.println("[KeelContainer] Starting Spring container");

    try
    {
      FileSystemXmlApplicationContext fsxac = (FileSystemXmlApplicationContext) (new FileSystemXmlApplicationContext(
              springFileConfigLocations));

      springApplicationContext = new ClassPathXmlApplicationContext(springClasspathConfigLocations, fsxac);
    }
    catch (Exception x)
    {
      System.err.println("[KeelContainer] Unable to create Spring container: " + x);
    }
  }

  /**
   * This method "prunes" top-level configuration entries (e.g. entries
   * immediately below the "keel" top element in the *-system.xconf file(s).
   * It first reads all the children of an element called "modules". Then
   * it examines each top-level element and looks for an attribute named "if"
   * If this attribute exists, it's value must exist in the list of names
   * in the module list, or that element is "pruned" from the tree.
   */
  private Configuration handleConditionalConfigs(Configuration orig) throws ConfigurationException
  {
    DefaultConfiguration newConfig = new DefaultConfiguration(orig.getName(), orig.getLocation(), orig
            .getNamespace(), "");

    newConfig.addAllAttributes(orig);

    Configuration[] children = orig.getChildren("module");
    Configuration oneChild = null;
    Set moduleList = new HashSet();

    for (int i = 0; i < children.length; i++)
    {
      oneChild = children[i];
      moduleList.add(oneChild.getValue());
    }

    if (moduleList.size() == 0)
    {
      System.err.println("WARNING: There were no modules listed in configuration");
    }

    Configuration[] allChildren = orig.getChildren();
    Configuration aChild = null;

    for (int j = 0; j < allChildren.length; j++)
    {
      aChild = allChildren[j];

      String condition = aChild.getAttribute("if", null);

      if (condition == null)
      {
        newConfig.addChild(aChild);
      }
      else
      {
        if (moduleList.contains(condition))
        {
          newConfig.addChild(aChild);
        }
        else
        {
          System.err.println("[KeelContainer] Configuration " + aChild.getName() + " skipped");
        } /* else */
      } /* else */
    } /* for */
    return newConfig;
  }

  /**
   * Root ServiceManager.  The Container may choose to have it's
   * ServiceManager delegate to the root manager, or it may choose to be
   * entirely self contained.
   */
  public void service(final ServiceManager parent) throws ServiceException
  {
    super.service(parent);

    //m_metaManager = new KeelMetaInfoManager();
    m_serviceManager = new KeelServiceManager(this, parent);

    if (m_context instanceof DefaultContext)
    {
      DefaultContext context = (DefaultContext) m_context;

      context.put(ContextManagerConstants.SERVICE_MANAGER, m_serviceManager);
      context.makeReadOnly();
    }

    svcDelegate = new KeelServiceableDelegate(m_serviceManager);
  }

  public void dispose()
  {
    for (Runnable shutdownHandler : shutdownHandlers)
    {
      try
      {
        shutdownHandler.run();
      }
      catch (Exception x)
      {
        System.err.println("[KeelContainer] Shutdown handler error: " + x);
      }
    }

    if (springApplicationContext != null)
    {
      System.err.println("[KeelContainer] Destroying Spring container");

      springApplicationContext.destroy();
    }

    try
    {
      // Release all serveis acquired for service manager
      svcDelegate.releaseServices();
      // Release all components acquired from container
      super.dispose();
    }
    catch (NullPointerException npe)
    {
      npe.printStackTrace(System.err);
    }
    catch (Throwable t)
    {
      t.printStackTrace(System.err);
    }
  }

  private void dumpConfigInfo(Configuration config) throws ConfigurationException
  {
    System.err.println("-----------------------------------");
    System.err.println("Configuration information dump:");

    ClassLoader loader = this.getClass().getClassLoader();

    System.err.println("Known services in classloader " + loader.toString() + ":");

    int serviceCount = 0;

    try
    {
      Enumeration enumeration = null;

      if (loader instanceof URLClassLoader)
      {
        URLClassLoader ul = (URLClassLoader) loader;

        enumeration = cleanUrlList(ul.findResources("services.list"));
      }
      else
      {
        enumeration = cleanUrlList(loader.getResources("services.list"));
      }

      while (enumeration.hasMoreElements())
      {
        serviceCount++;

        URL serviceList = (URL) enumeration.nextElement();

        processServiceList(serviceList, loader);
      }

      if (serviceCount == 0)
      {
        System.err
                .println("WARNING! There were no services listed, or no services.list resources found in the classpath");
        System.err.println("This indicates a bad build process, unless you are using roles.xconf exclusively,");
        System.err.println("Or a problem with the classloader.getResources() in this implementation.");

        if (loader instanceof URLClassLoader)
        {
          URLClassLoader ul = (URLClassLoader) loader;

          try
          {
            Enumeration e2 = ul.findResources("services.list");

            if (e2.hasMoreElements())
            {
              System.err
                      .println("NOTE: findResources found services.list entries - so this is probably a classloader issue");
            }
          }
          catch (Exception e)
          {
            e.printStackTrace(System.err);
          }
        }
      }

      //String serviceName = (String) enumeration.nextElement();
      //System.err.println("Service name: '" + serviceName + "'");
      Configuration[] allConfigs = config.getChildren();

      System.err.println("There are " + allConfigs.length + " elements to verify");

      for (int i = 0; i < allConfigs.length; i++)
      {
        Configuration oneConfig = allConfigs[i];

        System.err.println("Element '" + oneConfig.getName() + "'");
      }
    }
    catch (Exception ee)
    {
      ee.printStackTrace(System.err);
      throw new ConfigurationException("Unable to verify configuration");
    }
  }

  private void metaFailed() throws ConfigurationException
  {
    System.err
            .println("This probably means the meta collection process did not complete successfully on this application");
    System.err.println("Try doing an 'ant clean' (on this application) and a new assemble-deploy");
    throw new ConfigurationException("Can't verify configuration");
  }

  private void processServiceList(URL serviceList, ClassLoader loader) throws Exception
  {
    System.err.println("Resource '" + serviceList.toString() + "' contains these services:");

    InputStream serviceListStream = serviceList.openStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(serviceListStream));

    List entryList = new ArrayList();
    String oneEntry = reader.readLine();

    while (oneEntry != null)
    {
      entryList.add(oneEntry);

      oneEntry = reader.readLine();
    }

    reader.close();
    serviceListStream.close();

    for (Iterator i = entryList.iterator(); i.hasNext();)
    {
      processOneServiceEntry((String) i.next(), serviceList, loader);
    }
  }

  private void processOneServiceEntry(String oneEntry, URL serviceList, ClassLoader loader) throws Exception
  {
    System.err.println("\tRole:" + oneEntry);

    /* For this entry, there should be a META-INF/services/xxx" */
    /* file which lists the implementations of this service in this jar */
    StringTokenizer stk = new StringTokenizer(serviceList.toString(), "!");
    String jarFile = stk.nextToken();

    //System.err.println("Jar file is " + jarFile);
    URL theRightServiceEntry = null;
    Enumeration eachServicesEntry = null;

    if (loader instanceof URLClassLoader)
    {
      URLClassLoader ul = (URLClassLoader) loader;

      eachServicesEntry = ul.findResources("META-INF/services/" + oneEntry);
    }
    else
    {
      eachServicesEntry = cleanUrlList(loader.getResources("META-INF/services/" + oneEntry));
    }

    while (eachServicesEntry.hasMoreElements())
    {
      URL thisServiceEntry = (URL) eachServicesEntry.nextElement();
      StringTokenizer stk2 = new StringTokenizer(thisServiceEntry.toString(), "!");
      String thisJar = stk2.nextToken();

      if (thisJar.equals(jarFile))
      {
        /* We've found the right one */
        theRightServiceEntry = thisServiceEntry;
      }
    }

    if (theRightServiceEntry == null)
    {
      /* Check roles.xconf */
      System.err.println("WARNING: No such file as /META-INF/services/" + oneEntry + " in " + jarFile
              + ". This component's role implementations must be defined in roles.xconf");
    }
    else
    {
      processImplementationList(theRightServiceEntry, jarFile);
    }
  }

  private void processImplementationList(URL theRightServiceEntry, String jarFile) throws Exception
  {
    /* Now read that list */
    InputStream serviceEntryStream = theRightServiceEntry.openStream();
    BufferedReader reader2 = new BufferedReader(new InputStreamReader(serviceEntryStream));
    String oneImplClass = reader2.readLine();

    while (oneImplClass != null)
    {
      System.err.println("\t\t\tClass:" + oneImplClass);

      /* Now verify that the meta-info for that class can be located (e.g. the .meta file resource) */
      String metaName = SuperString.replace(oneImplClass, ".", "/") + ".meta";
      URL metaUrl = this.getClass().getClassLoader().getResource(metaName);

      if (metaUrl == null)
      {
        System.err.println("FATAL: No such file as " + metaName + " in jar file " + jarFile);
        metaFailed();
      }

      //BufferedReader metaReader =
      //  new BufferedReader(new InputStreamReader(metaUrl.openStream()));
      /* Now read the meta file */
      Properties p = new Properties();
      InputStream metaUrlStream = metaUrl.openStream();

      p.load(metaUrlStream);
      metaUrlStream.close();
      System.err.print("\t\t\tProperties list for " + metaName + " [");

      for (Iterator i = p.keySet().iterator(); i.hasNext();)
      {
        String key = (String) i.next();

        System.err.print(key + "=" + p.getProperty(key) + ",");
      }

      System.err.println("]");

      /* Now verify that that class can be found */
      this.getClass().getClassLoader().loadClass(oneImplClass);

      /* Keep a list of all mappings between short names/ids and classes */
      oneImplClass = reader2.readLine();
    }

    reader2.close();
    serviceEntryStream.close();
  }

  public Enumeration cleanUrlList(Enumeration originalURLs)
  {
    Vector v = new Vector();
    int origSize = 0;
    int valids = 0;
    ClassLoader l = getClass().getClassLoader();

    if (l instanceof URLClassLoader)
    {
      URLClassLoader ul = (URLClassLoader) l;
      URL[] validUrls = ul.getURLs();

      if (validUrls.length == 0)
      {
        return originalURLs;
      }

      while (originalURLs.hasMoreElements())
      {
        origSize++;

        URL oneURL = (URL) originalURLs.nextElement();
        StringTokenizer stk = new StringTokenizer(oneURL.getFile(), "!");
        String checkUrl = stk.nextToken();

        for (int i = 0; i < validUrls.length; i++)
        {
          if (validUrls[i].toString().equals(checkUrl))
          {
            v.addElement(oneURL);
            valids++;
          }
        }
      }
    }
    else
    {
      throw new IllegalArgumentException("Using a " + l.getClass().getName());
    }

    return v.elements();
  }

  /**
   * @see de.iritgo.aktera.core.container.Container#getSystemConfig()
   */
  public Configuration getSystemConfig() throws ConfigurationException
  {
    return m_configuration;
  }

  /**
   * Get the default container. This will be the first initialized container.
   * Since we use only exactly one container, we can be shure to always get
   * the same container from this method.
   */
  public static Container defaultContainer()
  {
    return defaultContainer;
  }

  /**
   * Get a Spring bean from the Spring container.
   *
   * @param name The name of the Spring bean.
   * @return The Spring bean.
   * @throws BeansException If the bean cannot be retrieved.
   */
  public Object getSpringBean(String name) throws BeansException
  {
    if (springApplicationContext != null)
    {
      return springApplicationContext.getBean(name);
    }
    else
    {
      return null;
    }
  }

  /**
   * @return
   */
  public ConfigurableBeanFactory getSpringBeanFactory()
  {
    return springApplicationContext.getBeanFactory();
  }

  public String[] getHibernateConfigLocations()
  {
    return hibernateConfigLocations;
  }

  public void addShutdownHandler(Runnable shutdownHandler)
  {
    shutdownHandlers.add(shutdownHandler);
  }

  public Logger getLogger(String category)
  {
    return loggerManager.getLoggerForCategory(category);
  }

  public void setLogLevel(String logLevel)
  {
    for (Configuration categoryConfigs : logConfig.getChild("categories").getChildren("category"))
    {
      setLogLevel(logLevel, categoryConfigs.getAttribute("name", ""));
    }
  }

  public void setLogLevel(String logLevel, String category)
  {
    if (StringTools.isTrimEmpty(category) || category.startsWith("system") || category.startsWith("keel")
            || category.startsWith("console"))
    {
      return;
    }

    Logger logger = loggerManager.getLoggerForCategory(category);

    if (logger != null && logger.getClass().equals(LogKitLogger.class))
    {
      for (Field field : LogKitLogger.class.getDeclaredFields())
      {
        if ("m_logger".equals(field.getName()))
        {
          try
          {
            field.setAccessible(true);

            Object apacheLogger = field.get(logger);

            if (apacheLogger != null && apacheLogger.getClass().equals(org.apache.log.Logger.class))
            {
              ((org.apache.log.Logger) apacheLogger).setPriority(org.apache.log.Priority
                      .getPriorityForName(logLevel));
            }
          }
          catch (IllegalArgumentException x)
          {
          }
          catch (IllegalAccessException x)
          {
          }
        }
      }
    }
  }
}
TOP

Related Classes of de.iritgo.aktera.core.container.KeelContainer

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.