This is an automated email from the ASF dual-hosted git repository.
doebele pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/empire-db.git
The following commit(s) were added to refs/heads/master by this push:
new 86f214f1 EMPIREDB-424 Allow programmatic Faces Configuration
86f214f1 is described below
commit 86f214f1ed5e7c7ec14b4d6c330934db91fa0968
Author: Rainer Döbele <[email protected]>
AuthorDate: Sun Apr 21 14:57:58 2024 +0200
EMPIREDB-424
Allow programmatic Faces Configuration
---
.../apache/empire/jsf2/app/FacesConfiguration.java | 578 +++++++++++++++++++++
.../empire/jsf2/app/WebAppStartupListener.java | 36 +-
.../org/apache/empire/jsf2/app/WebApplication.java | 4 +-
.../java/org/apache/empire/commons/ClassUtils.java | 95 +++-
...ErrorException.java => MiscErrorException.java} | 6 +-
5 files changed, 703 insertions(+), 16 deletions(-)
diff --git
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/FacesConfiguration.java
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/FacesConfiguration.java
new file mode 100644
index 00000000..186e1353
--- /dev/null
+++
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/FacesConfiguration.java
@@ -0,0 +1,578 @@
+/*
+ * 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.empire.jsf2.app;
+
+import java.util.Iterator;
+import java.util.List;
+
+import javax.el.ELResolver;
+import javax.faces.FactoryFinder;
+import javax.faces.application.Application;
+import javax.faces.application.NavigationHandler;
+import javax.faces.component.UIComponent;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.event.PhaseListener;
+import javax.faces.lifecycle.Lifecycle;
+import javax.faces.lifecycle.LifecycleFactory;
+import javax.faces.render.RenderKit;
+import javax.faces.render.RenderKitFactory;
+import javax.faces.render.Renderer;
+
+import org.apache.empire.commons.ClassUtils;
+import org.apache.empire.commons.StringUtils;
+import org.apache.empire.exceptions.InternalException;
+import org.apache.empire.exceptions.InvalidArgumentException;
+import org.apache.empire.exceptions.ItemExistsException;
+import org.apache.empire.exceptions.ItemNotFoundException;
+import org.apache.empire.exceptions.ObjectNotValidException;
+import org.apache.empire.exceptions.UnspecifiedErrorException;
+import org.apache.empire.jsf2.impl.FacesImplementation;
+import org.apache.empire.jsf2.pages.PageNavigationHandler;
+import org.apache.empire.jsf2.pages.PagePhaseListener;
+import org.apache.empire.jsf2.pages.PagesELResolver;
+import org.apache.myfaces.cdi.util.BeanEntry;
+import org.apache.myfaces.config.RuntimeConfig;
+import org.apache.myfaces.spi.InjectionProvider;
+import org.apache.myfaces.spi.InjectionProviderException;
+import org.apache.myfaces.spi.InjectionProviderFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * FacesConfiguration
+ * Allows programmatic Faces configuration as an alternative to the
faces-config.xml
+ * In order to provide custom configuration you must override the class
WebAppStartupListener
+ * and put it in the faces-config.xml
+ * <pre>
+ *
<system-event-listener-class>de.volkswagen.jsf.FacesStartupListener</system-event-listener-class>
+ * </pre>
+ * Further you must call the super constructor with a FacesConfiguration class
like this:
+ * <pre>
+ * public FacesStartupListener()
+ * {
+ * super(FacesExtensions.class);
+ * }
+ * </pre>
+ */
+public class FacesConfiguration
+{
+ protected static final Logger log =
LoggerFactory.getLogger(FacesConfiguration.class);
+
+ /*
+ * Initialized
+ */
+ private static boolean initialized = false;
+ public static boolean isInitialized()
+ {
+ return initialized;
+ }
+
+ /*
+ * Project Stage
+ */
+ private static final String PROJECT_STAGE_PARAM =
"javax.faces.PROJECT_STAGE";
+ private static String projectStage;
+ public static String getProjectStage()
+ {
+ if (projectStage==null)
+ throw new ObjectNotValidException(FacesConfiguration.class, "Not
Initialized");
+ return projectStage;
+ }
+
+ /**
+ * Static Initializer
+ * @param clazz
+ * @param context
+ */
+ public static <T extends FacesConfiguration> void initialize(Class<T>
configClass, FacesContext context, FacesImplementation facesImpl)
+ {
+ if (initialized)
+ throw new UnspecifiedErrorException("FacesConfiguration already
initialized!");
+ try
+ { // Create Instance an initialize
+ FacesConfiguration fConfig = configClass.newInstance();
+ fConfig.facesImpl = facesImpl;
+ fConfig.initialize(context);
+ initialized = true;
+ }
+ catch (InstantiationException | IllegalAccessException e)
+ {
+ throw new InternalException(e);
+ }
+ }
+
+ protected FacesImplementation facesImpl;
+
+ /*
+ * Temp Variables
+ */
+ protected Application application;
+ protected RuntimeConfig runtimeConfig;
+ protected BeanStorageProvider beanStorage;
+
+ public FacesConfiguration()
+ {
+ // Nothing
+ }
+
+ public final void initialize(FacesContext context)
+ {
+ try
+ { // Set temporary variables
+ ExternalContext externalContext = context.getExternalContext();
+ this.application = context.getApplication();
+ this.runtimeConfig =
RuntimeConfig.getCurrentInstance(externalContext);
+ this.beanStorage = new BeanStorageProvider(externalContext);
+
+ // Set ProjectStage
+ projectStage =
externalContext.getInitParameter(PROJECT_STAGE_PARAM);
+ log.info("Initializing Faces Configuration for {}", projectStage);
+
+ initAll(context);
+
+ // done
+ log.info("Faces Configuration complete");
+ }
+ finally
+ { // cleanup
+ this.beanStorage = null;
+ this.runtimeConfig = null;
+ this.application = null;
+ }
+ }
+
+ /*
+ * Overrideable methods
+ */
+
+ protected void initAll(FacesContext context)
+ {
+ log.info("Init NavigationHandler...");
+ initNavigationHandler();
+
+ log.info("Init ResourceHandler...");
+ initResourceHandler();
+
+ log.info("Registrating Converters...");
+ initConverters();
+
+ log.info("Registrating EL-Resolvers...");
+ initElResolvers();
+
+ log.info("Registrating Lifecycle...");
+ initLifecycle(new LifecycleUpdater(beanStorage));
+
+ log.info("Registrating Search Expression Resolvers...");
+ initSearchExpressionResolvers();
+
+ log.info("Registrating Components...");
+ initComponents();
+
+ log.info("Registrating Renderers...");
+ initRenderers(new RenderKitUpdater(getApplicationRenderKit(context)));
+
+ log.info("Registrating Managed Beans...");
+ initManagedBeans();
+
+ log.info("Registrating Controls...");
+ initControls();
+ }
+
+ protected void initNavigationHandler()
+ {
+ NavigationHandler wrapped = application.getNavigationHandler();
+ if (wrapped instanceof PageNavigationHandler)
+ return; // Already set
+ // replace
+ log.info("Setting NavigationHandler to {}",
PageNavigationHandler.class.getName());
+ application.setNavigationHandler(new PageNavigationHandler(wrapped));
+ }
+
+ protected void initResourceHandler()
+ {
+ // Not implemented
+ // application.setResourceHandler(new MyResourceHandler(wrapped));
+ }
+
+ protected void initConverters()
+ {
+ // Noting
+ }
+
+ protected void initElResolvers()
+ {
+ addELResolver(DBELResolver.class);
+ addELResolver(PagesELResolver.class);
+ }
+
+ protected void initLifecycle(LifecycleUpdater lcu)
+ {
+ lcu.addPhaseListener(FacesRequestPhaseListener.class);
+ lcu.addPhaseListener(PagePhaseListener.class);
+ }
+
+ protected void initSearchExpressionResolvers()
+ {
+ // Nothing
+ // SearchExpressionResolverFactory.registerResolver("@fragment", new
FragmentExpressionResolver());
+ }
+
+ protected void initComponents()
+ {
+ // Empire Components
+ String EMPIRE_FAMILY = "org.apache.empire.component";
+ addComponent(EMPIRE_FAMILY,
org.apache.empire.jsf2.components.ControlTag.class);
+ addComponent(EMPIRE_FAMILY,
org.apache.empire.jsf2.components.InputTag.class);
+ addComponent(EMPIRE_FAMILY,
org.apache.empire.jsf2.components.FormGridTag.class);
+ addComponent(EMPIRE_FAMILY,
org.apache.empire.jsf2.components.LabelTag.class);
+ addComponent(EMPIRE_FAMILY,
org.apache.empire.jsf2.components.LinkTag.class);
+ addComponent(EMPIRE_FAMILY,
org.apache.empire.jsf2.components.MenuItemTag.class);
+ addComponent(EMPIRE_FAMILY,
org.apache.empire.jsf2.components.MenuListTag.class);
+ addComponent(EMPIRE_FAMILY,
org.apache.empire.jsf2.components.RecordTag.class);
+ addComponent(EMPIRE_FAMILY,
org.apache.empire.jsf2.components.SelectTag.class);
+ addComponent(EMPIRE_FAMILY,
org.apache.empire.jsf2.components.TabPageTag.class);
+ addComponent(EMPIRE_FAMILY,
org.apache.empire.jsf2.components.TabViewTag.class);
+ addComponent(EMPIRE_FAMILY,
org.apache.empire.jsf2.components.TitleTag.class);
+ addComponent(EMPIRE_FAMILY,
org.apache.empire.jsf2.components.UnitTag.class);
+ addComponent(EMPIRE_FAMILY,
org.apache.empire.jsf2.components.ValueTag.class);
+ }
+
+ protected void initRenderers(RenderKitUpdater rku)
+ {
+ // Noting
+ // rku.replace("javax.faces.Input", "javax.faces.Text",
FacesTextInputRenderer.class);
+ }
+
+ protected void initManagedBeans()
+ {
+ // Nothing
+ // addManagedBean(ConfirmPopup.MANAGED_BEAN_NAME, ConfirmPopup.class,
ConfirmPopup.MANAGED_BEAN_SCOPE);
+ }
+
+ protected void initControls()
+ {
+ // Not implemented
+ // InputControlManager.registerControl(new
CustomCheckboxInputControl());
+ }
+
+ /*
+ * Helpers
+ */
+
+ protected RenderKit getApplicationRenderKit(FacesContext context)
+ {
+ String renderKitId = application.getDefaultRenderKitId();
+ return
((RenderKitFactory)FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY)).getRenderKit(context,
renderKitId);
+ }
+
+ protected void addConverter(Class<?> targetClass, Class<? extends
Converter> converterClass)
+ {
+ log.info("Adding Type-Converter for type \"{}\" using {}",
targetClass.getName(), converterClass.getName());
+ application.addConverter(targetClass, converterClass.getName());
+ }
+
+ protected void addComponent(String componentFamily, Class<? extends
UIComponent> clazz)
+ {
+ String type = StringUtils.concat(componentFamily, ".",
clazz.getSimpleName());
+ log.info("Adding component type \"{}\" using {}", type,
clazz.getName());
+ application.addComponent(type, clazz.getName());
+ }
+
+ protected void addManagedBean(String beanName, Class<?> beanClass, String
scope)
+ {
+ facesImpl.registerManagedBean(beanName, beanClass.getName(), scope);
+ }
+
+ protected void replaceComponent(Class<? extends UIComponent>
primeComponent, Class<? extends UIComponent> overrideComponent)
+ {
+ String type = (String) ClassUtils.getFieldValue(primeComponent, null,
"COMPONENT_TYPE", true);
+ if (StringUtils.isEmpty(type))
+ throw new InvalidArgumentException("primeComponent",
primeComponent.getName());
+ // check
+ checkComponentTypeExists(type);
+ log.info("Replacing component type \"{}\" with {}", type,
overrideComponent.getName());
+ application.addComponent(type, overrideComponent.getName());
+ }
+
+ protected void checkComponentTypeExists(String componentType)
+ {
+ Iterator<String> types = application.getComponentTypes();
+ while (types.hasNext())
+ {
+ String type = types.next();
+ if (componentType.equals(type))
+ return; // found;
+ }
+ throw new ItemNotFoundException("Component-Type: "+componentType);
+ }
+
+ protected void addELResolver(Class<? extends ELResolver> resolverClass)
+ {
+ List<ELResolver> list = runtimeConfig.getFacesConfigElResolvers();
+ if (list!=null) {
+ for (ELResolver resolver : list)
+ {
+ if (resolver.getClass().equals(resolverClass))
+ return; // already there
+ }
+ }
+ log.info("Adding FacesConfigElResolver {}", resolverClass.getName());
+ ELResolver elResolver = ClassUtils.newInstance(resolverClass);
+ // Add to bean storage
+ beanStorage.injectBean(elResolver);
+ // Add to RuntimeConfig
+ runtimeConfig.addFacesConfigElResolver(elResolver);
+ }
+
+ /*
+ * list
+ */
+ protected void listCompoennts()
+ {
+ ConfigTypeList list = new ConfigTypeList("Component-Types");
+ Iterator<String> types = application.getComponentTypes();
+ while (types.hasNext())
+ {
+ String componentType = types.next();
+ // log.info("Renderer-Family: {} Type {}", componentFamily,
rendererType);
+ list.addItem(componentType);
+ }
+ log.info(list.toString());
+ }
+
+ /**
+ * RenderKitReplacer
+ * @author doebele
+ */
+ protected static class RenderKitUpdater
+ {
+ private final RenderKit renderKit;
+ public RenderKitUpdater(RenderKit renderKit)
+ {
+ this.renderKit = renderKit;
+ }
+
+ public RenderKit getRenderKit()
+ {
+ return renderKit;
+ }
+
+ public void listAll()
+ { // list all
+ ConfigTypeList list = new ConfigTypeList("Renderer-Types");
+ Iterator<String> families = renderKit.getComponentFamilies();
+ while (families.hasNext())
+ {
+ String componentFamily = families.next();
+ Iterator<String> types =
renderKit.getRendererTypes(componentFamily);
+ while (types.hasNext())
+ {
+ String rendererType = types.next();
+ // log.info("Renderer-Family: {} Type {}",
componentFamily, rendererType);
+ list.addItem(componentFamily, rendererType);
+ }
+ }
+ log.info(list.toString());
+ }
+
+ public void add(String componentFamily, String rendererType, Class<?
extends Renderer> rendererClass)
+ {
+ Renderer check = findRenderer(componentFamily, rendererType);
+ if (check!=null)
+ { if (check.getClass().equals(rendererClass))
+ return; // already there
+ // Another renderer exists
+ throw new
ItemExistsException(StringUtils.concat(componentFamily, " / ", rendererType));
+ }
+ // add
+ log.info("Adding Renderer type \"{}\" using {}", rendererType,
rendererClass.getName());
+ renderKit.addRenderer(componentFamily, rendererType,
ClassUtils.newInstance(rendererClass));
+ }
+
+ public void replace(String componentFamily, String rendererType,
Class<? extends Renderer> replaceClass)
+ {
+ // checkRenderTypeExists(componentFamily, rendererType);
+ Renderer check = findRenderer(componentFamily, rendererType);
+ if (check==null)
+ throw new
ItemNotFoundException(StringUtils.concat(componentFamily, " / ", rendererType));
+ if (check.getClass().equals(replaceClass))
+ return; // Already replaced
+ // replace
+ log.info("Replacing Renderer type \"{}\" with class {}",
rendererType, replaceClass.getName());
+ renderKit.addRenderer(componentFamily, rendererType,
ClassUtils.newInstance(replaceClass));
+ }
+
+ /*
+ public void replace(Class<? extends CoreRenderer> orgClass, Class<?
extends CoreRenderer> replaceClass)
+ {
+ String name = orgClass.getName();
+ int sep = name.lastIndexOf('.');
+ replace(name.substring(0, sep), name.substring(sep+1),
replaceClass);
+ }
+ */
+
+ private Renderer findRenderer(String componentFamily, String
rendererType)
+ {
+ // list all
+ Iterator<String> families = renderKit.getComponentFamilies();
+ while (families.hasNext())
+ {
+ String family = families.next();
+ if (componentFamily.equals(family)) {
+ Iterator<String> types =
renderKit.getRendererTypes(family);
+ while (types.hasNext())
+ {
+ String type = types.next();
+ if (rendererType.equals(type))
+ return renderKit.getRenderer(componentFamily,
rendererType); // found
+ }
+ }
+ }
+ return null;
+ }
+
+ }
+
+ /**
+ * BeanStorageProvider
+ * @author doebele
+ */
+ protected static class BeanStorageProvider
+ {
+ private final List<BeanEntry> injectedBeanStorage;
+ private final InjectionProvider injectionProvider;
+
+ @SuppressWarnings("unchecked")
+ public BeanStorageProvider(ExternalContext ec)
+ {
+ this.injectionProvider =
InjectionProviderFactory.getInjectionProviderFactory(ec).getInjectionProvider(ec);
+ final String INJECTED_BEAN_STORAGE_KEY =
"org.apache.myfaces.spi.BEAN_ENTRY_STORAGE";
+ this.injectedBeanStorage =
(List<BeanEntry>)ec.getApplicationMap().get(INJECTED_BEAN_STORAGE_KEY);
+ if (this.injectedBeanStorage==null)
+ throw new ItemNotFoundException(INJECTED_BEAN_STORAGE_KEY);
+ }
+
+ public void injectBean(Object bean)
+ { try
+ { // Add to bean storage
+ Object creationMetaData = injectionProvider.inject(bean);
+ injectedBeanStorage.add(new BeanEntry(bean, creationMetaData));
+ injectionProvider.postConstruct(bean, creationMetaData);
+ }
+ catch (InjectionProviderException e)
+ {
+ throw new InternalException(e);
+ }
+ }
+ }
+
+ /**
+ * LifecycleUpdater
+ * @author doebele
+ */
+ protected static class LifecycleUpdater
+ {
+ private final BeanStorageProvider beanStorage;
+ private final Lifecycle lifecycle;
+ private PhaseListener[] phaseListeners;
+
+ public LifecycleUpdater(BeanStorageProvider beanStorage)
+ {
+ this.beanStorage = beanStorage;
+ // The DEFAULT Lifecycle
+ LifecycleFactory lifecycleFactory = (LifecycleFactory)
FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
+ this.lifecycle =
lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
+ this.phaseListeners = lifecycle.getPhaseListeners();
+ }
+
+ public void listAll()
+ {
+ ConfigTypeList list = new ConfigTypeList("Phase-Listeners");
+ this.phaseListeners = lifecycle.getPhaseListeners();
+ for (PhaseListener pl : phaseListeners)
+ {
+ list.addItem(pl.getClass(), pl.getPhaseId());
+ }
+ log.info(list.toString());
+ }
+
+ public void addPhaseListener(Class<? extends PhaseListener>
phaseListenerClass)
+ {
+ for (PhaseListener pl : phaseListeners)
+ {
+ if (pl.getClass().equals(phaseListenerClass))
+ return; // already there
+ }
+ // Not found: Create and Append
+ log.info("Adding Lifecycle PhaseListener {}",
phaseListenerClass.getName());
+ PhaseListener listener =
ClassUtils.newInstance(phaseListenerClass);
+ // Add to bean storage
+ beanStorage.injectBean(listener);
+ // Add to lifecycle
+ lifecycle.addPhaseListener(listener);
+ // refresh
+ // this.phaseListeners = lifecycle.getPhaseListeners();
+ }
+ }
+
+ /**
+ * ConfigTypeList
+ * @author doebele
+ */
+ protected static class ConfigTypeList
+ {
+ private static final String CRLF = "\r\n";
+ private static final String TAB = "\t";
+ private final StringBuilder b;
+ public ConfigTypeList(String listName)
+ {
+ this.b = new StringBuilder(200);
+ b.append(listName);
+ b.append(":");
+ b.append(CRLF);
+ }
+ public void addItem(Object item, Object... more)
+ {
+ b.append(TAB);
+ b.append(toString(item));
+ for (int i=0; i<more.length; i++)
+ {
+ b.append(TAB);
+ b.append(toString(more[i]));
+ }
+ b.append(CRLF);
+ }
+ protected String toString(Object o)
+ {
+ if (o instanceof Class<?>)
+ return ((Class<?>)o).getName();
+ if (o instanceof Enum<?>)
+ return ((Enum<?>)o).name();
+ return String.valueOf(o);
+ }
+ @Override
+ public String toString()
+ {
+ return this.b.toString();
+ }
+ }
+
+}
diff --git
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebAppStartupListener.java
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebAppStartupListener.java
index accccf4d..f6e06923 100644
---
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebAppStartupListener.java
+++
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebAppStartupListener.java
@@ -36,6 +36,24 @@ import org.slf4j.LoggerFactory;
public class WebAppStartupListener implements SystemEventListener
{
private static final Logger log =
LoggerFactory.getLogger(WebAppStartupListener.class);
+
+ private final Class<? extends FacesConfiguration> facesConfigClass;
+
+ /**
+ * Default Constructor with no initialization
+ */
+ public WebAppStartupListener()
+ {
+ this.facesConfigClass = null;
+ }
+
+ /**
+ * Default Constructor with additional configuration
+ */
+ public WebAppStartupListener(Class<? extends FacesConfiguration>
facesConfigClass)
+ {
+ this.facesConfigClass = facesConfigClass;
+ }
@Override
public boolean isListenerForSource(Object source)
@@ -51,8 +69,11 @@ public class WebAppStartupListener implements
SystemEventListener
if (event instanceof PostConstructApplicationEvent)
{
FacesContext startupContext = FacesContext.getCurrentInstance();
- // detect implementation
+ // Detect implementation
FacesImplementation facesImplementation =
detectFacesImplementation();
+ // Init Configuration
+ initFacesConfiguration(startupContext, facesImplementation);
+ // Create Application
Object app =
facesImplementation.getManagedBean(WebApplication.APPLICATION_BEAN_NAME,
startupContext);
if (!(app instanceof WebApplication))
throw new AbortProcessingException("Error: Application is not
a "+WebApplication.class.getName()+" instance. Please create a
ApplicationFactory!");
@@ -99,5 +120,18 @@ public class WebAppStartupListener implements
SystemEventListener
log.error("JSF-Implementation missing or unknown. Please make sure
either Apache MyFaces or Sun Mojarra implementation is provided");
throw new UnsupportedOperationException();
}
+
+ /**
+ * Allows to programmatically extend the faces configuration
+ * @param impl
+ */
+ protected void initFacesConfiguration(FacesContext startupContext,
FacesImplementation impl)
+ {
+ // Init FacesExtentions
+ if (facesConfigClass!=null) {
+ log.info("Initializing FacesExtentions");
+ FacesConfiguration.initialize(facesConfigClass, startupContext,
impl);
+ }
+ }
}
diff --git
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java
index 5ab31b26..986a12df 100644
---
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java
+++
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/app/WebApplication.java
@@ -465,7 +465,7 @@ public abstract class WebApplication
* @param db the database for which to obtain a connection
* @return the connection
*/
- protected synchronized Connection getConnection(DBDatabase db)
+ protected Connection getConnection(DBDatabase db)
{
// Get From Pool
try
@@ -488,7 +488,7 @@ public abstract class WebApplication
* @param commit flag whether to commit changes
* @param dbrm the rollback manager
*/
- protected synchronized void releaseConnection(Connection conn, boolean
commit, DBRollbackManager dbrm)
+ protected void releaseConnection(Connection conn, boolean commit,
DBRollbackManager dbrm)
{
try
{ // check
diff --git a/empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java
b/empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java
index 4e38dce4..66f63ef7 100644
--- a/empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java
+++ b/empire-db/src/main/java/org/apache/empire/commons/ClassUtils.java
@@ -29,6 +29,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.net.URISyntaxException;
import org.apache.commons.beanutils.ConstructorUtils;
import org.apache.empire.exceptions.EmpireException;
@@ -321,29 +322,56 @@ public final class ClassUtils
}
/**
- * Retrieve a field value using reflection
+ * Modifies a private field value using reflection
* @param clazz the class of the object
* @param object the object or null if static fields are to be changed
* @param property the field name
* @param value the field value
*/
- public static synchronized void setPrivateFieldValue(Class<?> clazz,
Object object, String property, Object value)
+ public static void setPrivateFieldValue(Class<?> clazz, Object object,
String property, Object value)
{
+ Field field = null;
+ boolean accessible = true;
try
- {
- Field field = clazz.getDeclaredField(property);
- field.setAccessible(true);
- // Object val = field.get(object);
+ { // Find field
+ field = clazz.getDeclaredField(property);
+ accessible = field.isAccessible();
+ if (accessible==false)
+ field.setAccessible(true);
+ // Set value
field.set(object, value);
- field.setAccessible(false);
}
- catch (Exception e)
+ catch (NoSuchFieldException e)
+ { // try superclass
+ clazz = clazz.getSuperclass();
+ if (clazz!=null && !clazz.equals(java.lang.Object.class))
+ setPrivateFieldValue(clazz, object, property, value);
+ // not found
+ log.error("Field \""+property+"\" not found on class
"+clazz.getName());
+ throw new InternalException(e);
+ }
+ catch (SecurityException | IllegalArgumentException |
IllegalAccessException e)
{ // Access Error
- log.error("Unable to modify private field '"+property+"* on class
'"+clazz.getName()+"'", e);
+ log.error("Failed to modify private field \""+property+"\" on
class "+clazz.getName(), e);
throw new InternalException(e);
+ } finally {
+ // restore accessible
+ if (field!=null && accessible==false)
+ field.setAccessible(false);
}
}
+ /**
+ * Modifies a private field value using reflection
+ * @param object the object or null if static fields are to be changed
+ * @param property the field name
+ * @param value the field value
+ */
+ public static void setPrivateFieldValue(Object object, String property,
Object value)
+ {
+ setPrivateFieldValue(object.getClass(), object, property, value);
+ }
+
/**
* Creates a new Object instance
* @param typeClass the class of the object to instantiate
@@ -616,4 +644,53 @@ public final class ClassUtils
return invokeSimpleMethod(object.getClass(), object, methodName, true);
}
+ /**
+ * Returns the JAR name that contains the implementation of a specific
class
+ * @param clazz the class
+ * @return the JAR File Name
+ */
+ public static String getImplemenationJarName(Class<?> clazz)
+ {
+ String implJar;
+ try
+ { // detect
+ implJar = clazz.getProtectionDomain()
+ .getCodeSource()
+ .getLocation()
+ .toURI()
+ .getPath();
+ // return JAR name
+ return implJar.substring(implJar.lastIndexOf('/')+1);
+ }
+ catch (URISyntaxException e)
+ {
+ log.error("getImplemenationJarName failed.", e);
+ return "[URISyntaxException]";
+ }
+ catch (NullPointerException e)
+ {
+ log.error("getImplemenationJarName failed.", e);
+ return "[NullPointerException]";
+ }
+ }
+
+ /**
+ * Returns the JAR name that contains the implementation of a specific
class
+ * @param className the class Name of the class
+ * @return the JAR File Name or "[ClassNotFoundException]" if the class is
not available
+ */
+ public static String getImplemenationJarName(String className)
+ {
+ try
+ { // Find the Class for the given name
+ Class<?> clazz = Class.forName(className);
+ return getImplemenationJarName(clazz);
+ }
+ catch (ClassNotFoundException e)
+ {
+ log.info("Class \"{}\" not found", className);
+ return "[ClassNotFoundException]";
+ }
+ }
+
}
diff --git
a/empire-db/src/main/java/org/apache/empire/exceptions/MiscellaneousErrorException.java
b/empire-db/src/main/java/org/apache/empire/exceptions/MiscErrorException.java
similarity index 83%
rename from
empire-db/src/main/java/org/apache/empire/exceptions/MiscellaneousErrorException.java
rename to
empire-db/src/main/java/org/apache/empire/exceptions/MiscErrorException.java
index 2d3e0d77..7402a20b 100644
---
a/empire-db/src/main/java/org/apache/empire/exceptions/MiscellaneousErrorException.java
+++
b/empire-db/src/main/java/org/apache/empire/exceptions/MiscErrorException.java
@@ -20,14 +20,12 @@ package org.apache.empire.exceptions;
/**
* MiscellaneousErrorException
- * @deprecated use UnspecifiedErrorException
*/
-@Deprecated
-public final class MiscellaneousErrorException extends
UnspecifiedErrorException
+public final class MiscErrorException extends UnspecifiedErrorException
{
private static final long serialVersionUID = 1L;
- public MiscellaneousErrorException(String errorMessage)
+ public MiscErrorException(String errorMessage)
{
super(errorMessage);
}