You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2013/10/12 16:48:11 UTC
svn commit: r1531537 [1/2] - in /myfaces/core/trunk:
api/src/main/java/javax/faces/
impl/src/main/java/org/apache/myfaces/cdi/checkenv/
impl/src/main/java/org/apache/myfaces/cdi/impl/
impl/src/main/java/org/apache/myfaces/config/ impl/src/main/java/org...
Author: lu4242
Date: Sat Oct 12 14:48:10 2013
New Revision: 1531537
URL: http://svn.apache.org/r1531537
Log:
MYFACES-3786 Web Container injection support should be provided for additional lifecycle artifacts (not just managed beans)
Added:
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/ (with props)
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/CheckInjectionWithWebServerExtension.java (with props)
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/DummyInjectableBean.java (with props)
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/DummyInjectedBean.java (with props)
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/impl/CDIAnnotationInjectionProvider.java (with props)
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProvider.java (with props)
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProviderException.java (with props)
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProviderFactory.java (with props)
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/AllAnnotationInjectionProvider.java (with props)
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultInjectionProviderFactory.java (with props)
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/NoAnnotationInjectionProvider.java (with props)
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/NoInjectionAnnotationInjectionProvider.java (with props)
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/ResourceAnnotationInjectionProvider.java (with props)
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/Tomcat7AnnotationInjectionProvider.java (with props)
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/TomcatAnnotationInjectionProvider.java (with props)
myfaces/core/trunk/impl/src/main/resources/META-INF/services/org.apache.myfaces.spi.InjectionProvider
Modified:
myfaces/core/trunk/api/src/main/java/javax/faces/FactoryFinder.java
myfaces/core/trunk/api/src/main/java/javax/faces/_FactoryFinderProviderFactory.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/FacesConfigurator.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/RuntimeConfig.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/webapp/AbstractFacesInitializer.java
myfaces/core/trunk/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/mc/test/core/AbstractMyFacesTestCase.java
Modified: myfaces/core/trunk/api/src/main/java/javax/faces/FactoryFinder.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/FactoryFinder.java?rev=1531537&r1=1531536&r2=1531537&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/FactoryFinder.java (original)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/FactoryFinder.java Sat Oct 12 14:48:10 2013
@@ -33,6 +33,7 @@ import javax.faces.application.Applicati
import javax.faces.component.visit.VisitContextFactory;
import javax.faces.context.ExceptionHandlerFactory;
import javax.faces.context.ExternalContextFactory;
+import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.context.FlashFactory;
import javax.faces.context.PartialViewContextFactory;
@@ -88,6 +89,8 @@ public final class FactoryFinder
private static final Set<String> VALID_FACTORY_NAMES = new HashSet<String>();
private static final Map<String, Class<?>> ABSTRACT_FACTORY_CLASSES = new HashMap<String, Class<?>>();
private static final ClassLoader MYFACES_CLASSLOADER;
+
+ private static final String INJECTION_PROVIDER_INSTANCE = "oam.spi.INJECTION_PROVIDER_KEY";
static
{
@@ -314,6 +317,7 @@ public final class FactoryFinder
List<String> classNames;
Object factory;
+ Object injectionProvider;
synchronized (factoryClassNames)
{
factory = factoryMap.get(factoryName);
@@ -323,10 +327,22 @@ public final class FactoryFinder
}
classNames = factoryClassNames.get(factoryName);
+
+ injectionProvider = factoryMap.get(INJECTION_PROVIDER_INSTANCE);
+ }
+
+ if (injectionProvider == null)
+ {
+ injectionProvider = getInjectionProvider();
+ synchronized (factoryClassNames)
+ {
+ factoryMap.put(INJECTION_PROVIDER_INSTANCE, injectionProvider);
+ }
}
// release lock while calling out
- factory = newFactoryInstance(ABSTRACT_FACTORY_CLASSES.get(factoryName), classNames.iterator(), classLoader);
+ factory = newFactoryInstance(ABSTRACT_FACTORY_CLASSES.get(factoryName),
+ classNames.iterator(), classLoader, injectionProvider);
synchronized (factoryClassNames)
{
@@ -339,14 +355,76 @@ public final class FactoryFinder
return factory;
}
+
+ private static Object getInjectionProvider()
+ {
+ try
+ {
+ // Remember the first call in a webapp over FactoryFinder.getFactory(...) comes in the
+ // initialization block, so there is a startup FacesContext active and
+ // also a valid startup ExternalContext. Note after that, we need to cache
+ // the injection provider for the classloader, because in a normal
+ // request there is no active FacesContext in the moment and this call will
+ // surely fail.
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ if (facesContext != null)
+ {
+ Object injectionProviderFactory =
+ _FactoryFinderProviderFactory.INJECTION_PROVIDER_FACTORY_GET_INSTANCE_METHOD
+ .invoke(_FactoryFinderProviderFactory.INJECTION_PROVIDER_CLASS);
+ Object injectionProvider =
+ _FactoryFinderProviderFactory.INJECTION_PROVIDER_FACTORY_GET_INJECTION_PROVIDER_METHOD
+ .invoke(injectionProviderFactory, facesContext.getExternalContext());
+ return injectionProvider;
+ }
+ }
+ catch (Exception e)
+ {
+ }
+ return null;
+ }
+
+ private static void injectAndPostConstruct(Object injectionProvider, Object instance)
+ {
+ if (injectionProvider != null)
+ {
+ try
+ {
+ _FactoryFinderProviderFactory.INJECTION_PROVIDER_INJECT_METHOD.invoke(
+ injectionProvider, instance);
+ _FactoryFinderProviderFactory.INJECTION_PROVIDER_POST_CONSTRUCT_METHOD.invoke(
+ injectionProvider, instance);
+ }
+ catch (Exception ex)
+ {
+ throw new FacesException(ex);
+ }
+ }
+ }
+
+ private static void preDestroy(Object injectionProvider, Object instance)
+ {
+ if (injectionProvider != null)
+ {
+ try
+ {
+ _FactoryFinderProviderFactory.INJECTION_PROVIDER_PRE_DESTROY_METHOD.invoke(
+ injectionProvider, instance);
+ }
+ catch (Exception ex)
+ {
+ throw new FacesException(ex);
+ }
+ }
+ }
private static Object newFactoryInstance(Class<?> interfaceClass, Iterator<String> classNamesIterator,
- ClassLoader classLoader)
+ ClassLoader classLoader, Object injectionProvider)
{
try
{
Object current = null;
-
+
while (classNamesIterator.hasNext())
{
String implClassName = classNamesIterator.next();
@@ -370,6 +448,7 @@ public final class FactoryFinder
{
// nothing to decorate
current = implClass.newInstance();
+ injectAndPostConstruct(injectionProvider, current);
}
else
{
@@ -382,6 +461,7 @@ public final class FactoryFinder
{
// create new decorator wrapping current
current = delegationConstructor.newInstance(new Object[] { current });
+ injectAndPostConstruct(injectionProvider, current);
}
catch (InstantiationException e)
{
@@ -400,6 +480,7 @@ public final class FactoryFinder
{
// no decorator pattern support
current = implClass.newInstance();
+ injectAndPostConstruct(injectionProvider, current);
}
}
}
@@ -570,10 +651,11 @@ public final class FactoryFinder
{
ClassLoader classLoader = getClassLoader();
+ Map<String, Object> factoryMap;
// This code must be synchronized
synchronized (registeredFactoryNames)
{
- factories.remove(classLoader);
+ factoryMap = factories.remove(classLoader);
// _registeredFactoryNames has as value type Map<String,List> and this must
// be cleaned before release (for gc).
@@ -585,6 +667,30 @@ public final class FactoryFinder
registeredFactoryNames.remove(classLoader);
}
+
+ if (factoryMap != null)
+ {
+ Object injectionProvider = factoryMap.remove(INJECTION_PROVIDER_INSTANCE);
+ if (injectionProvider != null)
+ {
+ for (Map.Entry<String, Object> entry : factoryMap.entrySet())
+ {
+ Object instance = entry.getValue();
+ while (instance != null)
+ {
+ preDestroy(injectionProvider, instance);
+ if (instance instanceof FacesWrapper)
+ {
+ instance = ((FacesWrapper) instance).getWrapped();
+ }
+ else
+ {
+ instance = null;
+ }
+ }
+ }
+ }
+ }
}
private static void checkFactoryName(String factoryName)
Modified: myfaces/core/trunk/api/src/main/java/javax/faces/_FactoryFinderProviderFactory.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/java/javax/faces/_FactoryFinderProviderFactory.java?rev=1531537&r1=1531536&r2=1531537&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/java/javax/faces/_FactoryFinderProviderFactory.java (original)
+++ myfaces/core/trunk/api/src/main/java/javax/faces/_FactoryFinderProviderFactory.java Sat Oct 12 14:48:10 2013
@@ -24,6 +24,7 @@ import java.security.PrivilegedActionExc
import java.security.PrivilegedExceptionAction;
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.faces.context.ExternalContext;
/**
* Provide utility methods used by FactoryFinder class to lookup for SPI interface FactoryFinderProvider.
@@ -39,6 +40,11 @@ class _FactoryFinderProviderFactory
public static final String FACTORY_FINDER_PROVIDER_CLASS_NAME = "org.apache.myfaces.spi.FactoryFinderProvider";
+ public static final String INJECTION_PROVIDER_FACTORY_CLASS_NAME =
+ "org.apache.myfaces.spi.InjectionProviderFactory";
+
+ public static final String INJECTION_PROVIDER_CLASS_NAME = "org.apache.myfaces.spi.InjectionProvider";
+
public static final Class<?> FACTORY_FINDER_PROVIDER_FACTORY_CLASS;
public static final Method FACTORY_FINDER_PROVIDER_GET_INSTANCE_METHOD;
@@ -48,7 +54,15 @@ class _FactoryFinderProviderFactory
public static final Method FACTORY_FINDER_PROVIDER_GET_FACTORY_METHOD;
public static final Method FACTORY_FINDER_PROVIDER_SET_FACTORY_METHOD;
public static final Method FACTORY_FINDER_PROVIDER_RELEASE_FACTORIES_METHOD;
-
+
+ public static final Class<?> INJECTION_PROVIDER_FACTORY_CLASS;
+ public static final Method INJECTION_PROVIDER_FACTORY_GET_INSTANCE_METHOD;
+ public static final Method INJECTION_PROVIDER_FACTORY_GET_INJECTION_PROVIDER_METHOD;
+ public static final Class<?> INJECTION_PROVIDER_CLASS;
+ public static final Method INJECTION_PROVIDER_INJECT_METHOD;
+ public static final Method INJECTION_PROVIDER_POST_CONSTRUCT_METHOD;
+ public static final Method INJECTION_PROVIDER_PRE_DESTROY_METHOD;
+
static
{
Class factoryFinderFactoryClass = null;
@@ -59,12 +73,18 @@ class _FactoryFinderProviderFactory
Method factoryFinderProviderGetFactoryMethod = null;
Method factoryFinderProviderSetFactoryMethod = null;
Method factoryFinderProviderReleaseFactoriesMethod = null;
+
+ Class injectionProviderFactoryClass = null;
+ Method injectionProviderFactoryGetInstanceMethod = null;
+ Method injectionProviderFactoryGetInjectionProviderMethod = null;
+ Class injectionProviderClass = null;
+ Method injectionProviderInjectMethod = null;
+ Method injectionProviderPostConstructMethod = null;
+ Method injectionProviderPreDestroyMethod = null;
try
{
factoryFinderFactoryClass = classForName(FACTORY_FINDER_PROVIDER_FACTORY_CLASS_NAME);
-
-
if (factoryFinderFactoryClass != null)
{
factoryFinderproviderFactoryGetMethod = factoryFinderFactoryClass.getMethod
@@ -83,6 +103,28 @@ class _FactoryFinderProviderFactory
factoryFinderProviderReleaseFactoriesMethod = factoryFinderProviderClass.getMethod
("releaseFactories", null);
}
+
+ injectionProviderFactoryClass = classForName(INJECTION_PROVIDER_FACTORY_CLASS_NAME);
+
+ if (injectionProviderFactoryClass != null)
+ {
+ injectionProviderFactoryGetInstanceMethod = injectionProviderFactoryClass.
+ getMethod("getInjectionProviderFactory", null);
+ injectionProviderFactoryGetInjectionProviderMethod = injectionProviderFactoryClass.
+ getMethod("getInjectionProvider", ExternalContext.class);
+ }
+
+ injectionProviderClass = classForName(INJECTION_PROVIDER_CLASS_NAME);
+
+ if (injectionProviderClass != null)
+ {
+ injectionProviderInjectMethod = injectionProviderClass.
+ getMethod("inject", Object.class);
+ injectionProviderPostConstructMethod = injectionProviderClass.
+ getMethod("postConstruct", Object.class);
+ injectionProviderPreDestroyMethod = injectionProviderClass.
+ getMethod("preDestroy", Object.class);
+ }
}
catch (Exception e)
{
@@ -97,6 +139,14 @@ class _FactoryFinderProviderFactory
FACTORY_FINDER_PROVIDER_GET_FACTORY_METHOD = factoryFinderProviderGetFactoryMethod;
FACTORY_FINDER_PROVIDER_SET_FACTORY_METHOD = factoryFinderProviderSetFactoryMethod;
FACTORY_FINDER_PROVIDER_RELEASE_FACTORIES_METHOD = factoryFinderProviderReleaseFactoriesMethod;
+
+ INJECTION_PROVIDER_FACTORY_CLASS = injectionProviderFactoryClass;
+ INJECTION_PROVIDER_FACTORY_GET_INSTANCE_METHOD = injectionProviderFactoryGetInstanceMethod;
+ INJECTION_PROVIDER_FACTORY_GET_INJECTION_PROVIDER_METHOD = injectionProviderFactoryGetInjectionProviderMethod;
+ INJECTION_PROVIDER_CLASS = injectionProviderClass;
+ INJECTION_PROVIDER_INJECT_METHOD = injectionProviderInjectMethod;
+ INJECTION_PROVIDER_POST_CONSTRUCT_METHOD = injectionProviderPostConstructMethod;
+ INJECTION_PROVIDER_PRE_DESTROY_METHOD = injectionProviderPreDestroyMethod;
}
public static Object getInstance()
Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/
------------------------------------------------------------------------------
bugtraq:number = true
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/CheckInjectionWithWebServerExtension.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/CheckInjectionWithWebServerExtension.java?rev=1531537&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/CheckInjectionWithWebServerExtension.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/CheckInjectionWithWebServerExtension.java Sat Oct 12 14:48:10 2013
@@ -0,0 +1,43 @@
+/*
+ * 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.cdi.checkenv;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.Extension;
+
+/**
+ * This extension registers a dummy bean that helps to test if the underlying
+ * web server integration is working with the CDI implementation or not. The
+ * idea is detect those cases where the web server is not integrated but CDI
+ * is available and should be preferred as InjectionProvider
+ *
+ * @author Leonardo Uribe
+ */
+public class CheckInjectionWithWebServerExtension implements Extension
+{
+ void beforeBeanDiscovery(
+ @Observes final BeforeBeanDiscovery event, BeanManager beanManager)
+ {
+ AnnotatedType bean = beanManager.createAnnotatedType(DummyInjectedBean.class);
+ event.addAnnotatedType(bean);
+ }
+}
Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/CheckInjectionWithWebServerExtension.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/DummyInjectableBean.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/DummyInjectableBean.java?rev=1531537&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/DummyInjectableBean.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/DummyInjectableBean.java Sat Oct 12 14:48:10 2013
@@ -0,0 +1,36 @@
+/*
+ * 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.cdi.checkenv;
+
+import javax.inject.Inject;
+
+/**
+ *
+ * @author Leonardo Uribe
+ */
+public class DummyInjectableBean
+{
+ @Inject
+ DummyInjectedBean injectedBean;
+
+ public boolean isDummyBeanInjected()
+ {
+ return injectedBean != null;
+ }
+}
Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/DummyInjectableBean.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/DummyInjectedBean.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/DummyInjectedBean.java?rev=1531537&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/DummyInjectedBean.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/DummyInjectedBean.java Sat Oct 12 14:48:10 2013
@@ -0,0 +1,30 @@
+/*
+ * 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.cdi.checkenv;
+
+import javax.enterprise.context.Dependent;
+
+/**
+ *
+ * @author Leonardo Uribe
+ */
+@Dependent
+public class DummyInjectedBean
+{
+}
Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/checkenv/DummyInjectedBean.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/impl/CDIAnnotationInjectionProvider.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/impl/CDIAnnotationInjectionProvider.java?rev=1531537&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/impl/CDIAnnotationInjectionProvider.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/impl/CDIAnnotationInjectionProvider.java Sat Oct 12 14:48:10 2013
@@ -0,0 +1,65 @@
+/*
+ * 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.cdi.impl;
+
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionTarget;
+import javax.faces.context.ExternalContext;
+import org.apache.myfaces.cdi.util.CDIUtils;
+import org.apache.myfaces.spi.InjectionProvider;
+import org.apache.myfaces.spi.InjectionProviderException;
+
+/**
+ *
+ * @author Leonardo Uribe
+ */
+public class CDIAnnotationInjectionProvider extends InjectionProvider
+{
+ private BeanManager beanManager;
+
+ public CDIAnnotationInjectionProvider(ExternalContext externalContext)
+ {
+ beanManager = CDIUtils.getBeanManager(externalContext);
+ }
+
+ @Override
+ public void inject(Object instance) throws InjectionProviderException
+ {
+ AnnotatedType annoType = beanManager.createAnnotatedType(instance.getClass());
+ InjectionTarget target = beanManager.createInjectionTarget(annoType);
+ target.inject(instance, beanManager.createCreationalContext(null));
+ }
+
+ @Override
+ public void postConstruct(Object instance) throws InjectionProviderException
+ {
+ AnnotatedType annoType = beanManager.createAnnotatedType(instance.getClass());
+ InjectionTarget target = beanManager.createInjectionTarget(annoType);
+ target.postConstruct(instance);
+ }
+
+ @Override
+ public void preDestroy(Object instance) throws InjectionProviderException
+ {
+ AnnotatedType annoType = beanManager.createAnnotatedType(instance.getClass());
+ InjectionTarget target = beanManager.createInjectionTarget(annoType);
+ target.preDestroy(instance);
+ }
+}
Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/cdi/impl/CDIAnnotationInjectionProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/FacesConfigurator.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/FacesConfigurator.java?rev=1531537&r1=1531536&r2=1531537&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/FacesConfigurator.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/FacesConfigurator.java Sat Oct 12 14:48:10 2013
@@ -39,6 +39,7 @@ import java.util.logging.Logger;
import javax.el.ELResolver;
import javax.faces.FacesException;
+import javax.faces.FacesWrapper;
import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.application.ApplicationFactory;
@@ -132,6 +133,9 @@ import org.apache.myfaces.shared_impl.ut
import org.apache.myfaces.shared_impl.util.serial.SerialFactory;
import org.apache.myfaces.spi.FacesConfigurationMerger;
import org.apache.myfaces.spi.FacesConfigurationMergerFactory;
+import org.apache.myfaces.spi.InjectionProvider;
+import org.apache.myfaces.spi.InjectionProviderException;
+import org.apache.myfaces.spi.InjectionProviderFactory;
import org.apache.myfaces.spi.ResourceLibraryContractsProvider;
import org.apache.myfaces.spi.ResourceLibraryContractsProviderFactory;
import org.apache.myfaces.util.ContainerUtils;
@@ -190,6 +194,8 @@ public class FacesConfigurator
private AnnotationConfigurator _annotationConfigurator;
private RuntimeConfig _runtimeConfig;
+
+ private InjectionProvider _injectionProvider;
private static long lastUpdate;
@@ -561,8 +567,10 @@ public class FacesConfigurator
FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY)).getApplication();
FacesConfigData dispenser = getDispenser();
- application.setActionListener(ClassUtils.buildApplicationObject(ActionListener.class,
- dispenser.getActionListenerIterator(), null));
+ ActionListener actionListener = ClassUtils.buildApplicationObject(ActionListener.class,
+ dispenser.getActionListenerIterator(), null);
+ _callInjectAndPostConstruct(actionListener);
+ application.setActionListener(actionListener);
if (dispenser.getDefaultLocale() != null)
{
@@ -578,20 +586,26 @@ public class FacesConfigurator
{
application.setMessageBundle(dispenser.getMessageBundle());
}
-
- application.setNavigationHandler(ClassUtils.buildApplicationObject(NavigationHandler.class,
+
+ NavigationHandler navigationHandler = ClassUtils.buildApplicationObject(NavigationHandler.class,
ConfigurableNavigationHandler.class,
BackwardsCompatibleNavigationHandlerWrapper.class,
dispenser.getNavigationHandlerIterator(),
- application.getNavigationHandler()));
+ application.getNavigationHandler());
+ _callInjectAndPostConstruct(navigationHandler);
+ application.setNavigationHandler(navigationHandler);
- application.setStateManager(ClassUtils.buildApplicationObject(StateManager.class,
+ StateManager stateManager = ClassUtils.buildApplicationObject(StateManager.class,
dispenser.getStateManagerIterator(),
- application.getStateManager()));
+ application.getStateManager());
+ _callInjectAndPostConstruct(stateManager);
+ application.setStateManager(stateManager);
- application.setResourceHandler(ClassUtils.buildApplicationObject(ResourceHandler.class,
+ ResourceHandler resourceHandler = ClassUtils.buildApplicationObject(ResourceHandler.class,
dispenser.getResourceHandlerIterator(),
- application.getResourceHandler()));
+ application.getResourceHandler());
+ _callInjectAndPostConstruct(resourceHandler);
+ application.setResourceHandler(resourceHandler);
List<Locale> locales = new ArrayList<Locale>();
for (String locale : dispenser.getSupportedLocalesIterator())
@@ -604,6 +618,9 @@ public class FacesConfigurator
application.setViewHandler(ClassUtils.buildApplicationObject(ViewHandler.class,
dispenser.getViewHandlerIterator(),
application.getViewHandler()));
+
+ RuntimeConfig runtimeConfig = getRuntimeConfig();
+
for (SystemEventListener systemEventListener : dispenser.getSystemEventListeners())
{
@@ -618,20 +635,22 @@ public class FacesConfigurator
? systemEventListener.getSystemEventClass()
: SystemEvent.class.getName());
+ javax.faces.event.SystemEventListener listener = (javax.faces.event.SystemEventListener)
+ ClassUtils.newInstance(systemEventListener.getSystemEventListenerClass());
+ _callInjectAndPostConstruct(listener);
+ runtimeConfig.addInjectedObject(listener);
if (systemEventListener.getSourceClass() != null && systemEventListener.getSourceClass().length() > 0)
{
application.subscribeToEvent(
(Class<? extends SystemEvent>) eventClass,
ClassUtils.classForName(systemEventListener.getSourceClass()),
- (javax.faces.event.SystemEventListener)
- ClassUtils.newInstance(systemEventListener.getSystemEventListenerClass()));
+ listener);
}
else
{
application.subscribeToEvent(
(Class<? extends SystemEvent>) eventClass,
- (javax.faces.event.SystemEventListener)
- ClassUtils.newInstance(systemEventListener.getSystemEventListenerClass()));
+ listener);
}
}
catch (ClassNotFoundException e)
@@ -732,8 +751,6 @@ public class FacesConfigurator
FacesContext.getCurrentInstance());
application.setFlowHandler(flowHandler);
- RuntimeConfig runtimeConfig = getRuntimeConfig();
-
if (MyfacesConfig.getCurrentInstance(_externalContext).isSupportJSPAndFacesEL())
{
// If no JSP and old Faces EL, there is no need to initialize PropertyResolver
@@ -754,6 +771,28 @@ public class FacesConfigurator
runtimeConfig.addContractMapping(urlPattern, contracts);
}
}
+
+ private void _callInjectAndPostConstruct(Object instance)
+ {
+ try
+ {
+ //invoke the injection over the inner one first
+ if (instance instanceof FacesWrapper)
+ {
+ Object innerInstance = ((FacesWrapper)instance).getWrapped();
+ if (innerInstance != null)
+ {
+ _callInjectAndPostConstruct(innerInstance);
+ }
+ }
+ getInjectionProvider().inject(instance);
+ getInjectionProvider().postConstruct(instance);
+ }
+ catch (InjectionProviderException ex)
+ {
+ log.log(Level.INFO, "Exception on PreDestroy", ex);
+ }
+ }
/**
* A mapper for the handful of system listener defaults
@@ -841,7 +880,17 @@ public class FacesConfigurator
for (String className : dispenser.getElResolvers())
{
- runtimeConfig.addFacesConfigElResolver((ELResolver) ClassUtils.newInstance(className, ELResolver.class));
+ ELResolver elResolver = (ELResolver) ClassUtils.newInstance(className, ELResolver.class);
+ try
+ {
+ getInjectionProvider().inject(elResolver);
+ getInjectionProvider().postConstruct(elResolver);
+ }
+ catch (InjectionProviderException e)
+ {
+ log.log(Level.SEVERE, "Error while injecting ELResolver", e);
+ }
+ runtimeConfig.addFacesConfigElResolver(elResolver);
}
runtimeConfig.setFacesVersion(dispenser.getFacesVersion());
@@ -1108,13 +1157,20 @@ public class FacesConfigurator
{
try
{
- lifecycle.addPhaseListener((PhaseListener)
- ClassUtils.newInstance(listenerClassName, PhaseListener.class));
+ PhaseListener listener = (PhaseListener)
+ ClassUtils.newInstance(listenerClassName, PhaseListener.class);
+ getInjectionProvider().inject(listener);
+ getInjectionProvider().postConstruct(listener);
+ lifecycle.addPhaseListener(listener);
}
catch (ClassCastException e)
{
log.severe("Class " + listenerClassName + " does not implement PhaseListener");
}
+ catch (InjectionProviderException e)
+ {
+ log.log(Level.SEVERE, "Error while injecting PhaseListener", e);
+ }
}
// if ProjectStage is Development, install the DebugPhaseListener
@@ -1191,6 +1247,8 @@ public class FacesConfigurator
RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(externalContext);
LifecycleProvider lifecycleProvider = LifecycleProviderFactory
.getLifecycleProviderFactory(externalContext).getLifecycleProvider(externalContext);
+ InjectionProvider injectionProvider = InjectionProviderFactory
+ .getInjectionProviderFactory(externalContext).getInjectionProvider(externalContext);
// create ManagedBeanDestroyer
ManagedBeanDestroyer mbDestroyer
@@ -1438,4 +1496,14 @@ public class FacesConfigurator
viewHandler.addProtectedView(urlPattern);
}
}
+
+ protected InjectionProvider getInjectionProvider()
+ {
+ if (_injectionProvider == null)
+ {
+ _injectionProvider = InjectionProviderFactory.getInjectionProviderFactory(
+ _externalContext).getInjectionProvider(_externalContext);
+ }
+ return _injectionProvider;
+ }
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/RuntimeConfig.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/RuntimeConfig.java?rev=1531537&r1=1531536&r2=1531537&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/RuntimeConfig.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/RuntimeConfig.java Sat Oct 12 14:48:10 2013
@@ -110,6 +110,8 @@ public class RuntimeConfig
new ArrayList<ComponentTagDeclaration>();
private List<String> _resourceResolvers = new ArrayList<String>();
+
+ private List<Object> _injectedObjects = new ArrayList<Object>();
public static RuntimeConfig getCurrentInstance(ExternalContext externalContext)
{
@@ -134,6 +136,7 @@ public class RuntimeConfig
_externalContextResourceLibraryContracts.clear();
_classLoaderResourceLibraryContracts.clear();
_resourceLibraryContracts.clear();
+ _injectedObjects.clear();
}
/**
@@ -502,4 +505,16 @@ public class RuntimeConfig
_resourceResolvers.add(resourceResolver);
}
+ /**
+ * @return the _injectedObjects
+ */
+ public List<Object> getInjectedObjects()
+ {
+ return _injectedObjects;
+ }
+
+ public void addInjectedObject(Object object)
+ {
+ _injectedObjects.add(object);
+ }
}
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProvider.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProvider.java?rev=1531537&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProvider.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProvider.java Sat Oct 12 14:48:10 2013
@@ -0,0 +1,39 @@
+/*
+ * 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.spi;
+
+/**
+ * Provide an interface to inject JSF artifacts using JavaEE annotations
+ * as described in JSF 2.2 spec section 5.4
+ *
+ * @author Leonardo Uribe
+ */
+public abstract class InjectionProvider
+{
+ public abstract void inject(Object instance) throws InjectionProviderException;
+
+ public abstract void postConstruct(Object instance) throws InjectionProviderException;
+
+ public abstract void preDestroy(Object instance) throws InjectionProviderException;
+
+ public boolean isAvailable()
+ {
+ return true;
+ }
+}
Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProviderException.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProviderException.java?rev=1531537&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProviderException.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProviderException.java Sat Oct 12 14:48:10 2013
@@ -0,0 +1,47 @@
+/*
+ * 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.spi;
+
+/**
+ *
+ * @author Leonardo Uribe
+ */
+public class InjectionProviderException extends Exception
+{
+
+ public InjectionProviderException()
+ {
+ }
+
+ public InjectionProviderException(String message)
+ {
+ super(message);
+ }
+
+ public InjectionProviderException(String message, Throwable cause)
+ {
+ super(message, cause);
+ }
+
+ public InjectionProviderException(Throwable cause)
+ {
+ super(cause);
+ }
+
+}
Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProviderException.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProviderFactory.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProviderFactory.java?rev=1531537&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProviderFactory.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProviderFactory.java Sat Oct 12 14:48:10 2013
@@ -0,0 +1,98 @@
+/*
+ * 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.spi;
+
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.util.Map;
+
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+
+import org.apache.myfaces.spi.impl.SpiUtils;
+
+public abstract class InjectionProviderFactory
+{
+ protected static final String FACTORY_DEFAULT =
+ "org.apache.myfaces.spi.impl.DefaultInjectionProviderFactory";
+
+ private static final String FACTORY_KEY = InjectionProviderFactory.class.getName();
+
+ public static InjectionProviderFactory getInjectionProviderFactory()
+ {
+ // Since we always provide a StartupFacesContext on initialization time, this is safe:
+ return getInjectionProviderFactory(FacesContext.getCurrentInstance().getExternalContext());
+ }
+
+ public static InjectionProviderFactory getInjectionProviderFactory(ExternalContext ctx)
+ {
+ Map<String, Object> applicationMap = ctx.getApplicationMap();
+ InjectionProviderFactory instance =
+ (InjectionProviderFactory) applicationMap.get(FACTORY_KEY);
+ if (instance != null)
+ {
+ return instance;
+ }
+ InjectionProviderFactory lpf = null;
+ try
+ {
+
+ if (System.getSecurityManager() != null)
+ {
+ final ExternalContext ectx = ctx;
+ lpf = (InjectionProviderFactory)
+ AccessController.doPrivileged(new java.security.PrivilegedExceptionAction<Object>()
+ {
+ public Object run() throws PrivilegedActionException
+ {
+ return SpiUtils.build(ectx,
+ InjectionProviderFactory.class,
+ FACTORY_DEFAULT);
+ }
+ });
+ }
+ else
+ {
+ lpf = (InjectionProviderFactory) SpiUtils.build(ctx,
+ InjectionProviderFactory.class, FACTORY_DEFAULT);
+ }
+ }
+ catch (PrivilegedActionException pae)
+ {
+ throw new FacesException(pae);
+ }
+ if (lpf != null)
+ {
+ applicationMap.put(FACTORY_KEY, lpf);
+ }
+ return lpf;
+ }
+
+
+ public static void setInjectionProviderFactory(InjectionProviderFactory instance)
+ {
+ FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().put(FACTORY_KEY, instance);
+ }
+
+ public abstract InjectionProvider getInjectionProvider(ExternalContext externalContext);
+
+ public abstract void release();
+
+}
Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/InjectionProviderFactory.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/AllAnnotationInjectionProvider.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/AllAnnotationInjectionProvider.java?rev=1531537&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/AllAnnotationInjectionProvider.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/AllAnnotationInjectionProvider.java Sat Oct 12 14:48:10 2013
@@ -0,0 +1,101 @@
+/*
+ * 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.spi.impl;
+
+import javax.naming.NamingException;
+import javax.naming.Context;
+import javax.annotation.Resource;
+import javax.ejb.EJB;
+import javax.persistence.PersistenceContext;
+import javax.persistence.PersistenceUnit;
+
+
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Field;
+
+// TODO @EJBs
+public class AllAnnotationInjectionProvider extends ResourceAnnotationInjectionProvider
+{
+
+ public AllAnnotationInjectionProvider(Context context)
+ {
+ super(context);
+ }
+
+ @Override
+ protected void checkMethodAnnotation(Method method, Object instance)
+ throws NamingException, IllegalAccessException, InvocationTargetException
+ {
+ super.checkMethodAnnotation(method, instance);
+ if (method.isAnnotationPresent(Resource.class))
+ {
+ Resource annotation = method.getAnnotation(Resource.class);
+ lookupMethodResource(context, instance, method, annotation.name());
+ }
+ if (method.isAnnotationPresent(EJB.class))
+ {
+ EJB annotation = method.getAnnotation(EJB.class);
+ lookupMethodResource(context, instance, method, annotation.name());
+ }
+ // TODO where i find WebServiceRef?
+ /*if (method.isAnnotationPresent(WebServiceRef.class)) {
+ WebServiceRef annotation =
+ (WebServiceRef) method.getAnnotation(WebServiceRef.class);
+ lookupMethodResource(context, instance, methods, annotation.name());
+ }*/
+ if (method.isAnnotationPresent(PersistenceContext.class))
+ {
+ PersistenceContext annotation = method.getAnnotation(PersistenceContext.class);
+ lookupMethodResource(context, instance, method, annotation.name());
+ }
+ if (method.isAnnotationPresent(PersistenceUnit.class))
+ {
+ PersistenceUnit annotation = method.getAnnotation(PersistenceUnit.class);
+ lookupMethodResource(context, instance, method, annotation.name());
+ }
+ }
+
+ @Override
+ protected void checkFieldAnnotation(Field field, Object instance)
+ throws NamingException, IllegalAccessException
+ {
+ super.checkFieldAnnotation(field, instance);
+ if (field.isAnnotationPresent(EJB.class))
+ {
+ EJB annotation = field.getAnnotation(EJB.class);
+ lookupFieldResource(context, instance, field, annotation.name());
+ }
+ /*if (field.isAnnotationPresent(WebServiceRef.class)) {
+ WebServiceRef annotation =
+ (WebServiceRef) field.getAnnotation(WebServiceRef.class);
+ lookupFieldResource(context, instance, field, annotation.name());
+ }*/
+ if (field.isAnnotationPresent(PersistenceContext.class))
+ {
+ PersistenceContext annotation = field.getAnnotation(PersistenceContext.class);
+ lookupFieldResource(context, instance, field, annotation.name());
+ }
+ if (field.isAnnotationPresent(PersistenceUnit.class))
+ {
+ PersistenceUnit annotation = field.getAnnotation(PersistenceUnit.class);
+ lookupFieldResource(context, instance, field, annotation.name());
+ }
+ }
+}
Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/AllAnnotationInjectionProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultInjectionProviderFactory.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultInjectionProviderFactory.java?rev=1531537&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultInjectionProviderFactory.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultInjectionProviderFactory.java Sat Oct 12 14:48:10 2013
@@ -0,0 +1,319 @@
+/*
+ * 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.spi.impl;
+
+import java.lang.reflect.InvocationTargetException;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
+import org.apache.myfaces.shared.util.ClassUtils;
+import org.apache.myfaces.spi.InjectionProvider;
+import org.apache.myfaces.spi.InjectionProviderFactory;
+import org.apache.myfaces.spi.ServiceProviderFinderFactory;
+import org.apache.myfaces.util.ExternalSpecifications;
+
+/**
+ *
+ *
+ */
+public class DefaultInjectionProviderFactory extends InjectionProviderFactory
+{
+ //private static Log log = LogFactory.getLog(DefaultLifecycleProviderFactory.class);
+ private static Logger log = Logger.getLogger(DefaultInjectionProviderFactory.class.getName());
+
+ /**
+ * Define the class implementing InjectionProvider interface to handle PostConstruct
+ * and PreDestroy annotations.
+ *
+ * <p>This also can be configured using a SPI entry (/META-INF/services/...).
+ * </p>
+ */
+ public static final String INJECTION_PROVIDER_INSTANCE_KEY
+ = InjectionProvider.class.getName() + ".INJECTION_PROVIDER_INSTANCE";
+
+ @JSFWebConfigParam(name="org.apache.myfaces.spi.InjectionProvider", since="2.2")
+ public static final String INJECTION_PROVIDER = InjectionProvider.class.getName();
+
+
+ public DefaultInjectionProviderFactory()
+ {
+ }
+
+ @Override
+ public InjectionProvider getInjectionProvider(ExternalContext externalContext)
+ {
+ InjectionProvider lifecycleProvider = null;
+ if (externalContext == null)
+ {
+ // Really in jsf 2.0, this will not happen, because a Startup/Shutdown
+ // FacesContext and ExternalContext are provided on initialization and shutdown,
+ // and in other scenarios the real FacesContext/ExternalContext is provided.
+ log.info("No ExternalContext using fallback InjectionProvider.");
+ lifecycleProvider = resolveFallbackInjectionProvider();
+ }
+ else
+ {
+ lifecycleProvider = (InjectionProvider)
+ externalContext.getApplicationMap().get(INJECTION_PROVIDER_INSTANCE_KEY);
+ }
+ if (lifecycleProvider == null)
+ {
+ if (!resolveInjectionProviderFromExternalContext(externalContext))
+ {
+ if (!resolveInjectionProviderFromService(externalContext))
+ {
+ lifecycleProvider = resolveFallbackInjectionProvider();
+ externalContext.getApplicationMap().put(INJECTION_PROVIDER_INSTANCE_KEY, lifecycleProvider);
+ }
+ else
+ {
+ //Retrieve it because it was resolved
+ lifecycleProvider = (InjectionProvider)
+ externalContext.getApplicationMap().get(INJECTION_PROVIDER_INSTANCE_KEY);
+ }
+ }
+ else
+ {
+ //Retrieve it because it was resolved
+ lifecycleProvider = (InjectionProvider)
+ externalContext.getApplicationMap().get(INJECTION_PROVIDER_INSTANCE_KEY);
+ }
+ log.info("Using InjectionProvider "+ lifecycleProvider.getClass().getName());
+ }
+ return lifecycleProvider;
+ }
+
+ @Override
+ public void release()
+ {
+ }
+
+
+
+ private boolean resolveInjectionProviderFromExternalContext(ExternalContext externalContext)
+ {
+ try
+ {
+ String lifecycleProvider = externalContext.getInitParameter(INJECTION_PROVIDER);
+ if (lifecycleProvider != null)
+ {
+
+ Object obj = createClass(lifecycleProvider, externalContext);
+
+ if (obj instanceof InjectionProvider)
+ {
+ externalContext.getApplicationMap().put(INJECTION_PROVIDER_INSTANCE_KEY, obj);
+ return true;
+ }
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ log.log(Level.SEVERE, "", e);
+ }
+ catch (InstantiationException e)
+ {
+ log.log(Level.SEVERE, "", e);
+ }
+ catch (IllegalAccessException e)
+ {
+ log.log(Level.SEVERE, "", e);
+ }
+ catch (InvocationTargetException e)
+ {
+ log.log(Level.SEVERE, "", e);
+ }
+ return false;
+ }
+
+
+ private boolean resolveInjectionProviderFromService(
+ ExternalContext externalContext)
+ {
+ boolean returnValue = false;
+ final ExternalContext extContext = externalContext;
+ try
+ {
+ if (System.getSecurityManager() != null)
+ {
+ returnValue = AccessController.doPrivileged(new java.security.PrivilegedExceptionAction<Boolean>()
+ {
+ public Boolean run() throws ClassNotFoundException,
+ NoClassDefFoundError,
+ InstantiationException,
+ IllegalAccessException,
+ InvocationTargetException,
+ PrivilegedActionException
+ {
+ List<String> classList
+ = ServiceProviderFinderFactory.getServiceProviderFinder(extContext).
+ getServiceProviderList(INJECTION_PROVIDER);
+ Iterator<String> iter = classList.iterator();
+ while (iter.hasNext())
+ {
+ String className = iter.next();
+ Object obj = createClass(className,extContext);
+ if (InjectionProvider.class.isAssignableFrom(obj.getClass()))
+ {
+ InjectionProvider discoverableInjectionProvider =
+ (InjectionProvider) obj;
+ if (discoverableInjectionProvider.isAvailable())
+ {
+ extContext.getApplicationMap().put(INJECTION_PROVIDER_INSTANCE_KEY,
+ discoverableInjectionProvider);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ });
+ }
+ else
+ {
+ List<String> classList = ServiceProviderFinderFactory.getServiceProviderFinder(extContext).
+ getServiceProviderList(INJECTION_PROVIDER);
+ Iterator<String> iter = classList.iterator();
+ while (iter.hasNext())
+ {
+ String className = iter.next();
+ Object obj = createClass(className,extContext);
+ if (InjectionProvider.class.isAssignableFrom(obj.getClass()))
+ {
+ InjectionProvider discoverableInjectionProvider
+ = (InjectionProvider) obj;
+ if (discoverableInjectionProvider.isAvailable())
+ {
+ extContext.getApplicationMap().put(INJECTION_PROVIDER_INSTANCE_KEY,
+ discoverableInjectionProvider);
+ return (Boolean) true;
+ }
+ }
+ }
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ // ignore
+ }
+ catch (NoClassDefFoundError e)
+ {
+ // ignore
+ }
+ catch (InstantiationException e)
+ {
+ log.log(Level.SEVERE, "", e);
+ }
+ catch (IllegalAccessException e)
+ {
+ log.log(Level.SEVERE, "", e);
+ }
+ catch (InvocationTargetException e)
+ {
+ log.log(Level.SEVERE, "", e);
+ }
+ catch (PrivilegedActionException e)
+ {
+ throw new FacesException(e);
+ }
+ return returnValue;
+ }
+
+ private Object createClass(String className, ExternalContext externalContext)
+ throws InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException
+ {
+ Class<?> clazz = ClassUtils.classForName(className);
+
+ try
+ {
+ return ClassUtils.newInstance(clazz, new Class<?>[]{ ExternalContext.class }, externalContext);
+ }
+ catch (NoSuchMethodException e)
+ {
+ return ClassUtils.newInstance(clazz);
+ }
+ }
+
+ private InjectionProvider resolveFallbackInjectionProvider()
+ {
+ return resolveFallbackInjectionProvider(FacesContext.getCurrentInstance().getExternalContext());
+ }
+
+ private InjectionProvider resolveFallbackInjectionProvider(ExternalContext externalContext)
+ {
+ if (ExternalSpecifications.isCDIAvailable(externalContext))
+ {
+ try
+ {
+ Class clazz = ClassUtils.simpleClassForName(
+ "org.apache.myfaces.cdi.impl.CDIAnnotationInjectionProvider");
+ return (InjectionProvider) clazz.getConstructor(
+ ExternalContext.class).newInstance(externalContext);
+ }
+ catch(Exception e)
+ {
+ //Ignore
+ }
+ }
+
+ try
+ {
+ ClassUtils.classForName("javax.annotation.PreDestroy");
+ }
+ catch (ClassNotFoundException e)
+ {
+ // no annotation available don't process annotations
+ return new NoAnnotationInjectionProvider();
+ }
+ Context context;
+ try
+ {
+ context = new InitialContext();
+ try
+ {
+ ClassUtils.classForName("javax.ejb.EJB");
+ // Asume full JEE 5 container
+ return new AllAnnotationInjectionProvider(context);
+ }
+ catch (ClassNotFoundException e)
+ {
+ // something else
+ return new ResourceAnnotationInjectionProvider(context);
+ }
+ }
+ catch (NamingException e)
+ {
+ // no initial context available no injection
+ log.log(Level.SEVERE, "No InitialContext found. Using NoInjectionAnnotationProcessor.", e);
+ return new NoInjectionAnnotationInjectionProvider();
+ }
+ }
+}
Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultInjectionProviderFactory.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/NoAnnotationInjectionProvider.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/NoAnnotationInjectionProvider.java?rev=1531537&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/NoAnnotationInjectionProvider.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/NoAnnotationInjectionProvider.java Sat Oct 12 14:48:10 2013
@@ -0,0 +1,44 @@
+/*
+ * 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.spi.impl;
+
+import org.apache.myfaces.spi.InjectionProvider;
+import org.apache.myfaces.spi.InjectionProviderException;
+
+public class NoAnnotationInjectionProvider extends InjectionProvider
+{
+
+ @Override
+ public void postConstruct(Object o) throws InjectionProviderException
+ {
+ // No op
+ }
+
+ @Override
+ public void inject(Object instance) throws InjectionProviderException
+ {
+ // No op
+ }
+
+ @Override
+ public void preDestroy(Object instance) throws InjectionProviderException
+ {
+ // No op
+ }
+}
Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/NoAnnotationInjectionProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/NoInjectionAnnotationInjectionProvider.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/NoInjectionAnnotationInjectionProvider.java?rev=1531537&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/NoInjectionAnnotationInjectionProvider.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/NoInjectionAnnotationInjectionProvider.java Sat Oct 12 14:48:10 2013
@@ -0,0 +1,247 @@
+/*
+ * 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.spi.impl;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.naming.NamingException;
+
+import org.apache.myfaces.shared.util.ClassUtils;
+import org.apache.myfaces.spi.InjectionProvider;
+import org.apache.myfaces.spi.InjectionProviderException;
+
+/**
+ * See SRV.14.5 Servlet Specification Version 2.5 JSR 154
+ * and Common Annotations for the Java Platform JSR 250
+
+ */
+
+public class NoInjectionAnnotationInjectionProvider extends InjectionProvider
+{
+ /**
+ * Cache the Method instances per ClassLoader using the Class-Name.
+ * NOTE that we do it this way, because the only other valid way in order to support a shared
+ * classloader scenario would be to use a WeakHashMap<Class<?>, Method[]>, but this
+ * creates a cyclic reference between the key and the value of the WeakHashMap which will
+ * most certainly cause a memory leak! Furthermore we can manually cleanup the Map when
+ * the webapp is undeployed just by removing the Map for the current ClassLoader.
+ */
+ private volatile static WeakHashMap<ClassLoader, Map<Class,Method[]> > declaredMethodBeans =
+ new WeakHashMap<ClassLoader, Map<Class, Method[]>>();
+
+ private static Map<Class,Method[]> getDeclaredMethodBeansMap()
+ {
+ ClassLoader cl = ClassUtils.getContextClassLoader();
+
+ Map<Class,Method[]> metadata = (Map<Class,Method[]>)
+ declaredMethodBeans.get(cl);
+
+ if (metadata == null)
+ {
+ // Ensure thread-safe put over _metadata, and only create one map
+ // per classloader to hold metadata.
+ synchronized (declaredMethodBeans)
+ {
+ metadata = createDeclaredMethodBeansMap(cl, metadata);
+ }
+ }
+
+ return metadata;
+ }
+
+ private static Map<Class,Method[]> createDeclaredMethodBeansMap(
+ ClassLoader cl, Map<Class,Method[]> metadata)
+ {
+ metadata = (Map<Class,Method[]>) declaredMethodBeans.get(cl);
+ if (metadata == null)
+ {
+ metadata = new HashMap<Class,Method[]>();
+ declaredMethodBeans.put(cl, metadata);
+ }
+ return metadata;
+ }
+
+ @Override
+ public void inject(Object object) throws InjectionProviderException
+ {
+ try
+ {
+ processAnnotations(object);
+ }
+ catch (IllegalAccessException ex)
+ {
+ throw new InjectionProviderException(ex);
+ }
+ catch (InvocationTargetException ex)
+ {
+ throw new InjectionProviderException(ex);
+ }
+ catch (NamingException ex)
+ {
+ throw new InjectionProviderException(ex);
+ }
+ }
+
+
+ Method[] getDeclaredMethods(Class clazz)
+ {
+ Map<Class,Method[]> declaredMethodBeansMap = getDeclaredMethodBeansMap();
+ Method[] methods = declaredMethodBeansMap.get(clazz);
+ if (methods == null)
+ {
+ methods = clazz.getDeclaredMethods();
+ synchronized(declaredMethodBeansMap)
+ {
+ declaredMethodBeansMap.put(clazz, methods);
+ }
+ }
+ return methods;
+ }
+
+ /**
+ * Call postConstruct method on the specified instance.
+ */
+ @Override
+ public void postConstruct(Object instance) throws InjectionProviderException
+ {
+ // TODO the servlet spec is not clear about searching in superclass??
+ Class clazz = instance.getClass();
+ Method[] methods = getDeclaredMethods(clazz);
+ if (methods == null)
+ {
+ methods = clazz.getDeclaredMethods();
+ Map<Class,Method[]> declaredMethodBeansMap = getDeclaredMethodBeansMap();
+ synchronized(declaredMethodBeansMap)
+ {
+ declaredMethodBeansMap.put(clazz, methods);
+ }
+ }
+ Method postConstruct = null;
+ for (int i = 0; i < methods.length; i++)
+ {
+ Method method = methods[i];
+ if (method.isAnnotationPresent(PostConstruct.class))
+ {
+ // a method that does not take any arguments
+ // the method must not be static
+ // must not throw any checked expections
+ // the return value must be void
+ // the method may be public, protected, package private or private
+
+ if ((postConstruct != null)
+ || (method.getParameterTypes().length != 0)
+ || (Modifier.isStatic(method.getModifiers()))
+ || (method.getExceptionTypes().length > 0)
+ || (!method.getReturnType().getName().equals("void")))
+ {
+ throw new IllegalArgumentException("Invalid PostConstruct annotation");
+ }
+ postConstruct = method;
+ }
+ }
+ try
+ {
+ invokeAnnotatedMethod(postConstruct, instance);
+ }
+ catch (IllegalAccessException ex)
+ {
+ throw new InjectionProviderException(ex);
+ }
+ catch (InvocationTargetException ex)
+ {
+ throw new InjectionProviderException(ex);
+ }
+ }
+
+ @Override
+ public void preDestroy(Object instance) throws InjectionProviderException
+ {
+
+ // TODO the servlet spec is not clear about searching in superclass??
+ // May be only check non private fields and methods
+ Class clazz = instance.getClass();
+ Method[] methods = getDeclaredMethods(clazz);
+ Method preDestroy = null;
+ for (int i = 0; i < methods.length; i++)
+ {
+ Method method = methods[i];
+ if (method.isAnnotationPresent(PreDestroy.class))
+ {
+ // must not throw any checked expections
+ // the method must not be static
+ // must not throw any checked expections
+ // the return value must be void
+ // the method may be public, protected, package private or private
+
+ if ((preDestroy != null)
+ || (method.getParameterTypes().length != 0)
+ || (Modifier.isStatic(method.getModifiers()))
+ || (method.getExceptionTypes().length > 0)
+ || (!method.getReturnType().getName().equals("void")))
+ {
+ throw new IllegalArgumentException("Invalid PreDestroy annotation");
+ }
+ preDestroy = method;
+ }
+ }
+
+ try
+ {
+ invokeAnnotatedMethod(preDestroy, instance);
+ }
+ catch (IllegalAccessException ex)
+ {
+ throw new InjectionProviderException(ex);
+ }
+ catch (InvocationTargetException ex)
+ {
+ throw new InjectionProviderException(ex);
+ }
+ }
+
+ private void invokeAnnotatedMethod(Method method, Object instance)
+ throws IllegalAccessException, InvocationTargetException
+ {
+ // At the end the annotated
+ // method is invoked
+ if (method != null)
+ {
+ boolean accessibility = method.isAccessible();
+ method.setAccessible(true);
+ method.invoke(instance);
+ method.setAccessible(accessibility);
+ }
+ }
+
+ /**
+ * Inject resources in specified instance.
+ */
+ protected void processAnnotations(Object instance)
+ throws IllegalAccessException, InvocationTargetException, NamingException
+ {
+
+ }
+}
Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/NoInjectionAnnotationInjectionProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/ResourceAnnotationInjectionProvider.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/ResourceAnnotationInjectionProvider.java?rev=1531537&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/ResourceAnnotationInjectionProvider.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/ResourceAnnotationInjectionProvider.java Sat Oct 12 14:48:10 2013
@@ -0,0 +1,254 @@
+/*
+ * 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.spi.impl;
+
+import javax.naming.NamingException;
+import javax.naming.Context;
+import javax.annotation.Resource;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
+import org.apache.myfaces.shared.util.ClassUtils;
+
+// TODO @Resources
+public class ResourceAnnotationInjectionProvider extends NoInjectionAnnotationInjectionProvider
+{
+ /**
+ * Cache the Method instances per ClassLoader using the Class-Name.
+ * NOTE that we do it this way, because the only other valid way in order to support a shared
+ * classloader scenario would be to use a WeakHashMap<Class<?>, Method[]>, but this
+ * creates a cyclic reference between the key and the value of the WeakHashMap which will
+ * most certainly cause a memory leak! Furthermore we can manually cleanup the Map when
+ * the webapp is undeployed just by removing the Map for the current ClassLoader.
+ */
+ private volatile static WeakHashMap<ClassLoader, Map<Class,Field[]> > declaredFieldBeans =
+ new WeakHashMap<ClassLoader, Map<Class, Field[]>>();
+
+ protected Context context;
+ private static final String JAVA_COMP_ENV = "java:comp/env/";
+
+ public ResourceAnnotationInjectionProvider(Context context)
+ {
+ this.context = context;
+ }
+
+ private static Map<Class,Field[]> getDeclaredFieldBeansMap()
+ {
+ ClassLoader cl = ClassUtils.getContextClassLoader();
+
+ Map<Class,Field[]> metadata = (Map<Class,Field[]>)
+ declaredFieldBeans.get(cl);
+
+ if (metadata == null)
+ {
+ // Ensure thread-safe put over _metadata, and only create one map
+ // per classloader to hold metadata.
+ synchronized (declaredFieldBeans)
+ {
+ metadata = createDeclaredFieldBeansMap(cl, metadata);
+ }
+ }
+
+ return metadata;
+ }
+
+ private static Map<Class,Field[]> createDeclaredFieldBeansMap(
+ ClassLoader cl, Map<Class,Field[]> metadata)
+ {
+ metadata = (Map<Class,Field[]>) declaredFieldBeans.get(cl);
+ if (metadata == null)
+ {
+ metadata = new HashMap<Class,Field[]>();
+ declaredFieldBeans.put(cl, metadata);
+ }
+ return metadata;
+ }
+
+ /**
+ * Inject resources in specified instance.
+ */
+ @Override
+ protected void processAnnotations(Object instance)
+ throws IllegalAccessException, InvocationTargetException, NamingException
+ {
+
+ if (context == null)
+ {
+ // No resource injection
+ return;
+ }
+
+ checkAnnotation(instance.getClass(), instance);
+
+ /*
+ * May be only check non private fields and methods
+ * for @Resource (JSR 250), if used all superclasses MUST be examined
+ * to discover all uses of this annotation.
+ */
+
+ Class superclass = instance.getClass().getSuperclass();
+ while (superclass != null && (!superclass.equals(Object.class)))
+ {
+ checkAnnotation(superclass, instance);
+ superclass = superclass.getSuperclass();
+ }
+ }
+
+ Field[] getDeclaredFieldBeans(Class clazz)
+ {
+ Map<Class,Field[]> declaredFieldBeansMap = getDeclaredFieldBeansMap();
+ Field[] fields = declaredFieldBeansMap.get(clazz);
+ if (fields == null)
+ {
+ fields = clazz.getDeclaredFields();
+ synchronized(declaredFieldBeansMap)
+ {
+ declaredFieldBeansMap.put(clazz, fields);
+ }
+ }
+ return fields;
+ }
+
+ private void checkAnnotation(Class<?> clazz, Object instance)
+ throws NamingException, IllegalAccessException, InvocationTargetException
+ {
+ // Initialize fields annotations
+ Field[] fields = getDeclaredFieldBeans(clazz);
+ for (int i = 0; i < fields.length; i++)
+ {
+ Field field = fields[i];
+ checkFieldAnnotation(field, instance);
+ }
+
+ // Initialize methods annotations
+ Method[] methods = getDeclaredMethods(clazz);
+ for (int i = 0; i < methods.length; i++)
+ {
+ Method method = methods[i];
+ checkMethodAnnotation(method, instance);
+ }
+ }
+
+ protected void checkMethodAnnotation(Method method, Object instance)
+ throws NamingException, IllegalAccessException, InvocationTargetException
+ {
+ if (method.isAnnotationPresent(Resource.class))
+ {
+ Resource annotation = method.getAnnotation(Resource.class);
+ lookupMethodResource(context, instance, method, annotation.name());
+ }
+ }
+
+ protected void checkFieldAnnotation(Field field, Object instance)
+ throws NamingException, IllegalAccessException
+ {
+ if (field.isAnnotationPresent(Resource.class))
+ {
+ Resource annotation = field.getAnnotation(Resource.class);
+ lookupFieldResource(context, instance, field, annotation.name());
+ }
+ }
+
+ /**
+ * Inject resources in specified field.
+ */
+ protected static void lookupFieldResource(javax.naming.Context context,
+ Object instance, Field field, String name)
+ throws NamingException, IllegalAccessException
+ {
+
+ Object lookedupResource;
+
+ if ((name != null) && (name.length() > 0))
+ {
+ // TODO local or global JNDI
+ lookedupResource = context.lookup(JAVA_COMP_ENV + name);
+ }
+ else
+ {
+ // TODO local or global JNDI
+ lookedupResource = context.lookup(JAVA_COMP_ENV + instance.getClass().getName() + "/" + field.getName());
+ }
+
+ boolean accessibility = field.isAccessible();
+ field.setAccessible(true);
+ field.set(instance, lookedupResource);
+ field.setAccessible(accessibility);
+ }
+
+
+ /**
+ * Inject resources in specified method.
+ */
+ protected static void lookupMethodResource(javax.naming.Context context,
+ Object instance, Method method, String name)
+ throws NamingException, IllegalAccessException, InvocationTargetException
+ {
+
+ if (!method.getName().startsWith("set")
+ || method.getParameterTypes().length != 1
+ || !method.getReturnType().getName().equals("void"))
+ {
+ throw new IllegalArgumentException("Invalid method resource injection annotation");
+ }
+
+ Object lookedupResource;
+
+ if ((name != null) && (name.length() > 0))
+ {
+ // TODO local or global JNDI
+ lookedupResource = context.lookup(JAVA_COMP_ENV + name);
+ }
+ else
+ {
+ // TODO local or global JNDI
+ lookedupResource =
+ context.lookup(JAVA_COMP_ENV + instance.getClass().getName() + "/" + getFieldName(method));
+ }
+
+ boolean accessibility = method.isAccessible();
+ method.setAccessible(true);
+ method.invoke(instance, lookedupResource);
+ method.setAccessible(accessibility);
+ }
+
+ /**
+ * Returns the field name for the given Method.
+ * E.g. setName() will be "name".
+ *
+ * @param setter the setter method
+ * @return the field name of the given setter method
+ */
+ protected static String getFieldName(Method setter)
+ {
+ StringBuilder name = new StringBuilder(setter.getName());
+
+ // remove 'set'
+ name.delete(0, 3);
+
+ // lowercase first char
+ name.setCharAt(0, Character.toLowerCase(name.charAt(0)));
+
+ return name.toString();
+ }
+
+}
Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/ResourceAnnotationInjectionProvider.java
------------------------------------------------------------------------------
svn:eol-style = native