Seam가 사용하는 FacesServlet 소스

h:commandButton 등으로 설정하는 action속성은 언제 실행될까? HTML에서 submit버튼을 클릭하게 되면 해당 버튼의 id 및 ViewState를 보낸다.(RESTORE_VIEW) 이후 Lifecycle에 의해 INVOKE_APPLICATION 에서는 AjaxViewRoot인스턴스를 생성후에 해당 UIComponent를 찾아서 broadcast한다. AjaxViewRoot.java에서 실제 호출하는 부분은 아래.

  public void processEvents(FacesContext context, EventsQueue phaseEventsQueue, boolean havePhaseEvents)
  {
    while (havePhaseEvents)
      try {
        FacesEvent event = (FacesEvent)phaseEventsQueue.remove();
        UIComponent source = event.getComponent();
        try {
          source.broadcast(event);
        } catch (AbortProcessingException e) {
          if (_log.isErrorEnabled()) {
            UIComponent component = event.getComponent();
            String id = null != component ? component.getClientId(context) : "";
            _log.error("Error processing faces event for the component " + id, e);
          }
        }
      }
      catch (NoSuchElementException e)
      {
        havePhaseEvents = false;
      }
  }
아래는 UICommand.java에서의 처리부분. (UICommand는 HtmlCommandButton의 슈퍼클래스)
  public void broadcast(FacesEvent event)
    throws AbortProcessingException
  {
    super.broadcast(event);
    if ((event instanceof ActionEvent)) {
      FacesContext context = getFacesContext();
      MethodBinding mb = getActionListener();
      if (mb != null) {
        mb.invoke(context, new Object[] { event });
      }
      ActionListener listener = context.getApplication().getActionListener();
      if (listener != null)
        listener.processAction((ActionEvent)event);
    }
  }
