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.faces;
018:
019: import org.apache.avalon.framework.activity.Initializable;
020: import org.apache.avalon.framework.configuration.Configurable;
021: import org.apache.avalon.framework.configuration.Configuration;
022: import org.apache.avalon.framework.configuration.ConfigurationException;
023: import org.apache.avalon.framework.context.ContextException;
024: import org.apache.avalon.framework.context.Contextualizable;
025: import org.apache.avalon.framework.logger.AbstractLogEnabled;
026: import org.apache.avalon.framework.parameters.Parameters;
027: import org.apache.avalon.framework.thread.ThreadSafe;
028:
029: import org.apache.cocoon.CascadingIOException;
030: import org.apache.cocoon.Constants;
031: import org.apache.cocoon.ProcessingException;
032: import org.apache.cocoon.acting.Action;
033: import org.apache.cocoon.environment.Context;
034: import org.apache.cocoon.environment.ObjectModelHelper;
035: import org.apache.cocoon.environment.Redirector;
036: import org.apache.cocoon.environment.Request;
037: import org.apache.cocoon.environment.Response;
038: import org.apache.cocoon.environment.SourceResolver;
039: import org.apache.cocoon.environment.portlet.ActionResponse;
040: import org.apache.cocoon.environment.portlet.PortletResponse;
041:
042: import javax.faces.FacesException;
043: import javax.faces.FactoryFinder;
044: import javax.faces.application.Application;
045: import javax.faces.application.ApplicationFactory;
046: import javax.faces.context.FacesContext;
047: import javax.faces.context.FacesContextFactory;
048: import javax.faces.lifecycle.Lifecycle;
049: import javax.faces.lifecycle.LifecycleFactory;
050: import javax.faces.webapp.FacesServlet;
051: import java.io.IOException;
052: import java.util.Map;
053:
054: /**
055: * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
056: * @version CVS $Id: FacesAction.java 433543 2006-08-22 06:22:54Z crossley $
057: */
058: public class FacesAction extends AbstractLogEnabled implements Action,
059: ThreadSafe, Contextualizable, Configurable, Initializable {
060:
061: public static final String REQUEST_REDIRECTOR_ATTRIBUTE = "org.apache.cocoon.faces.REDIRECTOR";
062:
063: private Context context;
064:
065: private String cutPrefix;
066: private String cutSuffix;
067: private String addPrefix;
068: private String addSuffix;
069:
070: private FacesContextFactory facesContextFactory;
071: private Application application;
072: private Lifecycle lifecycle;
073:
074: /**
075: *
076: */
077: class RedirectorImpl implements FacesRedirector {
078: private Redirector redirector;
079: private Request request;
080: private Response response;
081:
082: RedirectorImpl(Redirector redirector, Request request,
083: Response response) {
084: this .redirector = redirector;
085: this .request = request;
086: this .response = response;
087: }
088:
089: public void dispatch(String url) throws IOException {
090: // System.err.println("INFO: Dispatching to " + url);
091: try {
092: // TODO: HACK: Dependency on ActionResponse
093: if (response instanceof ActionResponse) {
094: // Can't render response. Redirect to another face.
095: redirector.redirect(true, url);
096: } else {
097: // Need to render face. Convert face URL to view URL.
098: int begin = 0;
099: int end = url.length();
100:
101: if (cutPrefix != null && url.startsWith(cutPrefix)) {
102: begin = cutPrefix.length();
103: }
104: if (cutSuffix != null && url.endsWith(cutSuffix)) {
105: end = end - cutSuffix.length();
106: }
107:
108: StringBuffer buffer = new StringBuffer();
109: if (addPrefix != null) {
110: buffer.append(addPrefix);
111: }
112: if (begin < end) {
113: buffer.append(url.substring(begin, end));
114: }
115: if (addSuffix != null) {
116: buffer.append(addSuffix);
117: }
118: url = buffer.toString();
119:
120: // System.err.println("INFO: Dispatching to view " + url);
121: redirector.redirect(true, "cocoon:/" + url);
122: }
123: } catch (Exception e) {
124: throw new CascadingIOException(e);
125: }
126: }
127:
128: public void redirect(String url) throws IOException {
129: // System.err.println("redirect: " + url);
130: try {
131: redirector.redirect(true, url);
132: } catch (Exception e) {
133: throw new CascadingIOException(e);
134: }
135: }
136:
137: public String encodeActionURL(String url) {
138: // System.err.println("encodeActionURL: " + url);
139: // TODO: HACK: Dependency on PortletResponse
140: if (response instanceof PortletResponse) {
141: final String context = request.getContextPath();
142:
143: if (url.startsWith(context)) {
144: url = url.substring(context.length());
145: // System.err.println("encodeActionURL: cut: " + url);
146: }
147:
148: return "portlet:action:" + response.encodeURL(url);
149: } else {
150: return response.encodeURL(url);
151: }
152: }
153:
154: public String encodeResourceURL(String url) {
155: // System.err.println("encodeResourceURL: " + url);
156: return response.encodeURL(url);
157: }
158: }
159:
160: public void contextualize(
161: org.apache.avalon.framework.context.Context avalonContext)
162: throws ContextException {
163: context = (Context) avalonContext
164: .get(Constants.CONTEXT_ENVIRONMENT_CONTEXT);
165: }
166:
167: public void configure(Configuration configuration)
168: throws ConfigurationException {
169: this .cutPrefix = configuration.getChild("cut-prefix").getValue(
170: null);
171: this .cutSuffix = configuration.getChild("cut-suffix").getValue(
172: ".faces");
173: this .addPrefix = configuration.getChild("add-prefix").getValue(
174: null);
175: this .addSuffix = configuration.getChild("add-suffix").getValue(
176: ".view");
177: }
178:
179: public void initialize() throws Exception {
180: if (getLogger().isDebugEnabled()) {
181: getLogger().debug("Initializing FacesAction");
182: }
183:
184: facesContextFactory = (FacesContextFactory) FactoryFinder
185: .getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
186: // facesContextFactory = new FacesContextFactoryImpl();
187:
188: ApplicationFactory applicationFactory = (ApplicationFactory) FactoryFinder
189: .getFactory(FactoryFinder.APPLICATION_FACTORY);
190: application = applicationFactory.getApplication();
191: // application.setDefaultRenderKitId("COCOON_BASIC_XHTML");
192:
193: LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
194: .getFactory(FactoryFinder.LIFECYCLE_FACTORY);
195: String lifecycleID = context
196: .getInitParameter(FacesServlet.LIFECYCLE_ID_ATTR);
197: if (lifecycleID == null) {
198: lifecycleID = "DEFAULT";
199: }
200: lifecycle = lifecycleFactory.getLifecycle(lifecycleID);
201:
202: if (getLogger().isDebugEnabled()) {
203: getLogger().debug(
204: "Faces context factory is "
205: + facesContextFactory.getClass().getName());
206: getLogger().debug(
207: "Faces application factory is "
208: + applicationFactory.getClass().getName());
209: getLogger().debug(
210: "Faces lifecycle factory is "
211: + lifecycleFactory.getClass().getName());
212: }
213: }
214:
215: public Map act(Redirector redirector, SourceResolver resolver,
216: Map objectModel, String source, Parameters parameters)
217: throws Exception {
218: Request request = ObjectModelHelper.getRequest(objectModel);
219: Response response = ObjectModelHelper.getResponse(objectModel);
220:
221: // Pass FacesRedirector to the FacesContext implementation.
222: request.setAttribute(REQUEST_REDIRECTOR_ATTRIBUTE,
223: new RedirectorImpl(redirector, request, response));
224:
225: FacesContext context = facesContextFactory.getFacesContext(
226: this .context, request, response, lifecycle);
227: try {
228: lifecycle.execute(context);
229: lifecycle.render(context);
230:
231: if (getLogger().isDebugEnabled()) {
232: getLogger().debug(
233: "Request processed; View root ID: "
234: + context.getViewRoot().getId());
235: }
236: } catch (FacesException e) {
237: throw new ProcessingException(
238: "Failed to process faces request", e);
239: } finally {
240: context.release();
241: }
242:
243: return null;
244: }
245: }
|