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