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.text.CharacterPredicates;
031import org.apache.commons.text.RandomStringGenerator;
032
033/**
034 * Abstract class for work run in a separate thread.
035 */
036public final class BackgroundEngineHelper
037{
038    private static RandomStringGenerator _randomStringGenerator = new RandomStringGenerator.Builder().withinRange('0', 'z').filteredBy(CharacterPredicates.LETTERS, CharacterPredicates.DIGITS).build();
039    
040    private BackgroundEngineHelper()
041    {
042        // Hides the default constructor.
043    }
044    
045    /**
046     * Test if cocoon is currently in an environment.
047     * @return true if cocoon is currently in an environment, false otherwise.
048     */
049    public static boolean environmentExists()
050    {
051        return CocoonComponentManager.getCurrentEnvironment() != null;
052    }
053    
054    /**
055     * Create and enter a cocoon environment specific to the engine.
056     * @param manager the avalon service manager.
057     * @param context the cocoon environment context.
058     * @param logger the class logger.
059     * @return a Map with the environment information.
060     */
061    public static Map<String, Object> createAndEnterEngineEnvironment(ServiceManager manager, Context context, Logger logger)
062    {
063        BackgroundEnvironment environment;
064        Processor processor;
065        
066        // Création de l'environnement cocoon particulier
067        try
068        {
069            environment = new BackgroundEnvironment(logger, context);
070            processor = (Processor) manager.lookup(Processor.ROLE);
071        }
072        catch (Exception e)
073        {
074            throw new CascadingRuntimeException("Error during environment's setup.", e);
075        }
076        
077        // Random request ID: used by AbstractCachingPipeline to implement pipeline locking.
078        String requestId = _randomStringGenerator.generate(8);
079        environment.getObjectModel().put(AbstractCommandLineEnvironment.CLI_REQUEST_ID, requestId);
080        
081        Object processingKey = CocoonComponentManager.startProcessing(environment);
082        int environmentDepth = CocoonComponentManager.markEnvironment();
083        
084        CocoonComponentManager.enterEnvironment(environment, new WrapperComponentManager(manager), processor);
085        
086        BackgroundEngineHookExtensionPoint backgroundEngineHookEP;
087        try
088        {
089            backgroundEngineHookEP = (BackgroundEngineHookExtensionPoint) manager.lookup(BackgroundEngineHookExtensionPoint.ROLE);
090        }
091        catch (Exception e)
092        {
093            throw new CascadingRuntimeException("Error during environment's setup.", e);
094        }
095        
096        Map<String, Object> result = new HashMap<>();
097        
098        result.put("manager", manager);
099        result.put("logger", logger);
100        result.put("environment", environment);
101        result.put("processor", processor);
102        result.put("processingKey", processingKey);
103        result.put("environmentDepth", new Integer(environmentDepth));
104        result.put("hookEP", backgroundEngineHookEP);
105        
106        // on enter hooks
107        for (String hookId : backgroundEngineHookEP.getExtensionsIds())
108        {
109            BackgroundEngineHook hook = backgroundEngineHookEP.getExtension(hookId);
110            hook.onEnteringEnvironment(result);
111        }
112        
113        return result;
114    }
115    
116    /**
117     * Leave the cocoon environment.
118     * @param environmentInformation the environment information.
119     */
120    public static void leaveEngineEnvironment(Map<String, Object> environmentInformation)
121    {
122        BackgroundEnvironment environment = (BackgroundEnvironment) environmentInformation.get("environment");
123        Processor processor = (Processor) environmentInformation.get("processor");
124        Object processingKey = environmentInformation.get("processingKey");
125        int environmentDepth = ((Integer) environmentInformation.get("environmentDepth")).intValue();
126        ServiceManager manager = (ServiceManager) environmentInformation.get("manager");
127        Logger logger = (Logger) environmentInformation.get("logger");
128        BackgroundEngineHookExtensionPoint backgroundEngineHookEP = (BackgroundEngineHookExtensionPoint) environmentInformation.get("hookEP");
129        
130        // on leave hooks
131        for (String hookId : backgroundEngineHookEP.getExtensionsIds())
132        {
133            BackgroundEngineHook hook = backgroundEngineHookEP.getExtension(hookId);
134            hook.onLeavingEnvironment(environmentInformation);
135        }
136        
137        CocoonComponentManager.leaveEnvironment();
138        CocoonComponentManager.endProcessing(environment, processingKey);
139        
140        try
141        {
142            CocoonComponentManager.checkEnvironment(environmentDepth, logger);
143        }
144        catch (Exception e)
145        {
146            throw new CascadingRuntimeException("Error checking the environment", e);
147        }
148        
149        manager.release(backgroundEngineHookEP);
150        manager.release(processor);
151    }
152}