/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * 
 *      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.drools.core.concurrent;

import org.kie.api.concurrent.KieExecutors;

import java.util.concurrent.CompletionService;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class ExecutorProviderImpl implements KieExecutors {

    public static final String THREAD_FACTORY_PROPERTY = "drools.threadFactory";

    private static class ExecutorHolder {
        private static final java.util.concurrent.ExecutorService executor;

        static {
            String threadFactoryClass = System.getProperty( THREAD_FACTORY_PROPERTY );
            ThreadFactory threadFactory;

            if (threadFactoryClass == null) {
                threadFactory = new DaemonThreadFactory();
            } else {
                try {
                    threadFactory = (ThreadFactory) Class.forName( threadFactoryClass ).newInstance();
                } catch (Exception e) {
                    throw new RuntimeException( "Unable to instance a ThreadFactory of class " + threadFactoryClass, e );
                }
            }

            executor = new ThreadPoolExecutor(Pool.SIZE, Pool.SIZE,
                                              60L, TimeUnit.SECONDS,
                                              new LinkedBlockingQueue<Runnable>(),
                                              threadFactory);
        }
    }

    public Executor getExecutor() {
        return ExecutorHolder.executor;
    }

    public Executor newSingleThreadExecutor() {
        return Executors.newSingleThreadExecutor(new DaemonThreadFactory());
    }

    public <T> CompletionService<T> getCompletionService() {
        return new ExecutorCompletionService<T>(getExecutor());
    }

    private static class DaemonThreadFactory implements ThreadFactory {
        private static final AtomicInteger threadCount = new AtomicInteger();

        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setName("drools-worker-" + threadCount.incrementAndGet());
            t.setDaemon(true);
            return t;
        }
    }
}

@@ -654,16 +654,89 @@
 utors;%0A%0A
+import javax.naming.InitialContext;%0Aimport javax.naming.NamingException;%0A
 import j
@@ -1414,16 +1414,436 @@
 tatic %7B%0A
+            java.util.concurrent.ExecutorService newExecutor = null;%0A%0A            try %7B%0A                InitialContext ctx = new InitialContext();%0A                newExecutor = (java.util.concurrent.ExecutorService) ctx.lookup(%22java:comp/env/concurrent/ThreadPool%22);%0A            %7D catch (NamingException e) %7B%0A                // not in a J2EE container -- ignore%0A            %7D%0A%0A            if (newExecutor == null) %7B%0A    
         
@@ -1929,24 +1929,28 @@
             
+    
 ThreadFactor
@@ -1979,20 +1979,25 @@
         
+   
+ 
 if (
+ 
 threadFa
@@ -2006,36 +2006,41 @@
 oryClass == null
+ 
 ) %7B%0A
+    
                 
@@ -2094,16 +2094,20 @@
         
+  
+  
 %7D else %7B
@@ -2115,32 +2115,36 @@
                 
+    
 try %7B%0A          
@@ -2145,32 +2145,36 @@
                 
+  
+  
 threadFactory = 
@@ -2248,32 +2248,36 @@
                 
+    
 %7D catch (Excepti
@@ -2304,16 +2304,20 @@
         
+   
+ 
 throw ne
@@ -2422,26 +2422,33 @@
             
-%7D%0A
+    %7D%0A   
             
@@ -2439,32 +2439,33 @@
 %0A               
+ 
 %7D%0A%0A            e
@@ -2463,17 +2463,24 @@
         
-e
+    newE
 xecutor 
@@ -2504,16 +2504,17 @@
 xecutor(
+ 
 Pool.SIZ
@@ -2527,16 +2527,24 @@
 l.SIZE,%0A
+        
         
@@ -2650,16 +2650,24 @@
         
+        
 new Link
@@ -2733,32 +2733,40 @@
                 
+        
 threadFactory);%0A
@@ -2762,17 +2762,69 @@
 dFactory
-)
+ );%0A            %7D%0A%0A            executor = newExecutor
 ;%0A      

use a ManagedExecutorService when running in a J2EE container (#775)