Я реализовал вариант для варианта 1 выше. например,
- написал динамический прокси для ServletContext, который перехватывает методы getInitParameter и getInitParameterNames, возвращающие соответствующие значения (в данном случае полученные из файлов свойств, специфичных для среды)
- написал очень маленький подкласс FacesContextFactoryImpl, который передает первый параметр / servletcontext в getFacesContext, а затем делегирует суперклассу.
- добавило предложение face-context-factory в мою конфигурацию лиц с именами моего класса FacesContextFactoryImpl
- У меня уже был механизм для загрузки файлов свойств, зависящих от среды, и предоставления их в виде объекта свойств приложению (фабрика в пункте 2 передает эти свойства прокси в точке 1 для использования в качестве альтернативного источника значения initParameter)
Прокси выглядит так:
package zzzzz.framework.context;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Map;
import javax.servlet.ServletContext;
import org.apache.commons.collections.IteratorUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* A proxy for ServletContext that intercepts accesses to the initParameters and
* returns values from the specified params instead. Generally useful if we have
* a set of properties (eg SystemContext.getInstance().getConfigProperties()) that
* we want to use in preference to the webapp initProperties.
*
*
*/
public class ServletContextProxy
implements InvocationHandler {
@SuppressWarnings("unused")
private static final Log log = LogFactory.getLog(ServletContextProxy.class);
@SuppressWarnings("unchecked")
public static ServletContext newInstance(ServletContext subject,
Map params) {
return newInstance(subject,
params,
true);
}
@SuppressWarnings("unchecked")
public static ServletContext newInstance(ServletContext subject,
Map params,
boolean overrideInitValues) {
return (ServletContext) Proxy.newProxyInstance(subject.getClass()
.getClassLoader(),
subject.getClass()
.getInterfaces(),
new ServletContextProxy(subject,
params,
overrideInitValues));
}
/**
* A convenience method to help extracting the initParameters from a
* ServletContext because it doesn't expose it's underlying Map
*
* @param config
* @return
*/
@SuppressWarnings("unchecked")
protected static Map copyInitParameters(Map parms,
ServletContext config) {
Enumeration names = config.getInitParameterNames();
// copy all the existing initParameters
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
parms.put(name,
config.getInitParameter(name));
}
return parms;
}
private boolean overrideInitValues = true;
@SuppressWarnings("unchecked")
private Map params;
private ServletContext subject;
@SuppressWarnings("unchecked")
public ServletContextProxy(ServletContext subject,
Map params,
boolean overrideInitValues) {
this.subject = subject;
this.overrideInitValues = overrideInitValues;
this.params = new Hashtable();
if (this.overrideInitValues) { // default behaviour... supplied parameters win
// start with initParameters
copyInitParameters(this.params,
subject);
// override and supplement with supplied params
if (params != null) {
this.params.putAll(params);
}
} else {
// start with supplied params
if (params != null) {
this.params.putAll(params);
}
// override and supplement with initParameters
copyInitParameters(this.params,
subject);
}
}
public Object invoke(Object proxy,
Method m,
Object[] args) throws Throwable {
Object result;
try {
if ("getInitParameter".equals(m.getName())) {
result = this.params.get(args[0]);
} else if ("getInitParameterNames".equals(m.getName())) {
result = IteratorUtils.asEnumeration(this.params.keySet()
.iterator());
} else {// else let it go through to the keeper
result = m.invoke(this.subject,
args);
}
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: "
+ e.getMessage());
}
return result;
}
}
Фабрика выглядит так:
<code>package zzz.faces.context;
import javax.faces.FacesException;
import javax.faces.context.FacesContext;
import javax.faces.lifecycle.Lifecycle;
import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import zzzzz.framework.context.ServletContextProxy;
import zzzzz.context.SystemContext;
/**
* A FacesContextFactory implementation that supplements/overrided the
* servletContext initParemeters with properties form
* SystemContext.configProperties
* <p>
* The point of this is that it allows us to substitute configuration in the
* web.xml like this (which requires rewriting web.xml to change)
* </p>
*
* <pre>
* <!-- Enables special Facelets debug output during development -->
* <context-param>
* <param-name>facelets.DEVELOPMENT</param-name>
* <param-value>true</param-value>
* </context-param>
*
*
*
* с настройками в соответствующем файле application.properties, как этот (который
* может быть изменено отдельно от веб-приложения)
*
*
*
* # Enables special Facelets debug output during development
* facelets.DEVELOPMENT=true
*
*
*
* использование: добавить выражение к Face-Config, как это:
*
*
* <factory>
* <faces-context-factory>zzzzz.faces.context.FacesContextFactoryImpl</faces-context-factory>
* </factory>
*
*
*
* /
открытый класс FacesContextFactoryImpl extends com.sun.faces.context.FacesContextFactoryImpl {
@SuppressWarnings ( "неиспользуемый")
private static final Log log = LogFactory.getLog (FacesContextFactoryImpl.class);
public FacesContextFactoryImpl () {
супер();
}
@Override
public FacesContext getFacesContext (Object sc,
Запрос объекта,
Ответ объекта,
Жизненный цикл жизненного цикла) выдает FacesException {
if (sc instanceof ServletContext
&&! (sc instanceof ServletContextProxy)) {
// оборачиваем контекст сервлета прокси для переопределения / дополнения initParameters
sc = ServletContextProxy.newInstance ((ServletContext) sc,
SystemContext.getInstance ()
.getConfigProperties (),
правда);
}
вернуть super.getFacesContext (sc,
запрос,
ответ,
жизненный цикл);
}
}
и face-config выглядит как
<faces-config>
blah waffle....
<factory>
<faces-context-factory>zzzz.faces.context.FacesContextFactoryImpl</faces-context-factory>
</factory>
</faces-config>
То, на что похож SystemContext.getInstance (). GetConfigProperties (), является упражнением для другого дня, но оно просто возвращает карту значений свойств, которые приложение должно использовать