Author: cziegeler
Date: Wed May 31 12:29:12 2017
New Revision: 1797026
URL: http://svn.apache.org/viewvc?rev=1797026&view=rev
Log:
Add launcher prototype
Added:
sling/whiteboard/cziegeler/feature-launcher/
sling/whiteboard/cziegeler/feature-launcher/pom.xml (with props)
sling/whiteboard/cziegeler/feature-launcher/src/
sling/whiteboard/cziegeler/feature-launcher/src/main/
sling/whiteboard/cziegeler/feature-launcher/src/main/java/
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/api/
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/api/Logger.java
(with props)
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
(with props)
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java
(with props)
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
(with props)
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
(with props)
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/artifacts/
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/artifacts/ArtifactHandler.java
(with props)
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/artifacts/ArtifactManager.java
(with props)
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/launchers/
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java
(with props)
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
(with props)
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkRunner.java
(with props)
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/spi/
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/spi/ArtifactProvider.java
(with props)
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/spi/ArtifactProviderContext.java
(with props)
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/spi/Launcher.java
(with props)
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/spi/LauncherPrepareContext.java
(with props)
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/spi/LauncherRunContext.java
(with props)
sling/whiteboard/cziegeler/feature-launcher/src/test/
sling/whiteboard/cziegeler/feature-launcher/src/test/java/
sling/whiteboard/cziegeler/feature-launcher/src/test/java/org/
sling/whiteboard/cziegeler/feature-launcher/src/test/java/org/apache/
sling/whiteboard/cziegeler/feature-launcher/src/test/java/org/apache/sling/
sling/whiteboard/cziegeler/feature-launcher/src/test/java/org/apache/sling/feature/
sling/whiteboard/cziegeler/feature-launcher/src/test/java/org/apache/sling/feature/launcher/
sling/whiteboard/cziegeler/feature-launcher/src/test/java/org/apache/sling/feature/launcher/impl/
sling/whiteboard/cziegeler/feature-launcher/src/test/java/org/apache/sling/feature/launcher/impl/artifacts/
sling/whiteboard/cziegeler/feature-launcher/src/test/java/org/apache/sling/feature/launcher/impl/artifacts/ArtifactManagerTest.java
(with props)
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/ApplicationJSONWriter.java
(with props)
Modified:
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONReader.java
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONWriter.java
Added: sling/whiteboard/cziegeler/feature-launcher/pom.xml
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-launcher/pom.xml?rev=1797026&view=auto
==============================================================================
--- sling/whiteboard/cziegeler/feature-launcher/pom.xml (added)
+++ sling/whiteboard/cziegeler/feature-launcher/pom.xml Wed May 31 12:29:12 2017
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+ <!--
+ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>sling</artifactId>
+ <version>30</version>
+ <relativePath />
+ </parent>
+
+ <artifactId>org.apache.sling.feature.launcher</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+
+ <name>Apache Sling Feature Launcher</name>
+ <description>
+ A application launcher using Apache Sling Features
+ </description>
+
+ <properties>
+ <sling.java.version>8</sling.java.version>
+ </properties>
+
+ <scm>
+
<connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/tooling/support/feature-launcher</connection>
+
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/tooling/support/featurelauncher</developerConnection>
+
<url>http://svn.apache.org/viewvc/sling/trunk/tooling/support/featurelauncher</url>
+ </scm>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack-dependencies</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <configuration>
+ <excludes>META-INF/**</excludes>
+
<outputDirectory>${project.build.directory}/classes</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+
<includeArtifactIds>org.apache.sling.provisioning.feature,commons-cli</includeArtifactIds>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+
<mainClass>org.apache.sling.feature.launcher.impl.Main</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.feature</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-cli</groupId>
+ <artifactId>commons-cli</artifactId>
+ <version>1.3.1</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>2.8.9</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
Propchange: sling/whiteboard/cziegeler/feature-launcher/pom.xml
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/whiteboard/cziegeler/feature-launcher/pom.xml
------------------------------------------------------------------------------
svn:keywords = Id
Added:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/api/Logger.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/api/Logger.java?rev=1797026&view=auto
==============================================================================
---
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/api/Logger.java
(added)
+++
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/api/Logger.java
Wed May 31 12:29:12 2017
@@ -0,0 +1,112 @@
+/*
+ * 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.feature.launcher.api;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.text.MessageFormat;
+
+/**
+ * A simple logger to be used by extensions for the launcher.
+ * Extensions should get the logger through the shared instance {@link #LOG}
+ * The returned logger instance is not thread-safe, it is assumed
+ * that all launching is single threaded!
+ */
+public class Logger {
+
+ /**
+ * The shared logger instance.
+ */
+ public static Logger LOG = new Logger();
+
+ /** Flag if debug is enabled. */
+ private volatile boolean isDebug = false;
+
+ /** Flag if info is enabled. */
+ private final boolean isInfo = true;
+
+ /** Flag if warn is enabled. */
+ private final boolean isWarn = true;
+
+ public boolean isDebugEnabled() {
+ return isDebug;
+ }
+
+ public boolean isInfoEnabled() {
+ return isInfo;
+ }
+
+ public boolean isWarnEnabled() {
+ return isWarn;
+ }
+
+ public void debug(final String msg, final Throwable t) {
+ if ( isDebug ) {
+ final StringWriter sw = new StringWriter();
+ final PrintWriter pw = new PrintWriter(sw);
+ t.printStackTrace(pw);
+ pw.flush();
+ log("[DEBUG]", msg);
+ log("[DEBUG]", sw.toString());
+ }
+ }
+
+ public void debug(final String msg, final Object... params) {
+ if ( isDebug ) {
+ log("[DEBUG]", msg, params);
+ }
+ }
+
+ public void info(final String msg, final Object... params) {
+ if ( isInfo ) {
+ log("[INFO]", msg, params);
+ }
+ }
+
+ public void warn(final String msg, final Object... params) {
+ if ( isWarn ) {
+ log("[WARN]", msg, params);
+ }
+ }
+
+ public void error(final String msg, final Throwable t, final Object...
params) {
+ log("[ERROR]", msg, params);
+ final StringWriter sw = new StringWriter();
+ final PrintWriter pw = new PrintWriter(sw);
+ t.printStackTrace(pw);
+ pw.flush();
+ log("[ERROR]", sw.toString());
+ }
+
+ public void error(final String msg, final Object... params) {
+ log("[ERROR]", msg, params);
+ }
+
+ public void log(final String msg, final Object... params) {
+ System.out.println(MessageFormat.format(msg, params));
+ }
+
+ private void log(final String prefix, final String msg, final Object...
params) {
+ System.out.print(prefix);
+ System.out.print(' ');
+ System.out.println(MessageFormat.format(msg, params));
+ }
+
+ public void setDebug(final boolean b) {
+ this.isDebug = b;
+ }
+}
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/api/Logger.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/api/Logger.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Added:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java?rev=1797026&view=auto
==============================================================================
---
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
(added)
+++
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
Wed May 31 12:29:12 2017
@@ -0,0 +1,156 @@
+/*
+ * 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.feature.launcher.impl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sling.feature.Application;
+import org.apache.sling.feature.Artifact;
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Configuration;
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionType;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.json.ApplicationJSONWriter;
+import org.apache.sling.feature.json.FeatureJSONReader;
+import org.apache.sling.feature.launcher.api.Logger;
+import org.apache.sling.feature.launcher.impl.LauncherConfig.StartupMode;
+import org.apache.sling.feature.launcher.impl.artifacts.ArtifactHandler;
+import org.apache.sling.feature.launcher.impl.artifacts.ArtifactManager;
+import org.apache.sling.feature.process.ApplicationBuilder;
+import org.apache.sling.feature.process.FeatureProvider;
+
+public class FeatureProcessor {
+
+ /**
+ * Initialize the launcher
+ * Read the features and prepare the application
+ * @param config The current configuration
+ * @param artifactManager The artifact manager
+ */
+ public static Application createApplication(final LauncherConfig config,
+ final ArtifactManager artifactManager) {
+ final List<Feature> features = new ArrayList<>();
+ try {
+ for(String initFile : config.getFeatureFiles()) {
+ try {
+ final Feature f = getFeature(config, initFile,
artifactManager);
+ features.add(f);
+ } catch ( final IOException iae) {
+ Logger.LOG.error("Unable to read feature {0} : {1}", iae,
initFile, iae.getMessage());
+ System.exit(1);
+ }
+ }
+ } catch ( final IOException iae) {
+ Logger.LOG.error("Unable to read feature : {0}", iae,
iae.getMessage());
+ System.exit(1);
+ }
+
+ final Application app = ApplicationBuilder.assemble(new
FeatureProvider() {
+
+ @Override
+ public Feature provide(ArtifactId id) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ }, features.toArray(new Feature[features.size()]));
+
+ final File file = new File(config.getHomeDirectory(), "resources" +
File.separatorChar + "provisioning" + File.separatorChar + "feature.txt");
+ file.getParentFile().mkdirs();
+
+ try (final FileWriter writer = new FileWriter(file)) {
+ ApplicationJSONWriter.write(writer, app);
+ } catch ( final IOException ioe) {
+ Logger.LOG.error("Error while writing application file: {0}", ioe,
ioe.getMessage());
+ System.exit(1);
+ }
+
+ return app;
+ }
+
+ /**
+ * Read the feature
+ * @param config The launcher configuration
+ * @param name The feature file
+ * @param artifactManager The artifact manager to read the model
+ * @return The read feature
+ * @throws IOException If reading fails
+ */
+ private static Feature getFeature(final LauncherConfig config,
+ final String file,
+ final ArtifactManager artifactManager) throws IOException {
+ ArtifactHandler featureArtifact = null;
+ try {
+ featureArtifact = artifactManager.getArtifactHandler(file);
+ } catch ( final IOException use) {
+ Logger.LOG.error("Invalid feature url {0}", file);
+ Logger.LOG.debug("Exception while getting artifact " + file, use);
+ System.exit(1);
+ }
+ Logger.LOG.log("- reading feature {0}",
featureArtifact.getArtifactUrl());
+
+ try (final FileInputStream is = new
FileInputStream(featureArtifact.getArtifact())) {
+ final Feature f = FeatureJSONReader.read(new InputStreamReader(is,
"UTF-8"), featureArtifact.getArtifactUrl());
+ return f;
+ }
+ }
+
+ /**
+ * Prepare the launcher
+ * - add all bundles to the bundle map of the installation object
+ * - add all other artifacts to the install directory (only if startup
mode is INSTALL)
+ * - process configurations
+ */
+ public static void prepareLauncher(final LauncherConfig config,
+ final ArtifactManager artifactManager,
+ final Application app) throws Exception {
+ for(final Map.Entry<Integer, List<Artifact>> entry :
app.getBundles().getBundlesByStartLevel().entrySet()) {
+ for(final Artifact a : entry.getValue()) {
+ final ArtifactHandler handler =
artifactManager.getArtifactHandler(":" + a.getId().toMvnPath());
+ final File artifactFile = handler.getArtifact();
+
+ config.getInstallation().addBundle(entry.getKey(),
artifactFile);
+ }
+ }
+ for(final Extension ext : app.getExtensions()) {
+ if ( ext.getType() == ExtensionType.ARTIFACTS ) {
+ for(final Artifact a : ext.getArtifacts() ) {
+ if ( config.getStartupMode() == StartupMode.PURE ) {
+ throw new Exception("Artifacts other than bundle are
not supported by framework launcher.");
+ }
+ final ArtifactHandler handler =
artifactManager.getArtifactHandler(":" + a.getId().toMvnPath());
+
config.getInstallation().addInstallableArtifact(handler.getArtifact());
+ }
+ }
+ }
+
+ for(final Configuration cfg : app.getConfigurations()) {
+ if ( cfg.isFactoryConfiguration() ) {
+ config.getInstallation().addConfiguration(cfg.getName(),
cfg.getFactoryPid(), cfg.getProperties());
+ } else {
+ config.getInstallation().addConfiguration(cfg.getPid(), null,
cfg.getProperties());
+ }
+ }
+ }
+}
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Added:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java?rev=1797026&view=auto
==============================================================================
---
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java
(added)
+++
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java
Wed May 31 12:29:12 2017
@@ -0,0 +1,137 @@
+/*
+ * 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.feature.launcher.impl;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sling.feature.launcher.spi.LauncherRunContext;
+
+/**
+ * This class holds the configuration of the launcher.
+ */
+public class Installation implements LauncherRunContext {
+
+ /** The map with the framework properties. */
+ private final Map<String, String> fwkProperties = new HashMap<>();
+
+ /** Bundle map */
+ private final Map<Integer, List<File>> bundleMap = new HashMap<>();
+
+ /** Artifacts to be installed */
+ private final List<File> installables = new ArrayList<>();
+
+ /** Configurations, they are installed on first start. */
+ private final List<Object[]> configurations = new ArrayList<>();
+
+ /** The list of app jars. */
+ private final List<File> appJars = new ArrayList<>();
+
+ /**
+ * Add an application jar.
+ * @param jar The application jar
+ */
+ public void addAppJar(final File jar) {
+ this.appJars.add(jar);
+ }
+
+ /**
+ * Get the list of application jars.
+ * @return The list of app jars
+ */
+ public List<File> getAppJars() {
+ return this.appJars;
+ }
+
+ /**
+ * Add a bundle with the given start level
+ * @param startLevel The start level
+ * @param file The bundle file
+ */
+ public void addBundle(final Integer startLevel, final File file) {
+ List<File> files = bundleMap.get(startLevel);
+ if ( files == null ) {
+ files = new ArrayList<>();
+ bundleMap.put(startLevel, files);
+ }
+ files.add(file);
+ }
+
+ /**
+ * Add an artifact to be installed by the installer
+ * @param file The file
+ */
+ public void addInstallableArtifact(final File file) {
+ this.installables.add(file);
+ }
+
+ /**
+ * Add a configuration
+ * @param pid The pid
+ * @param factoryPid The factory pid
+ * @param properties The propertis
+ */
+ public void addConfiguration(final String pid, final String factoryPid,
final Dictionary<String, Object> properties) {
+ this.configurations.add(new Object[] {pid, factoryPid, properties});
+ }
+
+ /**
+ * @see
org.apache.sling.feature.launcher.spi.LauncherRunContext#getFrameworkProperties()
+ */
+ @Override
+ public Map<String, String> getFrameworkProperties() {
+ return this.fwkProperties;
+ }
+
+ /**
+ * @see
org.apache.sling.feature.launcher.spi.LauncherRunContext#getBundleMap()
+ */
+ @Override
+ public Map<Integer, List<File>> getBundleMap() {
+ return this.bundleMap;
+ }
+
+ /**
+ * @see
org.apache.sling.feature.launcher.spi.LauncherRunContext#getConfigurations()
+ */
+ @Override
+ public List<Object[]> getConfigurations() {
+ return this.configurations;
+ }
+
+ /**
+ * @see
org.apache.sling.feature.launcher.spi.LauncherRunContext#getInstallableArtifacts()
+ */
+ @Override
+ public List<File> getInstallableArtifacts() {
+ return this.installables;
+ }
+
+ /**
+ * Clear all in-memory objects
+ */
+ public void clear() {
+ this.configurations.clear();
+ this.fwkProperties.clear();
+ this.bundleMap.clear();
+ this.installables.clear();
+ }
+}
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Added:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java?rev=1797026&view=auto
==============================================================================
---
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
(added)
+++
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
Wed May 31 12:29:12 2017
@@ -0,0 +1,296 @@
+/*
+ * 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.feature.launcher.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.apache.sling.feature.launcher.spi.ArtifactProviderContext;
+
+/**
+ * This class holds the configuration of the launcher.
+ */
+public class LauncherConfig implements ArtifactProviderContext {
+
+ public static final Comparator<String> FEATURE_PATH_COMP = new
Comparator<String>() {
+
+ @Override
+ public int compare(final String o1, final String o2) {
+ // windows path conversion
+ final String key1 = o1.replace(File.separatorChar, '/');
+ final String key2 = o2.replace(File.separatorChar, '/');
+
+ final int lastSlash1 = key1.lastIndexOf('/');
+ final int lastSlash2 = key2.lastIndexOf('/');
+ if ( lastSlash1 == -1 || lastSlash2 == -1 ) {
+ return o1.compareTo(o2);
+ }
+ final String path1 = key1.substring(0, lastSlash1 + 1);
+ final String path2 = key2.substring(0, lastSlash2 + 1);
+ if ( path1.equals(path2) ) {
+ return o1.compareTo(o2);
+ }
+ if ( path1.startsWith(path2) ) {
+ return 1;
+ } else if ( path2.startsWith(path1) ) {
+ return -1;
+ }
+ return o1.compareTo(o2);
+ }
+ };
+
+ public enum StartupMode {
+ INSTALLER,
+ PURE
+ };
+
+ private static final String HOME = "launcher";
+
+ private static final String CACHE_DIR = "cache";
+
+ /** The repository urls. */
+ private volatile String[] repositoryUrls;
+
+ /** The feature files or directories. */
+ private volatile String[] featureFiles;
+
+ private volatile StartupMode startupMode = StartupMode.PURE;
+
+ private volatile long cachedArtifacts;
+
+ private volatile long downloadedArtifacts;
+
+ private volatile long localArtifacts;
+
+ private final Installation installation = new Installation();
+
+ /**
+ * Create a new configuration object.
+ * Set the default values
+ */
+ public LauncherConfig() {
+ // set defaults
+ this.repositoryUrls = new String[] {
+ "file://" + System.getProperty("user.home") +
"/.m2/repository",
+ "https://repo.maven.apache.org/maven2/"
+ };
+ }
+
+ /**
+ * Set the repository urls
+ * @param repositoryUrl The repository urls
+ */
+ public void setRepositoryUrls(final String[] urls) {
+ if ( urls == null || urls.length == 0 ) {
+ this.repositoryUrls = null;
+ } else {
+ this.repositoryUrls = new String[urls.length];
+ System.arraycopy(urls, 0, this.repositoryUrls, 0, urls.length);
+ for(int i=0; i<this.repositoryUrls.length; i++) {
+ if ( this.repositoryUrls[i].endsWith("/") ) {
+ this.repositoryUrls[i] =
this.repositoryUrls[i].substring(0, this.repositoryUrls[i].length() - 1);
+ }
+ }
+ }
+ }
+
+ /**
+ * Set the list of feature files or directories.
+ * @param value The array with the feature file names.
+ */
+ public void setFeatureFiles(final String[] value) {
+ this.featureFiles = value;
+ if ( value != null && value.length == 0 ) {
+ this.featureFiles = null;
+ }
+ }
+
+ /**
+ * Get the repository urls.
+ * A repository url does not end with a slash.
+ * @return The repository urls.
+ */
+ public String[] getRepositoryUrls() {
+ return repositoryUrls;
+ }
+
+ private void processDir(final List<String> paths, final File dir)
+ throws IOException {
+ for(final File f : dir.listFiles()) {
+ if ( f.isFile() && !f.getName().startsWith(".")) {
+ // check if file is a reference
+ if ( f.getName().endsWith(".ref") ) {
+ final List<String> lines = Files.readAllLines(f.toPath());
+ for(String line : lines) {
+ line = line.trim();
+ if ( !line.isEmpty() && !line.startsWith("#") ) {
+ paths.add(line);
+ }
+ }
+ } else {
+ paths.add(f.getAbsolutePath());
+ }
+ }
+ }
+ }
+
+ private void processFile(final List<String> paths, final File f)
+ throws IOException {
+ if ( f.getName().endsWith(".ref") ) {
+ final List<String> lines = Files.readAllLines(f.toPath());
+ for(String line : lines) {
+ line = line.trim();
+ if ( !line.isEmpty() && !line.startsWith("#") ) {
+ if ( line.indexOf(':') == -1 ) {
+ paths.add(new File(line).getAbsolutePath());
+ } else {
+ paths.add(line);
+ }
+ }
+ }
+ } else {
+ paths.add(f.getAbsolutePath());
+ }
+ }
+
+ /**
+ * Get the list of feature files.
+ * @return The array of names.
+ * @throws IOException
+ */
+ public String[] getFeatureFiles() throws IOException {
+ if ( this.featureFiles == null ) {
+ // Default value - check feature directory otherwise features file
+ final File dir = new File(getHomeDirectory(), "features");
+ if ( dir.exists() && dir.isDirectory() ) {
+ this.featureFiles = new String[] {"features"};
+ } else {
+ this.featureFiles = new String[] {new
File("feature.txt").getAbsolutePath()};
+ }
+ }
+ final List<String> paths = new ArrayList<>();
+ for(final String name : this.featureFiles) {
+ // check for absolute
+ if ( name.indexOf(':') > 0 ) {
+ paths.add(name);
+ } else {
+ // relative
+ final File f = new File(name);
+ if ( f.exists() ) {
+ if ( f.isFile() ) {
+ this.processFile(paths, f);
+ } else {
+ this.processDir(paths, f);
+ }
+ } else if ( !f.exists() ) {
+ final File check = new File(getHomeDirectory(), "features"
+ File.separatorChar + name);
+ if ( check.exists() && !check.getName().startsWith(".") ) {
+ if ( check.isFile() ) {
+ this.processFile(paths, check);
+ } else {
+ this.processDir(paths, check);
+ }
+ }
+ }
+ }
+ }
+
+ Collections.sort(paths, FEATURE_PATH_COMP);
+ return paths.toArray(new String[paths.size()]);
+ }
+
+
+ /**
+ * Get the home directory.
+ * @return The home directory.
+ */
+ public File getHomeDirectory() {
+ return new File(HOME);
+ }
+
+ /**
+ * Get the cache directory
+ * @return The cache directory.
+ */
+ @Override
+ public File getCacheDirectory() {
+ final File dir = new File(CACHE_DIR);
+ if ( dir.isAbsolute() ) {
+ return dir;
+ }
+ return new File(getHomeDirectory(), CACHE_DIR);
+ }
+
+ /**
+ * Get the startup mode.
+ *
+ * @return The current startup mode.
+ */
+ public StartupMode getStartupMode() {
+ return this.startupMode;
+ }
+
+ /**
+ * Sets the startup mode to {@link StartupMode#INSTALLER}.
+ */
+ public void setUseInstaller() {
+ this.startupMode = StartupMode.INSTALLER;
+ }
+
+ public Installation getInstallation() {
+ return this.installation;
+ }
+
+ /**
+ * Clear all in-memory objects
+ */
+ public void clear() {
+ this.installation.clear();
+ }
+
+ @Override
+ public void incCachedArtifacts() {
+ this.cachedArtifacts++;
+ }
+
+ @Override
+ public void incDownloadedArtifacts() {
+ this.downloadedArtifacts++;
+ }
+
+ @Override
+ public void incLocalArtifacts() {
+ this.localArtifacts++;
+ }
+
+ public long getCachedArtifacts() {
+ return this.cachedArtifacts;
+ }
+
+ public long getDownloadedArtifacts() {
+ return this.downloadedArtifacts;
+ }
+
+ public long getLocalArtifacts() {
+ return this.localArtifacts;
+ }
+}
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Added:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/Main.java?rev=1797026&view=auto
==============================================================================
---
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
(added)
+++
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
Wed May 31 12:29:12 2017
@@ -0,0 +1,315 @@
+/*
+ * 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.feature.launcher.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.cli.BasicParser;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.sling.feature.Application;
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.launcher.api.Logger;
+import org.apache.sling.feature.launcher.impl.artifacts.ArtifactHandler;
+import org.apache.sling.feature.launcher.impl.artifacts.ArtifactManager;
+import org.apache.sling.feature.launcher.impl.launchers.FrameworkLauncher;
+import org.apache.sling.feature.launcher.spi.Launcher;
+import org.apache.sling.feature.launcher.spi.LauncherPrepareContext;
+
+/**
+ * This is the launcher main class.
+ * It parses command line parameters and prepares the launcher.
+ */
+public class Main {
+
+ /** Split a string into key and value */
+ private static String[] split(final String val) {
+ final int pos = val.indexOf('=');
+ if ( pos == -1 ) {
+ return new String[] {val, "true"};
+ }
+ return new String[] {val.substring(0, pos), val.substring(pos + 1)};
+ }
+
+ /**
+ * Parse the command line parameters and update a configuration object.
+ * @param args Command line parameters
+ * @return Configuration object.
+ */
+ private static void parseArgs(final LauncherConfig config, final String[]
args) {
+ Logger.LOG.log("Assembling configuration...");
+ final Options options = new Options();
+
+ final Option repoOption = new Option("u", true, "Set repository url");
+ final Option modelOption = new Option("f", true, "Set feature
files/directories");
+ final Option fwkProperties = new Option("D", true, "Set framework
properties");
+ fwkProperties.setArgs(20);
+ final Option debugOption = new Option("v", true, "Verbose");
+ debugOption.setArgs(0);
+ final Option installerOption = new Option("I", true, "Use OSGi
installer for additional artifacts.");
+ installerOption.setArgs(0);
+ options.addOption(repoOption);
+ options.addOption(modelOption);
+ options.addOption(fwkProperties);
+ options.addOption(debugOption);
+ options.addOption(installerOption);
+
+ final CommandLineParser clp = new BasicParser();
+ try {
+ final CommandLine cl = clp.parse(options, args);
+
+ if ( cl.hasOption(repoOption.getOpt()) ) {
+ final String value = cl.getOptionValue(repoOption.getOpt());
+ config.setRepositoryUrls(value.split(","));
+ }
+ if ( cl.hasOption(modelOption.getOpt()) ) {
+ final String value = cl.getOptionValue(modelOption.getOpt());
+ config.setFeatureFiles(value.split(","));
+ }
+ if ( cl.hasOption(fwkProperties.getOpt()) ) {
+ for(final String value :
cl.getOptionValues(fwkProperties.getOpt())) {
+ final String[] keyVal = split(value);
+
+
config.getInstallation().getFrameworkProperties().put(keyVal[0], keyVal[1]);
+ }
+ }
+ if ( cl.hasOption(debugOption.getOpt()) ) {
+ Logger.LOG.setDebug(true);
+ }
+ if ( cl.hasOption(installerOption.getOpt()) ) {
+ config.setUseInstaller();
+ }
+ } catch ( final ParseException pe) {
+ Logger.LOG.error("Unable to parse command line: {0}", pe,
pe.getMessage());
+ System.exit(1);
+ }
+ }
+
+ public static void main(final String[] args) {
+ Logger.LOG.log("");
+ Logger.LOG.log("Apache Sling Application Launcher");
+ Logger.LOG.log("---------------------------------");
+
+ // check if launcher has already been created
+ final LauncherConfig launcherConfig = new LauncherConfig();
+ parseArgs(launcherConfig, args);
+
+ ArtifactManager artifactManager = null;
+ try {
+
+ Logger.LOG.log("Initializing...");
+ try {
+ artifactManager =
ArtifactManager.getArtifactManager(launcherConfig);
+ } catch ( final IOException ioe) {
+ Logger.LOG.error("Unable to setup artifact manager: {0}", ioe,
ioe.getMessage());
+ System.exit(1);
+ }
+ Logger.LOG.log("Artifact Repositories: {0}",
Arrays.toString(launcherConfig.getRepositoryUrls()));
+ Logger.LOG.log("Assembling provisioning model...");
+
+ try {
+ final Launcher launcher = new FrameworkLauncher();
+ final Application app =
FeatureProcessor.createApplication(launcherConfig, artifactManager);
+
+ Logger.LOG.log("");
+ Logger.LOG.log("Assembling launcher...");
+ final ArtifactManager aMgr = artifactManager;
+ final LauncherPrepareContext ctx = new
LauncherPrepareContext() {
+
+ @Override
+ public File getArtifactFile(final ArtifactId artifact)
throws IOException {
+ final ArtifactHandler handler =
aMgr.getArtifactHandler(":" + artifact.toMvnPath());
+ return handler.getArtifact();
+ }
+
+ @Override
+ public void addAppJar(final File jar) {
+ launcherConfig.getInstallation().addAppJar(jar);
+ }
+ };
+ launcher.prepare(ctx, app);
+
+ FeatureProcessor.prepareLauncher(launcherConfig,
artifactManager, app);
+
+ } catch ( final Exception iae) {
+ Logger.LOG.error("Error while assembling launcher: {0}", iae,
iae.getMessage());
+ System.exit(1);
+ }
+
+ Logger.LOG.log("Using {0} local artifacts, {1} cached artifacts,
and {2} downloaded artifacts",
+ launcherConfig.getLocalArtifacts(),
launcherConfig.getCachedArtifacts(), launcherConfig.getDownloadedArtifacts());
+ } finally {
+ if ( artifactManager != null ) {
+ artifactManager.shutdown();
+ }
+ }
+
+ try {
+ run(launcherConfig);
+ } catch ( final Exception iae) {
+ Logger.LOG.error("Error while running launcher: {0}", iae,
iae.getMessage());
+ System.exit(1);
+ }
+ }
+
+ private static final String STORAGE_PROPERTY =
"org.osgi.framework.storage";
+
+ private static final String START_LEVEL_PROP =
"org.osgi.framework.startlevel.beginning";
+
+ /**
+ * Run launcher.
+ * @param config The configuration
+ * @throws Exception If anything goes wrong
+ */
+ private static void run(final LauncherConfig config) throws Exception {
+ Logger.LOG.log("");
+ Logger.LOG.log("Starting launcher...");
+ Logger.LOG.log("Launcher Home: {0}",
config.getHomeDirectory().getAbsolutePath());
+ Logger.LOG.log("Cache Directory: {0}",
config.getCacheDirectory().getAbsolutePath());
+ Logger.LOG.log("Startup Mode: {0}", config.getStartupMode());
+ Logger.LOG.log("");
+
+ final Installation installation = config.getInstallation();
+
+ // set sling home, and use separate locations for launchpad and
properties
+ installation.getFrameworkProperties().put("sling.home",
config.getHomeDirectory().getAbsolutePath());
+ installation.getFrameworkProperties().put("sling.launchpad",
config.getHomeDirectory().getAbsolutePath() + "/launchpad");
+ installation.getFrameworkProperties().put("sling.properties",
"conf/sling.properties");
+
+
+ // additional OSGi properties
+ // move storage inside launcher
+ if ( installation.getFrameworkProperties().get(STORAGE_PROPERTY) ==
null ) {
+ installation.getFrameworkProperties().put(STORAGE_PROPERTY,
config.getHomeDirectory().getAbsolutePath() + File.separatorChar + "framework");
+ }
+ // set start level to 30
+ if ( installation.getFrameworkProperties().get(START_LEVEL_PROP) ==
null ) {
+ installation.getFrameworkProperties().put(START_LEVEL_PROP, "30");
+ }
+
+ if ( Logger.LOG.isDebugEnabled() ) {
+ Logger.LOG.debug("Bundles:");
+ for(final Integer key : installation.getBundleMap().keySet()) {
+ Logger.LOG.debug("-- Start Level {0}", key);
+ for(final File f : installation.getBundleMap().get(key)) {
+ Logger.LOG.debug(" - {0}", f.getName());
+ }
+ }
+ Logger.LOG.debug("Settings: ");
+ for(final Map.Entry<String, String> entry :
installation.getFrameworkProperties().entrySet()) {
+ Logger.LOG.debug("- {0}={1}", entry.getKey(),
entry.getValue());
+ }
+ Logger.LOG.debug("Configurations: ");
+ for(final Object[] entry : installation.getConfigurations()) {
+ if ( entry[1] != null ) {
+ Logger.LOG.debug("- Factory {0} - {1}", entry[1],
entry[0]);
+ } else {
+ Logger.LOG.debug("- {0}", entry[0]);
+ }
+ }
+ Logger.LOG.debug("");
+ }
+
+ final Launcher launcher = new FrameworkLauncher();
+ launcher.run(installation, createClassLoader(installation));
+
+ config.clear();
+ }
+
+ /**
+ * Create the class loader.
+ * @param installation The launcher configuration
+ * @throws Exception If anything goes wrong
+ */
+ public static ClassLoader createClassLoader(final Installation
installation) throws Exception {
+ final List<URL> list = new ArrayList<>();
+ for(final File f : installation.getAppJars()) {
+ try {
+ list.add(f.toURI().toURL());
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+
list.add(Main.class.getProtectionDomain().getCodeSource().getLocation());
+
+ final URL[] urls = list.toArray(new URL[list.size()]);
+
+ if ( Logger.LOG.isDebugEnabled() ) {
+ Logger.LOG.debug("App classpath: ");
+ for (int i = 0; i < urls.length; i++) {
+ Logger.LOG.debug(" - {0}", urls[i]);
+ }
+ }
+
+ // create a paranoid class loader, loading from parent last
+ final ClassLoader cl = new URLClassLoader(urls) {
+ @Override
+ public final Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException {
+ // First check if it's already loaded
+ Class<?> clazz = findLoadedClass(name);
+
+ if (clazz == null) {
+
+ try {
+ clazz = findClass(name);
+ } catch (ClassNotFoundException cnfe) {
+ ClassLoader parent = getParent();
+ if (parent != null) {
+ // Ask to parent ClassLoader (can also throw a
CNFE).
+ clazz = parent.loadClass(name);
+ } else {
+ // Propagate exception
+ throw cnfe;
+ }
+ }
+ }
+
+ if (resolve) {
+ resolveClass(clazz);
+ }
+
+ return clazz;
+ }
+
+ @Override
+ public final URL getResource(final String name) {
+
+ URL resource = findResource(name);
+ ClassLoader parent = this.getParent();
+ if (resource == null && parent != null) {
+ resource = parent.getResource(name);
+ }
+
+ return resource;
+ }
+ };
+
+ Thread.currentThread().setContextClassLoader(cl);
+
+ return cl;
+ }
+}
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/Main.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Added:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/artifacts/ArtifactHandler.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/artifacts/ArtifactHandler.java?rev=1797026&view=auto
==============================================================================
---
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/artifacts/ArtifactHandler.java
(added)
+++
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/artifacts/ArtifactHandler.java
Wed May 31 12:29:12 2017
@@ -0,0 +1,42 @@
+/*
+ * 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.feature.launcher.impl.artifacts;
+
+import java.io.File;
+
+/**
+ * A handler provides a file object for an artifact.
+ */
+public class ArtifactHandler {
+
+ private final String url;
+
+ private final File file;
+
+ public ArtifactHandler(final String url, final File file) {
+ this.url = url;
+ this.file = file;
+ }
+
+ public String getArtifactUrl() {
+ return url;
+ }
+
+ public File getArtifact() {
+ return file;
+ }
+}
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/artifacts/ArtifactHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/artifacts/ArtifactHandler.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Added:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/artifacts/ArtifactManager.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/artifacts/ArtifactManager.java?rev=1797026&view=auto
==============================================================================
---
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/artifacts/ArtifactManager.java
(added)
+++
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/artifacts/ArtifactManager.java
Wed May 31 12:29:12 2017
@@ -0,0 +1,362 @@
+/*
+ * 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.feature.launcher.impl.artifacts;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.launcher.api.Logger;
+import org.apache.sling.feature.launcher.impl.LauncherConfig;
+import org.apache.sling.feature.launcher.spi.ArtifactProvider;
+import org.apache.sling.feature.launcher.spi.ArtifactProviderContext;
+
+/**
+ * The artifact manager is the central service to get artifacts.
+ * It uses {@link ArtifactProvider}s to get artifacts. The
+ * providers are loaded using the service loader.
+ */
+public class ArtifactManager {
+
+ /** The map of providers. */
+ private final Map<String, ArtifactProvider> providers;
+
+ /** The repository urls. */
+ private final String[] repositoryURLs;
+
+ /**
+ * Get an artifact manager based on the configuration
+ * @param config The configuration
+ * @return The artifact manager
+ * @throws IOException If the manager can't be initialized
+ */
+ public static ArtifactManager getArtifactManager(final LauncherConfig
config) throws IOException {
+ final ServiceLoader<ArtifactProvider> loader =
ServiceLoader.load(ArtifactProvider.class);
+ final Map<String, ArtifactProvider> providers = new HashMap<>();
+ for(final ArtifactProvider provider : loader) {
+ providers.put(provider.getProtocol(), provider);
+ }
+
+ final String[] repositoryURLs = new
String[config.getRepositoryUrls().length];
+ int index = 0;
+ for(final String urlString : config.getRepositoryUrls()) {
+ repositoryURLs[index] = urlString;
+ index++;
+ }
+ // default
+ if ( !providers.containsKey("*") ) {
+ providers.put("*", new DefaultArtifactHandler());
+ }
+
+ return new ArtifactManager(config, repositoryURLs, providers);
+ }
+
+ ArtifactManager(final LauncherConfig config, final String[] repoUrls,
final Map<String, ArtifactProvider> providers)
+ throws IOException {
+ this.repositoryURLs = repoUrls;
+ this.providers = providers;
+ try {
+ for(final ArtifactProvider provider : this.providers.values()) {
+ provider.init(config);
+ }
+ } catch ( final IOException io) {
+ shutdown();
+ throw io;
+ }
+ }
+
+ /**
+ * Shutdown the artifact manager.
+ */
+ public void shutdown() {
+ for(final ArtifactProvider provider : this.providers.values()) {
+ provider.shutdown();
+ }
+ this.providers.clear();
+ }
+
+ private final File getArtifactFromProviders(final String url, final String
relativeCachePath) throws IOException {
+ final int pos = url.indexOf(":");
+ final String scheme = url.substring(0, pos);
+
+ ArtifactProvider provider = this.providers.get(scheme);
+ if ( provider == null ) {
+ provider = this.providers.get("*");
+ }
+ if ( provider == null ) {
+ throw new IOException("No URL provider found for " + url);
+ }
+ return provider.getArtifact(url, relativeCachePath);
+ }
+
+ /**
+ * Get the full artifact url for an artifact.
+ * @param url Artifact url or relative path.
+ * @return Absolute url.
+ * @throws IOException If something goes wrong.
+ */
+ public ArtifactHandler getArtifactHandler(final String url) throws
IOException {
+ Logger.LOG.debug("Trying to get artifact for " + url);
+
+ final String path;
+
+ if ( url.startsWith("mvn:") ) {
+ // mvn url
+ path = ArtifactId.fromMvnUrl(url).toMvnPath();
+
+ } else if ( url.startsWith(":") ) {
+ // repository path
+ path = url.substring(1);
+
+ } else if ( url.indexOf(":/") > 0 ) {
+
+ // absolute URL
+ int pos = url.indexOf(":/") + 2;
+ while ( url.charAt(pos) == '/') {
+ pos++;
+ }
+ final File file = this.getArtifactFromProviders(url,
url.substring(pos));
+ if ( file == null || !file.exists()) {
+ throw new IOException("Artifact " + url + " not found.");
+ }
+ return new ArtifactHandler(url, file);
+
+ } else {
+ // file (either relative or absolute)
+ final File f = new File(url);
+ if ( !f.exists()) {
+ throw new IOException("Artifact " + url + " not found.");
+ }
+ return new ArtifactHandler(f.toURI().toString(), f);
+ }
+ Logger.LOG.debug("Querying repositories for " + path);
+
+ for(final String repoUrl : this.repositoryURLs) {
+ final StringBuilder builder = new StringBuilder();
+ builder.append(repoUrl);
+ builder.append('/');
+ builder.append(path);
+
+ final String artifactUrl = builder.toString();
+ final int pos = artifactUrl.indexOf(":");
+ final String scheme = artifactUrl.substring(0, pos);
+
+ ArtifactProvider handler = this.providers.get(scheme);
+ if ( handler == null ) {
+ handler = this.providers.get("*");
+ }
+ if ( handler == null ) {
+ throw new IOException("No URL handler found for " +
artifactUrl);
+ }
+
+ Logger.LOG.debug("Checking " + handler + " to get artifact from "
+ artifactUrl);
+
+ final File file = handler.getArtifact(artifactUrl, path);
+ if ( file != null ) {
+ Logger.LOG.debug("Found artifact " + artifactUrl);
+ return new ArtifactHandler(artifactUrl, file);
+ }
+
+ // check for SNAPSHOT
+ final int lastSlash = artifactUrl.lastIndexOf('/');
+ final int startSnapshot = artifactUrl.indexOf("-SNAPSHOT",
lastSlash + 1);
+
+ if ( startSnapshot > -1 ) {
+ // special snapshot handling
+ final String metadataUrl = artifactUrl.substring(0, lastSlash)
+ "/maven-metadata.xml";
+ try {
+ final ArtifactHandler metadataHandler =
this.getArtifactHandler(metadataUrl);
+
+ final String contents = getFileContents(metadataHandler);
+
+ final String latestVersion = getLatestSnapshot(contents);
+ if ( latestVersion != null ) {
+ final String name = artifactUrl.substring(lastSlash);
// includes slash
+ final String fullURL = artifactUrl.substring(0,
lastSlash) + name.replace("SNAPSHOT", latestVersion);
+ int pos2 = fullURL.indexOf(":/") + 2;
+ while ( fullURL.charAt(pos2) == '/') {
+ pos2++;
+ }
+ final File file2 =
this.getArtifactFromProviders(fullURL, path);
+ if ( file2 == null || !file2.exists()) {
+ throw new IOException("Artifact " + fullURL + "
not found.");
+ }
+ return new ArtifactHandler(artifactUrl, file2);
+ }
+ } catch ( final IOException ignore ) {
+ // we ignore this but report the original 404
+ }
+ }
+ }
+
+ throw new IOException("Artifact " + url + " not found in any
repository.");
+ }
+
+ protected String getFileContents(final ArtifactHandler handler) throws
IOException {
+ final StringBuilder sb = new StringBuilder();
+ for(final String line :
Files.readAllLines(handler.getArtifact().toPath())) {
+ sb.append(line).append('\n');
+ }
+
+ return sb.toString();
+ }
+
+ public static String getValue(final String xml, final String[] xpath) {
+ String value = null;
+ int pos = 0;
+ for(final String name : xpath) {
+ final String element = '<' + name + '>';
+
+ pos = xml.indexOf(element, pos);
+ if ( pos == -1 ) {
+ final String elementWithAttributes = '<' + name + ' ';
+ pos = xml.indexOf(elementWithAttributes, pos);
+ if ( pos == -1 ) {
+ break;
+ }
+ }
+ pos = xml.indexOf('>', pos) + 1;
+ }
+ if ( pos != -1 ) {
+ final int endPos = xml.indexOf("</", pos);
+ if ( endPos != -1 ) {
+ value = xml.substring(pos, endPos).trim();
+ }
+ }
+ return value;
+ }
+ public static String getLatestSnapshot(final String mavenMetadata) {
+ final String timestamp = getValue(mavenMetadata, new String[]
{"metadata", "versioning", "snapshot", "timestamp"});
+ final String buildNumber = getValue(mavenMetadata, new String[]
{"metadata", "versioning", "snapshot", "buildNumber"});
+
+ if ( timestamp != null && buildNumber != null ) {
+ return timestamp + '-' + buildNumber;
+ }
+
+ return null;
+ }
+
+ private static final class DefaultArtifactHandler implements
ArtifactProvider {
+
+ private volatile File cacheDir;
+
+ private volatile ArtifactProviderContext config;
+
+ @Override
+ public String getProtocol() {
+ return "*";
+ }
+
+ @Override
+ public void init(final ArtifactProviderContext config) throws
IOException {
+ this.cacheDir = config.getCacheDirectory();
+ this.config = config;
+ }
+
+ @Override
+ public void shutdown() {
+ this.config = null;
+ this.cacheDir = null;
+ }
+
+ @Override
+ public File getArtifact(final String url, final String
relativeCachePath) {
+ Logger.LOG.debug("Checking url to be local file " + url);
+ // check if this is already a local file
+ try {
+ final File f = new File(new URL(url).toURI());
+ if ( f.exists() ) {
+ this.config.incLocalArtifacts();
+ return f;
+ }
+ return null;
+ } catch ( final URISyntaxException ise) {
+ // ignore
+ } catch ( final IllegalArgumentException iae) {
+ // ignore
+ } catch ( final MalformedURLException mue) {
+ // ignore
+ }
+ Logger.LOG.debug("Checking remote url " + url);
+ try {
+ // check for url
+ if ( url.indexOf(":") == -1 ) {
+ return null;
+ }
+
+ final String filePath = (this.cacheDir.getAbsolutePath() +
File.separatorChar + relativeCachePath).replace('/', File.separatorChar);
+ final File cacheFile = new File(filePath);
+
+ if ( !cacheFile.exists() ) {
+ cacheFile.getParentFile().mkdirs();
+ final URL u = new URL(url);
+ final URLConnection con = u.openConnection();
+ con.connect();
+
+ final InputStream readIS = con.getInputStream();
+ final byte[] buffer = new byte[32768];
+ int l;
+ OutputStream os = null;
+ try {
+ os = new FileOutputStream(cacheFile);
+ while ( (l = readIS.read(buffer)) >= 0 ) {
+ os.write(buffer, 0, l);
+ }
+ } finally {
+ try {
+ readIS.close();
+ } catch ( final IOException ignore) {
+ // ignore
+ }
+ if ( os != null ) {
+ try {
+ os.close();
+ } catch ( final IOException ignore ) {
+ // ignore
+
+ }
+ }
+ }
+ this.config.incDownloadedArtifacts();
+ } else {
+ this.config.incCachedArtifacts();
+ }
+ return cacheFile;
+ } catch ( final Exception e) {
+ e.printStackTrace();
+ // ignore for now
+ return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "DefaultArtifactHandler";
+ }
+ }
+}
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/artifacts/ArtifactManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/artifacts/ArtifactManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Added:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java?rev=1797026&view=auto
==============================================================================
---
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java
(added)
+++
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java
Wed May 31 12:29:12 2017
@@ -0,0 +1,278 @@
+/*
+ * 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.feature.launcher.impl.launchers;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sling.feature.launcher.api.Logger;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.startlevel.BundleStartLevel;
+import org.osgi.framework.wiring.FrameworkWiring;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+/**
+ * Common functionality for the framework start.
+ */
+public class AbstractRunner {
+
+ private volatile ServiceTracker<Object, Object> configAdminTracker;
+
+ private volatile ServiceTracker<Object, Object> installerTracker;
+
+ private final List<Object[]> configurations;
+
+ private final List<File> installables;
+
+ public AbstractRunner(final List<Object[]> configurations, final
List<File> installables) {
+ this.configurations = new ArrayList<>(configurations);
+ this.installables = installables;
+ }
+
+ protected void setupFramework(final Framework framework, final
Map<Integer, List<File>> bundlesMap)
+ throws BundleException {
+ if ( !configurations.isEmpty() ) {
+ this.configAdminTracker = new
ServiceTracker<>(framework.getBundleContext(),
+ "org.osgi.service.cm.ConfigurationAdmin",
+ new ServiceTrackerCustomizer<Object, Object>() {
+
+ @Override
+ public Object addingService(final
ServiceReference<Object> reference) {
+ // get config admin
+ final Object cm =
framework.getBundleContext().getService(reference);
+ if ( cm != null ) {
+ try {
+ configure(cm);
+ } finally {
+
framework.getBundleContext().ungetService(reference);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<Object>
reference, Object service) {
+ // nothing to do
+ }
+
+ @Override
+ public void removedService(ServiceReference<Object>
reference, Object service) {
+ // nothing to do
+ }
+ });
+ this.configAdminTracker.open();
+ }
+ if ( installables != null && !installables.isEmpty() ) {
+ this.installerTracker = new
ServiceTracker<>(framework.getBundleContext(),
+ "org.apache.sling.installer.api.OsgiInstaller",
+ new ServiceTrackerCustomizer<Object, Object>() {
+
+ @Override
+ public Object addingService(final
ServiceReference<Object> reference) {
+ // get installer
+ final Object installer =
framework.getBundleContext().getService(reference);
+ if ( installer != null ) {
+ try {
+ install(installer);
+ } finally {
+
framework.getBundleContext().ungetService(reference);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<Object>
reference, Object service) {
+ // nothing to do
+ }
+
+ @Override
+ public void removedService(ServiceReference<Object>
reference, Object service) {
+ // nothing to do
+ }
+ });
+ this.installerTracker.open();
+ }
+ try {
+ this.install(framework, bundlesMap);
+ } catch ( final IOException ioe) {
+ throw new BundleException("Unable to install bundles.", ioe);
+ }
+ }
+
+ private void configure(final Object configAdmin) {
+ try {
+ final Method createConfig =
configAdmin.getClass().getDeclaredMethod("getConfiguration", String.class,
String.class);
+ final Method createFactoryConfig =
configAdmin.getClass().getDeclaredMethod("getFactoryConfiguration",
String.class, String.class, String.class);
+
+ Method updateMethod = null;
+ for(final Object[] obj : this.configurations) {
+ final Object cfg;
+ if ( obj[1] != null ) {
+ cfg = createFactoryConfig.invoke(configAdmin, obj[1],
obj[0], null);
+ } else {
+ cfg = createConfig.invoke(configAdmin, obj[0], null);
+ }
+ if ( updateMethod == null ) {
+ updateMethod = cfg.getClass().getDeclaredMethod("update",
Dictionary.class);
+ }
+ updateMethod.invoke(cfg, obj[2]);
+ }
+ } catch ( final Exception e) {
+ Logger.LOG.error("Unable to create configurations", e);
+ throw new RuntimeException(e);
+ }
+ final Thread t = new Thread(() -> { configAdminTracker.close();
configAdminTracker = null; });
+ t.setDaemon(false);
+ t.start();
+ this.configurations.clear();
+ }
+
+ private boolean isSystemBundleFragment(final Bundle installedBundle) {
+ final String fragmentHeader = getFragmentHostHeader(installedBundle);
+ return fragmentHeader != null
+ && fragmentHeader.indexOf(Constants.EXTENSION_DIRECTIVE) > 0;
+ }
+
+ /**
+ * Gets the bundle's Fragment-Host header.
+ */
+ private String getFragmentHostHeader(final Bundle b) {
+ return b.getHeaders().get( Constants.FRAGMENT_HOST );
+ }
+
+ /**
+ * Install the bundles
+ * @param bundleMap The map with the bundles indexed by start level
+ * @throws IOException, BundleException If anything goes wrong.
+ */
+ private void install(final Framework framework, final Map<Integer,
List<File>> bundleMap)
+ throws IOException, BundleException {
+ final BundleContext bc = framework.getBundleContext();
+ int defaultStartLevel = getProperty(bc, "felix.startlevel.bundle", 1);
+ for(final Integer startLevel : sortStartLevels(bundleMap.keySet(),
defaultStartLevel)) {
+ Logger.LOG.debug("Installing bundles with start level {0}",
startLevel);
+
+ for(final File file : bundleMap.get(startLevel)) {
+ Logger.LOG.debug("- {0}", file.getName());
+
+ // use reference protocol. This avoids copying the binary to
the cache directory
+ // of the framework
+ final Bundle bundle = bc.installBundle("reference:" +
file.toURI().toURL(), null);
+ if ( startLevel > 0 ) {
+
bundle.adapt(BundleStartLevel.class).setStartLevel(startLevel);
+ }
+
+ // fragment?
+ if ( !isSystemBundleFragment(bundle) ) {
+ final String fragmentHostHeader =
getFragmentHostHeader(bundle);
+ if (fragmentHostHeader != null) {
+ for (final Bundle b : bc.getBundles()) {
+ if
(fragmentHostHeader.equals(b.getSymbolicName())) {
+ final FrameworkWiring fw =
framework.adapt(FrameworkWiring.class);
+ fw.refreshBundles(Collections.singleton(b));
+ break;
+ }
+ }
+
+ } else {
+ bundle.start();
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Sort the start levels in the ascending order. The only exception is the
start level
+ * "0", which should be put at the position configured in {@code
felix.startlevel.bundle}.
+ *
+ * @param startLevels integer start levels
+ * @return sorted start levels
+ */
+ private static Iterable<Integer> sortStartLevels(final Collection<Integer>
startLevels, final int defaultStartLevel) {
+ final List<Integer> result = new ArrayList<>(startLevels);
+ Collections.sort(result, (o1, o2) -> {
+ int i1 = o1 == 0 ? defaultStartLevel : o1;
+ int i2 = o2 == 0 ? defaultStartLevel : o2;
+ return Integer.compare(i1, i2);
+ });
+ return result;
+ }
+
+ private static int getProperty(BundleContext bc, String propName, int
defaultValue) {
+ String val = bc.getProperty(propName);
+ if (val == null) {
+ return defaultValue;
+ } else {
+ return Integer.parseInt(val);
+ }
+ }
+
+ private void install(final Object installer) {
+ try {
+ final Class<?> installableResourceClass =
installer.getClass().getClassLoader().loadClass("org.apache.sling.installer.api.InstallableResource");
+ final Object resources =
Array.newInstance(installableResourceClass, this.installables.size());
+ final Method registerResources =
installer.getClass().getDeclaredMethod("registerResources", String.class,
resources.getClass());
+ final Constructor<?> constructor =
installableResourceClass.getDeclaredConstructor(String.class,
+ InputStream.class,
+ Dictionary.class,
+ String.class,
+ String.class,
+ Integer.class);
+
+ for(int i=0; i<this.installables.size();i++) {
+ final File f = this.installables.get(i);
+ final Dictionary<String, Object> dict = new Hashtable<>();
+ dict.put("resource.uri.hint", f.toURI().toString());
+ final Object rsrc =
constructor.newInstance(f.getAbsolutePath(),
+ new FileInputStream(f),
+ dict,
+ f.getName(),
+ "file",
+ null);
+ Array.set(resources, i, rsrc);
+ }
+ registerResources.invoke(installer, "cloudlauncher", resources);
+ } catch ( final Exception e) {
+ Logger.LOG.error("Unable to contact installer and install
additional artifacts", e);
+ throw new RuntimeException(e);
+ }
+ final Thread t = new Thread(() -> { installerTracker.close();
installerTracker = null; });
+ t.setDaemon(false);
+ t.start();
+ this.installables.clear();
+ }
+}
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Added:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java?rev=1797026&view=auto
==============================================================================
---
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
(added)
+++
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
Wed May 31 12:29:12 2017
@@ -0,0 +1,75 @@
+/*
+ * 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.feature.launcher.impl.launchers;
+
+import java.lang.reflect.Constructor;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sling.feature.Application;
+import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.ExtensionType;
+import org.apache.sling.feature.launcher.spi.Launcher;
+import org.apache.sling.feature.launcher.spi.LauncherPrepareContext;
+import org.apache.sling.feature.launcher.spi.LauncherRunContext;
+
+/**
+ * Launcher directly using the OSGi launcher API.
+ */
+public class FrameworkLauncher implements Launcher {
+
+ private static final String EXT_NAME = "framework";
+
+ @Override
+ public void prepare(final LauncherPrepareContext context, final
Application app) throws Exception {
+ // search for framework extension
+ Extension fwk = null;
+ for(final Extension e : app.getExtensions()) {
+ if ( e.getName().equals(EXT_NAME) ) {
+ fwk = e;
+ }
+ }
+ if ( fwk == null ) {
+ throw new Exception("No " + EXT_NAME + " extension for framework
found.");
+ }
+ if ( fwk.getType() != ExtensionType.ARTIFACTS ) {
+ throw new Exception("Extension " + EXT_NAME + " is of wrong type:
" + fwk.getType());
+ }
+ if ( fwk.getArtifacts().size() != 1 ) {
+ throw new Exception("Extension " + EXT_NAME + " must have exactly
one artifact: " + fwk.getArtifacts().size());
+ }
+ // add the framework to the classpath
+
context.addAppJar(context.getArtifactFile(fwk.getArtifacts().get(0).getId()));
+ }
+
+ /**
+ * Run the launcher
+ * @throws If anything goes wrong
+ */
+ @Override
+ public void run(final LauncherRunContext context, final ClassLoader cl)
throws Exception {
+ final Class<?> runnerClass =
cl.loadClass(this.getClass().getPackage().getName() + ".FrameworkRunner");
+ final Constructor<?> constructor =
runnerClass.getDeclaredConstructor(Map.class, Map.class, List.class,
List.class);
+ constructor.setAccessible(true);
+ constructor.newInstance(context.getFrameworkProperties(),
+ context.getBundleMap(),
+ context.getConfigurations(),
+ context.getInstallableArtifacts());
+
+ // nothing else to do, constructor starts everything
+ }
+}
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/whiteboard/cziegeler/feature-launcher/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url