| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF 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.apache.cocoon.components.flow.apples; |
| |
| import java.util.List; |
| |
| import org.apache.avalon.framework.CascadingRuntimeException; |
| import org.apache.avalon.framework.activity.Disposable; |
| import org.apache.avalon.framework.component.WrapperComponentManager; |
| import org.apache.avalon.framework.context.ContextException; |
| import org.apache.avalon.framework.context.DefaultContext; |
| import org.apache.avalon.framework.service.ServiceException; |
| import org.apache.avalon.framework.service.ServiceManager; |
| import org.apache.avalon.framework.service.Serviceable; |
| import org.apache.cocoon.components.ContextHelper; |
| import org.apache.cocoon.components.LifecycleHelper; |
| import org.apache.cocoon.components.flow.AbstractInterpreter; |
| import org.apache.cocoon.components.flow.ContinuationsDisposer; |
| import org.apache.cocoon.components.flow.InvalidContinuationException; |
| import org.apache.cocoon.components.flow.WebContinuation; |
| import org.apache.cocoon.environment.Redirector; |
| import org.apache.cocoon.environment.Request; |
| import org.apache.cocoon.environment.Response; |
| |
| /** |
| * ApplesProcessor is the core Cocoon component that provides the 'Apples' |
| * flow implementation. |
| */ |
| public class ApplesProcessor extends AbstractInterpreter implements Serviceable, ContinuationsDisposer { |
| |
| |
| //private ServiceManager serviceManager; |
| |
| |
| public void callFunction( |
| String className, |
| List params, |
| Redirector redirector) |
| throws Exception { |
| |
| AppleController app = instantiateController(className); |
| |
| WebContinuation wk = null; |
| if (!(app instanceof StatelessAppleController)) { |
| wk = this.continuationsMgr.createWebContinuation(app, null, 0, |
| getInterpreterID(), this); |
| if (getLogger().isDebugEnabled()) |
| getLogger().debug("Instantiated a stateful apple, continuationid = " + wk.getId()); |
| } |
| |
| DefaultContext appleContext = new DefaultContext(avalonContext); |
| if (wk != null) { |
| appleContext.put("continuation-id", wk.getId()); |
| } |
| |
| // Use the current sitemap's service manager for components |
| ServiceManager sitemapManager; |
| try { |
| sitemapManager = (ServiceManager)avalonContext.get(ContextHelper.CONTEXT_SITEMAP_SERVICE_MANAGER); |
| } catch (ContextException e) { |
| throw new CascadingRuntimeException("Cannot get sitemap service manager", e); |
| } |
| |
| LifecycleHelper.setupComponent( app, getLogger(), appleContext, |
| sitemapManager, new WrapperComponentManager(sitemapManager), |
| null, null, true); |
| |
| processApple(params, redirector, app, wk); |
| } |
| |
| |
| |
| public void handleContinuation( |
| String continuationId, |
| List params, |
| Redirector redirector) |
| throws Exception { |
| |
| WebContinuation wk = |
| this.continuationsMgr.lookupWebContinuation(continuationId, getInterpreterID()); |
| if (wk == null) { |
| // Throw an InvalidContinuationException to be handled inside the |
| // <map:handle-errors> sitemap element. |
| throw new InvalidContinuationException( |
| "The continuation ID " + continuationId + " is invalid."); |
| } |
| |
| AppleController app = |
| (AppleController) wk.getContinuation(); |
| |
| getLogger().debug("found apple from continuation: " + app); |
| |
| // TODO access control checks? exception to be thrown for illegal access? |
| processApple(params, redirector, app, wk); |
| |
| } |
| |
| |
| private AppleController instantiateController(String className) |
| throws Exception { |
| |
| // TODO think about dynamic reloading of these beasts in future |
| // classloading stuf et al. |
| |
| Class clazz = Class.forName(className); |
| Object o = clazz.newInstance(); |
| return (AppleController) o; |
| } |
| |
| |
| |
| private void processApple( |
| List params, |
| Redirector redirector, |
| AppleController app, |
| WebContinuation wk) |
| throws Exception { |
| |
| Request cocoonRequest = ContextHelper.getRequest(this.avalonContext); |
| AppleRequest req = new DefaultAppleRequest(params, cocoonRequest); |
| Response cocoonResponse = ContextHelper.getResponse(this.avalonContext); |
| DefaultAppleResponse res = new DefaultAppleResponse(cocoonResponse); |
| |
| try { |
| app.process(req, res); |
| } finally { |
| if (wk == null) { |
| // dispose stateless apple immediatelly |
| if (app instanceof Disposable) { |
| try { |
| ((Disposable)app).dispose(); |
| } catch (Exception e) { |
| getLogger().error("Error disposing Apple instance.", e); |
| } |
| } |
| } |
| } |
| |
| if (res.isRedirect()) { |
| redirector.redirect(false, res.getURI()); |
| } else { |
| String uri = res.getURI(); |
| if (getLogger().isDebugEnabled()) { |
| getLogger().debug("Apple forwards to " + uri + " with bizdata= " + res.getData() + (wk != null ? " and continuationid= " + wk.getId() : " without continuationid")); |
| } |
| |
| // Note: it is ok for wk to be null |
| this.forwardTo(uri, res.getData(), wk, redirector); |
| } |
| |
| //TODO allow for AppleResponse to set some boolean saying the use case |
| // is completed and the continuation can be invalidated ? |
| } |
| |
| |
| public void disposeContinuation(WebContinuation webContinuation) { |
| AppleController app = |
| (AppleController) webContinuation.getContinuation(); |
| if (app instanceof Disposable) { |
| ((Disposable)app).dispose(); |
| } |
| |
| } |
| |
| |
| public void service(ServiceManager serviceManager) throws ServiceException { |
| super.service(serviceManager); |
| //this.serviceManager = serviceManager; |
| } |
| |
| |
| } |