001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.components.flow.apples;
018:
019: import java.util.List;
020:
021: import org.apache.avalon.framework.CascadingRuntimeException;
022: import org.apache.avalon.framework.activity.Disposable;
023: import org.apache.avalon.framework.component.WrapperComponentManager;
024: import org.apache.avalon.framework.context.ContextException;
025: import org.apache.avalon.framework.context.DefaultContext;
026: import org.apache.avalon.framework.service.ServiceException;
027: import org.apache.avalon.framework.service.ServiceManager;
028: import org.apache.avalon.framework.service.Serviceable;
029: import org.apache.cocoon.components.ContextHelper;
030: import org.apache.cocoon.components.LifecycleHelper;
031: import org.apache.cocoon.components.flow.AbstractInterpreter;
032: import org.apache.cocoon.components.flow.ContinuationsDisposer;
033: import org.apache.cocoon.components.flow.InvalidContinuationException;
034: import org.apache.cocoon.components.flow.WebContinuation;
035: import org.apache.cocoon.environment.Redirector;
036: import org.apache.cocoon.environment.Request;
037: import org.apache.cocoon.environment.Response;
038:
039: /**
040: * ApplesProcessor is the core Cocoon component that provides the 'Apples'
041: * flow implementation.
042: */
043: public class ApplesProcessor extends AbstractInterpreter implements
044: Serviceable, ContinuationsDisposer {
045:
046: //private ServiceManager serviceManager;
047:
048: public void callFunction(String className, List params,
049: Redirector redirector) throws Exception {
050:
051: AppleController app = instantiateController(className);
052:
053: WebContinuation wk = null;
054: if (!(app instanceof StatelessAppleController)) {
055: wk = this .continuationsMgr.createWebContinuation(app, null,
056: 0, getInterpreterID(), this );
057: if (getLogger().isDebugEnabled())
058: getLogger().debug(
059: "Instantiated a stateful apple, continuationid = "
060: + wk.getId());
061: }
062:
063: DefaultContext appleContext = new DefaultContext(avalonContext);
064: if (wk != null) {
065: appleContext.put("continuation-id", wk.getId());
066: }
067:
068: // Use the current sitemap's service manager for components
069: ServiceManager sitemapManager;
070: try {
071: sitemapManager = (ServiceManager) avalonContext
072: .get(ContextHelper.CONTEXT_SITEMAP_SERVICE_MANAGER);
073: } catch (ContextException e) {
074: throw new CascadingRuntimeException(
075: "Cannot get sitemap service manager", e);
076: }
077:
078: LifecycleHelper.setupComponent(app, getLogger(), appleContext,
079: sitemapManager, new WrapperComponentManager(
080: sitemapManager), null, null, true);
081:
082: processApple(params, redirector, app, wk);
083: }
084:
085: public void handleContinuation(String continuationId, List params,
086: Redirector redirector) throws Exception {
087:
088: WebContinuation wk = this .continuationsMgr
089: .lookupWebContinuation(continuationId,
090: getInterpreterID());
091: if (wk == null) {
092: // Throw an InvalidContinuationException to be handled inside the
093: // <map:handle-errors> sitemap element.
094: throw new InvalidContinuationException(
095: "The continuation ID " + continuationId
096: + " is invalid.");
097: }
098:
099: AppleController app = (AppleController) wk.getContinuation();
100:
101: getLogger().debug("found apple from continuation: " + app);
102:
103: // TODO access control checks? exception to be thrown for illegal access?
104: processApple(params, redirector, app, wk);
105:
106: }
107:
108: private AppleController instantiateController(String className)
109: throws Exception {
110:
111: // TODO think about dynamic reloading of these beasts in future
112: // classloading stuf et al.
113:
114: Class clazz = Class.forName(className);
115: Object o = clazz.newInstance();
116: return (AppleController) o;
117: }
118:
119: private void processApple(List params, Redirector redirector,
120: AppleController app, WebContinuation wk) throws Exception {
121:
122: Request cocoonRequest = ContextHelper
123: .getRequest(this .avalonContext);
124: AppleRequest req = new DefaultAppleRequest(params,
125: cocoonRequest);
126: Response cocoonResponse = ContextHelper
127: .getResponse(this .avalonContext);
128: DefaultAppleResponse res = new DefaultAppleResponse(
129: cocoonResponse);
130:
131: try {
132: app.process(req, res);
133: } finally {
134: if (wk == null) {
135: // dispose stateless apple immediatelly
136: if (app instanceof Disposable) {
137: try {
138: ((Disposable) app).dispose();
139: } catch (Exception e) {
140: getLogger().error(
141: "Error disposing Apple instance.", e);
142: }
143: }
144: }
145: }
146:
147: if (res.isRedirect()) {
148: redirector.redirect(false, res.getURI());
149: } else {
150: String uri = res.getURI();
151: if (getLogger().isDebugEnabled()) {
152: getLogger().debug(
153: "Apple forwards to "
154: + uri
155: + " with bizdata= "
156: + res.getData()
157: + (wk != null ? " and continuationid= "
158: + wk.getId()
159: : " without continuationid"));
160: }
161:
162: // Note: it is ok for wk to be null
163: this .forwardTo(uri, res.getData(), wk, redirector);
164: }
165:
166: //TODO allow for AppleResponse to set some boolean saying the use case
167: // is completed and the continuation can be invalidated ?
168: }
169:
170: public void disposeContinuation(WebContinuation webContinuation) {
171: AppleController app = (AppleController) webContinuation
172: .getContinuation();
173: if (app instanceof Disposable) {
174: ((Disposable) app).dispose();
175: }
176:
177: }
178:
179: public void service(ServiceManager serviceManager)
180: throws ServiceException {
181: super .service(serviceManager);
182: //this.serviceManager = serviceManager;
183: }
184:
185: }
|