SLING-11332: Sling update to 47 (#1)

Co-authored-by: Ashok Pelluru <ashok.pelluru@aldi-sued.com>
diff --git a/bnd.bnd b/bnd.bnd
new file mode 100644
index 0000000..d590fb2
--- /dev/null
+++ b/bnd.bnd
@@ -0,0 +1,2 @@
+Bundle-Category: sling,jcr,jackrabbit
+Private-Package: org.apache.sling.jcr.classloader.internal.*
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 04df789..0da4edd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,14 +21,13 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.sling</groupId>
-        <artifactId>sling</artifactId>
-        <version>30</version>
+        <artifactId>sling-bundle-parent</artifactId>
+        <version>47</version>
         <relativePath />
     </parent>
 
     <artifactId>org.apache.sling.jcr.classloader</artifactId>
     <version>3.2.5-SNAPSHOT</version>
-    <packaging>bundle</packaging>
 
     <name>Apache Sling JCR ClassLoader</name>
     <description>
@@ -43,34 +42,19 @@
         <connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-classloader.git</connection>
         <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-jcr-classloader.git</developerConnection>
         <url>https://gitbox.apache.org/repos/asf?p=sling-org-apache-sling-jcr-classloader.git</url>
-      <tag>HEAD</tag>
-  </scm>
+        <tag>HEAD</tag>
+    </scm>
+
+    <properties>
+        <sling.java.version>8</sling.java.version>
+        <project.build.outputTimestamp>1</project.build.outputTimestamp>
+    </properties>
 
     <build>
         <plugins>
             <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-scr-plugin</artifactId>
-                <version>1.26.4</version>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <extensions>true</extensions>
-                <configuration>
-                    <instructions>
-                        <Bundle-Category>
-                            sling,jcr,jackrabbit
-                        </Bundle-Category>
-                        <Private-Package>
-                            org.apache.sling.jcr.classloader.internal.*
-                        </Private-Package>
-                        <!-- remove when upgrading to bnd Maven plugin -->
-                        <Provide-Capability>
-                            osgi.service;objectClass=org.apache.sling.commons.classloader.ClassLoaderWriter
-                        </Provide-Capability>
-                    </instructions>
-                </configuration>
+                <groupId>biz.aQute.bnd</groupId>
+                <artifactId>bnd-maven-plugin</artifactId>
             </plugin>
         </plugins>
     </build>
@@ -86,11 +70,6 @@
         </plugins>
     </reporting>
     <dependencies>
-      <!-- SCR Annotations -->
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.scr.annotations</artifactId>
-        </dependency>
        <dependency>
            <groupId>javax.jcr</groupId>
            <artifactId>jcr</artifactId>
@@ -109,12 +88,6 @@
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.commons.osgi</artifactId>
-            <version>2.1.0</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.settings</artifactId>
             <version>1.0.0</version>
             <scope>provided</scope>
@@ -130,10 +103,6 @@
             <artifactId>slf4j-api</artifactId>
         </dependency>
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>osgi.core</artifactId>
         </dependency>
@@ -141,5 +110,29 @@
             <groupId>org.osgi</groupId>
             <artifactId>osgi.cmpn</artifactId>
         </dependency>
+
+        <!-- Test dependencies -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>4.5.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.sling-mock.junit4</artifactId>
+            <version>3.2.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.testing.osgi-mock.junit4</artifactId>
+            <version>3.2.2</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git a/src/main/java/org/apache/sling/jcr/classloader/internal/ClassLoaderWriterImpl.java b/src/main/java/org/apache/sling/jcr/classloader/internal/ClassLoaderWriterImpl.java
index fe7ad9a..ecf8e4d 100644
--- a/src/main/java/org/apache/sling/jcr/classloader/internal/ClassLoaderWriterImpl.java
+++ b/src/main/java/org/apache/sling/jcr/classloader/internal/ClassLoaderWriterImpl.java
@@ -24,7 +24,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.Map;
 
 import javax.jcr.Item;
 import javax.jcr.Node;
@@ -33,23 +32,25 @@
 import javax.jcr.Session;
 import javax.jcr.SimpleCredentials;
 
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Properties;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
-import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.commons.classloader.ClassLoaderWriter;
 import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.apache.sling.commons.mime.MimeTypeService;
-import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.apache.sling.jcr.api.SlingRepository;
 import org.apache.sling.settings.SlingSettingsService;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ServiceScope;
+import org.osgi.service.component.propertytypes.ServiceDescription;
+import org.osgi.service.component.propertytypes.ServiceVendor;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -61,28 +62,31 @@
  * for clients to use for writing and reading such
  * classes and resources.
  */
-@Component(metatype=true, label="%loader.name", description="%loader.description",
-           name="org.apache.sling.jcr.classloader.internal.DynamicClassLoaderProviderImpl")
-@Service(value = ClassLoaderWriter.class, serviceFactory = true)
-@Properties({
-    @org.apache.felix.scr.annotations.Property(name="service.vendor", value="The Apache Software Foundation"),
-    @org.apache.felix.scr.annotations.Property(name="service.description", value="Repository based classloader writer")
-})
-public class ClassLoaderWriterImpl
-    implements ClassLoaderWriter {
+@Component(
+        name = "org.apache.sling.jcr.classloader.internal.DynamicClassLoaderProviderImpl",
+        service = ClassLoaderWriter.class,
+        scope = ServiceScope.BUNDLE)
+@ServiceDescription("Repository based classloader writer")
+@ServiceVendor("The Apache Software Foundation")
+public class ClassLoaderWriterImpl implements ClassLoaderWriter {
 
     /** Logger */
     private final Logger logger = LoggerFactory.getLogger(ClassLoaderWriterImpl.class);
 
     private static final String CLASS_PATH_DEFAULT = "/var/classes";
 
-    @org.apache.felix.scr.annotations.Property(value=CLASS_PATH_DEFAULT)
-    private static final String CLASS_PATH_PROP = "classpath";
+    @ObjectClassDefinition(name="%loader.name", description="%loader.description")
+    public @interface Config {
 
-    private static final boolean APPEND_ID_DEFAULT = true;
+        @AttributeDefinition
+        String classpath() default CLASS_PATH_DEFAULT;
 
-    @org.apache.felix.scr.annotations.Property(boolValue=APPEND_ID_DEFAULT)
-    private static final String APPEND_ID_PROP = "appendId";
+        @AttributeDefinition
+        boolean appendId() default true;
+
+        @AttributeDefinition
+        String owner() default OWNER_DEFAULT;
+    }
 
     /** Node type for packages/folders. */
     private static final String NT_FOLDER = "nt:folder";
@@ -90,9 +94,6 @@
     /** Default class loader owner. */
     private static final String OWNER_DEFAULT = "admin";
 
-    @org.apache.felix.scr.annotations.Property(value=OWNER_DEFAULT)
-    private static final String OWNER_PROP = "owner";
-
     @Reference
     private SlingSettingsService settings;
 
@@ -105,11 +106,11 @@
     @Reference
     private SlingRepository repository;
 
-    @Reference(policy=ReferencePolicy.DYNAMIC, cardinality=ReferenceCardinality.OPTIONAL_UNARY)
+    @Reference(policy= ReferencePolicy.DYNAMIC, cardinality= ReferenceCardinality.OPTIONAL)
     private volatile MimeTypeService mimeTypeService;
 
     @Reference(
-            referenceInterface = DynamicClassLoaderManager.class,
+            service = DynamicClassLoaderManager.class,
             bind = "bindDynamicClassLoaderManager",
             unbind = "unbindDynamicClassLoaderManager")
     private volatile ServiceReference dynamicClassLoaderManager;
@@ -123,19 +124,19 @@
     /**
      * Activate this component.
      * @param componentContext The component context
-     * @param properties The configuration properties
+     * @param config The configuration properties
      */
     @Activate
-    protected void activate(final ComponentContext componentContext, final Map<String, Object> properties) {
-        this.classPath = PropertiesUtil.toString(properties.get(CLASS_PATH_PROP), CLASS_PATH_DEFAULT);
+    protected void activate(final ComponentContext componentContext, Config config) {
+        this.classPath = config.classpath();
         if ( this.classPath.endsWith("/") ) {
             this.classPath = this.classPath.substring(0, this.classPath.length() - 1);
         }
-        if ( PropertiesUtil.toBoolean(properties.get(APPEND_ID_PROP), APPEND_ID_DEFAULT) ) {
+        if ( config.appendId()) {
             this.classPath = this.classPath + '/' + this.settings.getSlingId();
         }
 
-        this.classLoaderOwner = PropertiesUtil.toString(properties.get(OWNER_PROP), OWNER_DEFAULT);
+        this.classLoaderOwner = config.owner();
 
         this.callerBundle = componentContext.getUsingBundle();
     }
diff --git a/src/main/resources/OSGI-INF/l10n/metatype.properties b/src/main/resources/OSGI-INF/l10n/org.apache.sling.jcr.classloader.internal.ClassLoaderWriterImpl$Config.properties
similarity index 100%
rename from src/main/resources/OSGI-INF/l10n/metatype.properties
rename to src/main/resources/OSGI-INF/l10n/org.apache.sling.jcr.classloader.internal.ClassLoaderWriterImpl$Config.properties
diff --git a/src/test/java/org/apache/sling/jcr/classloader/internal/ClassLoaderWriterImplTest.java b/src/test/java/org/apache/sling/jcr/classloader/internal/ClassLoaderWriterImplTest.java
new file mode 100644
index 0000000..ac3d81f
--- /dev/null
+++ b/src/test/java/org/apache/sling/jcr/classloader/internal/ClassLoaderWriterImplTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.jcr.classloader.internal;
+
+import org.apache.sling.commons.classloader.ClassLoaderWriter;
+import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
+import org.apache.sling.commons.mime.MimeTypeService;
+import org.apache.sling.settings.SlingSettingsService;
+import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
+import org.apache.sling.testing.mock.sling.MockJcrSlingRepository;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import static org.junit.Assert.assertNotNull;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ClassLoaderWriterImplTest {
+
+    @Rule
+    public final OsgiContext context = new OsgiContext();
+
+    private ClassLoaderWriter classLoaderWriter;
+
+    @Before
+    public void setUp() {
+        Dictionary<String, Object> properties = new Hashtable<>();
+
+        context.registerInjectActivateService(new MockJcrSlingRepository());
+
+        //Mock DynamicClassLoaderManager
+        DynamicClassLoaderManager dynamicClassLoaderManager = Mockito.mock(DynamicClassLoaderManager.class);
+        context.registerService(DynamicClassLoaderManager.class, dynamicClassLoaderManager);
+
+        //Mock SlingSettingsService
+        SlingSettingsService slingSettingsService = Mockito.mock(SlingSettingsService.class);
+        context.registerService(SlingSettingsService.class, slingSettingsService);
+
+        //Mock MimeTypeService
+        MimeTypeService mimeTypeService = Mockito.mock(MimeTypeService.class);
+        context.registerService(MimeTypeService.class, mimeTypeService);
+
+        classLoaderWriter = context.registerInjectActivateService(new ClassLoaderWriterImpl(), properties);
+    }
+
+    @Test
+    public void testIfServiceActive() {
+        assertNotNull(classLoaderWriter);
+    }
+
+}
\ No newline at end of file