/**
* 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.openejb.config;
import org.apache.openejb.OpenEJB;
import org.apache.openejb.assembler.classic.AppInfo;
import org.apache.openejb.assembler.classic.Assembler;
import org.apache.openejb.assembler.classic.ClientInfo;
import org.apache.openejb.jee.AssemblyDescriptor;
import org.apache.openejb.jee.ConfigProperty;
import org.apache.openejb.jee.Connector;
import org.apache.openejb.jee.EjbJar;
import org.apache.openejb.jee.EnterpriseBean;
import org.apache.openejb.jee.SessionBean;
import org.apache.openejb.jee.TransactionSupportType;
import org.apache.openejb.jee.WebApp;
import org.apache.xbean.finder.Annotated;
import org.apache.xbean.finder.AnnotationFinder;
import org.apache.xbean.finder.ClassFinder;
import org.apache.xbean.finder.archive.ClassesArchive;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Test;
import javax.annotation.Resource;
import javax.ejb.ApplicationException;
import javax.ejb.Local;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.resource.Referenceable;
import javax.resource.ResourceException;
import javax.resource.cci.MessageListener;
import javax.resource.cci.Record;
import javax.resource.spi.Activation;
import javax.resource.spi.ActivationSpec;
import javax.resource.spi.AdministeredObject;
import javax.resource.spi.AuthenticationMechanism;
import javax.resource.spi.AuthenticationMechanism.CredentialInterface;
import javax.resource.spi.BootstrapContext;
import javax.resource.spi.ConnectionDefinition;
import javax.resource.spi.ConnectionManager;
import javax.resource.spi.ConnectionRequestInfo;
import javax.resource.spi.InvalidPropertyException;
import javax.resource.spi.ManagedConnection;
import javax.resource.spi.ManagedConnectionFactory;
import javax.resource.spi.ResourceAdapter;
import javax.resource.spi.ResourceAdapterInternalException;
import javax.resource.spi.SecurityPermission;
import javax.resource.spi.TransactionSupport.TransactionSupportLevel;
import javax.resource.spi.endpoint.MessageEndpointFactory;
import javax.resource.spi.work.WorkContext;
import javax.security.auth.Subject;
import javax.transaction.xa.XAResource;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* @version $Rev$ $Date$
*/
public class AnnotationDeployerTest {
@AfterClass
public static void afterClass() throws Exception {
OpenEJB.destroy();
}
@Test
/**
* For http://issues.apache.org/jira/browse/OPENEJB-980
*/
public void applicationExceptionInheritanceTest() throws Exception {
EjbModule ejbModule = testModule();
final AnnotationDeployer.DiscoverAnnotatedBeans discvrAnnBeans = new AnnotationDeployer.DiscoverAnnotatedBeans();
ejbModule = discvrAnnBeans.deploy(ejbModule);
final AssemblyDescriptor assemblyDescriptor = ejbModule.getEjbJar().getAssemblyDescriptor();
org.apache.openejb.jee.ApplicationException appEx =
assemblyDescriptor.getApplicationException(BusinessException.class);
assertThat(appEx, notNullValue());
assertThat(appEx.getExceptionClass(), is(BusinessException.class.getName()));
assertThat(appEx.isRollback(), is(true));
//inheritance is now handled at runtime, only explicitly mentioned exceptions are in the assembly descriptor
appEx = assemblyDescriptor.getApplicationException(ValueRequiredException.class);
assertThat(appEx, nullValue());
}
private EjbModule testModule() {
final EjbJar ejbJar = new EjbJar("test-classes");
final EjbModule ejbModule = new EjbModule(ejbJar);
ejbModule.setFinder(new ClassFinder(AnnotationDeployerTest.class,
BusinessException.class,
Exception.class,
GenericInterface.class,
InterceptedSLSBean.class,
MyMainClass.class,
TestLocalBean.class,
ValueRequiredException.class
));
return ejbModule;
}
@Test
public void testSortClasses() throws Exception {
final AnnotationFinder finder = new AnnotationFinder(new ClassesArchive(Emerald.class)).link();
final List<Annotated<Class<?>>> classes = finder.findMetaAnnotatedClasses(Resource.class);
assertTrue(classes.size() >= 3);
final List<Annotated<Class<?>>> sorted = AnnotationDeployer.sortClasses(classes);
assertTrue(sorted.size() >= 3);
assertEquals(Emerald.class, sorted.get(0).get());
assertEquals(Green.class, sorted.get(1).get());
assertEquals(Color.class, sorted.get(2).get());
}
@Test
public void testSortMethods() throws Exception {
final AnnotationFinder finder = new AnnotationFinder(new ClassesArchive(Emerald.class)).link();
final List<Annotated<Method>> classes = finder.findMetaAnnotatedMethods(Resource.class);
assertTrue(classes.size() >= 3);
final List<Annotated<Method>> sorted = AnnotationDeployer.sortMethods(classes);
assertTrue(sorted.size() >= 3);
assertEquals(Emerald.class, sorted.get(0).get().getDeclaringClass());
assertEquals(Green.class, sorted.get(1).get().getDeclaringClass());
assertEquals(Color.class, sorted.get(2).get().getDeclaringClass());
}
@Test
/**
* For https://issues.apache.org/jira/browse/OPENEJB-1063
*/
public void badMainClassFormatTest() throws Exception {
final ConfigurationFactory config = new ConfigurationFactory();
final Assembler assembler = new Assembler();
final AppModule app = new AppModule(this.getClass().getClassLoader(), "test-app");
final ClientModule clientModule = new ClientModule(null, app.getClassLoader(), app.getJarLocation(), null, null);
// change "." --> "/" to check that main class is changed by the AnnotationDeployer
final String mainClass = MyMainClass.class.getName().replaceAll("\\.", "/");
clientModule.setMainClass(mainClass);
app.getClientModules().add(clientModule);
final AppInfo appInfo = config.configureApplication(app);
assembler.createApplication(appInfo);
final ClientInfo clientInfo = appInfo.clients.get(0);
Assert.assertNotNull(clientInfo);
Assert.assertEquals(MyMainClass.class.getName(), clientInfo.mainClass);
}
/**
* For https://issues.apache.org/jira/browse/OPENEJB-1128
*/
@Test
public void interceptingGenericBusinessMethodCalls() throws Exception {
EjbModule ejbModule = testModule();
final EjbJar ejbJar = ejbModule.getEjbJar();
final AnnotationDeployer.DiscoverAnnotatedBeans discvrAnnBeans = new AnnotationDeployer.DiscoverAnnotatedBeans();
ejbModule = discvrAnnBeans.deploy(ejbModule);
final EnterpriseBean bean = ejbJar.getEnterpriseBean("InterceptedSLSBean");
assert bean != null;
}
/**
* For https://issues.apache.org/jira/browse/OPENEJB-1188
*
* @throws Exception
*/
@Test
public void testLocalBean() throws Exception {
final EjbModule ejbModule = testModule();
final EjbJar ejbJar = ejbModule.getEjbJar();
AppModule appModule = new AppModule(Thread.currentThread().getContextClassLoader(), "myapp");
appModule.getEjbModules().add(ejbModule);
final AnnotationDeployer annotationDeployer = new AnnotationDeployer();
appModule = annotationDeployer.deploy(appModule);
EnterpriseBean bean = ejbJar.getEnterpriseBean("TestLocalBean");
assert bean != null;
assert (((SessionBean) bean).getLocalBean() != null);
bean = ejbJar.getEnterpriseBean("InterceptedSLSBean");
assert bean != null;
assert (((SessionBean) bean).getLocalBean() == null);
}
@Test
public void testResourceAdapter() throws Exception {
final ConnectorModule connectorModule = testConnectorModule();
final AnnotationDeployer.DiscoverAnnotatedBeans discvrAnnBeans = new AnnotationDeployer.DiscoverAnnotatedBeans();
discvrAnnBeans.deploy(connectorModule);
final Connector connector = connectorModule.getConnector();
Assert.assertEquals("displayName", connector.getDisplayName());
Assert.assertEquals("description", connector.getDescription());
Assert.assertEquals("eisType", connector.getEisType());
Assert.assertEquals("vendorName", connector.getVendorName());
Assert.assertEquals("version", connector.getResourceAdapterVersion());
Assert.assertEquals("smallIcon", connector.getIcon().getSmallIcon());
Assert.assertEquals("largeIcon", connector.getIcon().getLargeIcon());
Assert.assertEquals("licenseDescription", connector.getLicense().getDescription());
Assert.assertEquals(true, connector.getLicense().isLicenseRequired());
final List<org.apache.openejb.jee.SecurityPermission> securityPermission = connector.getResourceAdapter().getSecurityPermission();
Assert.assertEquals("description", securityPermission.get(0).getDescription());
Assert.assertEquals("permissionSpec", securityPermission.get(0).getSecurityPermissionSpec());
final List<String> requiredWorkContext = connector.getRequiredWorkContext();
Assert.assertEquals(TestWorkContext.class.getName(), requiredWorkContext.get(0));
final List<org.apache.openejb.jee.AuthenticationMechanism> authenticationMechanism = connector.getResourceAdapter().getOutboundResourceAdapter().getAuthenticationMechanism();
Assert.assertEquals("authMechanism", authenticationMechanism.get(0).getAuthenticationMechanismType());
Assert.assertEquals(CredentialInterface.GenericCredential.toString(), authenticationMechanism.get(0).getCredentialInterface());
Assert.assertEquals("description", authenticationMechanism.get(0).getDescription());
Assert.assertEquals(TransactionSupportType.NO_TRANSACTION, connector.getResourceAdapter().getOutboundResourceAdapter().getTransactionSupport());
Assert.assertEquals(true, connector.getResourceAdapter().getOutboundResourceAdapter().isReauthenticationSupport());
Assert.assertEquals(Connection.class.getName(), connector.getResourceAdapter().getOutboundResourceAdapter().getConnectionDefinition().get(0).getConnectionInterface());
Assert.assertEquals(ConnectionImpl.class.getName(), connector.getResourceAdapter().getOutboundResourceAdapter().getConnectionDefinition().get(0).getConnectionImplClass());
Assert.assertEquals(ConnectionFactory.class.getName(), connector.getResourceAdapter().getOutboundResourceAdapter().getConnectionDefinition().get(0).getConnectionFactoryInterface());
Assert.assertEquals(ConnectionFactoryImpl.class.getName(), connector.getResourceAdapter().getOutboundResourceAdapter().getConnectionDefinition().get(0).getConnectionFactoryImplClass());
Assert.assertEquals(TestActivation.class.getName(), connector.getResourceAdapter().getInboundResourceAdapter().getMessageAdapter().getMessageListener().get(0).getActivationSpec().getActivationSpecClass());
Assert.assertEquals(TestMessageListener.class.getName(), connector.getResourceAdapter().getInboundResourceAdapter().getMessageAdapter().getMessageListener().get(0).getMessageListenerType());
Assert.assertEquals(TestAdminObject.class.getName(), connector.getResourceAdapter().getAdminObject().get(0).getAdminObjectClass());
Assert.assertEquals(TestAdminObjectInterface.class.getName(), connector.getResourceAdapter().getAdminObject().get(0).getAdminObjectInterface());
}
private ConnectorModule testConnectorModule() {
final Connector connector = new Connector();
final ConnectorModule connectorModule = new ConnectorModule(connector);
connectorModule.setFinder(new ClassFinder(TestConnector.class, TestManagedConnectionFactory.class, TestActivation.class, TestAdminObject.class));
return connectorModule;
}
@Test
public void testConfigProperties() throws Exception {
final ClassFinder finder = new ClassFinder(TestAdminObject.class);
final List<ConfigProperty> configProperty = new ArrayList<ConfigProperty>();
final Object object = new Object() {
public List<ConfigProperty> getConfigProperty() {
return configProperty;
}
};
new AnnotationDeployer.DiscoverAnnotatedBeans().process(null, TestAdminObject.class.getName(), object);
Assert.assertEquals(2, configProperty.size());
Assert.assertEquals("myNumber", configProperty.get(0).getConfigPropertyName());
Assert.assertEquals("java.lang.Integer", configProperty.get(0).getConfigPropertyType());
Assert.assertEquals("myProperty", configProperty.get(1).getConfigPropertyName());
Assert.assertEquals("java.lang.String", configProperty.get(1).getConfigPropertyType());
Assert.assertEquals("This is a test", configProperty.get(1).getConfigPropertyValue());
}
@ApplicationException(rollback = true)
public abstract class BusinessException extends Exception {
}
public class ValueRequiredException extends BusinessException {
}
public static final class MyMainClass {
public static void main(final String[] args) {
}
}
public static interface GenericInterface<T> {
T genericMethod(T t);
}
@Stateless
@Local(GenericInterface.class)
public static class InterceptedSLSBean implements GenericInterface<String> {
public String genericMethod(final String s) {
return s;
}
}
@Stateless
@LocalBean
public static class TestLocalBean {
public String echo(final String input) {
return input;
}
}
@Resource
public static class Color {
@Resource
public void color() {
}
}
@Resource
public static class Green extends Color {
@Resource
public void green() {
}
}
@Resource
public static class Emerald extends Green {
@Resource
public void emerald() {
}
}
@javax.resource.spi.Connector(description = "description",
displayName = "displayName", smallIcon = "smallIcon",
largeIcon = "largeIcon", vendorName = "vendorName",
eisType = "eisType",
version = "version",
licenseDescription = {"licenseDescription"},
licenseRequired = true,
authMechanisms = {@AuthenticationMechanism(authMechanism = "authMechanism",
credentialInterface = CredentialInterface.GenericCredential, description = {"description"})},
reauthenticationSupport = true,
securityPermissions = {@SecurityPermission(permissionSpec = "permissionSpec", description = "description")},
transactionSupport = TransactionSupportLevel.NoTransaction,
requiredWorkContexts = {TestWorkContext.class}
)
public static class TestConnector implements ResourceAdapter {
public void endpointActivation(final MessageEndpointFactory mef, final ActivationSpec spec) throws ResourceException {
}
public void endpointDeactivation(final MessageEndpointFactory mef, final ActivationSpec spec) {
}
public XAResource[] getXAResources(final ActivationSpec[] specs) throws ResourceException {
return null;
}
public void start(final BootstrapContext ctx) throws ResourceAdapterInternalException {
}
public void stop() {
}
}
@ConnectionDefinition(connection = Connection.class, connectionFactory = ConnectionFactory.class, connectionImpl = ConnectionImpl.class, connectionFactoryImpl = ConnectionFactoryImpl.class)
public static class TestManagedConnectionFactory implements ManagedConnectionFactory {
public Object createConnectionFactory() throws ResourceException {
return null;
}
public Object createConnectionFactory(final ConnectionManager connectionManager) throws ResourceException {
return null;
}
public ManagedConnection createManagedConnection(final Subject subject, final ConnectionRequestInfo connectionRequestInfo) throws ResourceException {
return null;
}
public PrintWriter getLogWriter() throws ResourceException {
return null;
}
public ManagedConnection matchManagedConnections(final Set managedConnections, final Subject subject, final ConnectionRequestInfo connectionRequestInfo) throws ResourceException {
return null;
}
public void setLogWriter(final PrintWriter writer) throws ResourceException {
}
}
public static class TestWorkContext implements WorkContext {
public String getDescription() {
return "Description";
}
public String getName() {
return "Name";
}
}
public static interface Connection {
}
public static class ConnectionImpl implements Connection {
}
public static interface ConnectionFactory extends Serializable, Referenceable {
}
public static class ConnectionFactoryImpl implements ConnectionFactory {
public void setReference(final Reference reference) {
}
public Reference getReference() throws NamingException {
return null;
}
}
@Activation(messageListeners = {TestMessageListener.class})
public static class TestActivation implements ActivationSpec, Serializable {
public ResourceAdapter getResourceAdapter() {
return null;
}
public void setResourceAdapter(final ResourceAdapter arg0) throws ResourceException {
}
public void validate() throws InvalidPropertyException {
}
}
public static class TestMessageListener implements MessageListener {
public Record onMessage(final Record arg0) throws ResourceException {
return null;
}
}
public static interface TestAdminObjectInterface {
}
public static interface SomeOtherInterface {
}
@AdministeredObject(adminObjectInterfaces = {TestAdminObjectInterface.class})
public static class TestAdminObject implements TestAdminObjectInterface, SomeOtherInterface {
private String myProperty = "This is a test";
@javax.resource.spi.ConfigProperty(ignore = true)
private int myNumber;
public String getMyProperty() {
return myProperty;
}
public void setMyProperty(final String myProperty) {
this.myProperty = myProperty;
}
public int getMyNumber() {
return myNumber;
}
public void setMyNumber(final int myNumber) {
this.myNumber = myNumber;
}
}
@Test
public void findRestClasses() throws Exception {
final WebApp webApp = new WebApp();
webApp.setContextRoot("/");
webApp.setId("web");
webApp.setVersion("2.5");
WebModule webModule = new WebModule(webApp, webApp.getContextRoot(), Thread.currentThread().getContextClassLoader(), "myapp", webApp.getId());
webModule.setFinder(new AnnotationFinder(new ClassesArchive(RESTClass.class, RESTMethod.class, RESTApp.class)).link());
final AnnotationDeployer annotationDeployer = new AnnotationDeployer();
webModule = annotationDeployer.deploy(webModule);
final Set<String> classes = webModule.getRestClasses();
final Set<String> applications = webModule.getRestApplications();
assertEquals(1, classes.size());
assertTrue(classes.contains(RESTClass.class.getName()));
// assertTrue(classes.contains(RESTMethod.class.getName()));
assertEquals(1, applications.size());
assertEquals(RESTApp.class.getName(), applications.iterator().next());
}
@Path("/")
public static class RESTClass {
}
public static class RESTMethod extends RESTClass {
@Path("/method")
public void noop() {
// no-op
}
}
@ApplicationPath("/")
public static class RESTApp extends Application {
public java.util.Set<java.lang.Class<?>> getClasses() {
return new HashSet<Class<?>>() {{
add(RESTClass.class);
add(RESTMethod.class);
}};
}
public java.util.Set<java.lang.Object> getSingletons() {
return new HashSet<Object>() {{
add(new RESTMethod());
add(new RESTMethod());
}};
}
}
}