You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by kw...@apache.org on 2019/12/06 12:05:10 UTC

[sling-org-apache-sling-installer-core] branch feature/url-handler created (now 1867f9c)

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a change to branch feature/url-handler
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-core.git.


      at 1867f9c  SLING-8877 automatically register URL handlers for all UpdateHandler services

This branch includes the following new commits:

     new 1867f9c  SLING-8877 automatically register URL handlers for all UpdateHandler services

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[sling-org-apache-sling-installer-core] 01/01: SLING-8877 automatically register URL handlers for all UpdateHandler services

Posted by kw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch feature/url-handler
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-core.git

commit 1867f9cc0037078c649aa56fa5e234aa011cc981
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Fri Dec 6 13:04:57 2019 +0100

    SLING-8877 automatically register URL handlers for all UpdateHandler
    services
---
 .../core/impl/InstallerResourceUrlHandler.java     | 82 ++++++++++++++++++++++
 .../installer/core/impl/OsgiInstallerImpl.java     |  5 +-
 .../installer/core/impl/UpdateHandlerTracker.java  | 82 ++++++++++++++++++++++
 .../core/impl/tasks/AbstractBundleTask.java        | 12 ++++
 .../core/impl/tasks/BundleInstallTask.java         |  1 +
 .../core/impl/tasks/BundleUpdateTask.java          |  1 +
 6 files changed, 181 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/apache/sling/installer/core/impl/InstallerResourceUrlHandler.java b/src/main/java/org/apache/sling/installer/core/impl/InstallerResourceUrlHandler.java
