/**
* Copyright (c) 2009-2011 VMware, Inc. All Rights Reserved.
*
* Licensed 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 com.springsource.insight.plugin.springcore;
import il.co.springsource.insight.MyApplicationListener;
import il.co.springsource.insight.MyApplicationListenerAndRepository;
import il.co.springsource.insight.MyEvent;
import il.co.springsource.insight.MyEventSource;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
import org.springframework.context.event.SourceFilteringListener;
import org.springframework.context.support.StaticApplicationContext;
import com.springsource.insight.collection.OperationCollector;
import com.springsource.insight.collection.OperationListCollector;
import com.springsource.insight.collection.test.OperationCollectionAspectTestSupport;
import com.springsource.insight.intercept.operation.Operation;
import com.springsource.insight.intercept.operation.OperationFields;
import com.springsource.insight.intercept.operation.OperationList;
import com.springsource.insight.util.ArrayUtil;
import com.springsource.insight.util.ListUtil;
public class ApplicationListenerMethodOperationCollectionAspectTest extends OperationCollectionAspectTestSupport {
public ApplicationListenerMethodOperationCollectionAspectTest() {
super();
}
@Override
protected OperationCollector createSpiedOperationCollector(OperationCollector originalCollector) {
assertNotNull("No original collector", originalCollector);
return new OperationListCollector();
}
@Override
protected Operation getLastEnteredOperation(OperationCollector spiedCollector) {
List<Operation> opsList = ((OperationListCollector) spiedCollector).getCollectedOperations();
if (ListUtil.size(opsList) <= 0) {
return null;
} else {
return opsList.get(opsList.size() - 1);
}
}
/**
* Verifies that if a regular listener and a @Repository annotated listener are called, that
* only the regular listener generates a MethodOperation. The @Repository
* annotation will generate a MethodOperation independently for those methods;
*/
@Test
public void testAppListenerCalled() {
StaticApplicationContext ctx = new StaticApplicationContext();
ctx.registerSingleton("myListener", MyApplicationListener.class);
ctx.registerSingleton("myListenerAndRepo", MyApplicationListenerAndRepository.class);
ctx.refresh();
MyApplicationListener listener = ctx.getBean(MyApplicationListener.class);
MyApplicationListenerAndRepository listenerAndRepo = ctx.getBean(MyApplicationListenerAndRepository.class);
MyEvent event = new MyEvent("fubar");
ctx.publishEvent(event);
assertSame("Mismatched listener event", event, listener.getLastEvent());
assertSame("Mismatched listener&repo event", event, listenerAndRepo.getLastEvent());
List<Operation> opsList = ((OperationListCollector) spiedOperationCollector).getCollectedOperations();
assertEquals("Mismatched number of collected operations", 2, ListUtil.size(opsList));
@SuppressWarnings("unchecked")
Collection<Class<?>> beanTypes = ListUtil.asSet((Class<?>) MyApplicationListener.class, (Class<?>) MyApplicationListenerAndRepository.class);
for (Operation op : opsList) {
Class<?> matchClass = assertOperationBelongsToClass(op, beanTypes);
assertTrue("Unexpected match: " + matchClass.getSimpleName(), beanTypes.remove(matchClass));
}
}
@Test
public void testSourceFilteredListener() {
StaticApplicationContext ctx = new StaticApplicationContext();
MyApplicationListener delegate = new MyApplicationListener();
MyEventSource source = new MyEventSource();
MyEvent event = new MyEvent(source);
ctx.addApplicationListener(new SourceFilteringListener(source, delegate));
ctx.refresh();
ctx.publishEvent(event);
assertSame("Mismatched delegate event", event, delegate.getLastEvent());
List<Operation> opsList = ((OperationListCollector) spiedOperationCollector).getCollectedOperations();
assertEquals("Mismatched number of collected operations", 1, ListUtil.size(opsList));
assertOperationBelongsToClass(opsList.get(0), MyApplicationListener.class);
}
private Class<?> assertOperationBelongsToClass(Operation op, Class<?>... beanTypes) {
return assertOperationBelongsToClass(op,
(ArrayUtil.length(beanTypes) <= 0)
? Collections.<Class<?>>emptyList()
: Arrays.asList(beanTypes));
}
private Class<?> assertOperationBelongsToClass(Operation op, Collection<Class<?>> beanTypes) {
if (op.isFinalizable()) {
op.finalizeConstruction();
}
assertEquals("Mismatched operation type", SpringCorePluginRuntimeDescriptor.APP_LISTENER_TYPE, op.getType());
String shortName = op.get(OperationFields.SHORT_CLASS_NAME, String.class);
Class<?> matchingClass = null;
for (Class<?> clazz : beanTypes) {
if (clazz.getSimpleName().equals(shortName)) {
if (matchingClass != null) {
fail("Muliple matches for " + shortName + ": " + matchingClass.getSimpleName());
}
matchingClass = clazz;
}
}
assertNotNull("Mismatched short class name: " + shortName, matchingClass);
String compType = op.get(StereotypedSpringBeanMethodOperationCollectionAspectSupport.COMP_TYPE_ATTR, String.class);
// make sure not intercepted by one of the stereotyped beans aspects
assertNull("Unexpected stereotyped bean method collection: " + compType, compType);
String methodName = op.get(OperationFields.METHOD_NAME, String.class, "");
assertTrue(shortName + methodName + " does not start with onApplicationEvent", methodName.startsWith("onApplicationEvent"));
assertEquals(shortName + ": mismatched event type",
MyEvent.class.getName(), op.get(SpringLifecycleMethodOperationCollectionAspect.EVENT_ATTR, String.class));
OperationList argsList = op.get(OperationFields.ARGUMENTS, OperationList.class);
assertNotNull(shortName + ": Missing arguments list", argsList);
assertEquals(shortName + ": Mismatched number of arguments", 1, argsList.size());
assertEquals(shortName + ": Mismatched argument type", MyEvent.class.getName(), argsList.get(0));
return matchingClass;
}
@Override
public ApplicationListenerMethodOperationCollectionAspect getAspect() {
return ApplicationListenerMethodOperationCollectionAspect.aspectOf();
}
}