001/*
002 *  Copyright 2012 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.core.engine;
017
018import java.util.HashMap;
019import java.util.Map;
020
021import org.apache.avalon.framework.CascadingRuntimeException;
022import org.apache.avalon.framework.component.WrapperComponentManager;
023import org.apache.avalon.framework.logger.Logger;
024import org.apache.avalon.framework.service.ServiceManager;
025import org.apache.cocoon.Processor;
026import org.apache.cocoon.components.CocoonComponentManager;
027import org.apache.cocoon.environment.Context;
028import org.apache.cocoon.environment.background.BackgroundEnvironment;
029import org.apache.cocoon.environment.commandline.AbstractCommandLineEnvironment;
030import org.apache.commons.lang3.RandomStringUtils;
031
032/**
033 * Abstract class for work run in a separate thread.
034 */
035public final class BackgroundEngineHelper
036{
037    
038    private BackgroundEngineHelper()
039    {
040        // Hides the default constructor.
041    }
042    
043    /**
044     * Test if cocoon is currently in an environment.
045     * @return true if cocoon is currently in an environment, false otherwise.
046     */
047    public static boolean environmentExists()
048    {
049        return CocoonComponentManager.getCurrentEnvironment() != null;
050    }
051    
052    /**
053     * Create and enter a cocoon environment specific to the engine.
054     * @param manager the avalon service manager.
055     * @param context the cocoon environment context.
056     * @param logger the class logger.
057     * @return a Map with the environment information.
058     */
059    public static Map<String, Object> createAndEnterEngineEnvironment(ServiceManager manager, Context context, Logger logger)
060    {
061        BackgroundEnvironment environment;
062        Processor processor;
063        
064        // Création de l'environnement cocoon particulier
065        try
066        {
067            environment = new BackgroundEnvironment(logger, context);
068            processor = (Processor) manager.lookup(Processor.ROLE);
069        }
070        catch (Exception e)
071        {
072            throw new CascadingRuntimeException("Error during environment's setup.", e);
073        }
074        
075        // Random request ID: used by AbstractCachingPipeline to implement pipeline locking.
076        String requestId = RandomStringUtils.randomAlphanumeric(8);
077        environment.getObjectModel().put(AbstractCommandLineEnvironment.CLI_REQUEST_ID, requestId);
078        
079        Object processingKey = CocoonComponentManager.startProcessing(environment);
080        int environmentDepth = CocoonComponentManager.markEnvironment();
081        
082        CocoonComponentManager.enterEnvironment(environment, new WrapperComponentManager(manager), processor);
083        
084        BackgroundEngineHookExtensionPoint backgroundEngineHookEP;
085        try
086        {
087            backgroundEngineHookEP = (BackgroundEngineHookExtensionPoint) manager.lookup(BackgroundEngineHookExtensionPoint.ROLE);
088        }
089        catch (Exception e)
090        {
091            throw new CascadingRuntimeException("Error during environment's setup.", e);
092        }
093        
094        Map<String, Object> result = new HashMap<>();
095        
096        result.put("manager", manager);
097        result.put("logger", logger);
098        result.put("environment", environment);
099        result.put("processor", processor);
100        result.put("processingKey", processingKey);
101        result.put("environmentDepth", new Integer(environmentDepth));
102        result.put("hookEP", backgroundEngineHookEP);
103        
104        // on enter hooks
105        for (String hookId : backgroundEngineHookEP.getExtensionsIds())
106        {
107            BackgroundEngineHook hook = backgroundEngineHookEP.getExtension(hookId);
108            hook.onEnteringEnvironment(result);
109        }
110        
111        return result;
112    }
113    
114    /**
115     * Leave the cocoon environment.
116     * @param environmentInformation the environment information.
117     */
118    public static void leaveEngineEnvironment(Map<String, Object> environmentInformation)
119    {
120        BackgroundEnvironment environment = (BackgroundEnvironment) environmentInformation.get("environment");
121        Processor processor = (Processor) environmentInformation.get("processor");
122        Object processingKey = environmentInformation.get("processingKey");
123        int environmentDepth = ((Integer) environmentInformation.get("environmentDepth")).intValue();
124        ServiceManager manager = (ServiceManager) environmentInformation.get("manager");
125        Logger logger = (Logger) environmentInformation.get("logger");
126        BackgroundEngineHookExtensionPoint backgroundEngineHookEP = (BackgroundEngineHookExtensionPoint) environmentInformation.get("hookEP");
127        
128        // on leave hooks
129        for (String hookId : backgroundEngineHookEP.getExtensionsIds())
130        {
131            BackgroundEngineHook hook = backgroundEngineHookEP.getExtension(hookId);
132            hook.onLeavingEnvironment(environmentInformation);
133        }
134        
135        CocoonComponentManager.leaveEnvironment();
136        CocoonComponentManager.endProcessing(environment, processingKey);
137        
138        try
139        {
140            CocoonComponentManager.checkEnvironment(environmentDepth, logger);
141        }
142        catch (Exception e)
143        {
144            throw new CascadingRuntimeException("Error checking the environment", e);
145        }
146        
147        manager.release(backgroundEngineHookEP);
148        manager.release(processor);
149    }
150}