blob: e0a0848ece03f25cf7fec485e4c0523334c27fdb [file] [log] [blame]
/*
* 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;
}
}