blob: 1c5e3bddfec64f25c546f67e61127c0c198797ca [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.myfaces.test.mock;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import javax.faces.FacesException;
import javax.faces.application.ProjectStage;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;
import javax.faces.event.SystemEventListenerHolder;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class MockApplication20 extends MockApplication12
{
// ------------------------------------------------------------ Constructors
public MockApplication20()
{
super();
}
private static class SystemListenerEntry
{
private List<SystemEventListener> _lstSystemEventListener;
private Map<Class<?>, List<SystemEventListener>> _sourceClassMap;
public SystemListenerEntry()
{
}
public void addListener(SystemEventListener listener)
{
assert listener != null;
addListenerNoDuplicate(getAnySourceListenersNotNull(), listener);
}
public void addListener(SystemEventListener listener, Class<?> source)
{
assert listener != null;
if (source == null)
{
addListener(listener);
}
else
{
addListenerNoDuplicate(
getSpecificSourceListenersNotNull(source), listener);
}
}
public void removeListener(SystemEventListener listener)
{
assert listener != null;
if (_lstSystemEventListener != null)
{
_lstSystemEventListener.remove(listener);
}
}
public void removeListener(SystemEventListener listener,
Class<?> sourceClass)
{
assert listener != null;
if (sourceClass == null)
{
removeListener(listener);
}
else
{
if (_sourceClassMap != null)
{
List<SystemEventListener> listeners = _sourceClassMap
.get(sourceClass);
if (listeners != null)
{
listeners.remove(listener);
}
}
}
}
public void publish(Class<? extends SystemEvent> systemEventClass,
Class<?> classSource, Object source, SystemEvent event)
{
if (source != null && _sourceClassMap != null)
{
event = _traverseListenerList(_sourceClassMap.get(classSource),
systemEventClass, source, event);
}
_traverseListenerList(_lstSystemEventListener, systemEventClass,
source, event);
}
private void addListenerNoDuplicate(
List<SystemEventListener> listeners,
SystemEventListener listener)
{
if (!listeners.contains(listener))
{
listeners.add(listener);
}
}
private synchronized List<SystemEventListener> getAnySourceListenersNotNull()
{
if (_lstSystemEventListener == null)
{
/*
* TODO: Check if modification occurs often or not, might have to use a synchronized list instead.
*
* Registrations found:
*/
_lstSystemEventListener = new CopyOnWriteArrayList<SystemEventListener>();
}
return _lstSystemEventListener;
}
private synchronized List<SystemEventListener> getSpecificSourceListenersNotNull(
Class<?> sourceClass)
{
if (_sourceClassMap == null)
{
_sourceClassMap = new ConcurrentHashMap<Class<?>, List<SystemEventListener>>();
}
List<SystemEventListener> list = _sourceClassMap.get(sourceClass);
if (list == null)
{
/*
* TODO: Check if modification occurs often or not, might have to use a synchronized list instead.
*
* Registrations found:
*/
list = new CopyOnWriteArrayList<SystemEventListener>();
_sourceClassMap.put(sourceClass, list);
}
return list;
}
}
// ------------------------------------------------------ Instance Variables
private static final Log log = LogFactory.getLog(MockApplication20.class);
private final Map<Class<? extends SystemEvent>, SystemListenerEntry> _systemEventListenerClassMap = new ConcurrentHashMap<Class<? extends SystemEvent>, SystemListenerEntry>();
private Map<String, String> _defaultValidatorsIds = new HashMap<String, String>();
private ProjectStage _projectStage;
// ----------------------------------------------------- Mock Object Methods
/**
* TODO: Implement this one correctly
*/
@Override
public Map<String, String> getDefaultValidatorInfo()
{
return _defaultValidatorsIds;
}
private static SystemEvent _traverseListenerList(
List<? extends SystemEventListener> listeners,
Class<? extends SystemEvent> systemEventClass, Object source,
SystemEvent event)
{
if (listeners != null && !listeners.isEmpty())
{
for (SystemEventListener listener : listeners)
{
// Call SystemEventListener.isListenerForSource(java.lang.Object), passing the source argument.
// If this returns false, take no action on the listener.
if (listener.isListenerForSource(source))
{
// Otherwise, if the event to be passed to the listener instances has not yet been constructed,
// construct the event, passing source as the argument to the one-argument constructor that takes
// an Object. This same event instance must be passed to all listener instances.
event = _createEvent(systemEventClass, source, event);
// Call SystemEvent.isAppropriateListener(javax.faces.event.FacesListener), passing the listener
// instance as the argument. If this returns false, take no action on the listener.
if (event.isAppropriateListener(listener))
{
// Call SystemEvent.processListener(javax.faces.event.FacesListener), passing the listener
// instance.
event.processListener(listener);
}
}
}
}
return event;
}
private static SystemEvent _createEvent(
Class<? extends SystemEvent> systemEventClass, Object source,
SystemEvent event)
{
if (event == null)
{
try
{
Constructor<? extends SystemEvent> constructor = systemEventClass
.getConstructor(Object.class);
event = constructor.newInstance(source);
}
catch (Exception e)
{
throw new FacesException(
"Couldn't instanciate system event of type "
+ systemEventClass.getName(), e);
}
}
return event;
}
private void checkNull(final Object param, final String paramName)
{
if (param == null)
{
throw new NullPointerException(paramName + " cannot be null.");
}
}
private void checkEmpty(final String param, final String paramName)
{
if (param.length() == 0)
{
throw new NullPointerException("String " + paramName + " cannot be empty.");
}
}
@Override
public void publishEvent(FacesContext facesContext, Class<? extends SystemEvent> systemEventClass, Class<?> sourceBaseType, Object source)
{
checkNull(systemEventClass, "systemEventClass");
checkNull(source, "source");
try
{
SystemEvent event = null;
if (source instanceof SystemEventListenerHolder)
{
SystemEventListenerHolder holder = (SystemEventListenerHolder) source;
// If the source argument implements SystemEventListenerHolder, call
// SystemEventListenerHolder.getListenersForEventClass(java.lang.Class) on it, passing the systemEventClass
// argument. If the list is not empty, perform algorithm traverseListenerList on the list.
event = _traverseListenerList(holder.getListenersForEventClass(systemEventClass), systemEventClass, source,
event);
}
SystemListenerEntry systemListenerEntry = _systemEventListenerClassMap.get(systemEventClass);
if (systemListenerEntry != null)
{
systemListenerEntry.publish(systemEventClass, sourceBaseType, source, event);
}
}
catch (AbortProcessingException e)
{
// If the act of invoking the processListener method causes an AbortProcessingException to be thrown,
// processing of the listeners must be aborted, no further processing of the listeners for this event must
// take place, and the exception must be logged with Level.SEVERE.
log.error("Event processing was aborted", e);
}
}
@Override
public void publishEvent(FacesContext facesContext, Class<? extends SystemEvent> systemEventClass, Object source)
{
publishEvent(facesContext, systemEventClass, source.getClass(), source);
}
@Override
public ProjectStage getProjectStage()
{
// If the value has already been determined by a previous call to this
// method, simply return that value.
if (_projectStage == null)
{
/*
String stageName = null;
// Look for a JNDI environment entry under the key given by the
// value of
// ProjectStage.PROJECT_STAGE_JNDI_NAME (return type of
// java.lang.String).
try
{
Context ctx = new InitialContext();
Object temp = ctx.lookup(ProjectStage.PROJECT_STAGE_JNDI_NAME);
if (temp != null)
{
if (temp instanceof String)
{
stageName = (String) temp;
}
else
{
log.severe("JNDI lookup for key " + ProjectStage.PROJECT_STAGE_JNDI_NAME
+ " should return a java.lang.String value");
}
}
}
catch (NamingException e)
{
// no-op
}*/
/*
* If found, continue with the algorithm below, otherwise, look for an entry in the initParamMap of the
* ExternalContext from the current FacesContext with the key ProjectStage.PROJECT_STAGE_PARAM_NAME
*/
//if (stageName == null)
//{
FacesContext context = FacesContext.getCurrentInstance();
String stageName = context.getExternalContext().getInitParameter(ProjectStage.PROJECT_STAGE_PARAM_NAME);
//}
/*
* If not found so far, let's try the Apache MyFaces extension (see MYFACES-2235)
*/
//if (stageName == null)
//{
// stageName = System.getProperty(MYFACES_PROJECT_STAGE_SYSTEM_PROPERTY_NAME);
//}
// If a value is found found
if (stageName != null)
{
/*
* see if an enum constant can be obtained by calling ProjectStage.valueOf(), passing the value from the
* initParamMap. If this succeeds without exception, save the value and return it.
*/
try
{
_projectStage = ProjectStage.valueOf(stageName);
return _projectStage;
}
catch (IllegalArgumentException e)
{
//log.log(Level.SEVERE, "Couldn't discover the current project stage", e);
}
}
else
{
//if (log.isLoggable(Level.INFO))
//{
// log.info("Couldn't discover the current project stage, using " + ProjectStage.Production);
//}
}
/*
* If not found, or any of the previous attempts to discover the enum constant value have failed, log a
* descriptive error message, assign the value as ProjectStage.Production and return it.
*/
_projectStage = ProjectStage.Production;
}
return _projectStage;
}
// ------------------------------------------------- ExternalContext Methods
}