/**
 * Licensed to the Austrian Association for Software Tool Integration (AASTI)
 * under one or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership. The AASTI 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 org.openengsb.core.common.util;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.springframework.security.core.context.SecurityContextHolder;

/**
 * provides util-methods for security purposes
 */
public final class SecurityUtils {

    private static ExecutorService executor = Executors.newCachedThreadPool();

    /**
     * Executes the given task with root-permissions. Use with care.
     *
     * @throws ExecutionException if an exception occurs during the execution of the task
     */
    public static <ReturnType> ReturnType executeWithSystemPermissions(Callable<ReturnType> task)
        throws ExecutionException {
        Future<ReturnType> future = executor.submit(new RootCallable<ReturnType>(task));
        try {
            return future.get();
        } catch (InterruptedException e) {
            throw new ExecutionException(e);
        }
    }

    /**
     * Executes the given task with root-permissions. Use with care.
     */
    public static void executeWithSystemPermissions(Runnable task) {
        executor.execute(new RootRunnable(task));
    }

    static class RootCallable<ReturnType> extends ContextAwareCallable<ReturnType> {
        public RootCallable(Callable<ReturnType> original) {
            super(original);
        }

        @Override
        public ReturnType call() throws Exception {
            SecurityContextHolder.getContext().setAuthentication(new BundleAuthenticationToken("", ""));
            try {
                return super.call();
            } finally {
                SecurityContextHolder.clearContext();
            }
        }
    }

    static class RootRunnable extends ContextAwareRunnable {

        public RootRunnable(Runnable original) {
            super(original);
        }

        @Override
        public void run() {
            SecurityContextHolder.getContext().setAuthentication(new BundleAuthenticationToken("", ""));
            try {
                super.run();
            } finally {
                SecurityContextHolder.getContext().setAuthentication(null);
            }
        }

    }

    private SecurityUtils() {
    }
}

@@ -1070,16 +1070,69 @@
 uture;%0A%0A
+import org.openengsb.core.api.context.ContextHolder;%0A
 import o
@@ -2181,29 +2181,20 @@
 pe%3E 
-extend
+implement
 s C
-ontextAwareC
 alla
@@ -2210,16 +2210,140 @@
 nType%3E %7B
+%0A        private Callable%3CReturnType%3E original;%0A        private String context = ContextHolder.get().getCurrentContextId();%0A
 %0A       
@@ -2404,38 +2404,48 @@
             
-super(
+this.original = 
 original
 );%0A        %7D
@@ -2424,33 +2424,32 @@
 ginal = original
-)
 ;%0A        %7D%0A%0A   
@@ -2612,32 +2612,94 @@
 Token(%22%22, %22%22));%0A
+            ContextHolder.get().setCurrentContextId(context);%0A
             try 
@@ -2723,21 +2723,24 @@
  return 
-super
+original
 .call();
@@ -2883,38 +2883,141 @@
 ble 
-extends ContextAwareRunnable %7B
+implements Runnable %7B%0A%0A        private Runnable original;%0A        private String context = ContextHolder.get().getCurrentContextId();
 %0A%0A  
@@ -3079,22 +3079,32 @@
     
-super(
+this.original = 
 original
 );%0A 
@@ -3099,17 +3099,16 @@
 original
-)
 ;%0A      
@@ -3255,32 +3255,94 @@
 Token(%22%22, %22%22));%0A
+            ContextHolder.get().setCurrentContextId(context);%0A
             try 
@@ -3363,13 +3363,16 @@
     
-super
+original
 .run

fix Security-utils for root-tasks