/**
* 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.camel.impl;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import org.apache.camel.NoFactoryAvailableException;
import org.apache.camel.spi.ClassResolver;
import org.apache.camel.spi.Injector;
import org.junit.Test;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.mock;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.hamcrest.Matchers.matchesPattern;
import static org.hamcrest.core.IsCollectionContaining.hasItem;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
public class DefaultFactoryFinderTest {
public static class TestImplA implements TestType {
}
public static class TestImplB implements TestType {
}
public interface TestType {
}
private static final String TEST_RESOURCE_PATH = "/org/apache/camel/impl/";
final DefaultFactoryFinder factoryFinder = new DefaultFactoryFinder(new DefaultClassResolver(), TEST_RESOURCE_PATH);
@Test
public void shouldComplainIfClassResolverCannotResolveClass() throws IOException {
final ClassResolver classResolver = mock(ClassResolver.class);
final String properties = "class=" + TestImplA.class.getName();
expect(classResolver.loadResourceAsStream("/org/apache/camel/impl/TestImplA"))
.andReturn(new ByteArrayInputStream(properties.getBytes()));
expect(classResolver.resolveClass(TestImplA.class.getName())).andReturn(null);
replay(classResolver);
final DefaultFactoryFinder factoryFinder = new DefaultFactoryFinder(classResolver, TEST_RESOURCE_PATH);
try {
factoryFinder.findClass("TestImplA", null);
fail("Should have thrown ClassNotFoundException");
} catch (final ClassNotFoundException e) {
verify(classResolver);
assertEquals(TestImplA.class.getName(), e.getMessage());
}
}
@Test
public void shouldComplainIfInstanceTypeIsNotAsExpected() throws ClassNotFoundException, IOException {
final Injector injector = createMock(Injector.class);
final TestImplA expected = new TestImplA();
expect(injector.newInstance(TestImplA.class)).andReturn(expected);
replay(injector);
try {
factoryFinder.newInstances("TestImplA", injector, TestImplB.class);
fail("ClassCastException should have been thrown");
} catch (final ClassCastException e) {
final String message = e.getMessage();
assertThat(message,
matchesPattern("Not instanceof org\\.apache\\.camel\\.impl\\.DefaultFactoryFinderTest\\$TestImplB "
+ "value: org\\.apache\\.camel\\.impl\\.DefaultFactoryFinderTest\\$TestImplA.*"));
}
}
@Test
public void shouldComplainIfUnableToCreateNewInstances() throws ClassNotFoundException, IOException {
try {
factoryFinder.newInstance("TestImplX");
fail("NoFactoryAvailableException should have been thrown");
} catch (final NoFactoryAvailableException e) {
assertEquals("Could not find factory class for resource: TestImplX", e.getMessage());
}
}
@Test
public void shouldComplainNoClassKeyInPropertyFile() throws ClassNotFoundException {
try {
factoryFinder.findClass("TestImplNoProperty");
fail("NoFactoryAvailableException should have been thrown");
} catch (final IOException e) {
assertEquals("Expected property is missing: class", e.getMessage());
}
}
@Test
public void shouldCreateNewInstances() throws ClassNotFoundException, IOException {
final Object instance = factoryFinder.newInstance("TestImplA");
assertThat(instance, instanceOf(TestImplA.class));
}
@Test
public void shouldCreateNewInstancesWithInjector() throws ClassNotFoundException, IOException {
final Injector injector = createMock(Injector.class);
final TestImplA expected = new TestImplA();
expect(injector.newInstance(TestImplA.class)).andReturn(expected);
replay(injector);
final List<TestType> instances = factoryFinder.newInstances("TestImplA", injector, TestType.class);
verify(injector);
assertEquals(1, instances.size());
assertThat(instances, hasItem(expected));
assertSame(expected, instances.get(0));
}
@Test
public void shouldFindSingleClass() throws ClassNotFoundException, IOException {
final Class<?> clazz = factoryFinder.findClass("TestImplA");
assertEquals(TestImplA.class, clazz);
}
@Test
public void shouldFindSingleClassFromClassMap() throws ClassNotFoundException, IOException {
final DefaultFactoryFinder factoryFinder = new DefaultFactoryFinder(null, null);
factoryFinder.addToClassMap("prefixkey", () -> TestImplA.class);
final Class<?> clazz = factoryFinder.findClass("key", "prefix");
assertEquals(TestImplA.class, clazz);
}
@Test
public void shouldFindSingleClassWithPropertyPrefix() throws ClassNotFoundException, IOException {
final Class<?> clazz = factoryFinder.findClass("TestImplA", "prefix.");
assertEquals(TestImplA.class, clazz);
}
@Test
public void shouldFindSingleClassWithPropertyPrefixAndExpectedType() throws ClassNotFoundException, IOException {
final Class<?> clazz = factoryFinder.findClass("TestImplA", "prefix.", TestType.class);
assertEquals(TestImplA.class, clazz);
}
URL urlFor(final Class<?> clazz) {
final String resourceName = clazz.getPackage().getName().replace('.', '/') + "/" + clazz.getSimpleName()
+ ".properties";
final ClassLoader classLoader = clazz.getClassLoader();
return classLoader.getResource(resourceName);
}
}