new file mode 100644
index 0000000..e2e1550
--- /dev/null
+++ b/src/main/java/org/apache/sling/installer/core/impl/InstallerResourceUrlHandler.java
@@ -0,0 +1,82 @@
+/*
+ * 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.installer.core.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+
+import org.apache.sling.installer.api.info.InfoProvider;
+import org.apache.sling.installer.api.info.ResourceGroup;
+import org.apache.sling.installer.api.tasks.ResourceState;
+import org.apache.sling.installer.core.impl.tasks.AbstractBundleTask;
+import org.osgi.service.url.AbstractURLStreamHandlerService;
+import org.osgi.service.url.URLStreamHandlerService;
+
+/**
+ * URL Handler for schemes used by the UpdateHandlers
+ * 
+ * @see <a href="https://osgi.org/specification/osgi.core/7.0.0/service.url.html#d0e42987">OSGi URL Handlers</a>
+ */
+public class InstallerResourceUrlHandler extends AbstractURLStreamHandlerService implements URLStreamHandlerService {
+
+    private final InfoProvider installerInfo;
+
+    public InstallerResourceUrlHandler(InfoProvider installerInfo) {
+        this.installerInfo = installerInfo;
+    }
+
+    private InputStream getInputStreamFromInstallerResourceUrl(URL url) throws IOException {
+        for (ResourceGroup resourceGroup : installerInfo.getInstallationState().getInstalledResources()) {
+            for (org.apache.sling.installer.api.info.Resource resource : resourceGroup.getResources()) {
+                String bundleLocation = AbstractBundleTask.getBundleLocation(resource);
+                if (url.toString().equals(bundleLocation) && resource.getState().equals(ResourceState.INSTALLED)) {
+                    return resource.getInputStream();
+                }
+            }
+        }
+        throw new IOException("Could not find OSGi installer resource with location " + url);
+    }
+
+    @Override
+    public URLConnection openConnection(URL url) throws IOException {
+        return new InputStreamConnection(url, getInputStreamFromInstallerResourceUrl(url));
+    }
+
+    private static final class InputStreamConnection extends URLConnection {
+
+        private final InputStream input;
+        
+        protected InputStreamConnection(URL url, InputStream input) {
+            super(url);
+            this.input = input;
+        }
+
+        @Override
+        public void connect() throws IOException {
+        }
+
+        @Override
+        public InputStream getInputStream() throws IOException {
+            return input;
+        }
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java b/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java
index b60685c..15ae3ed 100644
--- a/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java
+++ b/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java
@@ -70,6 +70,7 @@ import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.Version;
 import org.osgi.service.startlevel.StartLevel;
+import org.osgi.service.url.URLStreamHandlerService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -138,7 +139,7 @@ implements OsgiInstaller, ResourceChangeListener, RetryHandler, InfoProvider, Ru
     private SortingServiceTracker<ResourceTransformer> transformerTracker;
 
     /** A tracker for update handlers. */
-    private SortingServiceTracker<UpdateHandler> updateHandlerTracker;
+    private UpdateHandlerTracker updateHandlerTracker;
 
     /** A tracker for the factories. */
     private SortingServiceTracker<ResourceUpdater> updaterTracker;
@@ -236,7 +237,7 @@ implements OsgiInstaller, ResourceChangeListener, RetryHandler, InfoProvider, Ru
         // start service trackers
         this.factoryTracker = new SortingServiceTracker<>(ctx, InstallTaskFactory.class.getName(), this);
         this.transformerTracker = new SortingServiceTracker<>(ctx, ResourceTransformer.class.getName(), this);
-        this.updateHandlerTracker = new SortingServiceTracker<>(ctx, UpdateHandler.class.getName(), null);
+        this.updateHandlerTracker = new UpdateHandlerTracker(ctx, this);
         this.updaterTracker = new SortingServiceTracker<>(ctx, ResourceUpdater.class.getName(), this);
         this.factoryTracker.open();
         this.transformerTracker.open();
diff --git a/src/main/java/org/apache/sling/installer/core/impl/UpdateHandlerTracker.java b/src/main/java/org/apache/sling/installer/core/impl/UpdateHandlerTracker.java
new file mode 100644
index 0000000..67549cc
--- /dev/null
+++ b/src/main/java/org/apache/sling/installer/core/impl/UpdateHandlerTracker.java
@@ -0,0 +1,82 @@
+/*
+ * 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.installer.core.impl;
+
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.installer.api.UpdateHandler;
+import org.apache.sling.installer.api.info.InfoProvider;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.url.URLConstants;
+import org.osgi.service.url.URLStreamHandlerService;
+
+public class UpdateHandlerTracker extends SortingServiceTracker<UpdateHandler> {
+
+    private final InfoProvider infoProvider;
+    private final Map<ServiceReference, ServiceRegistration<URLStreamHandlerService>> urlHandlers;
+    public UpdateHandlerTracker(BundleContext ctx, InfoProvider infoProvider) {
+        super(ctx, UpdateHandler.class.getName(), null);
+        this.infoProvider = infoProvider;
+        this.urlHandlers = new HashMap<>();
+    }
+
+    @Override
+    public Object addingService(ServiceReference reference) {
+        final String[] schemes = PropertiesUtil.toStringArray(reference.getProperty(UpdateHandler.PROPERTY_SCHEMES));
+        if (schemes != null && schemes.length > 0) {
+            addUrlHandler(schemes);
+        }
+        return super.addingService(reference);
+    }
+
+    private ServiceRegistration<URLStreamHandlerService> addUrlHandler(String[] schemes) {
+        InstallerResourceUrlHandler service = new InstallerResourceUrlHandler(infoProvider);
+        Dictionary<String, String[]> properties = new Hashtable<>();
+        properties.put(URLConstants.URL_HANDLER_PROTOCOL, schemes);
+        return context.registerService(URLStreamHandlerService.class, service, properties);
+        
+    }
+    
+    private void removeUrlHandler(ServiceReference serviceReference) {
+        ServiceRegistration<URLStreamHandlerService> urlHandler = urlHandlers.get(serviceReference);
+        if (urlHandler != null) {
+            urlHandler.unregister();
+        }
+    }
+
+    @Override
+    public void removedService(ServiceReference reference, Object service) {
+        removeUrlHandler(reference);
+        super.removedService(reference, service);
+    }
+
+    @Override
+    public void close() {
+        for (ServiceReference serviceReference : urlHandlers.keySet()) {
+            removeUrlHandler(serviceReference);
+        }
+        super.close();
+    }
+}
diff --git a/src/main/java/org/apache/sling/installer/core/impl/tasks/AbstractBundleTask.java b/src/main/java/org/apache/sling/installer/core/impl/tasks/AbstractBundleTask.java
index 6c935f9..b5587c1 100644
--- a/src/main/java/org/apache/sling/installer/core/impl/tasks/AbstractBundleTask.java
+++ b/src/main/java/org/apache/sling/installer/core/impl/tasks/AbstractBundleTask.java
@@ -19,6 +19,8 @@
 package org.apache.sling.installer.core.impl.tasks;
 
 import org.apache.sling.installer.api.InstallableResource;
+import org.apache.sling.installer.api.info.Resource;
+import org.apache.sling.installer.api.tasks.TaskResource;
 import org.apache.sling.installer.api.tasks.TaskResourceGroup;
 import org.apache.sling.installer.core.impl.AbstractInstallTask;
 
@@ -27,10 +29,20 @@ import org.apache.sling.installer.core.impl.AbstractInstallTask;
  */
 public abstract class AbstractBundleTask extends AbstractInstallTask {
 
+    public final static String ATTRIBUTE_BUNDLE_LOCATION = "Bundle-Location";
+    
     public AbstractBundleTask(final TaskResourceGroup erl, final TaskSupport support) {
         super(erl, support);
     }
 
+    public static void setBundleLocation(TaskResource resource, String location) {
+        resource.setAttribute(ATTRIBUTE_BUNDLE_LOCATION, location);
+    }
+
+    public static String getBundleLocation(Resource resource) {
+        return (String) resource.getAttribute(ATTRIBUTE_BUNDLE_LOCATION);
+    }
+
     /**
      * Detect the start level for the resource.
      */
diff --git a/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleInstallTask.java b/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleInstallTask.java
index 7127e0a..6420eef 100644
--- a/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleInstallTask.java
+++ b/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleInstallTask.java
@@ -46,6 +46,7 @@ public class BundleInstallTask extends AbstractBundleTask {
         try {
             final Bundle b = this.getBundleContext().installBundle(getResource().getURL(), getResource().getInputStream());
             ctx.log("Installed bundle {} from resource {}", b, getResource());
+            setBundleLocation(getResource(), getResource().getURL());
             // optionally set the start level
             if ( startLevel > 0 ) {
                 final BundleStartLevel startLevelService = b.adapt(BundleStartLevel.class);
diff --git a/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUpdateTask.java b/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUpdateTask.java
index 8960ffc..4cd94bd 100644
--- a/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUpdateTask.java
+++ b/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleUpdateTask.java
@@ -102,6 +102,7 @@ public class BundleUpdateTask extends AbstractBundleTask {
             b.update(getResource().getInputStream());
             ctx.log("Updated bundle {} from resource {}", b, getResource());
 
+            setBundleLocation(getResource(), b.getLocation());
             // start level handling - after update to avoid starting the bundle
             // just before the update
             final BundleStartLevel startLevelService = b.adapt(BundleStartLevel.class);