| /* |
| * 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.sling.models.impl; |
| |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Dictionary; |
| import java.util.Hashtable; |
| |
| import org.apache.sling.models.testmodels.classes.ChildModel; |
| import org.apache.sling.models.testmodels.classes.SimpleModelWithInvalidSecondAnnotation; |
| import org.apache.sling.models.testmodels.classes.annotations.Hidden; |
| import org.junit.Assert; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.mockito.Mock; |
| import org.mockito.Mockito; |
| import org.mockito.invocation.InvocationOnMock; |
| import org.mockito.junit.MockitoJUnitRunner; |
| import org.mockito.stubbing.Answer; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.BundleEvent; |
| import org.springframework.core.OverridingClassLoader; |
| |
| @RunWith(MockitoJUnitRunner.class) |
| public class ModelPackageBundleListenerTest { |
| |
| @Mock |
| private BundleContext mockBundleContext; |
| |
| @Mock |
| private ModelAdapterFactory mockModelAdapterFactory; |
| |
| @Mock |
| private Bundle mockBundle; |
| |
| final AdapterImplementations adapterImplementations = new AdapterImplementations(); |
| |
| /** |
| * ClassLoader which doesn't delegate to the parent. In addition it blocks loading certain classes. |
| */ |
| private static final class HideClassesClassLoader extends OverridingClassLoader { |
| |
| private final Collection<String> classNamesToHide; |
| public HideClassesClassLoader(ClassLoader parent, String... classNamesToHide) { |
| super(parent); |
| this.classNamesToHide = Arrays.asList(classNamesToHide); |
| //Exclude Hidden class since its loading via default class loader and throws ClassNotFoundException in line:70 |
| this.excludeClass(Hidden.class.getName()); |
| } |
| |
| @Override |
| protected Class<?> loadClassForOverriding(String name) throws ClassNotFoundException { |
| if (classNamesToHide.contains(name)) { |
| throw new ClassNotFoundException("Could not find class " + name + " as it is hidden by this class loader!"); |
| } |
| return super.loadClassForOverriding(name); |
| } |
| } |
| |
| @Test |
| public void testAddingBundleWithResolvableModelAnnotation() throws ClassNotFoundException { |
| Assert.assertFalse("Model should not yet have been registered but was", adapterImplementations.isModelClass(ChildModel.class)); |
| ModelPackageBundleListener listener = createListenerForBundleWithClass(ChildModel.class); |
| listener.addingBundle(mockBundle, new BundleEvent(BundleEvent.STARTED, mockBundle)); |
| Assert.assertTrue("Model should have been registered but was not", adapterImplementations.isModelClass(ChildModel.class)); |
| } |
| |
| @Test |
| public void testAddingBundleWithNonResolvableNonModelAnnotation() throws ClassNotFoundException { |
| ClassLoader classLoader = new HideClassesClassLoader(this.getClass().getClassLoader(), Hidden.class.getName()); |
| ModelPackageBundleListener listener = createListenerForBundleWithClass(classLoader, SimpleModelWithInvalidSecondAnnotation.class.getName()); |
| listener.addingBundle(mockBundle, new BundleEvent(BundleEvent.STARTED, mockBundle)); |
| Assert.assertFalse("Model should not yet have been registered but was", adapterImplementations.isModelClass(SimpleModelWithInvalidSecondAnnotation.class)); |
| } |
| |
| private ModelPackageBundleListener createListenerForBundleWithClass(Class<?> modelClass) throws ClassNotFoundException { |
| return createListenerForBundleWithClass(modelClass.getClassLoader(), modelClass.getName()); |
| } |
| |
| private ModelPackageBundleListener createListenerForBundleWithClass(ClassLoader classLoader, String className) throws ClassNotFoundException { |
| Dictionary<String, String> headers = new Hashtable<>(); |
| headers.put(ModelPackageBundleListener.CLASSES_HEADER, className); |
| Mockito.when(mockBundle.getHeaders()).thenReturn(headers); |
| Mockito.when(mockBundle.loadClass(Mockito.anyString())).thenAnswer(new Answer<Class<?>>(){ |
| @Override |
| public Class<?>answer(InvocationOnMock invocation) throws Throwable { |
| Object argument = invocation.getArguments()[0]; |
| if (argument.equals(className)) { |
| return classLoader.loadClass(className); |
| } else { |
| throw new ClassNotFoundException("Could not find class with name " + argument); |
| } |
| } |
| }); |
| return new ModelPackageBundleListener(mockBundleContext, mockModelAdapterFactory, adapterImplementations, null, null); |
| } |
| |
| } |