/* * 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() + "]"; } }