Author: sseifert Date: Tue Dec 6 08:53:09 2016 New Revision: 1772846 URL: http://svn.apache.org/viewvc?rev=1772846&view=rev Log: SLING-6360 suppor registering of configuration annotation classes
Added: sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/ConfigurationMetadataUtil.java (with props) sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/MockContextAwareConfig.java (with props) sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/test/java/org/apache/sling/testing/mock/caconfig/example/ sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/test/java/org/apache/sling/testing/mock/caconfig/example/SimpleConfig.java (with props) Modified: sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/ContextPlugins.java sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/test/java/org/apache/sling/testing/mock/caconfig/ContextPluginsTest.java Added: sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/ConfigurationMetadataUtil.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/ConfigurationMetadataUtil.java?rev=1772846&view=auto ============================================================================== --- sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/ConfigurationMetadataUtil.java (added) +++ sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/ConfigurationMetadataUtil.java Tue Dec 6 08:53:09 2016 @@ -0,0 +1,269 @@ +/* + * 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.testing.mock.caconfig; + +import static org.apache.sling.caconfig.impl.ConfigurationNameConstants.CONFIGURATION_CLASSES_HEADER; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.security.cert.X509Certificate; +import java.util.Collection; +import java.util.Dictionary; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.testing.mock.osgi.ManifestScanner; +import org.apache.sling.testing.mock.osgi.MockOsgi; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleEvent; +import org.osgi.framework.BundleException; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.Version; + +/** + * Helper methods for registering Configuration annotation classes from the classpath. + */ +final class ConfigurationMetadataUtil { + + private static final String[] CONFIGURATION_CLASSES_FROM_MANIFEST; + + static { + // scan classpath for configuration classes bundle header entries only once + CONFIGURATION_CLASSES_FROM_MANIFEST = toArray(ManifestScanner.getValues(CONFIGURATION_CLASSES_HEADER)); + } + + private ConfigurationMetadataUtil() { + // static methods only + } + + private static String[] toArray(Collection<String> values) { + return values.toArray(new String[values.size()]); + } + + /** + * Search classpath for given class names to scan for and register all classes with @Configuration annotation. + * @param bundleContext Bundle context + * @param classNames Java class names + */ + public static void registerAnnotationClasses(BundleContext bundleContext, String... classNames) { + Bundle bundle = new RegisterConfigurationMetadataBundle(bundleContext, Bundle.ACTIVE, classNames); + BundleEvent event = new BundleEvent(BundleEvent.STARTED, bundle); + MockOsgi.sendBundleEvent(bundleContext, event); + } + + /** + * Search classpath for given class names to scan for and register all classes with @Configuration annotation. + * @param bundleContext Bundle context + * @param classNames Java class names + */ + public static void registerAnnotationClasses(BundleContext bundleContext, Class... classes) { + String[] classNames = new String[classes.length]; + for (int i = 0; i < classes.length; i++) { + classNames[i] = classes[i].getName(); + } + registerAnnotationClasses(bundleContext, classNames); + } + + /** + * Scan MANIFEST.MF in the classpath and automatically register all Configuration annotation classes found. + * @param bundleContext Bundle context + */ + public static void addAnnotationClassesForManifestEntries(BundleContext bundleContext) { + if (CONFIGURATION_CLASSES_FROM_MANIFEST.length > 0) { + registerAnnotationClasses(bundleContext, CONFIGURATION_CLASSES_FROM_MANIFEST); + } + } + + + private static class RegisterConfigurationMetadataBundle implements Bundle { + + private final BundleContext bundleContext; + private final int state; + private final String classNames; + + public RegisterConfigurationMetadataBundle(BundleContext bundleContext, int state, String[] classNames) { + this.bundleContext = bundleContext; + this.state = state; + this.classNames = normalizeValueList(classNames); + } + + private String normalizeValueList(String[] values) { + if (values == null || values.length == 0) { + return null; + } + return StringUtils.join(values, ","); + } + + @Override + public int getState() { + return this.state; + } + + @Override + public Dictionary<String,String> getHeaders() { + Dictionary<String, String> headers = new Hashtable<String, String>(); + headers.put(CONFIGURATION_CLASSES_HEADER, classNames); + return headers; + } + + @Override + public Enumeration<URL> findEntries(String path, String filePattern, boolean recurse) { + return new Vector<URL>().elements(); + } + + @Override + public Class<?> loadClass(String name) throws ClassNotFoundException { + return getClass().getClassLoader().loadClass(name); + } + + @Override + public BundleContext getBundleContext() { + return bundleContext; + } + + @Override + public void start(int options) throws BundleException { + // do nothing + } + + @Override + public void start() throws BundleException { + // do nothing + } + + @Override + public void stop(int options) throws BundleException { + // do nothing + } + + @Override + public void stop() throws BundleException { + // do nothing + } + + @Override + public void update(InputStream input) throws BundleException { + // do nothing + } + + @Override + public void update() throws BundleException { + // do nothing + } + + @Override + public void uninstall() throws BundleException { + // do nothing + } + + @Override + public long getBundleId() { + return 0; + } + + @Override + public String getLocation() { + return null; + } + + @Override + public ServiceReference<?>[] getRegisteredServices() { // NOPMD + return null; + } + + @Override + public ServiceReference<?>[] getServicesInUse() { // NOPMD + return null; + } + + @Override + public boolean hasPermission(Object permission) { + return false; + } + + @Override + public URL getResource(String name) { + return null; + } + + @Override + public Dictionary<String,String> getHeaders(String locale) { + return null; + } + + @Override + public String getSymbolicName() { + return null; + } + + @Override + public Enumeration<URL> getResources(String name) throws IOException { + return null; + } + + @Override + public Enumeration<String> getEntryPaths(String path) { + return null; + } + + @Override + public URL getEntry(String path) { + return null; + } + + @Override + public long getLastModified() { + return 0; + } + + @Override + public Map<X509Certificate, List<X509Certificate>> getSignerCertificates(int signersType) { + return null; + } + + @Override + public Version getVersion() { + return null; + } + + @Override + public int compareTo(Bundle o) { + return 0; + } + + @Override + public <A> A adapt(Class<A> type) { + return null; + } + + @Override + public File getDataFile(String filename) { + return null; + } + + } + +} Propchange: sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/ConfigurationMetadataUtil.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/ConfigurationMetadataUtil.java ------------------------------------------------------------------------------ --- svn:keywords (added) +++ svn:keywords Tue Dec 6 08:53:09 2016 @@ -0,0 +1 @@ +LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author Propchange: sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/ConfigurationMetadataUtil.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/ContextPlugins.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/ContextPlugins.java?rev=1772846&r1=1772845&r2=1772846&view=diff ============================================================================== --- sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/ContextPlugins.java (original) +++ sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/ContextPlugins.java Tue Dec 6 08:53:09 2016 @@ -23,6 +23,7 @@ import org.apache.sling.caconfig.impl.Co import org.apache.sling.caconfig.impl.ConfigurationResolverImpl; import org.apache.sling.caconfig.impl.def.DefaultConfigurationInheritanceStrategy; import org.apache.sling.caconfig.impl.def.DefaultConfigurationPersistenceStrategy; +import org.apache.sling.caconfig.impl.metadata.AnnotationClassConfigurationMetadataProvider; import org.apache.sling.caconfig.impl.metadata.ConfigurationMetadataProviderMultiplexer; import org.apache.sling.caconfig.impl.override.ConfigurationOverrideManager; import org.apache.sling.caconfig.management.impl.ConfigurationManagerImpl; @@ -35,10 +36,12 @@ import org.apache.sling.caconfig.resourc import org.apache.sling.testing.mock.osgi.context.AbstractContextPlugin; import org.apache.sling.testing.mock.osgi.context.ContextPlugin; import org.apache.sling.testing.mock.sling.context.SlingContextImpl; +import org.osgi.annotation.versioning.ProviderType; /** * Mock context plugins. */ +@ProviderType public final class ContextPlugins { private ContextPlugins() { @@ -56,6 +59,9 @@ public final class ContextPlugins { registerConfigurationManagement(context); registerConfigurationResourceResolverDefaultImpl(context); registerConfigurationResolverDefaultImpl(context); + + // Scan MANIFEST.MF in the classpath and automatically register all Configuration annotation classes found. + ConfigurationMetadataUtil.addAnnotationClassesForManifestEntries(context.bundleContext()); } }; @@ -115,6 +121,7 @@ public final class ContextPlugins { private static void registerConfigurationManagement(SlingContextImpl context) { context.registerInjectActivateService(new ConfigurationMetadataProviderMultiplexer()); context.registerInjectActivateService(new ConfigurationManagerImpl()); + context.registerInjectActivateService(new AnnotationClassConfigurationMetadataProvider()); } } Added: sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/MockContextAwareConfig.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/MockContextAwareConfig.java?rev=1772846&view=auto ============================================================================== --- sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/MockContextAwareConfig.java (added) +++ sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/MockContextAwareConfig.java Tue Dec 6 08:53:09 2016 @@ -0,0 +1,52 @@ +/* + * 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.testing.mock.caconfig; + +import org.osgi.annotation.versioning.ProviderType; +import org.osgi.framework.BundleContext; + +/** + * Helps setting up a mock environment for Context-Aware Configuration. + */ +@ProviderType +public final class MockContextAwareConfig { + + private MockContextAwareConfig() { + // static methods only + } + + /** + * Search classpath for given class names to scan for and register all classes with @Configuration annotation. + * @param bundleContext Bundle context + * @param classNames Java class names + */ + public static void registerAnnotationClasses(BundleContext bundleContext, String... classNames) { + ConfigurationMetadataUtil.registerAnnotationClasses(bundleContext, classNames); + } + + /** + * Search classpath for given class names to scan for and register all classes with @Configuration annotation. + * @param bundleContext Bundle context + * @param classNames Java class names + */ + public static void registerAnnotationClasses(BundleContext bundleContext, Class... classes) { + ConfigurationMetadataUtil.registerAnnotationClasses(bundleContext, classes); + } + +} Propchange: sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/MockContextAwareConfig.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/MockContextAwareConfig.java ------------------------------------------------------------------------------ --- svn:keywords (added) +++ svn:keywords Tue Dec 6 08:53:09 2016 @@ -0,0 +1 @@ +LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author Propchange: sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/main/java/org/apache/sling/testing/mock/caconfig/MockContextAwareConfig.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/test/java/org/apache/sling/testing/mock/caconfig/ContextPluginsTest.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/test/java/org/apache/sling/testing/mock/caconfig/ContextPluginsTest.java?rev=1772846&r1=1772845&r2=1772846&view=diff ============================================================================== --- sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/test/java/org/apache/sling/testing/mock/caconfig/ContextPluginsTest.java (original) +++ sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/test/java/org/apache/sling/testing/mock/caconfig/ContextPluginsTest.java Tue Dec 6 08:53:09 2016 @@ -20,12 +20,14 @@ package org.apache.sling.testing.mock.ca import static org.apache.sling.testing.mock.caconfig.ContextPlugins.CACONFIG; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ValueMap; import org.apache.sling.caconfig.ConfigurationBuilder; import org.apache.sling.caconfig.management.ConfigurationManager; import org.apache.sling.caconfig.spi.ConfigurationPersistData; +import org.apache.sling.testing.mock.caconfig.example.SimpleConfig; import org.apache.sling.testing.mock.sling.junit.SlingContext; import org.apache.sling.testing.mock.sling.junit.SlingContextBuilder; import org.junit.Before; @@ -47,22 +49,35 @@ public class ContextPluginsTest { public void setUp() { context.create().resource("/content/site1", "sling:configRef", "/conf/site1"); contextResource = context.create().resource("/content/site1/page1"); - } - - @Test - public void testPlugin() { + // register configuration annotation class + MockContextAwareConfig.registerAnnotationClasses(context.bundleContext(), SimpleConfig.class); + // write config ConfigurationManager configManager = context.getService(ConfigurationManager.class); configManager.persistConfiguration(contextResource, CONFIG_NAME, new ConfigurationPersistData(ImmutableMap.<String, Object>of( - "prop1", "value1", - "prop2", 123))); - + "stringParam", "value1", + "intParam", 123, + "boolParam", true))); + } + + @Test + public void testValueMap() { // read config ValueMap props = contextResource.adaptTo(ConfigurationBuilder.class).name(CONFIG_NAME).asValueMap(); - assertEquals("value1", props.get("prop1", String.class)); - assertEquals((Integer)123, props.get("prop2", Integer.class)); + assertEquals("value1", props.get("stringParam", String.class)); + assertEquals((Integer)123, props.get("intParam", Integer.class)); + assertTrue(props.get("boolParam", Boolean.class)); + } + + @Test + public void testAnnotationClass() { + // read config + SimpleConfig config = contextResource.adaptTo(ConfigurationBuilder.class).as(SimpleConfig.class); + assertEquals("value1", config.stringParam()); + assertEquals(123, config.intParam()); + assertTrue(config.boolParam()); } } Added: sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/test/java/org/apache/sling/testing/mock/caconfig/example/SimpleConfig.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/test/java/org/apache/sling/testing/mock/caconfig/example/SimpleConfig.java?rev=1772846&view=auto ============================================================================== --- sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/test/java/org/apache/sling/testing/mock/caconfig/example/SimpleConfig.java (added) +++ sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/test/java/org/apache/sling/testing/mock/caconfig/example/SimpleConfig.java Tue Dec 6 08:53:09 2016 @@ -0,0 +1,32 @@ +/* + * 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.testing.mock.caconfig.example; + +import org.apache.sling.caconfig.annotation.Configuration; + +@Configuration(name = "testConfig") +public @interface SimpleConfig { + + String stringParam(); + + int intParam() default 5; + + boolean boolParam(); + +} Propchange: sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/test/java/org/apache/sling/testing/mock/caconfig/example/SimpleConfig.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/test/java/org/apache/sling/testing/mock/caconfig/example/SimpleConfig.java ------------------------------------------------------------------------------ --- svn:keywords (added) +++ svn:keywords Tue Dec 6 08:53:09 2016 @@ -0,0 +1 @@ +LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author Propchange: sling/trunk/contrib/extensions/contextaware-config/testing/mocks/caconfig-mock-plugin/src/test/java/org/apache/sling/testing/mock/caconfig/example/SimpleConfig.java ------------------------------------------------------------------------------ svn:mime-type = text/plain