/******************************************************************************
* JBoss, a division of Red Hat *
* Copyright 2006, Red Hat Middleware, LLC, and individual *
* contributors as indicated by the @authors tag. See the *
* copyright.txt in the distribution for a full listing of *
* individual contributors. *
* *
* This is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2.1 of *
* the License, or (at your option) any later version. *
* *
* This software is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this software; if not, write to the Free *
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
* 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
******************************************************************************/
package org.jboss.portletbridge;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.portlet.PortletRequest;
import javax.portlet.faces.Bridge;
import javax.portlet.faces.BridgeException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.portletbridge.context.PortletBridgeContext;
import org.jboss.portletbridge.seam.FacesMessages;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.contexts.FacesLifecycle;
import org.jboss.seam.core.ConversationPropagation;
import org.jboss.seam.core.Manager;
import org.jboss.seam.exception.Exceptions;
import org.jboss.seam.transaction.Transaction;
import org.jboss.seam.transaction.UserTransaction;
/**
* @author asmirnov
* @author <a href="mailto:whales@redhat.com">Wesley Hales</a>
*/
public class SeamExceptionHandlerImpl extends ExceptionHandlerBase {
protected static final Log log = LogFactory
.getLog(SeamExceptionHandlerImpl.class);
protected String processException(FacesContext context,
BridgeRequestScope windowState, Exception e) {
windowState.setMessages(handleException(context, e));
PortletBridgeContext bridgeContext = PortletBridgeContext
.getCurrentInstance(context);
String redirectViewId = bridgeContext.getRedirectViewId();
return redirectViewId;
}
public static Class<?> classForName(String name)
throws ClassNotFoundException {
try {
return Thread.currentThread().getContextClassLoader().loadClass(
name);
} catch (Exception e) {
return Class.forName(name);
}
}
protected Map<String, List<FacesMessage>> handleException(
FacesContext facesContext, Exception e) throws BridgeException {
// if the event context was cleaned up, fish the conversation id
// directly out of the ServletRequest attributes, else get it from
// the event context
Manager manager = Contexts.isEventContextActive() ? (Manager) Contexts
.getEventContext().get(Manager.class) : null;
String conversationId = manager == null ? null : manager
.getCurrentConversationId();
// Initialize the temporary context objects
FacesLifecycle
.beginExceptionRecovery(facesContext.getExternalContext());
// If there is an existing long-running conversation on
// the failed request, propagate it
if (conversationId == null) {
Manager.instance().initializeTemporaryConversation();
} else {
ConversationPropagation.instance()
.setConversationId(conversationId);
Manager.instance().restoreConversation();
}
// Now do the exception handling
try {
Map<String, List<FacesMessage>> windowMessageMap = new HashMap<String, List<FacesMessage>>();
List<FacesMessage> messageList = new ArrayList<FacesMessage>();
Exceptions.instance().handle(e);
FacesMessages.afterPhase();
FacesMessages messages = FacesMessages.instance();
messageList.addAll(messages.getStatusMessages());
windowMessageMap.put("", messageList);
return windowMessageMap;
} catch (Exception ehe) {
log.error(
"Unable to process exception with Seam exception handler",
ehe);
throw new BridgeException(ehe);
} finally {
// Finally, clean up the contexts
try {
// ExternalContext externalContext = facesContext
// .getExternalContext();
// Manager.instance().endRequest(externalContext.getSessionMap());
rollbackTransactionIfNecessary();
// FacesLifecycle.endRequest(facesContext.getExternalContext());
log.debug("done running exception handlers");
} catch (Exception ere) {
log.error("could not destroy contexts", ere);
}
}
}
// @Override
// protected void setupErrorParameters(FacesContext context,
// Throwable throwable) {
// FacesLifecycle.beginRequest(context.getExternalContext());
// super.setupErrorParameters(context, throwable);
// }
protected void rollbackTransactionIfNecessary() {
try {
UserTransaction transaction = Transaction.instance();
if (transaction.isActiveOrMarkedRollback()
|| transaction.isRolledBack()) {
log.debug("killing transaction");
transaction.rollback();
}
} catch (Exception te) {
log.error("could not roll back transaction", te);
}
}
public void processEventException(FacesContext facesContext,
BridgeRequestScope windowState, Exception e) throws BridgeException {
rollbackTransactionIfNecessary();
super.processEventException(facesContext, windowState, e);
}
}