/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* Resin Open Source 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, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package javax.faces.component;
import java.util.*;
import java.util.logging.*;
import javax.el.*;
import javax.faces.*;
import javax.faces.application.*;
import javax.faces.context.*;
import javax.faces.event.*;
import javax.faces.webapp.*;
import javax.faces.lifecycle.*;
public class UIViewRoot extends UIComponentBase
{
private static final Logger log
= Logger.getLogger(UIViewRoot.class.getName());
public static final String COMPONENT_FAMILY = "javax.faces.ViewRoot";
public static final String COMPONENT_TYPE = "javax.faces.ViewRoot";
public static final String UNIQUE_ID_PREFIX = "j_id";
private String _renderKitId;
private ValueExpression _renderKitIdExpr;
private String _viewId;
private int _unique;
private Locale _locale;
private ValueExpression _localeExpr;
private ArrayList<PhaseListener> _phaseListeners;
private ArrayList<FacesEvent> _eventList;
private MethodExpression _beforePhaseListener;
private MethodExpression _afterPhaseListener;
private Lifecycle _lifecycle;
public UIViewRoot()
{
}
public String getFamily()
{
return COMPONENT_FAMILY;
}
public void setAfterPhaseListener(MethodExpression expr)
{
_afterPhaseListener = expr;
}
public MethodExpression getAfterPhaseListener()
{
return _afterPhaseListener;
}
public void setBeforePhaseListener(MethodExpression expr)
{
_beforePhaseListener = expr;
}
public MethodExpression getBeforePhaseListener()
{
return _beforePhaseListener;
}
public String getRenderKitId()
{
if (_renderKitId != null)
return _renderKitId;
else if (_renderKitIdExpr != null)
return Util.evalString(_renderKitIdExpr, getFacesContext());
else
return null;
}
public void setRenderKitId(String renderKitId)
{
_renderKitId = renderKitId;
}
public String getViewId()
{
return _viewId;
}
public void setViewId(String value)
{
_viewId = value;
}
public void setLocale(Locale locale)
{
_locale = locale;
}
public Locale getLocale()
{
if (_locale != null)
return _locale;
Locale locale = null;
FacesContext context = getFacesContext();
if (_localeExpr != null)
locale = toLocale(Util.eval(_localeExpr, context));
if (locale == null) {
ViewHandler viewHandler = context.getApplication().getViewHandler();
locale = viewHandler.calculateLocale(context);
}
return locale;
}
//
// expression map override
//
/**
* Returns the value expression with the given name.
*/
@Override
public ValueExpression getValueExpression(String name)
{
if ("renderKitId".equals(name))
return _renderKitIdExpr;
else if ("locale".equals(name))
return _localeExpr;
else {
return super.getValueExpression(name);
}
}
/**
* Sets the value expression with the given name.
*/
@Override
public void setValueExpression(String name, ValueExpression expr)
{
if ("renderKitId".equals(name)) {
if (expr != null && expr.isLiteralText()) {
_renderKitId = (String) expr.getValue(null);
return;
}
else
_renderKitIdExpr = expr;
}
else if ("locale".equals(name)) {
if (expr != null && expr.isLiteralText()) {
_locale = toLocale(expr.getValue(null));
return;
}
else
_localeExpr = expr;
}
super.setValueExpression(name, expr);
}
public void addPhaseListener(PhaseListener listener)
{
if (_phaseListeners == null)
_phaseListeners = new ArrayList<PhaseListener>();
_phaseListeners.add(listener);
}
public void removePhaseListener(PhaseListener listener)
{
if (_phaseListeners != null)
_phaseListeners.remove(listener);
}
public String createUniqueId()
{
return UNIQUE_ID_PREFIX + _unique++;
}
/**
* Process the application.
*/
public void processApplication(FacesContext context)
{
if (context == null)
throw new NullPointerException();
if (_beforePhaseListener != null || _phaseListeners != null)
beforePhase(context, PhaseId.INVOKE_APPLICATION);
broadcastEvents(PhaseId.INVOKE_APPLICATION);
if (_afterPhaseListener != null || _phaseListeners != null)
afterPhase(context, PhaseId.INVOKE_APPLICATION);
}
/**
* Process the decodes.
*/
public void processDecodes(FacesContext context)
{
if (_beforePhaseListener != null || _phaseListeners != null)
beforePhase(context, PhaseId.APPLY_REQUEST_VALUES);
super.processDecodes(context);
broadcastEvents(PhaseId.APPLY_REQUEST_VALUES);
if (_afterPhaseListener != null || _phaseListeners != null)
afterPhase(context, PhaseId.APPLY_REQUEST_VALUES);
}
/**
* Process the updates.
*/
public void processUpdates(FacesContext context)
{
if (_beforePhaseListener != null || _phaseListeners != null)
beforePhase(context, PhaseId.UPDATE_MODEL_VALUES);
super.processUpdates(context);
broadcastEvents(PhaseId.UPDATE_MODEL_VALUES);
if (_afterPhaseListener != null || _phaseListeners != null)
afterPhase(context, PhaseId.UPDATE_MODEL_VALUES);
}
/**
* Process the validators.
*/
@Override
public void processValidators(FacesContext context)
{
if (_beforePhaseListener != null || _phaseListeners != null)
beforePhase(context, PhaseId.PROCESS_VALIDATIONS);
super.processValidators(context);
broadcastEvents(PhaseId.PROCESS_VALIDATIONS);
if (_afterPhaseListener != null || _phaseListeners != null)
afterPhase(context, PhaseId.PROCESS_VALIDATIONS);
}
/**
* Begin rendering
*/
@Override
public void encodeBegin(FacesContext context)
throws java.io.IOException
{
if (_beforePhaseListener != null || _phaseListeners != null)
beforePhase(context, PhaseId.RENDER_RESPONSE);
super.encodeBegin(context);
}
/**
* Begin rendering
*/
@Override
public void encodeEnd(FacesContext context)
throws java.io.IOException
{
super.encodeEnd(context);
if (_afterPhaseListener != null || _phaseListeners != null)
afterPhase(context, PhaseId.RENDER_RESPONSE);
}
@Override
public void queueEvent(FacesEvent event)
{
if (_eventList == null)
_eventList = new ArrayList<FacesEvent>();
if (log.isLoggable(Level.FINE))
log.fine(this + " queueEvent " + event);
_eventList.add(event);
}
private void broadcastEvents(PhaseId phaseId)
{
if (_eventList != null) {
for (int i = 0; i < _eventList.size(); i++) {
FacesEvent event = _eventList.get(i);
PhaseId eventPhaseId = event.getPhaseId();
if (phaseId.equals(eventPhaseId)
|| PhaseId.ANY_PHASE.equals(eventPhaseId)) {
event.getComponent().broadcast(event);
_eventList.remove(i);
i--;
}
}
}
}
private void afterPhase(FacesContext context, PhaseId phaseId)
{
Lifecycle lifecycle = getLifecycle(context);
PhaseEvent event = new PhaseEvent(context, phaseId, lifecycle);
if (_afterPhaseListener != null) {
try {
_afterPhaseListener.invoke(context.getELContext(),
new Object[] { event });
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new FacesException(e);
}
}
if (_phaseListeners != null) {
for (int i = 0; i < _phaseListeners.size(); i++) {
PhaseListener listener = _phaseListeners.get(i);
listener.afterPhase(event);
}
}
}
private void beforePhase(FacesContext context, PhaseId phaseId)
{
Lifecycle lifecycle = getLifecycle(context);
PhaseEvent event = new PhaseEvent(context, phaseId, lifecycle);
if (_beforePhaseListener != null) {
try {
_beforePhaseListener.invoke(context.getELContext(),
new Object[] { event });
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new FacesException(e);
}
}
if (_phaseListeners != null) {
for (int i = 0; i < _phaseListeners.size(); i++) {
PhaseListener listener = _phaseListeners.get(i);
listener.beforePhase(event);
}
}
}
private Lifecycle getLifecycle(FacesContext context)
{
if (_lifecycle == null) {
LifecycleFactory factory = (LifecycleFactory)
FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
ExternalContext extContext = context.getExternalContext();
String id = extContext.getInitParameter(FacesServlet.LIFECYCLE_ID_ATTR);
if (id == null)
id = LifecycleFactory.DEFAULT_LIFECYCLE;
_lifecycle = factory.getLifecycle(id);
}
return _lifecycle;
}
//
// state
//
public Object saveState(FacesContext context)
{
return new Object[] {
super.saveState(context),
_viewId,
_renderKitId,
_locale == null ? null : _locale.toString(),
_unique,
_afterPhaseListener,
_beforePhaseListener,
saveAttachedState(context, _phaseListeners),
};
}
public void restoreState(FacesContext context, Object value)
{
Object []state = (Object []) value;
super.restoreState(context, state[0]);
_viewId = (String) state[1];
_renderKitId = (String) state[2];
_locale = toLocale((String) state[3]);
_unique = (Integer) state[4];
_afterPhaseListener = (MethodExpression) state[5];
_beforePhaseListener = (MethodExpression) state[6];
_phaseListeners = (ArrayList) restoreAttachedState(context, state[7]);
}
private Locale toLocale(Object value)
{
if (value instanceof Locale)
return (Locale) value;
else if (value instanceof String) {
String sValue = (String) value;
String []values = sValue.split("[-_]");
if (values.length > 2)
return new Locale(values[0], values[1], values[2]);
else if (values.length > 1)
return new Locale(values[0], values[1]);
else
return new Locale(sValue);
}
else if (value == null)
return null;
else
return (Locale) value;
}
public String toString()
{
return getClass().getSimpleName() + "[" + getViewId() + "]";
}
}