[exo-jcr-commits] exo-jcr SVN: r4021 - jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp and 3 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Fri Feb 25 15:24:28 EST 2011


Author: nfilotto
Date: 2011-02-25 15:24:27 -0500 (Fri, 25 Feb 2011)
New Revision: 4021

Added:
   kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/LifecycleVisitor.java
Modified:
   jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/proccess/WorkerService.java
   jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/FtpServerImpl.java
   kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/ConcurrentPicoContainer.java
   kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/ExoContainer.java
   kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/web/PortalContainerCreator.java
   kernel/trunk/exo.kernel.container/src/test/java/org/exoplatform/container/TestExoContainer.java
Log:
EXOJCR-1213: Thanks to this patch if an error occurs in the stop or dispose methods, the error will be logged with the debug level, such that we are sure that the stop and dispose methods will be called on all components. This patch also stops the RootContainer on context destroy of the starter.war, it is necessary since the shutdown hooks are not triggered on tomcat stop command. And finally this patch convert the FtpServer and the WorkerService into daemon to avoid blocking the JVM to stop normally.

Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/proccess/WorkerService.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/proccess/WorkerService.java	2011-02-25 14:56:08 UTC (rev 4020)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/proccess/WorkerService.java	2011-02-25 20:24:27 UTC (rev 4021)
@@ -79,7 +79,7 @@
     */
    public WorkerService(int threadCount)
    {
-      executor = new ScheduledThreadPoolExecutor(threadCount);
+      this(threadCount, "pool");
    }
 
    /**
@@ -90,7 +90,7 @@
     */
    public WorkerService(int threadCount, String threadNamePrefix)
    {
-      executor = new ScheduledThreadPoolExecutor(threadCount, new WorkerThreadFactory(threadNamePrefix));
+      this(threadCount, threadNamePrefix, true);
    }
 
    /**

Modified: jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/FtpServerImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/FtpServerImpl.java	2011-02-25 14:56:08 UTC (rev 4020)
+++ jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/FtpServerImpl.java	2011-02-25 20:24:27 UTC (rev 4021)
@@ -219,6 +219,7 @@
       {
          this.ftpServer = ftpServer;
          this.serverSocket = serverSocket;
+         setDaemon(true);
       }
 
       public void disable()

Modified: kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/ConcurrentPicoContainer.java
===================================================================
--- kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/ConcurrentPicoContainer.java	2011-02-25 14:56:08 UTC (rev 4020)
+++ kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/ConcurrentPicoContainer.java	2011-02-25 20:24:27 UTC (rev 4021)
@@ -35,7 +35,6 @@
 import org.picocontainer.defaults.DefaultPicoContainer;
 import org.picocontainer.defaults.DuplicateComponentKeyRegistrationException;
 import org.picocontainer.defaults.InstanceComponentAdapter;
-import org.picocontainer.defaults.LifecycleVisitor;
 import org.picocontainer.defaults.VerifyingVisitor;
 
 import java.io.Serializable;
@@ -460,6 +459,30 @@
    }
 
    /**
+    * Indicates whether or not the container can be started
+    */
+   protected boolean canBeStarted()
+   {
+      return !disposed.get() && !started.get();
+   }
+
+   /**
+    * Indicates whether or not the container can be stopped
+    */
+   protected boolean canBeStopped()
+   {
+      return !disposed.get() && started.get();
+   }
+
+   /**
+    * Indicates whether or not the container can be disposed
+    */
+   protected boolean canBeDisposed()
+   {
+      return !disposed.get();
+   }
+   
+   /**
     * Start the components of this PicoContainer and all its logical child containers.
     * Any component implementing the lifecycle interface {@link org.picocontainer.Startable} will be started.
     * @see #makeChildContainer()
@@ -468,7 +491,7 @@
     */
    public void start()
    {
-      if (disposed.get() || started.get())
+      if (!canBeStarted())
          return;
       LifecycleVisitor.start(this);
       started.set(true);
@@ -483,7 +506,7 @@
     */
    public void stop()
    {
-      if (disposed.get() || !started.get())
+      if (!canBeStopped())
          return;
       LifecycleVisitor.stop(this);
       started.set(false);
@@ -498,7 +521,7 @@
     */
    public void dispose()
    {
-      if (disposed.get())
+      if (!canBeDisposed())
          return;
       LifecycleVisitor.dispose(this);
       disposed.set(true);

Modified: kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/ExoContainer.java
===================================================================
--- kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/ExoContainer.java	2011-02-25 14:56:08 UTC (rev 4020)
+++ kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/ExoContainer.java	2011-02-25 20:24:27 UTC (rev 4021)
@@ -188,21 +188,24 @@
    }
 
    @Override
-   public void dispose()
+   public synchronized void dispose()
    {
       SecurityManager security = System.getSecurityManager();
       if (security != null)
          security.checkPermission(ContainerPermissions.MANAGE_CONTAINER_PERMISSION);
       
-      destroyContainerInternal();
-      super.dispose();
+      if (canBeDisposed())
+      {
+         destroyContainerInternal();
+         super.dispose();         
+      }
    }
 
    /**
     * Starts the container
     * @param init indicates if the container must be initialized first
     */
-   public void start(boolean init)
+   public synchronized void start(boolean init)
    {
       SecurityManager security = System.getSecurityManager();
       if (security != null)
@@ -217,24 +220,31 @@
    }
    
    @Override
-   public void start()
+   public synchronized void start()
    {
       SecurityManager security = System.getSecurityManager();
       if (security != null)
          security.checkPermission(ContainerPermissions.MANAGE_CONTAINER_PERMISSION);
-      super.start();
-      startContainerInternal();
+      
+      if (canBeStarted())
+      {
+         super.start();
+         startContainerInternal();         
+      }
    }
 
    @Override
-   public void stop()
+   public synchronized void stop()
    {
       SecurityManager security = System.getSecurityManager();
       if (security != null)
          security.checkPermission(ContainerPermissions.MANAGE_CONTAINER_PERMISSION);
       
-      stopContainerInternal();
-      super.stop();
+      if (canBeStopped())
+      {
+         stopContainerInternal();
+         super.stop();         
+      }
    }
 
    /**

Added: kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/LifecycleVisitor.java
===================================================================
--- kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/LifecycleVisitor.java	                        (rev 0)
+++ kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/LifecycleVisitor.java	2011-02-25 20:24:27 UTC (rev 4021)
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * 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.exoplatform.container;
+
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+import org.picocontainer.ComponentAdapter;
+import org.picocontainer.Disposable;
+import org.picocontainer.Parameter;
+import org.picocontainer.PicoContainer;
+import org.picocontainer.PicoIntrospectionException;
+import org.picocontainer.Startable;
+import org.picocontainer.defaults.AbstractPicoVisitor;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:nicolas.filotto at exoplatform.com">Nicolas Filotto</a>
+ * @version $Id$
+ */
+public class LifecycleVisitor extends AbstractPicoVisitor
+{
+
+   private static final Log LOG = ExoLogger.getLogger("exo.kernel.container.LifecycleVisitor");
+
+   private static final Method START;
+
+   private static final Method STOP;
+
+   private static final Method DISPOSE;
+   static
+   {
+      try
+      {
+         START = Startable.class.getMethod("start", (Class<?>[])null);
+         STOP = Startable.class.getMethod("stop", (Class<?>[])null);
+         DISPOSE = Disposable.class.getMethod("dispose", (Class<?>[])null);
+      }
+      catch (NoSuchMethodException e)
+      {
+         throw new InternalError(e.getMessage());
+      }
+   }
+
+   private final Method method;
+
+   private final Class<?> type;
+
+   private final boolean visitInInstantiationOrder;
+
+   private final List componentInstances;
+
+   private final boolean ignoreError;
+
+   public LifecycleVisitor(Method method, Class<?> ofType, boolean visitInInstantiationOrder, boolean ignoreError)
+   {
+      this.method = method;
+      this.type = ofType;
+      this.visitInInstantiationOrder = visitInInstantiationOrder;
+      this.componentInstances = new ArrayList();
+      this.ignoreError = ignoreError;
+   }
+
+   public Object traverse(Object node)
+   {
+      componentInstances.clear();
+      try
+      {
+         super.traverse(node);
+         if (!visitInInstantiationOrder)
+         {
+            Collections.reverse(componentInstances);
+         }
+         for (Iterator iterator = componentInstances.iterator(); iterator.hasNext();)
+         {
+            Object o = iterator.next();
+            try
+            {
+               method.invoke(o, (Object[])null);
+            }
+            catch (IllegalArgumentException e)
+            {
+               if (ignoreError)
+               {
+                  if (LOG.isDebugEnabled())
+                  {
+                     LOG.debug("Can't call " + method.getName() + " on " + o, e);
+                  }
+                  continue;
+               }
+               throw new PicoIntrospectionException("Can't call " + method.getName() + " on " + o, e);
+            }
+            catch (IllegalAccessException e)
+            {
+               if (ignoreError)
+               {
+                  if (LOG.isDebugEnabled())
+                  {
+                     LOG.debug("Can't call " + method.getName() + " on " + o, e);
+                  }
+                  continue;
+               }
+               throw new PicoIntrospectionException("Can't call " + method.getName() + " on " + o, e);
+            }
+            catch (InvocationTargetException e)
+            {
+               if (ignoreError)
+               {
+                  if (LOG.isDebugEnabled())
+                  {
+                     LOG.debug("Failed when calling " + method.getName() + " on " + o, e.getTargetException());
+                  }
+                  continue;
+               }
+               throw new PicoIntrospectionException("Failed when calling " + method.getName() + " on " + o,
+                  e.getTargetException());
+            }
+         }
+      }
+      finally
+      {
+         componentInstances.clear();
+      }
+      return Void.TYPE;
+   }
+
+   public void visitContainer(PicoContainer pico)
+   {
+      checkTraversal();
+      componentInstances.addAll(pico.getComponentInstancesOfType(type));
+   }
+
+   public void visitComponentAdapter(ComponentAdapter componentAdapter)
+   {
+      checkTraversal();
+   }
+
+   public void visitParameter(Parameter parameter)
+   {
+      checkTraversal();
+   }
+
+   /**
+    * Invoke the standard PicoContainer lifecycle for {@link Startable#start()}.
+    * @param node The node to start the traversal.
+    */
+   public static void start(Object node)
+   {
+      new LifecycleVisitor(START, Startable.class, true, false).traverse(node);;
+   }
+
+   /**
+    * Invoke the standard PicoContainer lifecycle for {@link Startable#stop()}.
+    * @param node The node to start the traversal.
+    */
+   public static void stop(Object node)
+   {
+      new LifecycleVisitor(STOP, Startable.class, false, true).traverse(node);;
+   }
+
+   /**
+    * Invoke the standard PicoContainer lifecycle for {@link Disposable#dispose()}.
+    * @param node The node to start the traversal.
+    */
+   public static void dispose(Object node)
+   {
+      new LifecycleVisitor(DISPOSE, Disposable.class, false, true).traverse(node);;
+   }
+
+}

Modified: kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/web/PortalContainerCreator.java
===================================================================
--- kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/web/PortalContainerCreator.java	2011-02-25 14:56:08 UTC (rev 4020)
+++ kernel/trunk/exo.kernel.container/src/main/java/org/exoplatform/container/web/PortalContainerCreator.java	2011-02-25 20:24:27 UTC (rev 4021)
@@ -45,6 +45,16 @@
     */
    public void contextDestroyed(ServletContextEvent event)
    {
+      SecurityHelper.doPrivilegedAction(new PrivilegedAction<Void>()
+      {
+         public Void run()
+         {
+            // Ensure that the root container is stopped properly since the shutdown hook
+            // doesn't work in some cases for example with tomcat when we call the stop command
+            RootContainer.getInstance().stop();
+            return null;
+         }
+      });
    }
 
    /**

Modified: kernel/trunk/exo.kernel.container/src/test/java/org/exoplatform/container/TestExoContainer.java
===================================================================
--- kernel/trunk/exo.kernel.container/src/test/java/org/exoplatform/container/TestExoContainer.java	2011-02-25 14:56:08 UTC (rev 4020)
+++ kernel/trunk/exo.kernel.container/src/test/java/org/exoplatform/container/TestExoContainer.java	2011-02-25 20:24:27 UTC (rev 4021)
@@ -22,6 +22,7 @@
 import org.exoplatform.container.support.ContainerBuilder;
 import org.exoplatform.container.xml.InitParams;
 import org.picocontainer.ComponentAdapter;
+import org.picocontainer.Disposable;
 import org.picocontainer.PicoContainer;
 import org.picocontainer.PicoInitializationException;
 import org.picocontainer.PicoIntrospectionException;
@@ -669,5 +670,170 @@
       public void stop()
       {         
       }
-   }   
+   }
+   
+   public void testLifeCycle() throws Throwable
+   {
+      ConcurrentPicoContainer container = new ConcurrentPicoContainer();
+      assertTrue(container.canBeStarted());
+      assertFalse(container.canBeStopped());
+      assertTrue(container.canBeDisposed());
+      container.registerComponentImplementation(LC1.class);
+      container.registerComponentImplementation(LC2.class);
+      container.registerComponentImplementation(LC3.class);
+      container.registerComponentImplementation(LC4.class);
+      container.registerComponentImplementation(LC5.class);
+      try
+      {
+         container.start();
+         fail("Should fail due to the start method of C1");
+      }
+      catch (Exception e)
+      {
+         // igonre me
+      }
+      LC1 c1 = (LC1)container.getComponentInstanceOfType(LC1.class);
+      LC2 c2 = (LC2)container.getComponentInstanceOfType(LC2.class);
+      LC3 c3 = (LC3)container.getComponentInstanceOfType(LC3.class);
+      LC4 c4 = (LC4)container.getComponentInstanceOfType(LC4.class);
+      LC5 c5 = (LC5)container.getComponentInstanceOfType(LC5.class);
+      assertFalse(c2.started && c3.started && c4.started);
+      assertTrue(container.canBeStarted());
+      assertFalse(container.canBeStopped());
+      assertTrue(container.canBeDisposed());
+      container.stop();
+      assertTrue(container.canBeStarted());
+      assertFalse(container.canBeStopped());
+      assertTrue(container.canBeDisposed());
+      container.dispose();
+      assertTrue(c1.disposed && c2.disposed && c5.disposed);
+      assertFalse(container.canBeStarted());
+      assertFalse(container.canBeStopped());
+      assertFalse(container.canBeDisposed());
+      container = new ConcurrentPicoContainer();
+      assertTrue(container.canBeStarted());
+      assertFalse(container.canBeStopped());
+      assertTrue(container.canBeDisposed());
+      container.registerComponentImplementation(LC2.class);
+      container.registerComponentImplementation(LC3.class);
+      container.registerComponentImplementation(LC4.class);
+      container.registerComponentImplementation(LC5.class);
+      container.start();
+      c2 = (LC2)container.getComponentInstanceOfType(LC2.class);
+      c3 = (LC3)container.getComponentInstanceOfType(LC3.class);
+      c4 = (LC4)container.getComponentInstanceOfType(LC4.class);
+      assertTrue(c2.started && c3.started && c4.started);
+      assertFalse(container.canBeStarted());
+      assertTrue(container.canBeStopped());
+      assertTrue(container.canBeDisposed());
+      container.stop();
+      assertTrue(container.canBeStarted());
+      assertFalse(container.canBeStopped());
+      assertTrue(container.canBeDisposed());
+      container.dispose();
+      assertTrue(c1.disposed && c2.disposed && c5.disposed);      
+      assertFalse(container.canBeStarted());
+      assertFalse(container.canBeStopped());
+      assertFalse(container.canBeDisposed());
+   }
+   
+   public static class LC1 implements Startable, Disposable
+   {
+
+      public boolean started;
+      public boolean stopped;
+      public boolean disposed;
+      
+      public void start()
+      {
+         throw new RuntimeException();
+      }
+
+      public void stop()
+      {
+         stopped = true;
+      }
+
+      public void dispose()
+      {
+         disposed = true;
+      }      
+   }
+   
+   public static class LC2 implements Startable, Disposable
+   {
+
+      public boolean started;
+      public boolean stopped;
+      public boolean disposed;
+      
+      public void start()
+      {
+         started = true;
+      }
+
+      public void stop()
+      {
+         throw new RuntimeException();
+      }
+
+      public void dispose()
+      {
+         disposed = true;
+      }      
+   }
+   
+   public static class LC3 implements Startable, Disposable
+   {
+
+      public boolean started;
+      public boolean stopped;
+      public boolean disposed;
+      
+      public void start()
+      {
+         started = true;
+      }
+
+      public void stop()
+      {
+         stopped = true;
+      }
+
+      public void dispose()
+      {
+         throw new RuntimeException();
+      }      
+   }
+   
+   public static class LC4 implements Startable
+   {
+
+      public boolean started;
+      public boolean stopped;
+      public boolean disposed;
+      
+      public void start()
+      {
+         started = true;
+      }
+
+      public void stop()
+      {
+         stopped = true;
+      }     
+   }
+   
+   public static class LC5 implements Disposable
+   {
+
+      public boolean started;
+      public boolean stopped;
+      public boolean disposed;
+
+      public void dispose()
+      {
+         disposed = true;
+      }      
+   }    
 }



More information about the exo-jcr-commits mailing list