Coverage Report - net.sourceforge.acelogger.factory.ExecutorManagerFactory
 
Classes in this File Line Coverage Branch Coverage Complexity
ExecutorManagerFactory
48%
27/56
33%
6/18
2,3
ExecutorManagerFactory$1
0%
0/4
N/A
2,3
 
 1  
 /*
 2  
  * This file is part of AceLogger.
 3  
  * 
 4  
  * AceLogger is free software: you can redistribute it and/or modify it under the terms of the GNU
 5  
  * Lesser General Public License as published by the Free Software Foundation, either version 3 of
 6  
  * the License, or (at your option) any later version.
 7  
  * 
 8  
  * AceLogger is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 9  
  * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 10  
  * Lesser General Public License for more details.
 11  
  * 
 12  
  * You should have received a copy of the GNU Lesser General Public License along with AceLogger.
 13  
  * If not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
 14  
  */
 15  
 package net.sourceforge.acelogger.factory;
 16  
 
 17  
 import java.util.ArrayList;
 18  
 import java.util.HashMap;
 19  
 import java.util.List;
 20  
 import java.util.Map;
 21  
 import java.util.concurrent.CountDownLatch;
 22  
 import java.util.concurrent.TimeUnit;
 23  
 
 24  
 import net.sourceforge.acelogger.constants.ExecutorManagerConstants;
 25  
 import net.sourceforge.acelogger.execution.LogController;
 26  
 import net.sourceforge.acelogger.execution.TerminationException;
 27  
 import net.sourceforge.acelogger.execution.manager.ExecutorManager;
 28  
 
 29  
 /**
 30  
  * Factory for managing instances of configured executor managers.
 31  
  * 
 32  
  * @author Zardi (https://sourceforge.net/users/daniel_zardi)
 33  
  * @version 1.0.0
 34  
  * @since 1.0.0
 35  
  */
 36  
 public final class ExecutorManagerFactory {
 37  
 
 38  
         /**
 39  
          * A instance of this class (the only one).
 40  
          */
 41  1
         private static final ExecutorManagerFactory INSTANCE = new ExecutorManagerFactory();
 42  
 
 43  
         /**
 44  
          * Used when no configured manager is found for a given identifier.
 45  
          */
 46  
         private ExecutorManager defaultExecutorManager;
 47  
 
 48  
         /**
 49  
          * Maps each configured manager to a unique identifier.
 50  
          */
 51  
         private final Map<String, ExecutorManager> registeredExecutors;
 52  
 
 53  
         /**
 54  
          * Indicates if this factory has ordered all of its managers a shutdown or not.
 55  
          */
 56  1
         private boolean shutdown = false;
 57  
 
 58  
         /**
 59  
          * Creates a new ExecutorManagerFactory (This class is a singleton).
 60  
          * 
 61  
          * @since 1.0.0
 62  
          */
 63  1
         private ExecutorManagerFactory() {
 64  1
                 registeredExecutors = new HashMap<String, ExecutorManager>();
 65  1
                 defaultExecutorManager = ExecutorManagerConstants.EMPTY;
 66  1
         }
 67  
 
 68  
         /**
 69  
          * Obtains a properly configured manager for the given identifier.
 70  
          * 
 71  
          * @param identifier
 72  
          *            The identifier of the intended manager.
 73  
          * @return A properly configured manager for the given identifier. If the identifier is not
 74  
          *         found, then the default manager is returned.
 75  
          * @see ExecutorManagerFactory#getDefaultExecutorManager()
 76  
          * @since 1.0.0
 77  
          */
 78  
         public static ExecutorManager getExecutorManager(String identifier) {
 79  0
                 LogController.ensureInitialization();
 80  0
                 ExecutorManager intendedExecutor = INSTANCE.registeredExecutors.get(identifier);
 81  0
                 if (intendedExecutor == null) {
 82  0
                         int lastDotIndex = identifier.lastIndexOf('.');
 83  0
                         if (lastDotIndex > 0) {
 84  0
                                 intendedExecutor = getExecutorManager(identifier.substring(0, lastDotIndex));
 85  
                         } else {
 86  0
                                 intendedExecutor = INSTANCE.defaultExecutorManager;
 87  
                         }
 88  
                 }
 89  0
                 return intendedExecutor;
 90  
         }
 91  
 
 92  
         /**
 93  
          * Sets the default manager of this factory, the one used when no manager is found for a given
 94  
          * identifier.
 95  
          * 
 96  
          * @param manager
 97  
          *            The manager that will be used as the default one from now.
 98  
          * @return The previous default manager.
 99  
          * @since 1.0.0
 100  
          */
 101  
         public static ExecutorManager setDefaultExecutorManager(ExecutorManager manager) {
 102  0
                 LogController.ensureInitialization();
 103  0
                 ExecutorManager previous = INSTANCE.defaultExecutorManager;
 104  0
                 if (manager != null) {
 105  0
                         INSTANCE.defaultExecutorManager = manager;
 106  
                 }
 107  0
                 return previous;
 108  
         }
 109  
 
 110  
         /**
 111  
          * Returns the default manager of this factory, the one used when no manager is found for a
 112  
          * given identifier.
 113  
          * 
 114  
          * @return The default manager.
 115  
          * @since 1.0.0
 116  
          */
 117  
         public static ExecutorManager getDefaultExecutorManager() {
 118  1
                 LogController.ensureInitialization();
 119  1
                 return INSTANCE.defaultExecutorManager;
 120  
         }
 121  
 
 122  
         /**
 123  
          * Registers an appender within this factory. The mapped identifier will be the managers
 124  
          * identifier.
 125  
          * 
 126  
          * @param manager
 127  
          *            The manager to be registered.
 128  
          * @return The default manager if there was no previous mapping for the identifier or the
 129  
          *         previous configured manager otherwise.
 130  
          * @see ExecutorManagerFactory#getDefaultExecutorManager()
 131  
          * @since 1.0.0
 132  
          */
 133  
         public static ExecutorManager registerExecutorManager(ExecutorManager manager) {
 134  5
                 LogController.ensureInitialization();
 135  5
                 ExecutorManager intendedExecutor = null;
 136  5
                 if (manager != null) {
 137  4
                         intendedExecutor = INSTANCE.registeredExecutors.put(manager.getIdentifier(), manager);
 138  
                 }
 139  5
                 if (intendedExecutor == null) {
 140  5
                         intendedExecutor = INSTANCE.defaultExecutorManager;
 141  
                 }
 142  5
                 return intendedExecutor;
 143  
         }
 144  
 
 145  
         /**
 146  
          * Returns a list of all managers registered in this factory.
 147  
          * 
 148  
          * @return A list of managers.
 149  
          * @since 1.0.0
 150  
          */
 151  
         public static List<ExecutorManager> getRegisteredExecutorManagers() {
 152  5
                 LogController.ensureInitialization();
 153  5
                 List<ExecutorManager> allExecutorManagers = new ArrayList<ExecutorManager>(
 154  
                                 INSTANCE.registeredExecutors.values());
 155  5
                 return allExecutorManagers;
 156  
         }
 157  
 
 158  
         /**
 159  
          * Indicates if this factory has ordered all of its managers a shutdown or not. If this factory
 160  
          * has ordered shutdown, it is not safe to execute any task.
 161  
          * 
 162  
          * @return True id the shutdown was previously ordered, false otherwise.
 163  
          * @since 1.0.0
 164  
          */
 165  
         public static boolean isShutdown() {
 166  0
                 LogController.ensureInitialization();
 167  0
                 return INSTANCE.shutdown;
 168  
         }
 169  
 
 170  
         /**
 171  
          * Shuts down each of the registered executor managers, this should be called to guarantee that
 172  
          * all tasks submitted will be run before termination.
 173  
          * 
 174  
          * @return True if all executors finished their tasks properly, false if there are tasks under
 175  
          * or awaiting execution.
 176  
          * @since 1.0.0
 177  
          */
 178  
         public static boolean doProperExecutorManagersShutdown() {
 179  1
                 if (INSTANCE.shutdown) {
 180  0
                         throw new IllegalStateException("");
 181  
                 } else {
 182  1
                         LogController.ensureInitialization();
 183  1
                         INSTANCE.shutdown = true;
 184  1
                         boolean properShutdown = true;
 185  1
                         List<ExecutorManager> allExecutorManagers = getRegisteredExecutorManagers();
 186  1
                         for (ExecutorManager currentExecutorManager : allExecutorManagers) {
 187  4
                                 currentExecutorManager.orderProperShutdown();
 188  4
                                 properShutdown &= currentExecutorManager.isTerminated();
 189  
                         }
 190  1
                         return properShutdown;
 191  
                 }
 192  
         }
 193  
 
 194  
         /**
 195  
          * Awaits for the execution of the remaining tasks in executor managers registered in this
 196  
          * factory. This method should be called after ordering a proper shutdown of the executors.
 197  
          * 
 198  
          * @param terminationTimeout
 199  
          *            The maximum time (in ms) to wait while executing the remaining tasks.
 200  
          * @return True if all executor managers terminated execution of its tasks before the supplied
 201  
          *         timeout; False otherwise.
 202  
          * @throws TerminationException
 203  
          *             if interrupted while waiting for managers to shutdown.
 204  
          * @since 1.0.0
 205  
          * @see ExecutorManagerFactory#doProperExecutorManagersShutdown()
 206  
          */
 207  
         public static boolean awaitExecutorManagersShutdown(final long terminationTimeout)
 208  
                         throws TerminationException {
 209  0
                 boolean allDone = false;
 210  0
                 if (INSTANCE.shutdown) {
 211  0
                         List<ExecutorManager> remainingExecutorManagers = getRegisteredExecutorManagers();
 212  0
                         final CountDownLatch synchronizer =
 213  
                                         new CountDownLatch(remainingExecutorManagers.size());
 214  0
                         for (final ExecutorManager currentManager : remainingExecutorManagers) {
 215  0
                                 LogController.submitBackgroundTask(new Runnable() {
 216  
                                         /**
 217  
                                          * Orders the termination of each manager under a given timeout.
 218  
                                          */
 219  
                                         public void run() {
 220  0
                                                 currentManager.awaitTermination(terminationTimeout);
 221  0
                                                 synchronizer.countDown();
 222  0
                                         }
 223  
                                 });
 224  
                         }
 225  
                         try {
 226  0
                                 allDone = synchronizer.await(terminationTimeout, TimeUnit.MILLISECONDS);
 227  0
                         } catch (InterruptedException e) {
 228  0
                                 throw new TerminationException("Interrupted while waiting executor to finish", e);
 229  0
                         }
 230  0
                 } else {
 231  0
                         throw new IllegalStateException(
 232  
                                         "Can only await executor managers shutdown after calling"
 233  
                                         + " doProperExecutorManagersShutdown");
 234  
                 }
 235  0
                 return allDone;
 236  
         }
 237  
 
 238  
 }