참고로 Lifecycle에서 각각의 phase에서 실행되는 doPhase에 등록된 listener는 아래와 같다. (sample.war작성하여 출력해본 결과)
listener.add> com.sun.faces.lifecycle.ELResolverInitPhaseListener listener.add> com.sun.faces.renderkit.JsfJsResourcePhaseListener listener.add> org.jboss.seam.debug.jsf.SeamDebugPhaseListener listener.add> org.jboss.seam.jsf.SeamPhaseListener listener.add> org.jboss.seam.document.DocumentStorePhaseListener listener.add> org.ajax4jsf.event.AjaxPhaseListener listener.add> org.ajax4jsf.event.InitPhaseListener listener.add> org.richfaces.component.FileUploadPhaselistener
아래는 Seam과 JSF에서 가장 핵심적인 부분의 소스를 찾아보았다.
package javax.faces.webapp;
import java.io.IOException;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public final class FacesServlet implements Servlet {
	public static final String CONFIG_FILES_ATTR = "javax.faces.CONFIG_FILES";
	public static final String LIFECYCLE_ID_ATTR = "javax.faces.LIFECYCLE_ID";
	private static final Logger LOGGER = Logger.getLogger("javax.faces.webapp", "javax.faces.LogStrings");
	private FacesContextFactory facesContextFactory = null;
	private Lifecycle lifecycle = null;
	private ServletConfig servletConfig = null;
	public void destroy() {
		this.facesContextFactory = null;
		this.lifecycle = null;
		this.servletConfig = null;
	}
	public ServletConfig getServletConfig() {
		return this.servletConfig;
	}
	public String getServletInfo() {
		return getClass().getName();
	}
	public void init(ServletConfig servletConfig) throws ServletException {
		this.servletConfig = servletConfig;
		try {
			this.facesContextFactory = ((FacesContextFactory) FactoryFinder.getFactory("javax.faces.context.FacesContextFactory"));
		} catch (FacesException e) {
			ResourceBundle rb = LOGGER.getResourceBundle();
			String msg = rb.getString("severe.webapp.facesservlet.init_failed");
			Throwable rootCause = e.getCause() != null ? e.getCause() : e;
			LOGGER.log(Level.SEVERE, msg, rootCause);
			throw new UnavailableException(msg);
		}
		try {
			LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder.getFactory("javax.faces.lifecycle.LifecycleFactory");
			String lifecycleId;
			if (null == (lifecycleId = servletConfig.getInitParameter("javax.faces.LIFECYCLE_ID"))) {
				lifecycleId = servletConfig.getServletContext().getInitParameter("javax.faces.LIFECYCLE_ID");
			}
			if (lifecycleId == null) {
				lifecycleId = "DEFAULT";
			}
			this.lifecycle = lifecycleFactory.getLifecycle(lifecycleId);
		} catch (FacesException e) {
			Throwable rootCause = e.getCause();
			if (rootCause == null) {
				throw e;
			}
			throw new ServletException(e.getMessage(), rootCause);
		}
	}
	public void service(ServletRequest request, ServletResponse response) throws IOException, ServletException {
		String pathInfo = ((HttpServletRequest) request).getPathInfo();
		if (pathInfo != null) {
			pathInfo = pathInfo.toUpperCase();
			if ((pathInfo.startsWith("/WEB-INF/")) || (pathInfo.equals("/WEB-INF")) || (pathInfo.startsWith("/META-INF/")) || (pathInfo.equals("/META-INF"))) {
				((HttpServletResponse) response).sendError(404);
				return;
			}
		}
		FacesContext context = this.facesContextFactory.getFacesContext(this.servletConfig.getServletContext(), request, response, this.lifecycle);
		System.out.println("> " + lifecycle);
		try {
			System.out.println("> lifecycle.execute(context)");
			this.lifecycle.execute(context);
			System.out.println("> lifecycle.render(context)");
			this.lifecycle.render(context);
		} catch (FacesException e) {
			Throwable t = e.getCause();
			if (t == null) {
				throw new ServletException(e.getMessage(), e);
			}
			if ((t instanceof ServletException))
				throw ((ServletException) t);
			if ((t instanceof IOException)) {
				throw ((IOException) t);
			}
			throw new ServletException(t.getMessage(), t);
		} finally {
			System.out.println("> context.release()");
			context.release();
		}
	}
}
package com.sun.faces.context;
import com.sun.faces.el.ELContextImpl;
import com.sun.faces.util.FacesLogger;
import com.sun.faces.util.RequestStateManager;
import com.sun.faces.util.Util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.el.ELContext;
import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.application.ApplicationFactory;
import javax.faces.application.FacesMessage;
import javax.faces.application.FacesMessage.Severity;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseStream;
import javax.faces.context.ResponseWriter;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.render.RenderKit;
import javax.faces.render.RenderKitFactory;
public class FacesContextImpl extends FacesContext {
	private static Logger LOGGER;
	private boolean released;
	private ResponseStream responseStream = null;
	private ResponseWriter responseWriter = null;
	private ExternalContext externalContext = null;
	private Application application = null;
	private UIViewRoot viewRoot = null;
	private ELContext elContext = null;
	private RenderKitFactory rkFactory;
	private RenderKit lastRk;
	private String lastRkId;
	private Map<String, List<FacesMessage>> componentMessageLists;
	private boolean renderResponse = false;
	private boolean responseComplete = false;
	public FacesContextImpl() {
	}
	public FacesContextImpl(ExternalContext ec, Lifecycle lifecycle) {
		Util.notNull("ec", ec);
		Util.notNull("lifecycle", lifecycle);
		this.externalContext = ec;
		setCurrentInstance(this);
		this.rkFactory = ((RenderKitFactory) FactoryFinder.getFactory("javax.faces.render.RenderKitFactory"));
	}
	public ExternalContext getExternalContext() {
		assertNotReleased();
		return this.externalContext;
	}
	public Application getApplication() {
		assertNotReleased();
		if (null != this.application) {
			return this.application;
		}
		ApplicationFactory aFactory = (ApplicationFactory) FactoryFinder.getFactory("javax.faces.application.ApplicationFactory");
		this.application = aFactory.getApplication();
		assert (null != this.application);
		return this.application;
	}
	public ELContext getELContext() {
		assertNotReleased();
		if (this.elContext == null) {
			this.elContext = new ELContextImpl(getApplication().getELResolver());
			this.elContext.putContext(FacesContext.class, this);
			UIViewRoot root = getViewRoot();
			if (null != root) {
				this.elContext.setLocale(root.getLocale());
			}
		}
		return this.elContext;
	}
	public Iterator<String> getClientIdsWithMessages() {
		assertNotReleased();
		if ( this.componentMessageLists == null ) {
			List<String> x = Collections.emptyList();
			return x.iterator();
		}
		return this.componentMessageLists.keySet().iterator();
	}
	public FacesMessage.Severity getMaximumSeverity() {
		assertNotReleased();
		FacesMessage.Severity result = null;
		if ((this.componentMessageLists != null) && (!this.componentMessageLists.isEmpty())) {
			Iterator i = new ComponentMessagesIterator(this.componentMessageLists);
			while (i.hasNext()) {
				FacesMessage.Severity severity = ((FacesMessage) i.next()).getSeverity();
				if ((result == null) || (severity.compareTo(result) > 0)) {
					result = severity;
				}
				if (result == FacesMessage.SEVERITY_FATAL) {
					break;
				}
			}
		}
		return result;
	}
	public Iterator<FacesMessage> getMessages() {
		assertNotReleased();
		if (null == this.componentMessageLists) {
			List emptyList = Collections.emptyList();
			return emptyList.iterator();
		}
		if (RequestStateManager.containsKey(this, "com.sun.faces.clientIdMessagesNotDisplayed")) {
			Set pendingClientIds = (Set) RequestStateManager.get(this, "com.sun.faces.clientIdMessagesNotDisplayed");
			pendingClientIds.clear();
		}
		if (this.componentMessageLists.size() > 0) {
			return new ComponentMessagesIterator(this.componentMessageLists);
		}
		List emptyList = Collections.emptyList();
		return emptyList.iterator();
	}
	public Iterator<FacesMessage> getMessages(String clientId) {
		assertNotReleased();
		Set pendingClientIds = (Set) RequestStateManager.get(this, "com.sun.faces.clientIdMessagesNotDisplayed");
		if ((pendingClientIds != null) && (!pendingClientIds.isEmpty())) {
			pendingClientIds.remove(clientId);
		}
		if (null == this.componentMessageLists) {
			List emptyList = Collections.emptyList();
			return emptyList.iterator();
		}
		List list = (List) this.componentMessageLists.get(clientId);
		if (list == null) {
			List emptyList = Collections.emptyList();
			return emptyList.iterator();
		}
		return list.iterator();
	}
	public RenderKit getRenderKit() {
		assertNotReleased();
		UIViewRoot vr = getViewRoot();
		if (vr == null) {
			return null;
		}
		String renderKitId = vr.getRenderKitId();
		if (renderKitId == null) {
			return null;
		}
		if (renderKitId.equals(this.lastRkId)) {
			return this.lastRk;
		}
		this.lastRk = this.rkFactory.getRenderKit(this, renderKitId);
		this.lastRkId = renderKitId;
		return this.lastRk;
	}
	public ResponseStream getResponseStream() {
		assertNotReleased();
		return this.responseStream;
	}
	public void setResponseStream(ResponseStream responseStream) {
		assertNotReleased();
		Util.notNull("responseStream", responseStream);
		this.responseStream = responseStream;
	}
	public UIViewRoot getViewRoot() {
		assertNotReleased();
		return this.viewRoot;
	}
	public void setViewRoot(UIViewRoot viewRoot) {
		assertNotReleased();
		Util.notNull("viewRoot", viewRoot);
		this.viewRoot = viewRoot;
	}
	public ResponseWriter getResponseWriter() {
		assertNotReleased();
		return this.responseWriter;
	}
	public void setResponseWriter(ResponseWriter responseWriter) {
		assertNotReleased();
		Util.notNull("responseWriter", responseWriter);
		this.responseWriter = responseWriter;
	}
	public void addMessage(String clientId, FacesMessage message) {
		assertNotReleased();
		Util.notNull("message", message);
		if (this.componentMessageLists == null) {
			this.componentMessageLists = new LinkedHashMap();
		}
		List list = (List) this.componentMessageLists.get(clientId);
		if (list == null) {
			list = new ArrayList();
			this.componentMessageLists.put(clientId, list);
		}
		list.add(message);
		if (LOGGER.isLoggable(Level.FINE))
			LOGGER.fine("Adding Message[sourceId=" + (clientId != null ? clientId : "<<NONE>>") + ",summary=" + message.getSummary() + ")");
	}
	public void release() {
		RequestStateManager.remove(this, "com.sun.faces.FacesContextImpl");
		RequestStateManager.remove(this, "com.sun.faces.clientIdMessagesNotDisplayed");
		this.released = true;
		this.externalContext = null;
		this.responseStream = null;
		this.responseWriter = null;
		this.componentMessageLists = null;
		this.renderResponse = false;
		this.responseComplete = false;
		this.viewRoot = null;
		setCurrentInstance(null);
	}
	public void renderResponse() {
		assertNotReleased();
		this.renderResponse = true;
	}
	public void responseComplete() {
		assertNotReleased();
		this.responseComplete = true;
	}
	public boolean getRenderResponse() {
		assertNotReleased();
		return this.renderResponse;
	}
	public boolean getResponseComplete() {
		assertNotReleased();
		return this.responseComplete;
	}
	private void assertNotReleased() {
		if (this.released)
			throw new IllegalStateException();
	}
	static {
		LOGGER = FacesLogger.CONTEXT.getLogger();
	}
	private static final class ComponentMessagesIterator implements Iterator<FacesMessage> {
		private Map<String, List<FacesMessage>> messages;
		private int outerIndex = -1;
		private int messagesSize;
		private Iterator<FacesMessage> inner;
		private Iterator<String> keys;
		ComponentMessagesIterator(Map<String, List<FacesMessage>> messages) {
			this.messages = messages;
			this.messagesSize = messages.size();
			this.keys = messages.keySet().iterator();
		}
		public boolean hasNext() {
			if (this.outerIndex == -1) {
				this.outerIndex += 1;
				this.inner = ((List) this.messages.get(this.keys.next())).iterator();
			}
			while (!this.inner.hasNext()) {
				this.outerIndex += 1;
				if (this.outerIndex < this.messagesSize) {
					this.inner = ((List) this.messages.get(this.keys.next())).iterator();
					continue;
				}
				return false;
			}
			return this.inner.hasNext();
		}
		public FacesMessage next() {
			if (this.outerIndex >= this.messagesSize) {
				throw new NoSuchElementException();
			}
			if ((this.inner != null) && (this.inner.hasNext())) {
				return (FacesMessage) this.inner.next();
			}
			if (!hasNext()) {
				throw new NoSuchElementException();
			}
			return (FacesMessage) this.inner.next();
		}
		public void remove() {
			if (this.outerIndex == -1) {
				throw new IllegalStateException();
			}
			this.inner.remove();
		}
	}
}
package com.sun.faces.lifecycle;
import com.sun.faces.util.FacesLogger;
import com.sun.faces.util.MessageUtils;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.FacesException;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.faces.lifecycle.Lifecycle;
public class LifecycleImpl extends Lifecycle {
	private static Logger LOGGER = FacesLogger.LIFECYCLE.getLogger();
	private Phase response = new RenderResponsePhase();
	private Phase[] phases = { null, new RestoreViewPhase(), new ApplyRequestValuesPhase(), new ProcessValidationsPhase(), new UpdateModelValuesPhase(), new InvokeApplicationPhase(), this.response };
	private List<PhaseListener> listeners = new CopyOnWriteArrayList();
	public void execute(FacesContext context) throws FacesException {
		if (context == null) {
			throw new NullPointerException(MessageUtils.getExceptionMessageString("com.sun.faces.NULL_PARAMETERS_ERROR", new Object[] { "context" }));
		}
		if (LOGGER.isLoggable(Level.FINE)) {
			LOGGER.fine("execute(" + context + ")");
		}
		int i = 1;
		for (int len = this.phases.length - 1; i < len; i++) {
			if ((context.getRenderResponse()) || (context.getResponseComplete())) {
				break;
			}
			this.phases[i].doPhase(context, this, this.listeners.listIterator());
		}
	}
	public void render(FacesContext context) throws FacesException {
		if (context == null) {
			throw new NullPointerException(MessageUtils.getExceptionMessageString("com.sun.faces.NULL_PARAMETERS_ERROR", new Object[] { "context" }));
		}
		if (LOGGER.isLoggable(Level.FINE)) {
			LOGGER.fine("render(" + context + ")");
		}
		if (!context.getResponseComplete())
			this.response.doPhase(context, this, this.listeners.listIterator());
	}
	public void addPhaseListener(PhaseListener listener) {
		if (listener == null) {
			throw new NullPointerException(MessageUtils.getExceptionMessageString("com.sun.faces.NULL_PARAMETERS_ERROR", new Object[] { "listener" }));
		}
		if (this.listeners == null) {
			this.listeners = new CopyOnWriteArrayList();
		}
		if (this.listeners.contains(listener)) {
			if (LOGGER.isLoggable(Level.FINE)) {
				LOGGER.log(Level.FINE, "jsf.lifecycle.duplicate_phase_listener_detected", listener.getClass().getName());
			}
		} else {
			if (LOGGER.isLoggable(Level.FINE)) {
				LOGGER.log(Level.FINE, "addPhaseListener({0},{1})", new Object[] { listener.getPhaseId().toString(), listener.getClass().getName() });
			}
			this.listeners.add(listener);
		}
	}
	public PhaseListener[] getPhaseListeners() {
		return (PhaseListener[]) this.listeners.toArray(new PhaseListener[this.listeners.size()]);
	}
	public void removePhaseListener(PhaseListener listener) {
		if (listener == null) {
			throw new NullPointerException(MessageUtils.getExceptionMessageString("com.sun.faces.NULL_PARAMETERS_ERROR", new Object[] { "listener" }));
		}
		if ((this.listeners.remove(listener)) && (LOGGER.isLoggable(Level.FINE)))
			LOGGER.log(Level.FINE, "removePhaseListener({0})", new Object[] { listener.getClass().getName() });
	}
}
package org.ajax4jsf.application;
import java.io.IOException;
import java.util.Map;
import javax.faces.FacesException;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.ajax4jsf.Messages;
import org.ajax4jsf.component.AjaxViewRoot;
import org.ajax4jsf.context.AjaxContext;
import org.ajax4jsf.context.ViewIdHolder;
import org.ajax4jsf.context.ViewResources;
import org.ajax4jsf.resource.InternetResource;
import org.ajax4jsf.resource.InternetResourceBuilder;
import org.ajax4jsf.webapp.FilterServletResponseWrapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.richfaces.event.RenderPhaseComponentListener;
public class AjaxViewHandler extends ViewHandlerWrapper
{
  public static final String RESOURCES_PROCESSED = "org.ajax4jsf.framework.HEADER_PROCESSED";
  public static final String STATE_MARKER_KEY = "org.ajax4jsf.view.state";
  public static final String SERIALIZED_STATE_KEY = "org.ajax4jsf.view.serializedstate";
  private static final Log _log = LogFactory.getLog(AjaxViewHandler.class);
  public static final String VIEW_EXPIRED = "org.ajax4jsf.view.EXPIRED";
  public static final String VIEW_ID_KEY = "org.ajax4jsf.VIEW_ID";
  public AjaxViewHandler(ViewHandler parent)
  {
    super(parent);
    if (_log.isDebugEnabled())
      _log.debug("Create instance of Ajax ViewHandler");
  }
  public UIViewRoot createView(FacesContext facesContext, String viewId)
  {
    AjaxContext ajaxContext = AjaxContext.getCurrentInstance(facesContext);
    ViewIdHolder viewIdHolder = ajaxContext.getViewIdHolder();
    UIViewRoot riRoot;
    UIViewRoot riRoot;
    if ((null != viewIdHolder) && (viewIdHolder.skipNavigation(viewId))) {
      viewIdHolder.setViewId(viewId);
      riRoot = facesContext.getViewRoot();
    } else {
      riRoot = super.createView(facesContext, viewId);
      riRoot.addPhaseListener(new RenderPhaseComponentListener());
      if (null != facesContext.getViewRoot()) {
        ajaxContext.setAjaxRequest(false);
      }
    }
    return riRoot;
  }
  public void writeState(FacesContext context)
    throws IOException
  {
    AjaxContext ajaxContext = AjaxContext.getCurrentInstance(context);
    if ((ajaxContext.isAjaxRequest()) && (ajaxContext.isSelfRender()))
    {
      ResponseWriter writer = context.getResponseWriter();
      writer.startElement("span", null);
      writer.writeAttribute("id", "org.ajax4jsf.view.state", null);
      writer.writeAttribute("name", "org.ajax4jsf.view.state", null);
      writer.endElement("span");
    } else {
      super.writeState(context);
    }
  }
  public String getResourceURL(FacesContext context, String url)
  {
    String resourceURL;
    String resourceURL;
    if (url.startsWith("resource://")) {
      InternetResource resource = InternetResourceBuilder.getInstance().createResource(null, url.substring(InternetResource.RESOURCE_URI_PREFIX_LENGTH));
      resourceURL = resource.getUri(context, null);
    } else {
      resourceURL = super.getResourceURL(context, url);
    }
    return resourceURL;
  }
  public void renderView(FacesContext context, UIViewRoot root)
    throws IOException, FacesException
  {
    AjaxContext ajaxContext = AjaxContext.getCurrentInstance(context);
    if ((root instanceof AjaxViewRoot)) {
      AjaxViewRoot ajaxRoot = (AjaxViewRoot)root;
      if (ajaxContext.isAjaxRequest()) {
        processAjaxEvents(context, ajaxRoot);
        if (ajaxContext.isSelfRender())
        {
          ajaxContext.renderAjax(context);
        }
      }
      if (!context.getResponseComplete())
        super.renderView(context, root);
    }
    else {
      super.renderView(context, root);
    }
    Map requestMap = context.getExternalContext().getRequestMap();
    FilterServletResponseWrapper filterServletResponseWrapper = (FilterServletResponseWrapper)requestMap.get("com.exade.vcp.Filter.ResponseWrapper");
    if (null != filterServletResponseWrapper) {
      if ((!filterServletResponseWrapper.isError()) &&
        (!Boolean.TRUE.equals(requestMap.get("org.ajax4jsf.framework.HEADER_PROCESSED"))))
      {
        ViewResources viewResources = new ViewResources();
        viewResources.initialize(context);
        viewResources.processHeadResources(context);
        requestMap.put("org.ajax4jsf.framework.HEAD_EVENTS_LIST", viewResources.getHeadEvents());
        requestMap.put("org.ajax4jsf.framework.HEADER_PROCESSED", Boolean.TRUE);
      }
      requestMap.put("org.ajax4jsf.VIEW_ID", context.getViewRoot().getViewId());
    }
  }
  private void processAjaxEvents(FacesContext context, AjaxViewRoot ajaxRoot)
  {
    if (_log.isDebugEnabled()) {
      _log.debug(Messages.getMessage("PROCESS_AJAX_EVENTS_INFO"));
    }
    ajaxRoot.broadcastAjaxEvents(context);
  }
}
package javax.faces.component;
import javax.el.ELException;
import javax.el.MethodExpression;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.application.Application;
import javax.faces.context.FacesContext;
import javax.faces.el.MethodBinding;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
import javax.faces.event.FacesEvent;
import javax.faces.event.PhaseId;
public class UICommand extends UIComponentBase
  implements ActionSource2
{
  public static final String COMPONENT_TYPE = "javax.faces.Command";
  public static final String COMPONENT_FAMILY = "javax.faces.Command";
  private Object value = null;
  private Boolean immediate;
  private MethodBinding methodBindingActionListener = null;
  private MethodExpression actionExpression = null;
  private Object[] values;
  public UICommand()
  {
    setRendererType("javax.faces.Button");
  }
  public String getFamily()
  {
    return "javax.faces.Command";
  }
  /** @deprecated */
  public MethodBinding getAction()
  {
    MethodBinding result = null;
    MethodExpression me;
    if (null != (me = getActionExpression()))
    {
      if (me.getClass().equals(MethodExpressionMethodBindingAdapter.class)) {
        result = ((MethodExpressionMethodBindingAdapter)me).getWrapped();
      }
      else
      {
        result = new MethodBindingMethodExpressionAdapter(me);
      }
    }
    return result;
  }
  /** @deprecated */
  public void setAction(MethodBinding action)
  {
    if (null != action) {
      MethodExpressionMethodBindingAdapter adapter = new MethodExpressionMethodBindingAdapter(action);
      setActionExpression(adapter);
    }
    else {
      setActionExpression(null);
    }
  }
  /** @deprecated */
  public MethodBinding getActionListener()
  {
    return this.methodBindingActionListener;
  }
  /** @deprecated */
  public void setActionListener(MethodBinding actionListener)
  {
    this.methodBindingActionListener = actionListener;
  }
  public boolean isImmediate()
  {
    if (this.immediate != null) {
      return this.immediate.booleanValue();
    }
    ValueExpression ve = getValueExpression("immediate");
    if (ve != null) {
      try {
        return Boolean.TRUE.equals(ve.getValue(getFacesContext().getELContext()));
      }
      catch (ELException e) {
        throw new FacesException(e);
      }
    }
    return false;
  }
  public void setImmediate(boolean immediate)
  {
    this.immediate = Boolean.valueOf(immediate);
  }
  public Object getValue()
  {
    if (this.value != null) {
      return this.value;
    }
    ValueExpression ve = getValueExpression("value");
    if (ve != null) {
      try {
        return ve.getValue(getFacesContext().getELContext());
      }
      catch (ELException e) {
        throw new FacesException(e);
      }
    }
    return null;
  }
  public void setValue(Object value)
  {
    this.value = value;
  }
  public MethodExpression getActionExpression()
  {
    return this.actionExpression;
  }
  public void setActionExpression(MethodExpression actionExpression) {
    this.actionExpression = actionExpression;
  }
  public void addActionListener(ActionListener listener)
  {
    addFacesListener(listener);
  }
  public ActionListener[] getActionListeners()
  {
    ActionListener[] al = (ActionListener[])(ActionListener[])getFacesListeners(ActionListener.class);
    return al;
  }
  public void removeActionListener(ActionListener listener)
  {
    removeFacesListener(listener);
  }
  public Object saveState(FacesContext context)
  {
    if (this.values == null) {
      this.values = new Object[5];
    }
    this.values[0] = super.saveState(context);
    this.values[1] = saveAttachedState(context, this.methodBindingActionListener);
    this.values[2] = saveAttachedState(context, this.actionExpression);
    this.values[3] = this.immediate;
    this.values[4] = this.value;
    return this.values;
  }
  public void restoreState(FacesContext context, Object state)
  {
    this.values = ((Object[])(Object[])state);
    super.restoreState(context, this.values[0]);
    this.methodBindingActionListener = ((MethodBinding)restoreAttachedState(context, this.values[1]));
    this.actionExpression = ((MethodExpression)restoreAttachedState(context, this.values[2]));
    this.immediate = ((Boolean)this.values[3]);
    this.value = this.values[4];
  }
  public void broadcast(FacesEvent event)
    throws AbortProcessingException
  {
    super.broadcast(event);
    if ((event instanceof ActionEvent)) {
      FacesContext context = getFacesContext();
      MethodBinding mb = getActionListener();
      if (mb != null) {
        mb.invoke(context, new Object[] { event });
      }
      ActionListener listener = context.getApplication().getActionListener();
      if (listener != null)
        listener.processAction((ActionEvent)event);
    }
  }
  public void queueEvent(FacesEvent e)
  {
    UIComponent c = e.getComponent();
    if (((e instanceof ActionEvent)) && ((c instanceof ActionSource))) {
      if (((ActionSource)c).isImmediate())
        e.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
      else {
        e.setPhaseId(PhaseId.INVOKE_APPLICATION);
      }
    }
    super.queueEvent(e);
  }
}
package org.ajax4jsf.component;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.el.MethodExpression;
import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.component.ContextCallback;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.FacesEvent;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.faces.render.Renderer;
import org.ajax4jsf.Messages;
import org.ajax4jsf.context.AjaxContext;
import org.ajax4jsf.context.InvokerCallback;
import org.ajax4jsf.context.ViewIdHolder;
import org.ajax4jsf.event.AjaxListener;
import org.ajax4jsf.event.EventsQueue;
import org.ajax4jsf.renderkit.AjaxContainerRenderer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class AjaxViewRoot extends UIViewRoot
  implements AjaxContainer
{
  public static final String ROOT_ID = "_viewRoot";
  public static final String JS_NULL = "null";
  private Lifecycle lifecycle;
  private AjaxRegionBrige _brige;
  private static final Log _log = LogFactory.getLog(AjaxViewRoot.class);
  private List<PhaseListener> phaseListeners = null;
  private EventsQueue[] events;
  private EventsQueue ajaxEvents = new EventsQueue();
  private InvokerCallback _decodeInvoker = new InvokerCallback()
  {
    public void invokeContextCallback(FacesContext context, UIComponent component)
    {
      component.processDecodes(context);
    }
    public void invokeRoot(FacesContext context) {
      AjaxViewRoot.this.decode(context);
    }
  };
  private InvokerCallback _updatesInvoker = new InvokerCallback()
  {
    public void invokeContextCallback(FacesContext context, UIComponent component)
    {
      component.processUpdates(context);
    }
    public void invokeRoot(FacesContext context)
    {
    }
  };
  private InvokerCallback _validatorsInvoker = new InvokerCallback()
  {
    public void invokeContextCallback(FacesContext context, UIComponent component)
    {
      component.processValidators(context);
    }
    public void invokeRoot(FacesContext context)
    {
    }
  };
  private ContextCallback _ajaxInvoker = new ContextCallback()
  {
    public void invokeContextCallback(FacesContext context, UIComponent component)
    {
      try {
        if ((component instanceof AjaxContainer)) {
          AjaxContainer ajax = (AjaxContainer)component;
          ajax.encodeAjax(context);
        }
        else {
          AjaxViewRoot.this.encodeAjax(context);
        }
      } catch (IOException e) {
        throw new FacesException(e);
      }
    }
  };
  public AjaxViewRoot()
  {
    super.setId("_viewRoot");
    this._brige = new AjaxRegionBrige(this);
  }
  public String getRendererType()
  {
    return "javax.faces.ViewRoot";
  }
  public void broadcast(FacesEvent event)
    throws AbortProcessingException
  {
    super.broadcast(event);
    getBrige().broadcast(event);
  }
  public MethodExpression getAjaxListener()
  {
    return getBrige().getAjaxListener();
  }
  public boolean isImmediate()
  {
    return getBrige().isImmediate();
  }
  public boolean isSubmitted()
  {
    return getBrige().isSubmitted();
  }
  public void removePhaseListener(PhaseListener toRemove)
  {
    if (null != this.phaseListeners) {
      this.phaseListeners.remove(toRemove);
    }
    super.removePhaseListener(toRemove);
  }
  public void addPhaseListener(PhaseListener newPhaseListener) {
    if (null == this.phaseListeners) {
      this.phaseListeners = new ArrayList();
    }
    this.phaseListeners.add(newPhaseListener);
    super.addPhaseListener(newPhaseListener);
  }
  protected void processPhaseListeners(FacesContext context, PhaseId phase, boolean before)
  {
    MethodExpression listenerExpression = before ? getBeforePhaseListener() : getAfterPhaseListener();
    PhaseEvent event = null;
    if (null != listenerExpression) {
      event = createPhaseEvent(context, phase);
      listenerExpression.invoke(context.getELContext(), new Object[] { event });
    }
    if (null != this.phaseListeners)
      for (PhaseListener listener : this.phaseListeners) {
        PhaseId phaseId = listener.getPhaseId();
        if ((phaseId == phase) || (phaseId == PhaseId.ANY_PHASE)) {
          if (null == event) {
            event = createPhaseEvent(context, phase);
          }
          if (before)
            listener.beforePhase(event);
          else
            listener.afterPhase(event);
        }
      }
  }
  protected PhaseEvent createPhaseEvent(FacesContext context, PhaseId phaseId)
    throws FacesException
  {
    if (this.lifecycle == null) {
      LifecycleFactory lifecycleFactory = (LifecycleFactory)FactoryFinder.getFactory("javax.faces.lifecycle.LifecycleFactory");
      String lifecycleId = context.getExternalContext().getInitParameter("javax.faces.LIFECYCLE_ID");
      if (lifecycleId == null) {
        lifecycleId = "DEFAULT";
      }
      this.lifecycle = lifecycleFactory.getLifecycle(lifecycleId);
    }
    return new PhaseEvent(context, phaseId, this.lifecycle);
  }
  protected void processPhase(FacesContext context, PhaseId phase, InvokerCallback callback)
  {
    processPhaseListeners(context, phase, true);
    InvokerCallback invokerCallback;
    if ((null != callback) && (!context.getRenderResponse()) && (!context.getResponseComplete()))
    {
      AjaxContext ajaxContext = AjaxContext.getCurrentInstance(context);
      String submittedRegionClientId = ajaxContext.getSubmittedRegionClientId();
      if ((ajaxContext.isAjaxRequest()) && (submittedRegionClientId != null) && (!submittedRegionClientId.equals("null")) && (!submittedRegionClientId.equals(getClientId(context))))
      {
        invokeOnComponent(context, submittedRegionClientId, new InvokerCallbackWrapper(callback));
      }
      else
      {
        try {
          callback.invokeRoot(context);
        } catch (RuntimeException e) {
          context.renderResponse();
          throw e;
        }
        String ajaxSingleClientId = ajaxContext.getAjaxSingleClientId();
        if (null == ajaxSingleClientId) {
          Iterator iter = getFacetsAndChildren();
          while (iter.hasNext())
            callback.invokeContextCallback(context, (UIComponent)iter.next());
        }
        else {
          invokerCallback = new InvokerCallbackWrapper(callback);
          invokeOnComponent(context, ajaxSingleClientId, invokerCallback);
          Set areasToProcess = ajaxContext.getAjaxAreasToProcess();
          if (null != areasToProcess) {
            for (String areaId : areasToProcess) {
              invokeOnComponent(context, areaId, invokerCallback);
            }
          }
        }
      }
    }
    broadcastEvents(context, phase);
    processPhaseListeners(context, phase, false);
  }
  public void queueEvent(FacesEvent event)
  {
    if (event == null) {
      throw new NullPointerException(Messages.getMessage("NULL_EVENT_SUBMITTED_ERROR"));
    }
    if (event.getPhaseId().compareTo(PhaseId.RENDER_RESPONSE) == 0)
    {
      getAjaxEventsQueue().offer(event);
    }
    else getEventsQueue(event.getPhaseId()).offer(event);
  }
  void broadcastEvents(FacesContext context, PhaseId phaseId)
  {
    EventsQueue[] events = getEvents();
    EventsQueue anyPhaseEvents = events[PhaseId.ANY_PHASE.getOrdinal()];
    EventsQueue phaseEvents = events[phaseId.getOrdinal()];
    if ((phaseEvents.isEmpty()) && (anyPhaseEvents.isEmpty())) {
      return;
    }
    boolean haveAnyPhaseEvents = !anyPhaseEvents.isEmpty();
    boolean havePhaseEvents = !phaseEvents.isEmpty();
    do
    {
      processEvents(context, anyPhaseEvents, haveAnyPhaseEvents);
      processEvents(context, phaseEvents, havePhaseEvents);
      haveAnyPhaseEvents = !anyPhaseEvents.isEmpty();
      havePhaseEvents = !phaseEvents.isEmpty();
    }while ((haveAnyPhaseEvents) || (havePhaseEvents));
    if ((context.getRenderResponse()) || (context.getResponseComplete()))
      clearEvents();
  }
  public void processEvents(FacesContext context, EventsQueue phaseEventsQueue, boolean havePhaseEvents)
  {
    while (havePhaseEvents)
      try {
        FacesEvent event = (FacesEvent)phaseEventsQueue.remove();
        UIComponent source = event.getComponent();
        try {
          source.broadcast(event);
        } catch (AbortProcessingException e) {
          if (_log.isErrorEnabled()) {
            UIComponent component = event.getComponent();
            String id = null != component ? component.getClientId(context) : "";
            _log.error("Error processing faces event for the component " + id, e);
          }
        }
      }
      catch (NoSuchElementException e)
      {
        havePhaseEvents = false;
      }
  }
  public void broadcastAjaxEvents(FacesContext context)
  {
    EventsQueue queue = getAjaxEventsQueue();
    processEvents(context, queue, !queue.isEmpty());
  }
  protected EventsQueue getEventsQueue(PhaseId phase)
  {
    return getEvents()[phase.getOrdinal()];
  }
  protected EventsQueue[] getEvents()
  {
    if (this.events == null) {
      clearEvents();
    }
    return this.events;
  }
  protected EventsQueue getAjaxEventsQueue()
  {
    return this.ajaxEvents;
  }
  public void clearEvents()
  {
    int len;
    this.events = new EventsQueue[len = PhaseId.VALUES.size()];
    for (int i = 0; i < len; i++)
      this.events[i] = new EventsQueue();
  }
  public void processDecodes(FacesContext context)
  {
    if (context == null)
      throw new NullPointerException("context");
    processPhase(context, PhaseId.APPLY_REQUEST_VALUES, this._decodeInvoker);
  }
  public void processUpdates(FacesContext context)
  {
    if (context == null)
      throw new NullPointerException("context");
    processPhase(context, PhaseId.UPDATE_MODEL_VALUES, this._updatesInvoker);
  }
  public void processValidators(FacesContext context)
  {
    if (context == null)
      throw new NullPointerException("context");
    processPhase(context, PhaseId.PROCESS_VALIDATIONS, this._validatorsInvoker);
  }
  public void processApplication(FacesContext context)
  {
    if (context == null)
      throw new NullPointerException("context");
    processPhase(context, PhaseId.INVOKE_APPLICATION, null);
  }
  public void encodeBegin(FacesContext context)
    throws IOException
  {
    processPhaseListeners(context, PhaseId.RENDER_RESPONSE, true);
    String rendererType = getRendererType();
    if (rendererType != null) {
      Renderer renderer = getRenderer(context);
      if (renderer != null)
        renderer.encodeBegin(context, this);
    }
  }
  public void encodeEnd(FacesContext context)
    throws IOException
  {
    String rendererType = getRendererType();
    if (rendererType != null) {
      Renderer renderer = getRenderer(context);
      if (renderer != null) {
        renderer.encodeEnd(context, this);
      }
    }
    processPhaseListeners(context, PhaseId.RENDER_RESPONSE, false);
  }
  public void encodeChildren(FacesContext context)
    throws IOException
  {
    AjaxContext ajaxContext = AjaxContext.getCurrentInstance(context);
    if (ajaxContext.isAjaxRequest()) {
      String submittedRegionClientId = ajaxContext.getSubmittedRegionClientId();
      boolean invoked = false;
      if ((submittedRegionClientId != null) && (!submittedRegionClientId.equals("null")) && (!submittedRegionClientId.equals(getClientId(context)))) {
        invoked = invokeOnComponent(context, submittedRegionClientId, this._ajaxInvoker);
      }
      if (!invoked)
        encodeAjax(context);
    }
    else {
      super.encodeChildren(context);
    }
  }
  public void restoreState(FacesContext context, Object state)
  {
    Object[] mystate = (Object[])(Object[])state;
    super.restoreState(context, mystate[0]);
    getBrige().restoreState(context, mystate[1]);
    Object listeners = restoreAttachedState(context, mystate[2]);
    if (null != listeners)
      this.phaseListeners = ((List)listeners);
  }
  public Object saveState(FacesContext context)
  {
    Object[] state = new Object[3];
    state[0] = super.saveState(context);
    state[1] = getBrige().saveState(context);
    state[2] = saveAttachedState(context, this.phaseListeners);
    return state;
  }
  public String getViewId() {
    ViewIdHolder viewIdHolder = AjaxContext.getCurrentInstance().getViewIdHolder();
    String viewId;
    String viewId;
    if (null != viewIdHolder)
      viewId = viewIdHolder.getViewId();
    else {
      viewId = super.getViewId();
    }
    return viewId;
  }
  public void setAjaxListener(MethodExpression ajaxListener)
  {
    getBrige().setAjaxListener(ajaxListener);
  }
  public void setImmediate(boolean immediate)
  {
    getBrige().setImmediate(immediate);
  }
  public void setSubmitted(boolean submitted)
  {
    getBrige().setSubmitted(submitted);
  }
  public void addAjaxListener(AjaxListener listener) {
    addFacesListener(listener);
  }
  public AjaxListener[] getAjaxListeners() {
    return (AjaxListener[])(AjaxListener[])getFacesListeners(AjaxListener.class);
  }
  public void removeAjaxListener(AjaxListener listener) {
    removeFacesListener(listener);
  }
  public boolean isSelfRendered()
  {
    return false;
  }
  public void setSelfRendered(boolean selfRendered)
  {
  }
  public boolean getRendersChildren()
  {
    FacesContext context = FacesContext.getCurrentInstance();
    return AjaxContext.getCurrentInstance(context).isAjaxRequest();
  }
  public boolean isRenderRegionOnly()
  {
    return false;
  }
  public void setRenderRegionOnly(boolean reRenderPage)
  {
  }
  public void encodeAjax(FacesContext context) throws IOException {
    String rendererType = getRendererType();
    if (rendererType != null)
      ((AjaxContainerRenderer)getRenderer(context)).encodeAjax(context, this);
  }
  protected AjaxRegionBrige getBrige()
  {
    return this._brige;
  }
}
package com.sun.facelets;
import com.sun.facelets.compiler.Compiler;
import com.sun.facelets.compiler.SAXCompiler;
import com.sun.facelets.compiler.TagLibraryConfig;
import com.sun.facelets.impl.DefaultFaceletFactory;
import com.sun.facelets.impl.DefaultResourceResolver;
import com.sun.facelets.impl.ResourceResolver;
import com.sun.facelets.tag.TagDecorator;
import com.sun.facelets.tag.TagLibrary;
import com.sun.facelets.tag.jsf.ComponentSupport;
import com.sun.facelets.tag.ui.UIDebug;
import com.sun.facelets.util.DevTools;
import com.sun.facelets.util.FacesAPI;
import com.sun.facelets.util.ReflectionUtil;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.el.ELException;
import javax.faces.FacesException;
import javax.faces.application.Application;
import javax.faces.application.StateManager;
import javax.faces.application.StateManager.SerializedView;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.RenderKit;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FaceletViewHandler extends ViewHandler
{
  protected static final Logger log = Logger.getLogger("facelets.viewhandler");
  public static final long DEFAULT_REFRESH_PERIOD = 2L;
  public static final String PARAM_REFRESH_PERIOD = "facelets.REFRESH_PERIOD";
  /** @deprecated */
  public static final String PARAM_REFRESH_PERIO = "facelets.REFRESH_PERIOD";
  public static final String PARAM_SKIP_COMMENTS = "facelets.SKIP_COMMENTS";
  public static final String PARAM_VIEW_MAPPINGS = "facelets.VIEW_MAPPINGS";
  public static final String PARAM_LIBRARIES = "facelets.LIBRARIES";
  public static final String PARAM_DECORATORS = "facelets.DECORATORS";
  public static final String PARAM_DEVELOPMENT = "facelets.DEVELOPMENT";
  public static final String PARAM_RESOURCE_RESOLVER = "facelets.RESOURCE_RESOLVER";
  public static final String PARAM_BUILD_BEFORE_RESTORE = "facelets.BUILD_BEFORE_RESTORE";
  public static final String PARAM_BUFFER_SIZE = "facelets.BUFFER_SIZE";
  private static final String STATE_KEY = "~facelets.VIEW_STATE~";
  private static final int STATE_KEY_LEN = "~facelets.VIEW_STATE~".length();
  private static final Object STATE_NULL = new Object();
  private final ViewHandler parent;
  private boolean developmentMode = false;
  private boolean buildBeforeRestore = false;
  private int bufferSize;
  private String defaultSuffix;
  private FaceletFactory faceletFactory;
  private String[] extensionsArray;
  private String[] prefixesArray;
  public FaceletViewHandler(ViewHandler parent)
  {
    this.parent = parent;
  }
  protected void initialize(FacesContext context)
  {
    synchronized (this) {
      if (this.faceletFactory == null) {
        log.fine("Initializing");
        Compiler c = createCompiler();
        initializeCompiler(c);
        this.faceletFactory = createFaceletFactory(c);
        initializeMappings(context);
        initializeMode(context);
        initializeBuffer(context);
        log.fine("Initialization Successful");
      }
    }
  }
  private void initializeMode(FacesContext context) {
    ExternalContext external = context.getExternalContext();
    String param = external.getInitParameter("facelets.DEVELOPMENT");
    this.developmentMode = "true".equals(param);
    String restoreMode = external.getInitParameter("facelets.BUILD_BEFORE_RESTORE");
    this.buildBeforeRestore = "true".equals(restoreMode);
  }
  private void initializeBuffer(FacesContext context) {
    ExternalContext external = context.getExternalContext();
    String param = external.getInitParameter("facelets.BUFFER_SIZE");
    this.bufferSize = ((param != null) && (!"".equals(param)) ? Integer.parseInt(param) : -1);
  }
  private void initializeMappings(FacesContext context)
  {
    ExternalContext external = context.getExternalContext();
    String viewMappings = external.getInitParameter("facelets.VIEW_MAPPINGS");
    if ((viewMappings != null) && (viewMappings.length() > 0)) {
      String[] mappingsArray = viewMappings.split(";");
      List extensionsList = new ArrayList(mappingsArray.length);
      List prefixesList = new ArrayList(mappingsArray.length);
      for (int i = 0; i < mappingsArray.length; i++) {
        String mapping = mappingsArray[i].trim();
        int mappingLength = mapping.length();
        if (mappingLength <= 1)
        {
          continue;
        }
        if (mapping.charAt(0) == '*')
          extensionsList.add(mapping.substring(1));
        else if (mapping.charAt(mappingLength - 1) == '*') {
          prefixesList.add(mapping.substring(0, mappingLength - 1));
        }
      }
      this.extensionsArray = new String[extensionsList.size()];
      extensionsList.toArray(this.extensionsArray);
      this.prefixesArray = new String[prefixesList.size()];
      prefixesList.toArray(this.prefixesArray);
    }
  }
  protected FaceletFactory createFaceletFactory(Compiler c)
  {
    long refreshPeriod = 2L;
    FacesContext ctx = FacesContext.getCurrentInstance();
    String userPeriod = ctx.getExternalContext().getInitParameter("facelets.REFRESH_PERIOD");
    if ((userPeriod != null) && (userPeriod.length() > 0)) {
      refreshPeriod = Long.parseLong(userPeriod);
    }
    ResourceResolver resolver = new DefaultResourceResolver();
    String resolverName = ctx.getExternalContext().getInitParameter("facelets.RESOURCE_RESOLVER");
    if ((resolverName != null) && (resolverName.length() > 0)) {
      try {
        resolver = (ResourceResolver)ReflectionUtil.forName(resolverName).newInstance();
      }
      catch (Exception e) {
        throw new FacesException("Error Initializing ResourceResolver[" + resolverName + "]", e);
      }
    }
    return new DefaultFaceletFactory(c, resolver, refreshPeriod);
  }
  protected Compiler createCompiler() {
    return new SAXCompiler();
  }
  protected void initializeCompiler(Compiler c) {
    FacesContext ctx = FacesContext.getCurrentInstance();
    ExternalContext ext = ctx.getExternalContext();
    String libParam = ext.getInitParameter("facelets.LIBRARIES");
    if (libParam != null) {
      libParam = libParam.trim();
      String[] libs = libParam.split(";");
      for (int i = 0; i < libs.length; i++) {
        try {
          URL src = ext.getResource(libs[i].trim());
          if (src == null) {
            throw new FileNotFoundException(libs[i]);
          }
          TagLibrary libObj = TagLibraryConfig.create(src);
          c.addTagLibrary(libObj);
          log.fine("Successfully Loaded Library: " + libs[i]);
        } catch (IOException e) {
          log.log(Level.SEVERE, "Error Loading Library: " + libs[i], e);
        }
      }
    }
    String decParam = ext.getInitParameter("facelets.DECORATORS");
    if (decParam != null) {
      decParam = decParam.trim();
      String[] decs = decParam.split(";");
      for (int i = 0; i < decs.length; i++) {
        try {
          TagDecorator decObj = (TagDecorator)ReflectionUtil.forName(decs[i]).newInstance();
          c.addTagDecorator(decObj);
          log.fine("Successfully Loaded Decorator: " + decs[i]);
        } catch (Exception e) {
          log.log(Level.SEVERE, "Error Loading Decorator: " + decs[i], e);
        }
      }
    }
    String skipParam = ext.getInitParameter("facelets.SKIP_COMMENTS");
    if ((skipParam != null) && ("true".equals(skipParam)))
      c.setTrimmingComments(true);
  }
  public UIViewRoot restoreView(FacesContext context, String viewId)
  {
    if (UIDebug.debugRequest(context)) {
      return new UIViewRoot();
    }
    if ((!this.buildBeforeRestore) || (!handledByFacelets(viewId))) {
      return this.parent.restoreView(context, viewId);
    }
    if (this.faceletFactory == null) {
      initialize(context);
    }
    if ((FacesAPI.getVersion() < 12) &&
      (!isPostback11(context))) {
      return null;
    }
    ViewHandler outerViewHandler = context.getApplication().getViewHandler();
    String renderKitId = outerViewHandler.calculateRenderKitId(context);
    UIViewRoot viewRoot = createView(context, viewId);
    context.setViewRoot(viewRoot);
    try {
      buildView(context, viewRoot);
    } catch (IOException ioe) {
      log.log(Level.SEVERE, "Error Building View", ioe);
    }
    context.getApplication().getStateManager().restoreView(context, viewId, renderKitId);
    return viewRoot;
  }
  protected ViewHandler getWrapped()
  {
    return this.parent;
  }
  protected ResponseWriter createResponseWriter(FacesContext context) throws IOException, FacesException
  {
    ExternalContext extContext = context.getExternalContext();
    RenderKit renderKit = context.getRenderKit();
    if (renderKit == null) {
      String id = context.getViewRoot().getRenderKitId();
      throw new IllegalStateException("No render kit was available for id \"" + id + "\"");
    }
    ServletResponse response = (ServletResponse)extContext.getResponse();
    if (this.bufferSize != -1) {
      response.setBufferSize(this.bufferSize);
    }
    String contentType = (String)extContext.getRequestMap().get("facelets.ContentType");
    String encoding = (String)extContext.getRequestMap().get("facelets.Encoding");
    if ((contentType != null) && (!contentType.equals("*/*"))) {
      contentType = contentType + ",*/*";
    }
    try
    {
      writer = renderKit.createResponseWriter(NullWriter.Instance, contentType, encoding);
    }
    catch (IllegalArgumentException e)
    {
      log.fine("The impl didn't correctly handled '*/*' in the content type list.  Trying '*/*' directly.");
      writer = renderKit.createResponseWriter(NullWriter.Instance, "*/*", encoding);
    }
    contentType = getResponseContentType(context, writer.getContentType());
    encoding = getResponseEncoding(context, writer.getCharacterEncoding());
    response.setContentType(contentType + "; charset=" + encoding);
    ResponseWriter writer = writer.cloneWithWriter(response.getWriter());
    return writer;
  }
  protected String getResponseEncoding(FacesContext context, String orig)
  {
    String encoding = orig;
    Map m = context.getExternalContext().getRequestMap();
    Map sm = context.getExternalContext().getSessionMap();
    if (m.containsKey("facelets.Encoding")) {
      encoding = (String)m.get("facelets.Encoding");
      if (log.isLoggable(Level.FINEST)) {
        log.finest("Facelet specified alternate encoding '" + encoding + "'");
      }
      sm.put("javax.faces.request.charset", encoding);
    }
    Object request = context.getExternalContext().getRequest();
    if ((encoding == null) && ((request instanceof ServletRequest))) {
      encoding = ((ServletRequest)request).getCharacterEncoding();
    }
    if (encoding == null) {
      encoding = (String)sm.get("javax.faces.request.charset");
      if (log.isLoggable(Level.FINEST)) {
        log.finest("Session specified alternate encoding '" + encoding + "'");
      }
    }
    if (encoding == null) {
      encoding = "UTF-8";
      if (log.isLoggable(Level.FINEST)) {
        log.finest("ResponseWriter created had a null CharacterEncoding, defaulting to UTF-8");
      }
    }
    return encoding;
  }
  protected String getResponseContentType(FacesContext context, String orig)
  {
    String contentType = orig;
    Map m = context.getExternalContext().getRequestMap();
    if (m.containsKey("facelets.ContentType")) {
      contentType = (String)m.get("facelets.ContentType");
      if (log.isLoggable(Level.FINEST)) {
        log.finest("Facelet specified alternate contentType '" + contentType + "'");
      }
    }
    if (contentType == null) {
      contentType = "text/html";
      if (log.isLoggable(Level.FINEST)) {
        log.finest("ResponseWriter created had a null ContentType, defaulting to text/html");
      }
    }
    return contentType;
  }
  protected void buildView(FacesContext context, UIViewRoot viewToRender)
    throws IOException, FacesException
  {
    String renderedViewId = getRenderedViewId(context, viewToRender.getViewId());
    viewToRender.setViewId(renderedViewId);
    if (log.isLoggable(Level.FINE)) {
      log.fine("Building View: " + renderedViewId);
    }
    Facelet f = null;
    FaceletFactory.setInstance(this.faceletFactory);
    try {
      f = this.faceletFactory.getFacelet(viewToRender.getViewId());
    } finally {
      FaceletFactory.setInstance(null);
    }
    long time = System.currentTimeMillis();
    f.apply(context, viewToRender);
    time = System.currentTimeMillis() - time;
    if (log.isLoggable(Level.FINE))
      log.fine("Took " + time + "ms to build view: " + viewToRender.getViewId());
  }
  public void renderView(FacesContext context, UIViewRoot viewToRender)
    throws IOException, FacesException
  {
    if (this.faceletFactory == null) {
      initialize(context);
    }
    if (!viewToRender.isRendered()) {
      return;
    }
    if (!handledByFacelets(viewToRender.getViewId())) {
      this.parent.renderView(context, viewToRender);
      return;
    }
    if (log.isLoggable(Level.FINE)) {
      log.fine("Rendering View: " + viewToRender.getViewId());
    }
    StateWriter stateWriter = null;
    try
    {
      if ((!this.buildBeforeRestore) || (viewToRender.getChildren().isEmpty()))
      {
        buildView(context, viewToRender);
      }
      ResponseWriter origWriter = createResponseWriter(context);
      stateWriter = new StateWriter(origWriter, this.bufferSize != -1 ? this.bufferSize : 1024);
      ResponseWriter writer = origWriter.cloneWithWriter(stateWriter);
      context.setResponseWriter(writer);
      StateManager stateMgr = context.getApplication().getStateManager();
      if (!stateMgr.isSavingStateInClient(context)) {
        context.getExternalContext().getSession(true);
      }
      long time = System.currentTimeMillis();
      writer.startDocument();
      if (FacesAPI.getVersion() >= 12)
        viewToRender.encodeAll(context);
      else {
        ComponentSupport.encodeRecursive(context, viewToRender);
      }
      writer.endDocument();
      writer.close();
      if (FacesAPI.getVersion() < 12) {
        ComponentSupport.removeTransient(viewToRender);
      }
      boolean writtenState = stateWriter.isStateWritten();
      if (writtenState) {
        String content = stateWriter.getAndResetBuffer();
        int end = content.indexOf("~facelets.VIEW_STATE~");
        if (end >= 0)
        {
          Object stateObj = stateMgr.saveSerializedView(context);
          String stateStr;
          String stateStr;
          if (stateObj == null) {
            stateStr = null;
          } else {
            stateMgr.writeState(context, (StateManager.SerializedView)stateObj);
            stateStr = stateWriter.getAndResetBuffer();
          }
          int start = 0;
          while (end != -1) {
            origWriter.write(content, start, end - start);
            if (stateStr != null) {
              origWriter.write(stateStr);
            }
            start = end + STATE_KEY_LEN;
            end = content.indexOf("~facelets.VIEW_STATE~", start);
          }
          origWriter.write(content, start, content.length() - start);
        }
        else
        {
          origWriter.write(content);
          if ((FacesAPI.getVersion() < 12) && (!stateMgr.isSavingStateInClient(context)))
          {
            stateMgr.saveSerializedView(context);
          }
        }
      }
      time = System.currentTimeMillis() - time;
      if (log.isLoggable(Level.FINE)) {
        log.fine("Took " + time + "ms to render view: " + viewToRender.getViewId());
      }
    }
    catch (FileNotFoundException fnfe)
    {
      handleFaceletNotFound(context, viewToRender.getViewId());
    } catch (Exception e) {
      handleRenderException(context, e);
    } finally {
      if (stateWriter != null)
        stateWriter.release();
    }
  }
  protected void handleRenderException(FacesContext context, Exception e) throws IOException, ELException, FacesException
  {
    Object resp = context.getExternalContext().getResponse();
    if (log.isLoggable(Level.SEVERE)) {
      UIViewRoot root = context.getViewRoot();
      StringBuffer sb = new StringBuffer(64);
      sb.append("Error Rendering View");
      if (root != null) {
        sb.append('[');
        sb.append(root.getViewId());
        sb.append(']');
      }
      log.log(Level.SEVERE, sb.toString(), e);
    }
    if ((this.developmentMode) && (!context.getResponseComplete()) && ((resp instanceof HttpServletResponse)))
    {
      HttpServletResponse httpResp = (HttpServletResponse)resp;
      if (!httpResp.isCommitted()) {
        httpResp.reset();
        httpResp.setContentType("text/html; charset=UTF-8");
        Writer w = httpResp.getWriter();
        DevTools.debugHtml(w, context, e);
        w.flush();
        context.responseComplete();
      }
    } else {
      if ((e instanceof RuntimeException))
        throw ((RuntimeException)e);
      if ((e instanceof IOException)) {
        throw ((IOException)e);
      }
      throw new FacesException(e.getMessage(), e);
    }
  }
  protected void handleFaceletNotFound(FacesContext context, String viewId) throws FacesException, IOException
  {
    String actualId = getActionURL(context, viewId);
    Object respObj = context.getExternalContext().getResponse();
    if ((respObj instanceof HttpServletResponse)) {
      HttpServletResponse respHttp = (HttpServletResponse)respObj;
      respHttp.sendError(404, actualId);
      context.responseComplete();
    }
  }
  private boolean handledByFacelets(String viewId)
  {
    if ((this.extensionsArray == null) && (this.prefixesArray == null)) {
      return true;
    }
    if (this.extensionsArray != null) {
      for (int i = 0; i < this.extensionsArray.length; i++) {
        String extension = this.extensionsArray[i];
        if (viewId.endsWith(extension)) {
          return true;
        }
      }
    }
    if (this.prefixesArray != null) {
      for (int i = 0; i < this.prefixesArray.length; i++) {
        String prefix = this.prefixesArray[i];
        if (viewId.startsWith(prefix)) {
          return true;
        }
      }
    }
    return false;
  }
  public String getDefaultSuffix(FacesContext context) throws FacesException {
    if (this.defaultSuffix == null) {
      ExternalContext extCtx = context.getExternalContext();
      String viewSuffix = extCtx.getInitParameter("javax.faces.DEFAULT_SUFFIX");
      this.defaultSuffix = (viewSuffix != null ? viewSuffix : ".jsp");
    }
    return this.defaultSuffix;
  }
  protected String getRenderedViewId(FacesContext context, String actionId) {
    ExternalContext extCtx = context.getExternalContext();
    String viewId = actionId;
    if (extCtx.getRequestPathInfo() == null) {
      String viewSuffix = getDefaultSuffix(context);
      viewId = new StringBuffer(viewId).replace(viewId.lastIndexOf('.'), viewId.length(), viewSuffix).toString();
    }
    if (log.isLoggable(Level.FINE)) {
      log.fine("ActionId -> ViewId: " + actionId + " -> " + viewId);
    }
    return viewId;
  }
  public void writeState(FacesContext context) throws IOException {
    if (handledByFacelets(context.getViewRoot().getViewId()))
    {
      StateWriter.getCurrentInstance().writingState();
      context.getResponseWriter().write("~facelets.VIEW_STATE~");
    } else {
      this.parent.writeState(context);
    }
  }
  public Locale calculateLocale(FacesContext context) {
    return this.parent.calculateLocale(context);
  }
  public String calculateRenderKitId(FacesContext context) {
    return this.parent.calculateRenderKitId(context);
  }
  public UIViewRoot createView(FacesContext context, String viewId) {
    if (UIDebug.debugRequest(context)) {
      return new UIViewRoot();
    }
    return this.parent.createView(context, viewId);
  }
  public String getActionURL(FacesContext context, String viewId) {
    return this.parent.getActionURL(context, viewId);
  }
  public String getResourceURL(FacesContext context, String path) {
    return this.parent.getResourceURL(context, path);
  }
  private static boolean isPostback11(FacesContext context)
  {
    Object reqObject = context.getExternalContext().getRequest();
    if ((reqObject instanceof HttpServletRequest)) {
      HttpServletRequest request = (HttpServletRequest)reqObject;
      String method = request.getMethod();
      return ("POST".equals(method)) || ("PUT".equals(method));
    }
    Map paramMap = context.getExternalContext().getRequestParameterMap();
    return !paramMap.isEmpty();
  }
  protected static class NullWriter extends Writer
  {
    static final NullWriter Instance = new NullWriter();
    public void write(char[] buffer)
    {
    }
    public void write(char[] buffer, int off, int len)
    {
    }
    public void write(String str)
    {
    }
    public void write(int c)
    {
    }
    public void write(String str, int off, int len)
    {
    }
    public void close()
    {
    }
    public void flush()
    {
    }
  }
}
PhaseListener는 아래와 같은것들이 등록되어 있는데 이중에서 중요한것은 SeamPhaseListener이다. 13:53:40,494 INFO [ lifecycle: 80] [] listener.add> com.sun.faces.lifecycle.ELResolverInitPhaseListener 13:53:40,499 INFO [ lifecycle: 80] [] listener.add> com.sun.faces.renderkit.JsfJsResourcePhaseListener 13:53:40,509 INFO [ lifecycle: 80] [] listener.add> org.jboss.seam.debug.jsf.SeamDebugPhaseListener 13:53:40,517 INFO [ lifecycle: 80] [] listener.add> org.jboss.seam.jsf.SeamPhaseListener 13:53:40,522 INFO [ lifecycle: 80] [] listener.add> org.jboss.seam.document.DocumentStorePhaseListener 13:53:40,525 INFO [ lifecycle: 80] [] listener.add> org.ajax4jsf.event.AjaxPhaseListener 13:53:40,534 INFO [ lifecycle: 80] [] listener.add> org.ajax4jsf.event.InitPhaseListener 13:53:40,539 INFO [ lifecycle: 80] [] listener.add> org.richfaces.component.FileUploadPhaselistener
/*
 * JBoss, Home of Professional Open Source
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.seam.jsf;
import static javax.faces.event.PhaseId.ANY_PHASE;
import static javax.faces.event.PhaseId.INVOKE_APPLICATION;
import static javax.faces.event.PhaseId.PROCESS_VALIDATIONS;
import static javax.faces.event.PhaseId.RENDER_RESPONSE;
import static javax.faces.event.PhaseId.RESTORE_VIEW;
import static org.jboss.seam.transaction.Transaction.TRANSACTION_FAILED;
import java.lang.reflect.Method;
import java.util.Map;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpServletRequest;
import org.jboss.seam.Seam;
import org.jboss.seam.contexts.Context;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.contexts.FacesLifecycle;
import org.jboss.seam.core.ConversationPropagation;
import org.jboss.seam.core.Events;
import org.jboss.seam.core.Init;
import org.jboss.seam.core.Manager;
import org.jboss.seam.exception.Exceptions;
import org.jboss.seam.faces.FacesManager;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.faces.FacesPage;
import org.jboss.seam.faces.Switcher;
import org.jboss.seam.faces.Validation;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
import org.jboss.seam.navigation.Pages;
import org.jboss.seam.pageflow.Pageflow;
import org.jboss.seam.persistence.PersistenceContexts;
import org.jboss.seam.transaction.Transaction;
import org.jboss.seam.transaction.UserTransaction;
import org.jboss.seam.util.Reflections;
import org.jboss.seam.web.ServletContexts;
/**
 * Manages the Seam contexts associated with a JSF request
 * throughout the lifecycle of the request. Performs
 * transaction demarcation when Seam transaction management
 * is enabled. Hacks the JSF lifecyle to provide page
 * actions and page parameters.
 *
 * @author Gavin King
 */
