/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2009-2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.glassfish.weld;
import org.jvnet.hk2.component.Habitat;
import com.sun.enterprise.deployment.*;
import com.sun.enterprise.container.common.spi.util.ComponentEnvManager;
import org.glassfish.api.naming.GlassfishNamingManager;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.annotation.Annotation;
public class InjectionPointHelper {
private final Habitat habitat;
private final ComponentEnvManager compEnvManager;
private final GlassfishNamingManager namingManager;
public InjectionPointHelper(Habitat h) {
habitat = h;
compEnvManager = habitat.getByContract(ComponentEnvManager.class);
namingManager = habitat.getByContract(GlassfishNamingManager.class);
}
public Object resolveInjectionPoint(java.lang.reflect.Member member, Application app)
throws javax.naming.NamingException {
Object result = null;
Field field = null;
Method method = null;
Annotation[] annotations;
if( member instanceof Field ) {
field = (Field) member;
annotations = field.getDeclaredAnnotations();
} else if( member instanceof Method ) {
method = (Method) member;
annotations = method.getDeclaredAnnotations();
} else {
throw new IllegalArgumentException("Member must be Field or Method");
}
Annotation envAnnotation = getEnvAnnotation(annotations);
if( envAnnotation == null ) {
throw new IllegalArgumentException("No Java EE env dependency annotation found on " +
member);
}
String envAnnotationName = null;
try {
Method m = envAnnotation.annotationType().getDeclaredMethod("name");
envAnnotationName = (String) m.invoke(envAnnotation);
} catch(Exception e) {
throw new IllegalArgumentException("Invalid annotation : must have name() attribute " +
envAnnotation.toString(), e);
}
String envDependencyName = envAnnotationName;
Class declaringClass = member.getDeclaringClass();
if( (envAnnotationName == null) || envAnnotationName.equals("") ) {
if( field != null ) {
envDependencyName = declaringClass.getName() + "/" + field.getName();
} else {
envDependencyName = declaringClass.getName() + "/" +
getInjectionMethodPropertyName(method);
}
}
if( envAnnotationName.startsWith("java:global/") ) {
javax.naming.Context ic = namingManager.getInitialContext();
result = ic.lookup(envAnnotationName);
} else {
BundleDescriptor matchingBundle = null;
for(BundleDescriptor bundle : app.getBundleDescriptors()) {
if( (bundle instanceof EjbBundleDescriptor) ||
(bundle instanceof WebBundleDescriptor) ) {
JndiNameEnvironment jndiEnv = (JndiNameEnvironment) bundle;
// TODO normalize for java:comp/env/ prefix
for(InjectionCapable next :
jndiEnv.getInjectableResourcesByClass(declaringClass.getName())) {
if( next.getComponentEnvName().equals(envDependencyName) ) {
matchingBundle = bundle;
break;
}
}
}
if( matchingBundle != null ) {
break;
}
}
if( matchingBundle == null ) {
throw new IllegalArgumentException("Cannot find matching env dependency for " +
member + " in Application " + app.getAppName());
}
String componentId = compEnvManager.getComponentEnvId((JndiNameEnvironment)matchingBundle);
String lookupName = envDependencyName.startsWith("java:") ?
envDependencyName : "java:comp/env/" + envDependencyName;
result = namingManager.lookup(componentId, lookupName);
}
return result;
}
private String getInjectionMethodPropertyName(Method method)
{
String methodName = method.getName();
String propertyName = methodName;
if( (methodName.length() > 3) &&
methodName.startsWith("set") ) {
// Derive javabean property name.
propertyName =
methodName.substring(3, 4).toLowerCase() +
methodName.substring(4);
} else {
throw new IllegalArgumentException("Illegal env dependency setter name" +
method.getName());
}
return propertyName;
}
private Annotation getEnvAnnotation(Annotation[] annotations) {
Annotation envAnnotation = null;
for(Annotation next : annotations) {
String className = next.annotationType().getName();
if( className.equals("javax.ejb.EJB") ||
className.equals("javax.annotation.Resource") ||
className.equals("javax.persistence.PersistenceContext") ||
className.equals("javax.persistence.PersistenceUnit") ||
className.equals("javax.xml.ws.WebServiceRef") ) {
envAnnotation = next;
break;
}
}
return envAnnotation;
}
}