public class SeamPhaseListener implements PhaseListener
{
   private static final long serialVersionUID = -9127555729455066493L;
   private static final LogProvider log = Logging.getLogProvider(SeamPhaseListener.class);
   private static boolean exists = false;
   private static final Method SET_RENDER_PARAMETER;
   private static final Class ACTION_RESPONSE;
   private static final Class PORTLET_REQUEST;
   static
   {
      Method method = null;
      Class actionResponseClass = null;
      Class portletRequestClass = null;
      try
      {
         Class[] parameterTypes = { String.class, String.class };
         actionResponseClass = Class.forName("javax.portlet.ActionResponse");
         portletRequestClass = Class.forName("javax.portlet.PortletRequest");
         method = actionResponseClass.getMethod("setRenderParameter", parameterTypes);
      }
      catch (Exception e) {}
      SET_RENDER_PARAMETER = method;
      ACTION_RESPONSE = actionResponseClass;
      PORTLET_REQUEST = portletRequestClass;
   }
   public SeamPhaseListener()
   {
      if (exists)
      {
         log.warn("There should only be one Seam phase listener per application");
      }
      exists=true;
   }
   public PhaseId getPhaseId()
   {
      return ANY_PHASE;
   }
   public void beforePhase(PhaseEvent event)
   {
      log.trace( "before phase: " + event.getPhaseId() );
      FacesLifecycle.setPhaseId( event.getPhaseId() );
      try
      {
         if ( isPortletRequest(event) )
         {
            beforePortletPhase(event);
         }
         else
         {
            beforeServletPhase(event);
         }
         raiseEventsBeforePhase(event);
      }
      catch (Exception e)
      {
         try
         {
            Exceptions.instance().handle(e);
         }
         catch (Exception ehe)
         {
            log.error("swallowing exception", e);
         }
      }
   }
   private void beforeServletPhase(PhaseEvent event)
   {
      if ( event.getPhaseId() == RESTORE_VIEW )
      {
         beforeRestoreView( event.getFacesContext() );
         ServletContexts.instance().setRequest((HttpServletRequest) event.getFacesContext().getExternalContext().getRequest());
      }
      handleTransactionsBeforePhase(event);
      if ( event.getPhaseId() == RENDER_RESPONSE )
      {
         beforeRenderResponse( event.getFacesContext() );
      }
   }
   private void beforePortletPhase(PhaseEvent event)
   {
      FacesContext facesContext = event.getFacesContext();
      boolean notInitialised=false;
      if ( event.getPhaseId() == RESTORE_VIEW )
      {
         beforeRestoreView(facesContext);
      }
      if ( event.getPhaseId() == RENDER_RESPONSE && !Contexts.isApplicationContextActive() )
      {
          beforeRestoreView(facesContext);
          notInitialised = true;
      }
      //delegate to subclass:
      handleTransactionsBeforePhase(event);
      if (event.getPhaseId() == RENDER_RESPONSE)
      {
         if (notInitialised)
         {
            afterRestoreView(facesContext);
         }
         beforeRenderResponse(event.getFacesContext());
      }
   }
   public void afterPhase(PhaseEvent event)
   {
      log.trace( "after phase: " + event.getPhaseId() );
      try
      {
         raiseEventsAfterPhase(event);
         if ( isPortletRequest(event) )
         {
            afterPortletPhase(event);
         }
         else
         {
            afterServletPhase(event);
         }
      }
      catch (Exception e)
      {
         log.warn("uncaught exception, passing to exception handler", e);
         try
         {
            Exceptions.instance().handle(e);
            // A redirect occurred inside the error handler, and we are in after
            // phase, so we need to clean up now as there are no more after
            // phases to be run
            if ( event.getFacesContext().getResponseComplete() )
            {
               afterResponseComplete(event.getFacesContext());
            }
         }
         catch (Exception ehe)
         {
            log.error("swallowing exception", e);
         }
      }
      FacesLifecycle.clearPhaseId();
   }
   private void afterServletPhase(PhaseEvent event)
   {
      FacesContext facesContext = event.getFacesContext();
      if ( event.getPhaseId() == RESTORE_VIEW )
      {
         afterRestoreView(facesContext);
      }
      else if ( event.getPhaseId() == INVOKE_APPLICATION )
      {
         afterInvokeApplication();
      }
      else if ( event.getPhaseId() == PROCESS_VALIDATIONS )
      {
         afterProcessValidations(facesContext);
      }
      //has to happen after, since restoreAnyConversationContext()
      //can add messages
      FacesMessages.afterPhase();
      handleTransactionsAfterPhase(event);
      if ( event.getPhaseId() == RENDER_RESPONSE )
      {
         afterRenderResponse(facesContext);
      }
      else if ( facesContext.getResponseComplete() )
      {
         afterResponseComplete(facesContext);
      }
   }
   private void afterPortletPhase(PhaseEvent event)
   {
      Object portletPhase = event.getFacesContext().getExternalContext().getRequestMap().get("javax.portlet.faces.phase");
      if (event.getPhaseId() == RESTORE_VIEW)
      {
         afterRestoreView(event.getFacesContext());
      }
      else if (event.getPhaseId() == INVOKE_APPLICATION)
      {
         afterInvokeApplication();
      }
      else if (event.getPhaseId() == PROCESS_VALIDATIONS)
      {
         afterProcessValidations(event.getFacesContext());
      }
      FacesMessages.afterPhase();
      // delegate to subclass:
      handleTransactionsAfterPhase(event);
      if (event.getPhaseId() == RENDER_RESPONSE)
      {
         // writeConversationIdToResponse(
         // facesContext.getExternalContext().getResponse() );
         afterRenderResponse(event.getFacesContext());
      }
      else if ( (null != portletPhase && "ActionPhase".equals(portletPhase.toString()) )
             && (event.getPhaseId() == INVOKE_APPLICATION
                     || event.getFacesContext().getRenderResponse()
                     || event.getFacesContext().getResponseComplete()) )
      {
         Manager.instance().beforeRedirect();
         if ( Manager.instance().isLongRunningConversation() )
         {
             setPortletRenderParameter(
                   event.getFacesContext().getExternalContext().getResponse(),
                   Manager.instance().getConversationIdParameter(),
                     Manager.instance().getCurrentConversationId() );
         }
         afterResponseComplete( event.getFacesContext() );
      }
   }
   private static void setPortletRenderParameter(Object response, String conversationIdParameter, String conversationId)
   {
      if ( ACTION_RESPONSE.isInstance(response) )
      {
         Reflections.invokeAndWrap(SET_RENDER_PARAMETER, response, conversationIdParameter, conversationId);
      }
   }
   private static boolean isPortletRequest(PhaseEvent event)
   {
      return PORTLET_REQUEST!=null &&
            PORTLET_REQUEST.isInstance( event.getFacesContext().getExternalContext().getRequest() );
   }
   public void handleTransactionsBeforePhase(PhaseEvent event)
   {
      if ( Init.instance().isTransactionManagementEnabled() )
      {
         PhaseId phaseId = event.getPhaseId();
         boolean beginTran = phaseId == PhaseId.RENDER_RESPONSE ||
               phaseId == ( Transaction.instance().isConversationContextRequired() ? PhaseId.APPLY_REQUEST_VALUES : PhaseId.RESTORE_VIEW );
               //( phaseId == PhaseId.RENDER_RESPONSE && !Init.instance().isClientSideConversations() );
         if (beginTran)
         {
            begin(phaseId);
         }
      }
   }
   public void handleTransactionsAfterPhase(PhaseEvent event)
   {
      if ( Init.instance().isTransactionManagementEnabled() )
      {
         PhaseId phaseId = event.getPhaseId();
         boolean commitTran = phaseId == PhaseId.INVOKE_APPLICATION ||
               event.getFacesContext().getRenderResponse() || //TODO: no need to commit the tx if we failed to restore the view
               event.getFacesContext().getResponseComplete() ||
               phaseId == PhaseId.RENDER_RESPONSE;
               //( phaseId == PhaseId.RENDER_RESPONSE && !Init.instance().isClientSideConversations() );
         if (commitTran)
         {
            commitOrRollback(phaseId); //we commit before destroying contexts, cos the contexts have the PC in them
         }
      }
   }
   protected void handleTransactionsAfterPageActions(FacesContext facesContext)
   {
      if ( Init.instance().isTransactionManagementEnabled() )
      {
         commitOrRollback("after invoking page actions");
         if ( !facesContext.getResponseComplete() )
         {
            begin("before continuing render");
         }
      }
   }
   protected void afterInvokeApplication()
   {
      if ( Init.instance().isTransactionManagementEnabled() )
      {
         raiseTransactionFailedEvent();
      }
   }
   protected void afterProcessValidations(FacesContext facesContext)
   {
      Validation.instance().afterProcessValidations(facesContext);
   }
   /**
    * Set up the Seam contexts, except for the conversation
    * context
    */
   protected void beforeRestoreView(FacesContext facesContext)
   {
      FacesLifecycle.beginRequest( facesContext.getExternalContext() );
   }
   /**
    * Restore the page and conversation contexts during a JSF request
    */
   protected void afterRestoreView(FacesContext facesContext)
   {
      FacesLifecycle.resumePage();
      Map parameters = facesContext.getExternalContext().getRequestParameterMap();
      ConversationPropagation.instance().restoreConversationId(parameters);
      boolean conversationFound = Manager.instance().restoreConversation();
      FacesLifecycle.resumeConversation( facesContext.getExternalContext() );
      postRestorePage(facesContext, parameters, conversationFound);
   }
   public void raiseEventsBeforePhase(PhaseEvent event)
   {
      if ( Contexts.isApplicationContextActive() )
      {
         Events.instance().raiseEvent("org.jboss.seam.beforePhase", event);
      }
      /*if ( Contexts.isConversationContextActive() && Init.instance().isJbpmInstalled() && Pageflow.instance().isInProcess() )
      {
         String name;
         PhaseId phaseId = event.getPhaseId();
         if ( phaseId == PhaseId.PROCESS_VALIDATIONS )
         {
            name = "process-validations";
         }
         else if ( phaseId == PhaseId.UPDATE_MODEL_VALUES )
         {
            name = "update-model-values";
         }
         else if ( phaseId == PhaseId.INVOKE_APPLICATION )
         {
            name = "invoke-application";
         }
         else if ( phaseId == PhaseId.RENDER_RESPONSE )
         {
            name = "render-response";
         }
         else
         {
            return;
         }
         Pageflow.instance().processEvents(name);
      }*/
   }
   public void raiseEventsAfterPhase(PhaseEvent event)
   {
      if ( Contexts.isApplicationContextActive() )
      {
         Events.instance().raiseEvent("org.jboss.seam.afterPhase", event);
      }
   }
   /**
    * Raise an event so that an observer may add a faces message when Seam-managed transactions fail.
    */
   protected void raiseTransactionFailedEvent()
   {
      try
      {
         UserTransaction tx = Transaction.instance();
         if ( tx.isRolledBackOrMarkedRollback() )
         {
            if (Events.exists()) Events.instance().raiseEvent(TRANSACTION_FAILED, tx.getStatus());
         }
      }
      catch (Exception e) {} //swallow silently, not important
   }
   protected void beforeRenderResponse(FacesContext facesContext)
   {
      if ( Contexts.isPageContextActive() )
      {
         Context pageContext = Contexts.getPageContext();
         //after every time that the view may have changed,
         //we need to flush the page context, since the
         //attribute map is being discarder
         pageContext.flush();
         //force refresh of the conversation lists (they are kept in PAGE context)
         pageContext.remove(Seam.getComponentName(Switcher.class));
         pageContext.remove("org.jboss.seam.core.conversationList");
         pageContext.remove("org.jboss.seam.core.conversationStack");
      }
      preRenderPage(facesContext);
      if ( facesContext.getResponseComplete() )
      {
         //workaround for a bug in MyFaces prior to 1.1.3
         if ( Init.instance().isMyFacesLifecycleBug() )
         {
            FacesLifecycle.endRequest( facesContext.getExternalContext() );
         }
      }
      else //if the page actions did not call responseComplete()
      {
         FacesMessages.instance().beforeRenderResponse();
         //do this both before and after render, since conversations
         //and pageflows can begin during render
         FacesManager.instance().prepareBackswitch(facesContext);
      }
      FacesPage.instance().storeConversation();
      FacesPage.instance().storePageflow();
      PersistenceContexts persistenceContexts = PersistenceContexts.instance();
      if (persistenceContexts != null)
      {
          persistenceContexts.beforeRender();
      }
   }
   protected void afterRenderResponse(FacesContext facesContext)
   {
      //do this both before and after render, since conversations
      //and pageflows can begin during render
      FacesManager.instance().prepareBackswitch(facesContext);
      PersistenceContexts persistenceContexts = PersistenceContexts.instance();
      if (persistenceContexts != null)
      {
          persistenceContexts.afterRender();
      }
      ExternalContext externalContext = facesContext.getExternalContext();
      Manager.instance().endRequest( externalContext.getSessionMap() );
      FacesLifecycle.endRequest(externalContext);
   }
   protected void afterResponseComplete(FacesContext facesContext)
   {
      //responseComplete() was called by one of the other phases,
      //so we will never get to the RENDER_RESPONSE phase
      //Note: we can't call Manager.instance().beforeRedirect() here,
      //since a redirect is not the only reason for a responseComplete
      ExternalContext externalContext = facesContext.getExternalContext();
      Manager.instance().endRequest( externalContext.getSessionMap() );
      FacesLifecycle.endRequest( facesContext.getExternalContext() );
   }
   private void postRestorePage(FacesContext facesContext, Map parameters, boolean conversationFound)
   {
      if ( !Pages.isDebugPage() )
      {
         // Only redirect to no-conversation-view if a login redirect isn't required
         if (!conversationFound && !Pages.instance().isLoginRedirectRequired(facesContext))
         {
            Pages.instance().redirectToNoConversationView();
         }
         Manager.instance().handleConversationPropagation(parameters);
         if ( Init.instance().isJbpmInstalled() && !isExceptionHandlerRedirect() )
         {
            Pageflow.instance().validatePageflow(facesContext);
         }
         Pages.instance().postRestore(facesContext);
      }
   }
   private boolean preRenderPage(FacesContext facesContext)
   {
      if ( Pages.isDebugPage() )
      {
         return false;
      }
      else
      {
         FacesLifecycle.setPhaseId(PhaseId.INVOKE_APPLICATION);
         boolean actionsWereCalled = false;
         try
         {
            actionsWereCalled = Pages.instance().preRender(facesContext);
            return actionsWereCalled;
         }
         finally
         {
            FacesLifecycle.setPhaseId(PhaseId.RENDER_RESPONSE);
            if (actionsWereCalled)
            {
               FacesMessages.afterPhase();
               handleTransactionsAfterPageActions(facesContext); //TODO: does it really belong in the finally?
            }
         }
      }
   }
   private boolean isExceptionHandlerRedirect()
   {
      return Contexts.getConversationContext().isSet("org.jboss.seam.handledException");
   }
   void begin(PhaseId phaseId)
   {
      begin("prior to phase: " + phaseId);
   }
   void begin(String phaseString)
   {
      try
      {
         if ( !Transaction.instance().isActiveOrMarkedRollback() )
         {
            log.debug("beginning transaction " + phaseString);
            Transaction.instance().begin();
         }
      }
      catch (Exception e)
      {
         throw new IllegalStateException("Could not start transaction", e);
      }
   }
   void commitOrRollback(PhaseId phaseId)
   {
      commitOrRollback("after phase: " + phaseId);
   }
   void commitOrRollback(String phaseString)
   {
      try {
         if (Transaction.instance().isActive()) {
             try {
                 log.debug("committing transaction " + phaseString);
                 Transaction.instance().commit();
             } catch (IllegalStateException e) {
                 log.warn("TX commit failed with illegal state exception. This may be " +
                          "because the tx timed out and was rolled back in the background.", e);
             }
         } else if ( Transaction.instance().isRolledBackOrMarkedRollback()) {
            log.debug("rolling back transaction " + phaseString);
            Transaction.instance().rollback();
         }
      } catch (Exception e) {
         throw new IllegalStateException("Could not commit transaction", e);
      }
   }
}
]]>

Related Posts