You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2020/04/24 12:24:29 UTC
[sling-org-apache-sling-feature-io] branch master updated:
Deprecate module, all contents has been merged into org.apache.sling.feature
This is an automated email from the ASF dual-hosted git repository.
cziegeler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-io.git
The following commit(s) were added to refs/heads/master by this push:
new 2d9fdc8 Deprecate module, all contents has been merged into org.apache.sling.feature
2d9fdc8 is described below
commit 2d9fdc8818ba91ad358b3636fc3933707d7c6718
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Fri Apr 24 14:24:14 2020 +0200
Deprecate module, all contents has been merged into org.apache.sling.feature
---
.asf.yaml | 6 +
Jenkinsfile | 20 -
bnd.bnd | 3 -
design/feature-model.json | 123 ----
pom.xml | 169 -----
readme.md | 9 +-
.../apache/sling/feature/io/CloseShieldWriter.java | 43 --
.../apache/sling/feature/io/ConfiguratorUtil.java | 80 ---
.../java/org/apache/sling/feature/io/IOUtils.java | 300 ---------
.../sling/feature/io/archive/ArchiveReader.java | 180 ------
.../sling/feature/io/archive/ArchiveWriter.java | 191 ------
.../sling/feature/io/archive/package-info.java | 23 -
.../feature/io/artifacts/ArtifactHandler.java | 71 --
.../feature/io/artifacts/ArtifactManager.java | 527 ---------------
.../io/artifacts/ArtifactManagerConfig.java | 183 ------
.../sling/feature/io/artifacts/package-info.java | 23 -
.../feature/io/artifacts/spi/ArtifactProvider.java | 58 --
.../io/artifacts/spi/ArtifactProviderContext.java | 49 --
.../feature/io/artifacts/spi/package-info.java | 23 -
.../feature/io/json/ConfigurationJSONReader.java | 73 ---
.../feature/io/json/ConfigurationJSONWriter.java | 69 --
.../sling/feature/io/json/FeatureJSONReader.java | 716 ---------------------
.../sling/feature/io/json/FeatureJSONWriter.java | 415 ------------
.../sling/feature/io/json/JSONConstants.java | 85 ---
.../sling/feature/io/json/ManifestUtils.java | 518 ---------------
.../apache/sling/feature/io/json/package-info.java | 23 -
.../org/apache/sling/feature/io/package-info.java | 23 -
.../META-INF/feature/Feature-1.0.0.schema.json | 226 -------
.../sling/feature/io/ConfiguratorUtilTest.java | 126 ----
.../org/apache/sling/feature/io/IOUtilsTest.java | 170 -----
.../feature/io/archive/ArchiveWriterTest.java | 120 ----
.../feature/io/artifacts/ArtifactManagerTest.java | 96 ---
.../sling/feature/io/json/ArtifactsExtensions.java | 57 --
.../feature/io/json/FeatureJSONReaderTest.java | 116 ----
.../feature/io/json/FeatureJSONWriterTest.java | 135 ----
.../java/org/apache/sling/feature/io/json/U.java | 73 ---
.../resources/features/artifacts-extension.json | 9 -
src/test/resources/features/complete.json | 4 -
src/test/resources/features/feature-model.json | 123 ----
src/test/resources/features/final.json | 5 -
src/test/resources/features/repoinit.json | 4 -
src/test/resources/features/repoinit2.json | 7 -
src/test/resources/features/test.json | 92 ---
src/test/resources/features/test2.json | 7 -
src/test/resources/features/test3.json | 7 -
45 files changed, 11 insertions(+), 5369 deletions(-)
diff --git a/.asf.yaml b/.asf.yaml
new file mode 100644
index 0000000..0060433
--- /dev/null
+++ b/.asf.yaml
@@ -0,0 +1,6 @@
+github:
+ description: "Apache Sling Feature Model IO"
+ homepage: "https://sling.apache.org/"
+ labels:
+ - sling
+ - deprecated
diff --git a/Jenkinsfile b/Jenkinsfile
deleted file mode 100644
index f582519..0000000
--- a/Jenkinsfile
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * 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.
- */
-
-slingOsgiBundleBuild()
diff --git a/bnd.bnd b/bnd.bnd
deleted file mode 100644
index 62f82d8..0000000
--- a/bnd.bnd
+++ /dev/null
@@ -1,3 +0,0 @@
--conditionalpackage: org.apache.felix.utils.collections,\\
- org.apache.felix.utils.resource,\\
- org.apache.felix.utils.version
diff --git a/design/feature-model.json b/design/feature-model.json
deleted file mode 100644
index aff0e66..0000000
--- a/design/feature-model.json
+++ /dev/null
@@ -1,123 +0,0 @@
-{
- // this is a comment
- "id": "org.apache.sling:my.app:slingosgifeature:my-classifier:1.0",
-
- "title": "A title for the feature. (optional)",
- "description": "A description for the feature. (optional)",
- "vendor": "The feature vendor, for example 'Apache Software Foundation'. (optional)",
- "license": "The license of this feature file, for example 'ASL-2'. (optional)",
-
- // A complete feature has no external dependencies
- "complete": true,
-
- // A final feature cannot be used as a prototype for another feature
- "final": false,
-
- // variables used in configuration and framework properties are substituted at launch time.
- "variables": {
- "cfgvar": "somedefault",
- "org.abc.xyz": "1.2.3",
-
- // When converting to provisioning model, if you need a special name
- "provisioning.model.name": ":boot"
- },
-
- // A prototype is another feature that is used as a prototype for this one
- // Bundles, configurations and framework properties can be removed from the
- //prototype. Bundles with the same artifact ID defined in the feature override
- // bundles with this artifact ID in the Prototype
- "prototype":
- {
- "id": "org.apache.sling:some-other-feature:1.2.3",
- "removals": {
- "configurations": [],
- "bundles": [],
- "framework-properties": []
- }
- },
-
- // Requirements over and above the requirements in the bundles referenced by
- // feature.
- "requirements": [
- {
- "namespace": "osgi.contract",
- "directives": {
- "filter": "(&(osgi.contract=JavaServlet)(version=3.1))"
- }
- }
- ],
-
- // Capabilities over and above the capabilities provided by the bundles referenced
- // by the feature.
- "capabilities": [
- {
- "namespace": "osgi.implementation",
- "attributes": {
- "osgi.implementation": "osgi.http",
- "version:Version": "1.1"
- },
- "directives": {
- "uses": "javax.servlet,javax.servlet.http,org.osgi.service.http.context,org.osgi.service.http.whiteboard"
- }
- },
- {
- "namespace": "osgi.service",
- "attributes": {
- "objectClass:List<String>": "org.osgi.service.http.runtime.HttpServiceRuntime"
- },
- "directives": {
- "uses": "org.osgi.service.http.runtime,org.osgi.service.http.runtime.dto"
- }
- }
- ],
-
- // Framework properties to be provided to the running OSGi Framework
- "framework-properties": {
- "foo": 1,
- "org.osgi.framework.storage": "${tempdir}",
- "org.apache.felix.scr.directory": "launchpad/scr"
- },
-
- // The bundles that are part of the feature. Bundles are referenced using Maven
- // coordinates and can have additional metadata associated with them. Bundles can
- // specified as either a simple string (the Maven coordinates of the bundle) or
- // as an object with 'id' and additional metadata.
- "bundles": [
- {
- "id": "org.apache.sling:security-server:2.2.0",
- "hash": "4632463464363646436",
-
- // This is the relative start order inside the feature
- "start-order": 5
- },
- {
- "id": "org.apache.sling:application-bundle:2.0.0",
- "start-order": 10
- },
- "org.apache.sling:foo-xyz:1.2.3"
- ],
-
- // The configurations are specified following the format defined by the OSGi Configurator
- // specification: https://osgi.org/specification/osgi.cmpn/7.0.0/service.configurator.html
- // Variables declared in the variables section can be used for late binding of variables
- // they can be specified with the Launcher, or the default from the variables section is used.
- // Factory configurations can be specified using the named factory syntax, which separates
- // The factory PID and the name with a tilde '~'
- "configurations": {
- "my.pid": {
- "foo": 5,
- "something-enabled": false,
- "bar": "${cfgvar}",
-
- // The tempdir variable is not specified at the variables section.
- // It needs to be provided at launch, otherwise the launch will stop.
- "tempdir": "${tempdir}",
-
-
- "number:Integer": 7
- },
- "my.factory.pid~name": {
- "a.value":"yeah"
- }
- }
-}
diff --git a/pom.xml b/pom.xml
deleted file mode 100644
index 871ad0f..0000000
--- a/pom.xml
+++ /dev/null
@@ -1,169 +0,0 @@
-<?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-bundle-parent</artifactId>
- <version>38</version>
- <relativePath />
- </parent>
-
- <artifactId>org.apache.sling.feature.io</artifactId>
- <version>1.3.1-SNAPSHOT</version>
-
- <name>Apache Sling Feature IO Module</name>
- <description>
- IO functionality for the Feature Model
- </description>
-
- <properties>
- <sling.java.version>8</sling.java.version>
- </properties>
-
- <scm>
- <connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-io.git</connection>
- <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-io.git</developerConnection>
- <url>https://gitbox.apache.org/repos/asf?p=sling-org-apache-sling-feature-io.git</url>
- <tag>HEAD</tag>
- </scm>
-
- <build>
- <plugins>
- <plugin>
- <groupId>biz.aQute.bnd</groupId>
- <artifactId>bnd-baseline-maven-plugin</artifactId>
- <configuration>
- <skip>true</skip>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.rat</groupId>
- <artifactId>apache-rat-plugin</artifactId>
- <configuration>
- <excludes>
- <exclude>readme.md</exclude>
- </excludes>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-shade-plugin</artifactId>
- <version>3.2.1</version>
- <executions>
- <execution>
- <phase>package</phase>
- <goals>
- <goal>shade</goal>
- </goals>
- <configuration>
- <createSourcesJar>true</createSourcesJar>
- <shadeSourcesContent>true</shadeSourcesContent>
- <relocations>
- <relocation>
- <pattern>org.apache.felix.utils</pattern>
- <shadedPattern>org.apache.sling.feature.io.impl.felix</shadedPattern>
- </relocation>
- </relocations>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
-
- <dependencies>
- <dependency>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.converter</artifactId>
- <version>1.0.12</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.cm.json</artifactId>
- <version>1.0.2</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.utils</artifactId>
- <version>1.11.4</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.geronimo.specs</groupId>
- <artifactId>geronimo-json_1.1_spec</artifactId>
- <version>1.2</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.feature</artifactId>
- <version>1.1.8</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.annotation.versioning</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.framework</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.resource</artifactId>
- <version>1.0.0</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </dependency>
-
- <!-- Testing -->
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <version>3.3.3</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.johnzon</groupId>
- <artifactId>johnzon-core</artifactId>
- <version>1.2.3</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.util.function</artifactId>
- <version>1.0.0</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-lang3</artifactId>
- <version>3.9</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
-</project>
diff --git a/readme.md b/readme.md
index c68e599..fa623ab 100644
--- a/readme.md
+++ b/readme.md
@@ -1,9 +1,10 @@
[<img src="http://sling.apache.org/res/logos/sling.png"/>](http://sling.apache.org)
- [![Build Status](https://builds.apache.org/buildStatus/icon?job=sling-org-apache-sling-feature-io-1.8)](https://builds.apache.org/view/S-Z/view/Sling/job/sling-org-apache-sling-feature-io-1.8) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.sling/org.apache.sling.feature.io/badge.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.apache.sling%22%20a%3A%22org.apache.sling.feature.io%22) [![JavaDocs](https://www.javadoc.io/badge/org.apache.sling/org. [...]
-# IO Functionality for the Sling Feature Model
+# Sling Feature Model IO (deprecated)
-This project contains functionality to deal with the IO needs of the feature model. This includes interfacing with Maven Repositories and reading and writing Feature Model JSON files.
+This module is no longer maintained as a separate module, all its contents has been merged into
+https://github.com/apache/sling-org-apache-sling-feature/blob/master/readme.md
-For further documentation see: https://github.com/apache/sling-org-apache-sling-feature/blob/master/readme.md
+
+For reference use branch [maintenance](https://github.com/apache/sling-org-apache-sling-feature-io/tree/maintenance).
diff --git a/src/main/java/org/apache/sling/feature/io/CloseShieldWriter.java b/src/main/java/org/apache/sling/feature/io/CloseShieldWriter.java
deleted file mode 100644
index f5add8b..0000000
--- a/src/main/java/org/apache/sling/feature/io/CloseShieldWriter.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.io;
-
-import java.io.FilterWriter;
-import java.io.IOException;
-import java.io.Writer;
-
-/**
- * Proxy writer that prevents the underlying writer from being closed.
- * <p>
- * This class is typically used in cases where a writer needs to be passed to a component that wants to explicitly close
- * the writer even if other components would still use the writer for output.
- * </p>
- * @deprecated
- */
-@Deprecated
-public class CloseShieldWriter extends FilterWriter {
-
- public CloseShieldWriter(Writer out) {
- super(out);
- }
-
- @Override
- public void close() throws IOException {
- // NOOP
- }
-
-}
diff --git a/src/main/java/org/apache/sling/feature/io/ConfiguratorUtil.java b/src/main/java/org/apache/sling/feature/io/ConfiguratorUtil.java
deleted file mode 100644
index 2428db3..0000000
--- a/src/main/java/org/apache/sling/feature/io/ConfiguratorUtil.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.io;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Collections;
-import java.util.Dictionary;
-
-import javax.json.Json;
-import javax.json.stream.JsonGenerator;
-import javax.json.stream.JsonGeneratorFactory;
-
-import org.apache.felix.cm.json.Configurations;
-import org.apache.sling.feature.Configuration;
-
-/**
- * Helper class to write JSON structures as defined in
- * <a href="https://osgi.org/specification/osgi.cmpn/7.0.0/service.configurator.html#d0e131765">OSGi Configurator Specification 1.0</a>.
- * @deprecated Use {@link org.apache.felix.cm.json.Configurations} instead.
- */
-@Deprecated
-public class ConfiguratorUtil {
-
- private ConfiguratorUtil() {
- }
-
- protected static final JsonGenerator newGenerator(final Writer writer) {
- JsonGeneratorFactory generatorFactory = Json.createGeneratorFactory(Collections.singletonMap(JsonGenerator.PRETTY_PRINTING, true));
-
- // prevent closing of the underlying writer
- Writer closeShieldWriter = new CloseShieldWriter(writer);
- return generatorFactory.createGenerator(closeShieldWriter);
- }
-
- /** Write the OSGi configuration to a JSON structure.
- * The writer is not closed.
- *
- * @param writer Writer
- * @param props The configuration properties to write */
- public static void writeConfiguration(final Writer writer, final Dictionary<String, Object> props) {
- final Object artifactId = props.remove(Configuration.PROP_ARTIFACT_ID);
- try {
- Configurations.buildWriter().build(writer).writeConfiguration(props);
- } catch (IOException e) {
- throw new RuntimeException("Unable to write configuration.", e);
- } finally {
- if ( artifactId != null ) {
- props.put(Configuration.PROP_ARTIFACT_ID, artifactId);
- }
- }
- }
-
- public static void writeConfiguration(final JsonGenerator generator, final Dictionary<String, Object> props) {
- final Object artifactId = props.remove(Configuration.PROP_ARTIFACT_ID);
- try {
- Configurations.buildWriter().build(generator).writeConfiguration(props);
- } catch (IOException e) {
- throw new RuntimeException("Unable to write configuration.", e);
- } finally {
- if ( artifactId != null ) {
- props.put(Configuration.PROP_ARTIFACT_ID, artifactId);
- }
- }
- }
-}
diff --git a/src/main/java/org/apache/sling/feature/io/IOUtils.java b/src/main/java/org/apache/sling/feature/io/IOUtils.java
deleted file mode 100644
index fa64815..0000000
--- a/src/main/java/org/apache/sling/feature/io/IOUtils.java
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * 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.io;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.JarURLConnection;
-import java.net.MalformedURLException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.jar.JarFile;
-
-public class IOUtils {
-
- /** The extension for a reference file. */
- public static final String EXTENSION_REF_FILE = ".ref";
-
- /** The extension for a feature file. */
- public static final String EXTENSION_FEATURE_FILE = ".json";
-
- /** The default directory to search for features. */
- public static final String DEFAULT_DIRECTORY = "features";
-
- /** The default name of the feature file. */
- public static final String DEFAULT_FEATURE_FILE = "feature" + EXTENSION_FEATURE_FILE;
-
- /**
- * Parse a feature reference file
- * @param file The file
- * @return The referenced features
- * @throws IOException If reading fails
- */
- public static List<String> parseFeatureRefFile(final File file)
- throws IOException {
- final List<String> result = new ArrayList<>();
- final List<String> lines = Files.readAllLines(file.toPath());
- for(String line : lines) {
- line = line.trim();
- if ( !line.isEmpty() && !line.startsWith("#") ) {
- if ( line.indexOf(':') == -1 ) {
- result.add(new File(line).getAbsolutePath());
- } else {
- result.add(line);
- }
- }
- }
- return result;
- }
-
- /**
- * Get the list of feature files.
- * If the provided list of files is {@code null} or an empty array, the default is used.
- * The default checks for the following places, the first one found is used. If none is
- * found an empty list is returned.
- * <ol>
- * <li>A directory named {@link #DEFAULT_DIRECTORY} in the current directory
- * <li>A file named {@link #DEFAULT_FEATURE_FILE} in the current directory
- * <li>A directory named {@link #DEFAULT_DIRECTORY} in the home directory
- * <li>A file named {@link #DEFAULT_FEATURE_FILE} in the home directory
- * </ol>
- *
- * The list of files is processed one after the other. If it is relative, it is
- * first tried to be resolved against the current directory and then against the
- * home directory.
- * If an entry denotes a directory, all children ending in {@link #EXTENSION_FEATURE_FILE} or
- * {@link #EXTENSION_REF_FILE} of that directory are read.
- * If a file ends in {@link #EXTENSION_REF_FILE} the contents is read and every line not
- * starting with the hash sign is considered a reference to a feature artifact.
- *
- * @param homeDirectory If relative files should be resolved, this is the directory to use
- * @param files Optional list of files. If none is provided, a default is used.
- * @return The list of files.
- * @throws IOException If an error occurs.
- */
- public static List<String> getFeatureFiles(final File homeDirectory, final String... files)
- throws IOException {
- String[] featureFiles = files;
- if ( featureFiles == null || featureFiles.length == 0 ) {
- // Default value - check feature directory otherwise features file
- final File[] candidates = new File[] {
- new File(homeDirectory, DEFAULT_DIRECTORY),
- new File(homeDirectory, DEFAULT_FEATURE_FILE),
- new File(DEFAULT_DIRECTORY),
- new File(DEFAULT_FEATURE_FILE)
- };
- File f = null;
- for(final File c : candidates) {
- if ( c.exists() ) {
- f = c;
- break;
- }
- }
- // nothing found, we default to the first candidate and fail later
- if ( f == null ) {
- f = candidates[0];
- }
-
- featureFiles = new String[] {f.getAbsolutePath()};
- }
-
- final List<String> paths = new ArrayList<>();
- for(final String name : featureFiles) {
- // check for absolute
- if ( name.indexOf(':') > 1 ) {
- paths.add(name);
- } else {
- // file or relative
- File f = null;
- final File test = new File(name);
- if ( test.isAbsolute() ) {
- f = test;
- } else {
- final File[] candidates = {
- new File(homeDirectory, name),
- new File(homeDirectory, DEFAULT_DIRECTORY + File.separatorChar + name),
- new File(name),
- new File(DEFAULT_DIRECTORY + File.separatorChar + name),
- };
- for(final File c : candidates) {
- if ( c.exists() && c.isFile() ) {
- f = c;
- break;
- }
- }
- }
-
- if ( f != null && f.exists() ) {
- if ( f.isFile() ) {
- processFile(paths, f);
- } else {
- processDir(paths, f);
- }
- } else {
- // we simply add the path and fail later on
- paths.add(new File(name).getAbsolutePath());
- }
- }
- }
-
- Collections.sort(paths, FEATURE_PATH_COMP);
- return paths;
- }
-
- /**
- * Get a File from a local URL (if possible)
- *
- * @param url a local url (like a file: url or a jar:file: url
- * @param cache if an attempt should be made to download the content of the url locally
- * if it can not be presented as a file directly
- * @param tmpDir the tmpDir to use (null for default)
- * @return the file the url points to (or null if none) - or a tmp file if cache is true and the url could be cached
- * @throws IOException
- */
- public static File getFileFromURL(URL url, boolean cache, File tmpDir) throws IOException {
- File result;
- if (url.getProtocol().equals("file")) {
- try {
- result = new File(url.toURI());
- } catch (URISyntaxException e) {
- result = new File(url.getPath());
- }
- } else if (url.getProtocol().equals("jar")) {
- String innerURL = url.getPath();
- if (innerURL.endsWith("!/") && innerURL.indexOf("!/") == innerURL.lastIndexOf("!/")) {
- innerURL = innerURL.substring(0, innerURL.indexOf("!/"));
- try {
- result = getFileFromURL(new URL(innerURL), cache, tmpDir);
- } catch (IOException ex) {
- result = null;
- }
- }
- else {
- result = null;
- }
- }
- else {
- result = null;
- }
-
- if ((result == null || !result.exists()) && cache) {
- File tmp = File.createTempFile("jar", ".jar", tmpDir);
- try (InputStream input = url.openStream(); OutputStream output = new FileOutputStream(tmp)) {
- byte[] buffer =new byte[64 * 1024];
- for (int i = input.read(buffer); i != -1;i = input.read(buffer)) {
- output.write(buffer, 0, i);
- }
- }
- result = tmp;
- }
- return result;
- }
-
- /**
- * Get a JarFile from a local URL (if possible)
- *
- * @param url a local url (like a file: url or a jar:file: url
- * @param cache if an attempt should be made to download the content of the url locally
- * if it can not be presented as a jarfile directly
- * @param tmpDir the tmpDir to use (null for default)
- *
- * @return the jarfile the url points to
- * @throws IOException if the url can't be represented as a jarfile
- */
- public static JarFile getJarFileFromURL(URL url, boolean cache, File tmpDir) throws IOException {
- try {
- URL targetURL = url;
- if (!url.getProtocol().equals("jar")) {
- targetURL = new URL("jar:" + toURLString(url) + "!/");
- }
- else if (!url.getPath().endsWith("!/")) {
- targetURL = new URL(toURLString(url) + "!/");
- }
- return ((JarURLConnection) targetURL.openConnection()).getJarFile();
- } catch (IOException ex) {
- File file = getFileFromURL(url, cache, tmpDir);
- if (file != null) {
- return new JarFile(file);
- }
- else {
- throw ex;
- }
- }
- }
-
- private static String toURLString(URL url) {
- try {
- return url.toURI().toURL().toString();
- } catch (URISyntaxException | MalformedURLException e) {
- return url.toString();
- }
- }
- 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);
- }
- };
-
- private static 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(EXTENSION_REF_FILE) || f.getName().endsWith(EXTENSION_FEATURE_FILE) ) {
- processFile(paths, f);
- }
- }
- }
- }
-
- private static void processFile(final List<String> paths, final File f)
- throws IOException {
- if ( f.getName().endsWith(EXTENSION_REF_FILE) ) {
- paths.addAll(parseFeatureRefFile(f));
- } else {
- paths.add(f.getAbsolutePath());
- }
- }
-}
diff --git a/src/main/java/org/apache/sling/feature/io/archive/ArchiveReader.java b/src/main/java/org/apache/sling/feature/io/archive/ArchiveReader.java
deleted file mode 100644
index 80c6e35..0000000
--- a/src/main/java/org/apache/sling/feature/io/archive/ArchiveReader.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * 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.io.archive;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.jar.JarEntry;
-import java.util.jar.JarInputStream;
-import java.util.jar.Manifest;
-import java.util.stream.Collectors;
-
-import org.apache.sling.feature.Artifact;
-import org.apache.sling.feature.ArtifactId;
-import org.apache.sling.feature.Extension;
-import org.apache.sling.feature.ExtensionType;
-import org.apache.sling.feature.Feature;
-import org.apache.sling.feature.io.json.FeatureJSONReader;
-
-/**
- * The feature archive reader can be used to read an archive based on a feature
- * model. The archive contains the model and all artifacts.
- */
-public class ArchiveReader {
-
- @FunctionalInterface
- public interface ArtifactConsumer {
-
- /**
- * Consume the artifact from the archive The input stream must not be closed by
- * the consumer.
- *
- * @param artifactId The artifact id
- * @param is The input stream for the artifact
- * @throws IOException If the artifact can't be consumed
- */
- void consume(ArtifactId artifactId, final InputStream is) throws IOException;
- }
-
- /**
- * Read a feature model archive. The input stream is not closed. It is up to the
- * caller to close the input stream.
- *
- * @param in The input stream to read from.
- * @param consumer The plugin consuming the binaries, including the features.
- * If no consumer is provided, only the features will be returned.
- * @return The feature models mentioned in the manifest of the archive
- * @throws IOException If anything goes wrong
- */
- public static Set<Feature> read(final InputStream in,
- final ArtifactConsumer consumer)
- throws IOException {
- final JarInputStream jis = new JarInputStream(in);
-
- // validate manifest and get feature ids
- final String[] featureIds = checkHeaderAndExtractContents(jis.getManifest());
- final List<String> featurePaths = Arrays.asList(featureIds).stream()
- .map(id -> ArtifactId.parse(id).toMvnPath()).collect(Collectors.toList());
-
-
- // read contents
- final Set<Feature> features = new HashSet<>();
- final Set<ArtifactId> artifacts = new HashSet<>();
-
- JarEntry entry = null;
- while ( ( entry = jis.getNextJarEntry() ) != null ) {
- if (!entry.isDirectory() && !entry.getName().startsWith("META-INF/")) {
- final ArtifactId id = ArtifactId.fromMvnPath(entry.getName());
-
- if (featurePaths.contains(entry.getName())) {
- // feature - read to string first
- final String contents;
- try ( final StringWriter writer = new StringWriter()) {
- // don't close the input stream
- final Reader reader = new InputStreamReader(jis, "UTF-8");
- final char[] buffer = new char[2048];
- int l;
- while ( (l = reader.read(buffer)) > 0) {
- writer.write(buffer, 0, l);
- }
- writer.flush();
- contents = writer.toString();
- }
- // add to features
- try ( final Reader reader = new StringReader(contents) ) {
- final Feature feature = FeatureJSONReader.read(reader, entry.getName());
- features.add(feature);
- }
- // pass to consumer
- if ( consumer != null ) {
- try ( final InputStream is = new ByteArrayInputStream(contents.getBytes(StandardCharsets.UTF_8))) {
- consumer.consume(id, is);
- }
- }
- } else {
- // artifact
- if (consumer != null) {
- consumer.consume(id, jis);
- }
- artifacts.add(id);
- }
- }
- jis.closeEntry();
- }
- if (features.isEmpty()) {
- throw new IOException("Not a feature model archive - feature file is missing.");
- }
-
- // check whether all artifacts from the models are in the archive
- for (final Feature feature : features) {
- for (final Artifact a : feature.getBundles()) {
- if (!artifacts.contains(a.getId())) {
- throw new IOException("Artifact " + a.getId().toMvnId() + " is missing in archive");
- }
- }
-
- for (final Extension e : feature.getExtensions()) {
- if (e.getType() == ExtensionType.ARTIFACTS) {
- for (final Artifact a : e.getArtifacts()) {
- if (!artifacts.contains(a.getId())) {
- throw new IOException("Artifact " + a.getId().toMvnId() + " is missing in archive");
- }
- }
- }
- }
- }
- return features;
- }
-
- private static String[] checkHeaderAndExtractContents(final Manifest manifest) throws IOException {
- if (manifest == null) {
- throw new IOException("Not a feature model archive - manifest is missing.");
- }
- // check version header
- final String version = manifest.getMainAttributes().getValue(ArchiveWriter.VERSION_HEADER);
- if (version == null) {
- throw new IOException("Not a feature model archive - version manifest header is missing.");
- }
- // validate version header
- try {
- final int number = Integer.valueOf(version);
- if (number < 1 || number > ArchiveWriter.ARCHIVE_VERSION) {
- throw new IOException("Not a feature model archive - invalid manifest header value: " + version);
- }
- } catch (final NumberFormatException nfe) {
- throw new IOException("Not a feature model archive - invalid manifest header value: " + version);
- }
-
- // check contents header
- final String contents = manifest.getMainAttributes().getValue(ArchiveWriter.CONTENTS_HEADER);
- if (contents == null) {
- throw new IOException("Not a feature model archive - contents manifest header is missing.");
- }
-
- return contents.split(",");
- }
-}
diff --git a/src/main/java/org/apache/sling/feature/io/archive/ArchiveWriter.java b/src/main/java/org/apache/sling/feature/io/archive/ArchiveWriter.java
deleted file mode 100644
index 3207e56..0000000
--- a/src/main/java/org/apache/sling/feature/io/archive/ArchiveWriter.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * 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.io.archive;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.Writer;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.jar.JarEntry;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
-import java.util.stream.Collectors;
-import java.util.zip.Deflater;
-
-import org.apache.sling.feature.Artifact;
-import org.apache.sling.feature.ArtifactId;
-import org.apache.sling.feature.Extension;
-import org.apache.sling.feature.ExtensionType;
-import org.apache.sling.feature.Feature;
-import org.apache.sling.feature.builder.ArtifactProvider;
-import org.apache.sling.feature.io.json.FeatureJSONReader;
-import org.apache.sling.feature.io.json.FeatureJSONWriter;
-
-/**
- * The feature archive writer can be used to create an archive based on a
- * feature model. The archive contains the feature model file and all artifacts
- * using a maven repository layout.
- */
-public class ArchiveWriter {
-
- /** The manifest header marking an archive as a feature archive. */
- public static final String VERSION_HEADER = "Feature-Archive-Version";
-
- /** The manifest header listing the features in this archive. */
- public static final String CONTENTS_HEADER = "Feature-Archive-Contents";
-
- /** Current support version of the feature model archive. */
- public static final int ARCHIVE_VERSION = 1;
-
- /**
- * Create a feature model archive. The output stream will not be closed by this
- * method. The caller must call {@link JarOutputStream#close()}
- * on the return output stream. The caller can
- * add additional files through the return stream. However, the files
- * should not be compressed (which is the default for the output stream).
- *
- * A feature model can be in different states: it might be a partial feature
- * model, a complete feature model or an assembled feature model. This method
- * takes the feature model as provided and only writes the listed bundles and
- * artifacts of this feature model into the archive. In general, the best
- * approach for sharing features is to archive {@link Feature#isComplete()
- * complete} features.
- *
- * @param out The output stream to write to
- * @param baseManifest Optional base manifest used for creating the manifest.
- * @param provider The artifact provider
- * @param features The features model to archive
- * @return The jar output stream.
- * @throws IOException If anything goes wrong
- */
- public static JarOutputStream write(final OutputStream out,
- final Manifest baseManifest,
- final ArtifactProvider provider, final Feature... features)
- throws IOException {
- // create manifest
- final Manifest manifest = (baseManifest == null ? new Manifest() : new Manifest(baseManifest));
- manifest.getMainAttributes().putValue("Manifest-Version", "1.0");
- manifest.getMainAttributes().putValue(VERSION_HEADER, String.valueOf(ARCHIVE_VERSION));
- manifest.getMainAttributes().putValue(CONTENTS_HEADER, String.join(",", Arrays.asList(features).stream()
- .map(feature -> feature.getId().toMvnId()).collect(Collectors.toList())));
-
- final Set<ArtifactId> artifacts = new HashSet<>();
- final byte[] buffer = new byte[1024*1024*256];
-
- // create archive
- final JarOutputStream jos = new JarOutputStream(out, manifest);
-
- // write everything without compression
- jos.setLevel(Deflater.NO_COMPRESSION);
- for (final Feature feature : features) {
- writeFeature(artifacts, feature, provider, jos, buffer);
- }
-
-
-
- for (final Feature feature : features) {
- for (final Artifact a : feature.getBundles()) {
- writeArtifact(artifacts, provider, a, jos, buffer);
- }
-
- for (final Extension e : feature.getExtensions()) {
- if (e.getType() == ExtensionType.ARTIFACTS) {
- final boolean isFeature = Extension.EXTENSION_NAME_ASSEMBLED_FEATURES.equals(e.getName());
- for (final Artifact a : e.getArtifacts()) {
- if ( isFeature ) {
- writeFeature(artifacts, provider, a.getId(), jos, buffer);
- } else {
- writeArtifact(artifacts, provider, a, jos, buffer);
- }
- }
- }
- }
- }
- return jos;
- }
-
- private static void writeFeature(final Set<ArtifactId> artifacts,
- final Feature feature,
- final ArtifactProvider provider,
- final JarOutputStream jos, final byte[] buffer) throws IOException {
- if ( artifacts.add(feature.getId())) {
- final JarEntry entry = new JarEntry(feature.getId().toMvnPath());
- jos.putNextEntry(entry);
- final Writer writer = new OutputStreamWriter(jos, StandardCharsets.UTF_8);
- FeatureJSONWriter.write(writer, feature);
- writer.flush();
- jos.closeEntry();
-
- if ( feature.getPrototype() != null ) {
- writeFeature(artifacts, provider, feature.getPrototype().getId(), jos, buffer);
- }
- }
- }
-
- private static void writeFeature(final Set<ArtifactId> artifacts,
- final ArtifactProvider provider,
- final ArtifactId featureId,
- final JarOutputStream jos, final byte[] buffer) throws IOException {
- if ( !artifacts.contains(featureId)) {
- final URL url = provider.provide(featureId);
- try ( final ByteArrayOutputStream baos = new ByteArrayOutputStream();
- final InputStream is = url.openStream()) {
- int l = 0;
- while ( (l = is.read(buffer)) > 0 ) {
- baos.write(buffer, 0, l);
- }
- final String contents = new String(baos.toByteArray(), StandardCharsets.UTF_8);
- try ( final Reader reader = new StringReader(contents)) {
- final Feature feature = FeatureJSONReader.read(reader, featureId.toMvnId());
- writeFeature(artifacts, feature, provider, jos, buffer);
- }
- }
- }
- }
-
- private static void writeArtifact(final Set<ArtifactId> artifacts,
- final ArtifactProvider provider,
- final Artifact artifact,
- final JarOutputStream jos,
- final byte[] buffer) throws IOException {
- if ( artifacts.add(artifact.getId())) {
- final JarEntry artifactEntry = new JarEntry(artifact.getId().toMvnPath());
- jos.putNextEntry(artifactEntry);
-
- final URL url = provider.provide(artifact.getId());
- if (url == null) {
- throw new IOException("Unable to find artifact " + artifact.getId().toMvnId());
- }
- try (final InputStream is = url.openStream()) {
- int l = 0;
- while ( (l = is.read(buffer)) > 0 ) {
- jos.write(buffer, 0, l);
- }
- }
- jos.closeEntry();
- }
- }
-}
diff --git a/src/main/java/org/apache/sling/feature/io/archive/package-info.java b/src/main/java/org/apache/sling/feature/io/archive/package-info.java
deleted file mode 100644
index 46413c3..0000000
--- a/src/main/java/org/apache/sling/feature/io/archive/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.
- */
-
-@org.osgi.annotation.versioning.Version("1.0.0")
-package org.apache.sling.feature.io.archive;
-
-
diff --git a/src/main/java/org/apache/sling/feature/io/artifacts/ArtifactHandler.java b/src/main/java/org/apache/sling/feature/io/artifacts/ArtifactHandler.java
deleted file mode 100644
index c4d87ce..0000000
--- a/src/main/java/org/apache/sling/feature/io/artifacts/ArtifactHandler.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.io.artifacts;
-
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-/**
- * A handler provides a file object for an artifact.
- */
-public class ArtifactHandler {
-
- private final String url;
-
- private final URL localURL;
-
- /**
- * Create a new handler.
- *
- * @param url The url of the artifact
- * @param localURL The local URL for the artifact
- */
- public ArtifactHandler(final String url, final URL localURL) {
- this.url = url;
- this.localURL = localURL;
- }
-
- /**
- * Create a new handler.
- *
- * @param file The file for the artifact
- * @throws MalformedURLException
- * @since 1.1.0
- */
- public ArtifactHandler(final File file) throws MalformedURLException {
- this(file.toURI().toString(), file.toURI().toURL());
- }
-
- /**
- * Get the url of the artifact
- *
- * @return The url.
- */
- public String getUrl() {
- return url;
- }
-
- /**
- * Get a local url for the artifact
- *
- * @return The file
- */
- public URL getLocalURL() {
- return localURL;
- }
-}
diff --git a/src/main/java/org/apache/sling/feature/io/artifacts/ArtifactManager.java b/src/main/java/org/apache/sling/feature/io/artifacts/ArtifactManager.java
deleted file mode 100644
index d1515ac..0000000
--- a/src/main/java/org/apache/sling/feature/io/artifacts/ArtifactManager.java
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * 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.io.artifacts;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.lang.ProcessBuilder.Redirect;
-import java.net.MalformedURLException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Base64;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.ServiceLoader;
-
-import org.apache.sling.feature.ArtifactId;
-import org.apache.sling.feature.Feature;
-import org.apache.sling.feature.builder.FeatureProvider;
-import org.apache.sling.feature.io.artifacts.spi.ArtifactProvider;
-import org.apache.sling.feature.io.artifacts.spi.ArtifactProviderContext;
-import org.apache.sling.feature.io.json.FeatureJSONReader;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * 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
- implements AutoCloseable, org.apache.sling.feature.builder.ArtifactProvider {
-
- private final Logger logger = LoggerFactory.getLogger(this.getClass());
-
- /** The map of providers. */
- private final Map<String, ArtifactProvider> providers;
-
- /** The configuration */
- private final ArtifactManagerConfig config;
-
- /**
- * 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 ArtifactManagerConfig 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, providers);
- }
-
- /**
- * Internal constructor for the manager
- * @param config The configuration
- * @param providers The provider map
- * @throws IOException If the manager can't be initialized
- */
- ArtifactManager(final ArtifactManagerConfig config, final Map<String, ArtifactProvider> providers)
- throws IOException {
- this.config = config;
- 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();
- }
-
- @Override
- public void close() {
- shutdown();
- }
-
- @Override
- public URL provide(final ArtifactId id) {
- try {
- final ArtifactHandler handler = this.getArtifactHandler(id.toMvnUrl());
- return handler.getLocalURL();
- } catch (final IOException e) {
- // ignore
- return null;
- }
- }
-
- /**
- * Return a feature provider based on this artifact manager
- *
- * @return A feature provider
- * @since 1.1.0
- */
- public FeatureProvider toFeatureProvider() {
- return (id -> {
- try {
- final ArtifactHandler handler = this.getArtifactHandler(id.toMvnUrl());
- try (final Reader r = new InputStreamReader(handler.getLocalURL().openStream(), "UTF-8")) {
- final Feature f = FeatureJSONReader.read(r, handler.getUrl());
- return f;
- }
- } catch (final IOException e) {
- // ignore
- return null;
- }
- });
- }
-
- private final URL 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 and file for an artifact.
- *
- * @param url Artifact url or relative path.
- * @return Absolute url and file in the form of a handler.
- * @throws IOException If something goes wrong or the artifact can't be found.
- */
- public ArtifactHandler getArtifactHandler(final String url) throws IOException {
- logger.debug("Trying to get artifact for {}", url);
-
- final String path;
-
- ArtifactId artifactId = null;
-
- if ( url.startsWith("mvn:") ) {
- // mvn url
- try {
- artifactId = ArtifactId.fromMvnUrl(url);
- path = artifactId.toMvnPath();
- } catch (final IllegalArgumentException iae) {
- throw new IOException(iae.getMessage(), iae);
- }
- } 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 URL file = this.getArtifactFromProviders(url, url.substring(pos));
- if ( file == null ) {
- 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);
- }
- logger.debug("Querying repositories for {}", path);
-
- for(final String repoUrl : this.config.getRepositoryUrls()) {
- 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.debug("Checking {} to get artifact from {}", handler, artifactUrl);
-
- final URL file = handler.getArtifact(artifactUrl, path);
- if ( file != null ) {
- logger.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 URL file2 = this.getArtifactFromProviders(fullURL, path);
- if ( file2 == null ) {
- throw new IOException("Artifact " + fullURL + " not found.");
- }
- return new ArtifactHandler(artifactUrl, file2);
- }
- } catch ( final IOException ignore ) {
- // we ignore this but report the original 404
- }
- }
- }
-
- // if we have an artifact id and using mvn is enabled, we try this as a last
- // resort
- if (artifactId != null && this.config.isUseMvn()) {
- final File file = getArtifactFromMvn(artifactId);
- if (file != null) {
- return new ArtifactHandler(file);
- }
- }
- throw new IOException("Artifact " + url + " not found in any repository.");
- }
-
- protected String getFileContents(final ArtifactHandler handler) throws IOException {
- final StringBuilder sb = new StringBuilder();
- try (BufferedReader reader = new BufferedReader(new InputStreamReader(handler.getLocalURL().openStream(), "UTF-8"))) {
- for(String line = reader.readLine(); line != null; line = reader.readLine()) {
- 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 final Logger logger = LoggerFactory.getLogger(this.getClass());
-
- 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 URL getArtifact(final String url, final String relativeCachePath) {
- logger.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.toURI().toURL();
- }
- return null;
- } catch ( final URISyntaxException ise) {
- // ignore
- } catch ( final IllegalArgumentException iae) {
- // ignore
- } catch ( final MalformedURLException mue) {
- // ignore
- }
- logger.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();
- final String userInfo = u.getUserInfo();
- if (userInfo != null) {
- con.addRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString(u.toURI().getUserInfo().getBytes("UTF-8")));
- }
- 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.toURI().toURL();
- } catch ( final FileNotFoundException e) {
- logger.trace("File not found here (keep on looking): '{}'", url);
- // Do not report if the file does not exist as we cycle through the various sources
- return null;
- } catch ( final Exception e) {
- logger.info("Artifact not found in one repository", e);
- // ignore for now
- return null;
- }
- }
-
- @Override
- public String toString() {
- return "DefaultArtifactHandler";
- }
- }
-
- private File getArtifactFromMvn(final ArtifactId artifactId) {
- final String filePath = this.config.getMvnHome()
- .concat(artifactId.toMvnPath().replace('/', File.separatorChar));
- logger.debug("Trying to fetch artifact {} from local mvn repository {}", artifactId.toMvnId(), filePath);
- final File f = new File(filePath);
- if (!f.exists() || !f.isFile() || !f.canRead()) {
- logger.debug("Trying to download {}", artifactId.toMvnId());
- try {
- this.downloadArtifact(artifactId);
- } catch (final IOException ioe) {
- logger.debug("Error downloading file.", ioe);
- }
- if (!f.exists() || !f.isFile() || !f.canRead()) {
- logger.info("Artifact not found {}", artifactId.toMvnId());
-
- return null;
- }
- }
- return f;
- }
-
- /**
- * Download artifact from maven
- *
- * @throws IOException
- */
- private void downloadArtifact(final ArtifactId artifactId) throws IOException {
- // create fake pom
- final Path dir = Files.createTempDirectory(null);
- try {
- final List<String> lines = new ArrayList<String>();
- lines.add(
- "<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\">");
- lines.add(" <modelVersion>4.0.0</modelVersion>");
- lines.add(" <groupId>org.apache.sling</groupId>");
- lines.add(" <artifactId>temp-artifact</artifactId>");
- lines.add(" <version>1-SNAPSHOT</version>");
- lines.add(" <dependencies>");
- lines.add(" <dependency>");
- lines.add(" <groupId>".concat(artifactId.getGroupId()).concat("</groupId>"));
- lines.add(" <artifactId>".concat(artifactId.getArtifactId()).concat("</artifactId>"));
- lines.add(" <version>".concat(artifactId.getVersion()).concat("</version>"));
- if (artifactId.getClassifier() != null) {
- lines.add(" <classifier>".concat(artifactId.getClassifier()).concat("</classifier>"));
- }
- if (!"bundle".equals(artifactId.getType()) && !"jar".equals(artifactId.getType())) {
- lines.add(" <type>".concat(artifactId.getType()).concat("</type>"));
- }
- lines.add(" <scope>provided</scope>");
- lines.add(" </dependency>");
- lines.add(" </dependencies>");
- lines.add("</project>");
- logger.debug("Writing pom to {}", dir);
- Files.write(dir.resolve("pom.xml"), lines, Charset.forName("UTF-8"));
-
- final File output = dir.resolve("output.txt").toFile();
- final File error = dir.resolve("error.txt").toFile();
-
- // invoke maven
- logger.debug("Invoking mvn...");
- final ProcessBuilder pb = new ProcessBuilder("mvn", "verify");
- pb.directory(dir.toFile());
- pb.redirectOutput(Redirect.to(output));
- pb.redirectError(Redirect.to(error));
-
- final Process p = pb.start();
- try {
- p.waitFor();
- } catch (final InterruptedException e) {
- Thread.currentThread().interrupt();
- }
-
- } finally {
- Files.walk(dir).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
- }
- }
-}
diff --git a/src/main/java/org/apache/sling/feature/io/artifacts/ArtifactManagerConfig.java b/src/main/java/org/apache/sling/feature/io/artifacts/ArtifactManagerConfig.java
deleted file mode 100644
index 82e6476..0000000
--- a/src/main/java/org/apache/sling/feature/io/artifacts/ArtifactManagerConfig.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * 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.io.artifacts;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.apache.sling.feature.io.artifacts.spi.ArtifactProviderContext;
-
-/**
- * This class holds the configuration of artifact manager.
- */
-public class ArtifactManagerConfig implements ArtifactProviderContext {
-
- /** The repository urls. */
- private volatile String[] repositoryUrls;
-
- /** The cache directory. */
- private volatile File cacheDirectory;
-
- /** Metrics for artifacts used from the cache. */
- private final AtomicLong cachedArtifacts = new AtomicLong();
-
- /** Metrics for artifacts needed to be downloaded. */
- private final AtomicLong downloadedArtifacts = new AtomicLong();
-
- /** Metrics for artifacts read locally. */
- private final AtomicLong localArtifacts = new AtomicLong();
-
- /** Whether locally mvn command can be used to download artifacts. */
- private volatile boolean useMvn = false;
-
- /**
- * The .m2 directory.
- */
- private final String repoHome;
-
- /**
- * Create a new configuration object. Set the default values
- */
- public ArtifactManagerConfig() {
- // set defaults
- this.repositoryUrls = new String[] {
- "file://" + new File(System.getProperty("user.home")).toURI().getPath() + ".m2/repository",
- "https://repo.maven.apache.org/maven2",
- "https://repository.apache.org/content/groups/snapshots"
- };
- try {
- this.cacheDirectory = Files.createTempDirectory("slingfeature").toFile();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- this.repoHome = System.getProperty("user.home") + "/.m2/repository/";
- }
-
- /**
- * Set the repository urls
- * @param urls 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);
- }
- }
- }
- }
-
- /**
- * Get the repository urls.
- * A repository url does not end with a slash.
- * @return The repository urls.
- */
- public String[] getRepositoryUrls() {
- return repositoryUrls;
- }
-
- /**
- * Get the cache directory
- * @return The cache directory.
- */
- @Override
- public File getCacheDirectory() {
- return cacheDirectory;
- }
-
- /**
- * Set the cache directory
- * @param dir The cache directory
- */
- public void setCacheDirectory(final File dir) {
- this.cacheDirectory = dir;
- }
-
- @Override
- public void incCachedArtifacts() {
- this.cachedArtifacts.incrementAndGet();
- }
-
- @Override
- public void incDownloadedArtifacts() {
- this.downloadedArtifacts.incrementAndGet();
- }
-
- @Override
- public void incLocalArtifacts() {
- this.localArtifacts.incrementAndGet();
- }
-
- /**
- * Get the number of cached artifacts
- * @return The number of cached artifacts
- */
- public long getCachedArtifacts() {
- return this.cachedArtifacts.get();
- }
-
- /**
- * Get the number of downloaded artifacts
- * @return The number of downloaded artifacts
- */
- public long getDownloadedArtifacts() {
- return this.downloadedArtifacts.get();
- }
-
- /**
- * Get the number of local artifacts
- * @return The number of local artifacts
- */
- public long getLocalArtifacts() {
- return this.localArtifacts.get();
- }
-
- /**
- * Should mvn be used if an artifact can't be found in the repositories
- *
- * @return Whether mvn command should be used.
- * @since 1.1.0
- */
- public boolean isUseMvn() {
- return useMvn;
- }
-
- /**
- * Set whether mvn should be used to get artifacts.
- *
- * @param useMvn flag for enabling mvn
- * @since 1.1.0
- */
- public void setUseMvn(final boolean useMvn) {
- this.useMvn = useMvn;
- }
-
- /**
- * Return mvn home
- *
- * @since 1.1.0
- */
- String getMvnHome() {
- return this.repoHome;
- }
-}
diff --git a/src/main/java/org/apache/sling/feature/io/artifacts/package-info.java b/src/main/java/org/apache/sling/feature/io/artifacts/package-info.java
deleted file mode 100644
index f2229fb..0000000
--- a/src/main/java/org/apache/sling/feature/io/artifacts/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.
- */
-
-@org.osgi.annotation.versioning.Version("1.1.0")
-package org.apache.sling.feature.io.artifacts;
-
-
diff --git a/src/main/java/org/apache/sling/feature/io/artifacts/spi/ArtifactProvider.java b/src/main/java/org/apache/sling/feature/io/artifacts/spi/ArtifactProvider.java
deleted file mode 100644
index 5127ac5..0000000
--- a/src/main/java/org/apache/sling/feature/io/artifacts/spi/ArtifactProvider.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.io.artifacts.spi;
-
-import java.io.IOException;
-import java.net.URL;
-
-import org.osgi.annotation.versioning.ConsumerType;
-
-/**
- * The artifact provider is an extension point for providing artifacts
- * from different sources, like for example s3.
- */
-@ConsumerType
-public interface ArtifactProvider {
-
- /**
- * The protocol name of the provider, e.g. "s3"
- * @return The protocol name.
- */
- String getProtocol();
-
- /**
- * Initialize the provider.
- * @param context The context
- * @throws IOException If the provider can't be initialized.
- */
- void init(ArtifactProviderContext context) throws IOException;
-
- /**
- * Shutdown the provider.
- */
- void shutdown();
-
- /**
- * Get a local file for the artifact URL.
- *
- * @param url Artifact url
- * @param relativeCachePath A relative path that can be used as a cache path
- * by the provider. The path does not start with a slash.
- * @return A local url if the artifact exists or {@code null}
- */
- URL getArtifact(String url, String relativeCachePath);
-}
diff --git a/src/main/java/org/apache/sling/feature/io/artifacts/spi/ArtifactProviderContext.java b/src/main/java/org/apache/sling/feature/io/artifacts/spi/ArtifactProviderContext.java
deleted file mode 100644
index dccfbfc..0000000
--- a/src/main/java/org/apache/sling/feature/io/artifacts/spi/ArtifactProviderContext.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.io.artifacts.spi;
-
-import java.io.File;
-
-import org.osgi.annotation.versioning.ProviderType;
-
-/**
- * This is the context for the artifact providers
- */
-@ProviderType
-public interface ArtifactProviderContext {
-
- /**
- * Get the cache directory
- * @return The cache directory.
- */
- File getCacheDirectory();
-
- /**
- * Inform about an artifact found in the cache.
- */
- void incCachedArtifacts();
-
- /**
- * Inform about an artifact being downloaded
- */
- void incDownloadedArtifacts();
-
- /**
- * Inform about an artifact found locally.
- */
- void incLocalArtifacts();
-}
diff --git a/src/main/java/org/apache/sling/feature/io/artifacts/spi/package-info.java b/src/main/java/org/apache/sling/feature/io/artifacts/spi/package-info.java
deleted file mode 100644
index bb0c1f0..0000000
--- a/src/main/java/org/apache/sling/feature/io/artifacts/spi/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.
- */
-
-@org.osgi.annotation.versioning.Version("1.0.0")
-package org.apache.sling.feature.io.artifacts.spi;
-
-
diff --git a/src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONReader.java b/src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONReader.java
deleted file mode 100644
index 7d4c555..0000000
--- a/src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONReader.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.io.json;
-
-import java.io.IOException;
-import java.io.Reader;
-import java.util.Hashtable;
-import java.util.Map;
-
-import org.apache.felix.cm.json.ConfigurationReader;
-import org.apache.felix.cm.json.ConfigurationResource;
-import org.apache.sling.feature.Configuration;
-import org.apache.sling.feature.Configurations;
-
-/**
- * JSON Reader for configurations.
- */
-public class ConfigurationJSONReader {
-
- /**
- * Read a map of configurations from the reader
- * The reader is not closed. It is up to the caller to close the reader.
- *
- * @param reader The reader for the configuration
- * @param location Optional location
- * @return The read configurations
- * @throws IOException If an IO errors occurs or the JSON is invalid.
- */
- public static Configurations read(final Reader reader, final String location)
- throws IOException {
- try {
- final ConfigurationJSONReader mr = new ConfigurationJSONReader();
- return mr.readConfigurations(location, reader);
- } catch (final IllegalStateException | IllegalArgumentException e) {
- throw new IOException(e);
- }
- }
-
- Configurations readConfigurations(final String location, final Reader reader) throws IOException {
- final Configurations result = new Configurations();
-
- final ConfigurationReader cfgReader = org.apache.felix.cm.json.Configurations
- .buildReader()
- .withIdentifier(location)
- .verifyAsBundleResource(true)
- .build(reader);
- final ConfigurationResource rsrc = cfgReader.readConfigurationResource();
- for(Map.Entry<String, Hashtable<String, Object>> entry : rsrc.getConfigurations().entrySet() ) {
- final Configuration cf = new Configuration(entry.getKey());
- for(final Map.Entry<String, Object> prop : entry.getValue().entrySet()) {
- cf.getProperties().put(prop.getKey(), prop.getValue());
- }
- }
-
- return result;
- }
-}
-
-
diff --git a/src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONWriter.java b/src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONWriter.java
deleted file mode 100644
index e189e3b..0000000
--- a/src/main/java/org/apache/sling/feature/io/json/ConfigurationJSONWriter.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.io.json;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Collections;
-import java.util.Hashtable;
-
-import org.apache.felix.cm.json.ConfigurationResource;
-import org.apache.felix.cm.json.ConfigurationWriter;
-import org.apache.sling.feature.Configuration;
-import org.apache.sling.feature.Configurations;
-
-/** JSON writer for configurations */
-public class ConfigurationJSONWriter {
-
- /** Writes the configurations to the writer. The writer is not closed.
- *
- * @param writer Writer
- * @param configs List of configurations
- * @throws IOException If writing fails */
- public static void write(final Writer writer, final Configurations configs)
- throws IOException {
- final ConfigurationJSONWriter w = new ConfigurationJSONWriter();
- w.writeConfigurations(writer, configs);
- }
-
- private void writeConfigurations(final Writer writer, final Configurations configs)
- throws IOException {
-
- final ConfigurationWriter cfgWriter = org.apache.felix.cm.json.Configurations
- .buildWriter()
- .build(writer);
-
- final ConfigurationResource rsrc = new ConfigurationResource();
- for(final Configuration cfg : configs) {
- final Hashtable<String, Object> properties;
- if ( cfg.getProperties() instanceof Hashtable && cfg.getProperties().get(Configuration.PROP_ARTIFACT_ID) == null ) {
- properties = (Hashtable<String, Object>)cfg.getProperties();
- } else {
- properties = org.apache.felix.cm.json.Configurations.newConfiguration();
- for(final String name : Collections.list(cfg.getProperties().keys()) ) {
- if ( !Configuration.PROP_ARTIFACT_ID.equals(name) ) {
- properties.put(name, cfg.getProperties().get(name));
- }
- }
- }
- rsrc.getConfigurations().put(cfg.getPid(), properties);
- }
- cfgWriter.writeConfigurationResource(rsrc);
- }
-
-
-}
diff --git a/src/main/java/org/apache/sling/feature/io/json/FeatureJSONReader.java b/src/main/java/org/apache/sling/feature/io/json/FeatureJSONReader.java
deleted file mode 100644
index 71c1e07..0000000
--- a/src/main/java/org/apache/sling/feature/io/json/FeatureJSONReader.java
+++ /dev/null
@@ -1,716 +0,0 @@
-/*
- * 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.io.json;
-
-import java.io.IOException;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.BiConsumer;
-
-import javax.json.Json;
-import javax.json.JsonArray;
-import javax.json.JsonException;
-import javax.json.JsonObject;
-import javax.json.JsonString;
-import javax.json.JsonStructure;
-import javax.json.JsonValue;
-import javax.json.JsonValue.ValueType;
-
-import org.apache.felix.cm.json.ConfigurationReader;
-import org.apache.felix.cm.json.ConfigurationResource;
-import org.apache.felix.utils.resource.CapabilityImpl;
-import org.apache.felix.utils.resource.RequirementImpl;
-import org.apache.sling.feature.Artifact;
-import org.apache.sling.feature.ArtifactId;
-import org.apache.sling.feature.Bundles;
-import org.apache.sling.feature.Configuration;
-import org.apache.sling.feature.Configurations;
-import org.apache.sling.feature.Extension;
-import org.apache.sling.feature.ExtensionState;
-import org.apache.sling.feature.ExtensionType;
-import org.apache.sling.feature.Extensions;
-import org.apache.sling.feature.Feature;
-import org.apache.sling.feature.MatchingRequirement;
-import org.apache.sling.feature.Prototype;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Resource;
-
-/**
- * This class offers a static method to read a {@code Feature} using a {@code Reader} instance.
- */
-public class FeatureJSONReader {
-
- /**
- * Read a new feature from the reader
- * The reader is not closed. It is up to the caller to close the reader.
- *
- * @param reader The reader for the feature
- * @param location Optional location
- * @return The read feature
- * @throws IOException If an IO errors occurs or the JSON is invalid.
- */
- public static Feature read(final Reader reader, final String location)
- throws IOException {
- try {
- final FeatureJSONReader mr = new FeatureJSONReader(location);
- return mr.readFeature(reader);
- } catch (final IllegalStateException | IllegalArgumentException | JsonException e) {
- throw new IOException(e);
- }
- }
-
- /** The read feature. */
- private Feature feature;
-
- /** The optional location. */
- private final String location;
-
- /** Exception prefix containing the location (if set) */
- private final String exceptionPrefix;
-
- /**
- * private constructor
- * @param location Optional location
- */
- private FeatureJSONReader(final String location) {
- this.location = location;
- if ( location == null ) {
- exceptionPrefix = "";
- } else {
- exceptionPrefix = location.concat(" : ");
- }
- }
-
- /**
- * Get the feature id
- * @param json The feature json
- * @return The artifact id
- * @throws IOException If the id is missing
- */
- private ArtifactId getFeatureId(final JsonObject json) throws IOException {
- if ( !json.containsKey(JSONConstants.FEATURE_ID) ) {
- throw new IOException(this.exceptionPrefix.concat("Feature id is missing"));
- }
- return checkTypeArtifactId(JSONConstants.FEATURE_ID, json.get(JSONConstants.FEATURE_ID));
- }
-
- private String getProperty(final JsonObject json, final String key) throws IOException {
- final JsonValue val = json.get(key);
- if ( val != null ) {
- return checkTypeString(key, val);
- }
- return null;
- }
-
- /**
- * Read the variables section
- * @param json The json describing the feature or application
- * @param kvMap The variables will be written to this Key Value Map
- * @throws IOException If the json is invalid.
- */
- private void readVariables(JsonObject json, Map<String,String> kvMap) throws IOException {
- if (json.containsKey(JSONConstants.FEATURE_VARIABLES)) {
- final JsonValue variablesObj = json.get(JSONConstants.FEATURE_VARIABLES);
-
- for (final Map.Entry<String, JsonValue> entry : checkTypeObject(JSONConstants.FEATURE_VARIABLES, variablesObj).entrySet()) {
- final String key = entry.getKey();
- // skip comments
- if ( !key.startsWith("#") ) {
- if (kvMap.get(key) != null) {
- throw new IOException(this.exceptionPrefix.concat("Duplicate variable ").concat(key));
- }
- final String value = checkScalarType("variable value", entry.getValue(), true);
- kvMap.put(key, value);
- }
- }
- }
- }
-
-
- /**
- * Read the bundles / start levels section
- * @param json The json object describing the feature
- * @param container The bundles container
- * @param configContainer The configurations container
- * @throws IOException If the json is invalid.
- */
- private void readBundles(
- final JsonObject json,
- final Bundles container,
- final Configurations configContainer) throws IOException {
- if ( json.containsKey(JSONConstants.FEATURE_BUNDLES)) {
- final List<Artifact> list = new ArrayList<>();
- readArtifacts(JSONConstants.FEATURE_BUNDLES, "bundle", list, json.get(JSONConstants.FEATURE_BUNDLES), configContainer);
-
- for(final Artifact a : list) {
- if ( container.containsExact(a.getId())) {
- throw new IOException(exceptionPrefix + "Duplicate identical bundle " + a.getId().toMvnId());
- }
- try {
- // check start order
- a.getStartOrder();
- } catch ( final IllegalArgumentException nfe) {
- throw new IOException(exceptionPrefix + "Illegal start order '" + a.getMetadata().get(Artifact.KEY_START_ORDER) + "'");
- }
- container.add(a);
- }
- }
- }
-
- private void readArtifacts(final String section,
- final String artifactType,
- final List<Artifact> artifacts,
- final JsonValue listObj,
- final Configurations container)
- throws IOException {
- for(final JsonValue entry : checkTypeArray(section, listObj)) {
- final Artifact artifact;
- checkTypeObjectOrString(artifactType, entry);
- if ( entry.getValueType() == ValueType.STRING ) {
- // skip comments
- if ( ((JsonString)entry).getString().startsWith("#") ) {
- continue;
- }
- artifact = new Artifact(checkTypeArtifactId(artifactType, entry));
- } else {
- final JsonObject bundleObj = (JsonObject) entry;
- if ( !bundleObj.containsKey(JSONConstants.ARTIFACT_ID) ) {
- throw new IOException(exceptionPrefix.concat(" ").concat(artifactType).concat(" is missing required artifact id"));
- }
- final ArtifactId id = checkTypeArtifactId(artifactType.concat(" ").concat(JSONConstants.ARTIFACT_ID), bundleObj.get(JSONConstants.ARTIFACT_ID));
-
- artifact = new Artifact(id);
- for(final Map.Entry<String, JsonValue> metadataEntry : bundleObj.entrySet()) {
- final String key = metadataEntry.getKey();
- // skip comments
- if ( key.startsWith("#") ) {
- continue;
- }
- if ( JSONConstants.ARTIFACT_KNOWN_PROPERTIES.contains(key) ) {
- continue;
- }
- final String mval = checkScalarType(artifactType.concat(" metadata ").concat(key), metadataEntry.getValue(), false);
- artifact.getMetadata().put(key, mval);
- }
- if ( bundleObj.containsKey(JSONConstants.FEATURE_CONFIGURATIONS) ) {
- final JsonObject cfgs = checkTypeObject(artifactType.concat(" configurations"), bundleObj.get(JSONConstants.FEATURE_CONFIGURATIONS));
- addConfigurations(cfgs, artifact, container);
- }
- }
- artifacts.add(artifact);
- }
- }
-
- private void addConfigurations(final JsonObject json,
- final Artifact artifact,
- final Configurations container) throws IOException {
- final ConfigurationReader reader = org.apache.felix.cm.json.Configurations.buildReader()
- .verifyAsBundleResource(true)
- .withIdentifier(this.location)
- .build(json);
- final ConfigurationResource rsrc = reader.readConfigurationResource();
- if ( !reader.getIgnoredErrors().isEmpty() ) {
- final StringBuilder builder = new StringBuilder(exceptionPrefix);
- builder.append("Errors in configurations:");
- for(final String w : reader.getIgnoredErrors()) {
- builder.append("\n");
- builder.append(w);
- }
- throw new IOException(builder.toString());
- }
-
- for(final Map.Entry<String, Hashtable<String, Object>> c : rsrc.getConfigurations().entrySet()) {
- final Configuration config = new Configuration(c.getKey());
-
- for(final Map.Entry<String, Object> prop : c.getValue().entrySet()) {
- config.getProperties().put(prop.getKey(), prop.getValue());
- }
- if ( config.getProperties().get(Configuration.PROP_ARTIFACT_ID) != null ) {
- throw new IOException(exceptionPrefix.concat("Configuration must not define property ").concat(Configuration.PROP_ARTIFACT_ID));
- }
- if ( artifact != null ) {
- config.getProperties().put(Configuration.PROP_ARTIFACT_ID, artifact.getId().toMvnId());
- }
- for(final Configuration current : container) {
- if ( current.equals(config) ) {
- throw new IOException(exceptionPrefix.concat("Duplicate configuration ").concat(config.getPid()));
- }
- }
- container.add(config);
- }
- }
-
-
- private void readConfigurations(final JsonObject json,
- final Configurations container) throws IOException {
- if ( json.containsKey(JSONConstants.FEATURE_CONFIGURATIONS) ) {
- final JsonObject cfgs = checkTypeObject(JSONConstants.FEATURE_CONFIGURATIONS, json.get(JSONConstants.FEATURE_CONFIGURATIONS));
- addConfigurations(cfgs, null, container);
- }
- }
-
- private void readFrameworkProperties(final JsonObject json,
- final Map<String,String> container) throws IOException {
- if ( json.containsKey(JSONConstants.FEATURE_FRAMEWORK_PROPERTIES) ) {
- final JsonValue propsObj= json.get(JSONConstants.FEATURE_FRAMEWORK_PROPERTIES);
-
- for(final Map.Entry<String, JsonValue> entry : checkTypeObject(JSONConstants.FEATURE_FRAMEWORK_PROPERTIES, propsObj).entrySet()) {
- // skip comments
- if ( entry.getKey().startsWith("#") ) {
- continue;
- }
- if ( container.get(entry.getKey()) != null ) {
- throw new IOException(this.exceptionPrefix.concat("Duplicate framework property ").concat(entry.getKey()));
- }
- final String value = checkScalarType("framework property value", entry.getValue(), false);
- container.put(entry.getKey(), value);
- }
-
- }
- }
-
- private void readExtensions(final JsonObject json,
- final List<String> keywords,
- final Extensions container,
- final Configurations configContainer) throws IOException {
- final Set<String> keySet = new HashSet<>(json.keySet());
- keySet.removeAll(keywords);
- // the remaining keys are considered extensions!
- for(final String key : keySet) {
- if ( key.startsWith("#") ) {
- // skip comments
- continue;
- }
- final int pos = key.indexOf(':');
- final String postfix = pos == -1 ? null : key.substring(pos + 1);
- final int sep = (postfix == null ? key.indexOf('|') : postfix.indexOf('|'));
- final String name;
- final String type;
- final String state;
- if ( pos == -1 ) {
- type = ExtensionType.ARTIFACTS.name();
- if ( sep == -1 ) {
- name = key;
- state = ExtensionState.OPTIONAL.name();
- } else {
- name = key.substring(0, sep);
- state = key.substring(sep + 1);
- }
- } else {
- name = key.substring(0, pos);
- if ( sep == -1 ) {
- type = postfix;
- state = ExtensionState.OPTIONAL.name();
- } else {
- type = postfix.substring(0, sep);
- state = postfix.substring(sep + 1);
- }
- }
- if ( JSONConstants.FEATURE_KNOWN_PROPERTIES.contains(name) ) {
- throw new IOException(this.exceptionPrefix.concat("Extension is using reserved name : ").concat(name));
- }
- if ( container.getByName(name) != null ) {
- throw new IOException(exceptionPrefix.concat("Duplicate extension with name ").concat(name));
- }
-
- final ExtensionType extType = ExtensionType.valueOf(type);
- final ExtensionState extState;
- if (ExtensionState.OPTIONAL.name().equalsIgnoreCase(state)) {
- extState = ExtensionState.OPTIONAL;
- } else if (ExtensionState.REQUIRED.name().equalsIgnoreCase(state)) {
- extState = ExtensionState.REQUIRED;
- } else if (ExtensionState.TRANSIENT.name().equalsIgnoreCase(state)) {
- extState = ExtensionState.TRANSIENT;
- } else {
- final boolean opt = Boolean.valueOf(state).booleanValue();
- extState = opt ? ExtensionState.REQUIRED : ExtensionState.OPTIONAL;
- }
-
- final Extension ext = new Extension(extType, name, extState);
- final JsonValue value = json.get(key);
- switch ( extType ) {
- case ARTIFACTS : final List<Artifact> list = new ArrayList<>();
- readArtifacts("Extension ".concat(name), "artifact", list, value, configContainer);
- for(final Artifact a : list) {
- if ( ext.getArtifacts().contains(a) ) {
- throw new IOException(exceptionPrefix.concat("Duplicate artifact in extension ").concat(name).concat(" : ").concat(a.getId().toMvnId()));
- }
- ext.getArtifacts().add(a);
- }
- break;
- case JSON : if ( value.getValueType() != ValueType.ARRAY && value.getValueType() != ValueType.OBJECT ) {
- throw new IOException(this.exceptionPrefix.concat("JSON Extension ").concat(name).concat(" is neither an object nor an array : ").concat(value.getValueType().name()));
- }
- ext.setJSONStructure((JsonStructure)value);
- break;
- case TEXT : if ( value.getValueType() != ValueType.ARRAY && value.getValueType() != ValueType.STRING ) {
- throw new IOException(this.exceptionPrefix.concat("Text Extension ").concat(name).concat(" is neither a string nor an array : ").concat(value.getValueType().name()));
- }
- if ( value.getValueType() == ValueType.STRING ) {
- // string
- ext.setText(((JsonString)value).getString());
- } else {
- // list (array of strings)
- final StringBuilder sb = new StringBuilder();
- for(final JsonValue o : value.asJsonArray()) {
- final String textValue = checkTypeString("Text Extension ".concat(name).concat(", value ").concat(o.toString()), o);
- sb.append(textValue);
- sb.append('\n');
- }
- ext.setText(sb.toString());
- }
- break;
- }
-
- container.add(ext);
- }
- }
-
- /**
- * Check if the value is a scalar type
- * @param key A key for the error message
- * @param value The value to check
- * @param allowNull Whether null is allowed as value
- * @return A string representing the value or {@code null}
- * @throws IOException If the value is not of the specified types
- */
- private String checkScalarType(final String key, final JsonValue value, boolean allowNull) throws IOException {
- if ( allowNull && value.getValueType() == ValueType.NULL ) {
- return null;
- }
- if ( value.getValueType() == ValueType.STRING || value.getValueType() == ValueType.NUMBER || value.getValueType() == ValueType.FALSE || value.getValueType() == ValueType.TRUE ) {
- return org.apache.felix.cm.json.Configurations.convertToObject(value).toString();
- }
- throw new IOException(this.exceptionPrefix.concat("Key ").concat(key).concat(" is not one of the allowed types string, number or boolean : ").concat(value.getValueType().name()));
- }
-
- /**
- * Check if the value is an object or a string
- * @param key A key for the error message
- * @param value The value to check
- * @throws IOException If the value is not of the specified types
- */
- private void checkTypeObjectOrString(final String key, final JsonValue value) throws IOException {
- if ( value.getValueType() != ValueType.STRING && value.getValueType() != ValueType.OBJECT ) {
- throw new IOException(this.exceptionPrefix.concat("Key ").concat(key).concat(" is neither a string nor an object : ").concat(value.getValueType().name()));
- }
- }
-
- /**
- * Check if the value is a boolean
- * @param key A key for the error message
- * @param value The value to check
- * @return The boolean value
- * @throws IOException If the value is not of the specified types
- */
- private boolean checkTypeBoolean(final String key, final JsonValue value) throws IOException {
- if ( value.getValueType() == ValueType.TRUE || value.getValueType() == ValueType.FALSE ) {
- return (Boolean)org.apache.felix.cm.json.Configurations.convertToObject(value);
- }
- throw new IOException(this.exceptionPrefix.concat("Key ").concat(key).concat(" is not of type boolean : ").concat(value.getValueType().name()));
- }
-
- /**
- * Check if the value is an artifact id
- * @param key A key for the error message
- * @param value The value to check
- * @return The artifact id
- * @throws IOException If the value is not a string and not a valid artifact id
- */
- private ArtifactId checkTypeArtifactId(final String key, final JsonValue value) throws IOException {
- final String textValue = checkTypeString(key, value);
- try {
- return ArtifactId.parse(textValue);
- } catch ( final IllegalArgumentException iae) {
- throw new IOException(this.exceptionPrefix.concat("Key ").concat(key).concat(" is not a valid artifact id : ").concat(textValue));
- }
- }
-
- /**
- * Check if the value is a string
- * @param key A key for the error message
- * @param value The value to check
- * @return The string value
- * @throws IOException If the value is not a string
- */
- private String checkTypeString(final String key, final JsonValue value) throws IOException {
- if ( value.getValueType() == ValueType.STRING) {
- return ((JsonString)value).getString();
- }
- throw new IOException(this.exceptionPrefix.concat("Key ").concat(key).concat(" is not of type string : ").concat(value.getValueType().name()));
- }
-
- /**
- * Check if the value is an object
- * @param key A key for the error message
- * @param value The value to check
- * @return The object
- * @throws IOException If the value is not an object
- */
- private JsonObject checkTypeObject(final String key, final JsonValue value) throws IOException {
- if ( value.getValueType() == ValueType.OBJECT) {
- return value.asJsonObject();
- }
- throw new IOException(this.exceptionPrefix.concat("Key ").concat(key).concat(" is not of type object : ").concat(value.getValueType().name()));
- }
-
- /**
- * Check if the value is an array
- * @param key A key for the error message
- * @param value The value to check
- * @return The array
- * @throws IOException If the value is not of the specified types
- */
- private JsonArray checkTypeArray(final String key, final JsonValue value) throws IOException {
- if ( value.getValueType() == ValueType.ARRAY) {
- return value.asJsonArray();
- }
- throw new IOException(this.exceptionPrefix.concat("Key ").concat(key).concat(" is not of type array : ").concat(value.getValueType().name()));
- }
-
- private Prototype readPrototype(final JsonObject json) throws IOException {
- if ( json.containsKey(JSONConstants.FEATURE_PROTOTYPE)) {
- final JsonValue prototypeObj = json.get(JSONConstants.FEATURE_PROTOTYPE);
- checkTypeObjectOrString(JSONConstants.FEATURE_PROTOTYPE, prototypeObj);
-
- final Prototype prototype;
- if ( prototypeObj.getValueType() == ValueType.STRING ) {
- prototype = new Prototype(checkTypeArtifactId(JSONConstants.FEATURE_PROTOTYPE, prototypeObj));
- } else {
- final JsonObject obj = (JsonObject) prototypeObj;
- if ( !obj.containsKey(JSONConstants.ARTIFACT_ID) ) {
- throw new IOException(exceptionPrefix.concat(" prototype is missing required artifact id"));
- }
- prototype = new Prototype(checkTypeArtifactId("Prototype ".concat(JSONConstants.ARTIFACT_ID), obj.get(JSONConstants.ARTIFACT_ID)));
-
- if ( obj.containsKey(JSONConstants.PROTOTYPE_REMOVALS) ) {
- final JsonObject removalObj = checkTypeObject("Prototype removals", obj.get(JSONConstants.PROTOTYPE_REMOVALS));
- if ( removalObj.containsKey(JSONConstants.FEATURE_BUNDLES) ) {
- for(final JsonValue val : checkTypeArray("Prototype removal bundles", removalObj.get(JSONConstants.FEATURE_BUNDLES))) {
- if ( checkTypeString("Prototype removal bundles", val).startsWith("#")) {
- continue;
- }
- prototype.getBundleRemovals().add(checkTypeArtifactId("Prototype removal bundles", val));
- }
- }
- if ( removalObj.containsKey(JSONConstants.FEATURE_CONFIGURATIONS) ) {
- for(final JsonValue val : checkTypeArray("Prototype removal configuration", removalObj.get(JSONConstants.FEATURE_CONFIGURATIONS))) {
- final String propVal = checkTypeString("Prototype removal configuration", val);
- if ( propVal.startsWith("#") ) {
- continue;
- }
- prototype.getConfigurationRemovals().add(propVal);
- }
- }
- if ( removalObj.containsKey(JSONConstants.FEATURE_FRAMEWORK_PROPERTIES) ) {
- for(final JsonValue val : checkTypeArray("Prototype removal framework properties", removalObj.get(JSONConstants.FEATURE_FRAMEWORK_PROPERTIES))) {
- final String propVal = checkTypeString("Prototype removal framework properties", val);
- if ( propVal.startsWith("#") ) {
- continue;
- }
- prototype.getFrameworkPropertiesRemovals().add(propVal);
- }
- }
- if ( removalObj.containsKey(JSONConstants.PROTOTYPE_EXTENSION_REMOVALS) ) {
- for(final JsonValue val : checkTypeArray("Prototype removal extensions", removalObj.get(JSONConstants.PROTOTYPE_EXTENSION_REMOVALS))) {
- checkTypeObjectOrString("Prototype removal extension", val);
- if ( val.getValueType() == ValueType.STRING ) {
- final String propVal = org.apache.felix.cm.json.Configurations.convertToObject(val).toString();
- if ( propVal.startsWith("#")) {
- continue;
- }
- prototype.getExtensionRemovals().add(propVal);
- } else {
- final JsonObject removalMap = (JsonObject)val;
- final JsonValue nameObj = removalMap.get("name");
- final String name = checkTypeString("Prototype removal extension", nameObj);
- if ( removalMap.containsKey("artifacts") ) {
- final List<ArtifactId> ids = new ArrayList<>();
- for(final JsonValue aid : checkTypeArray("Prototype removal extension artifacts", removalMap.get("artifacts"))) {
- if ( checkTypeString("Prototype removal extension artifact", aid).startsWith("#")) {
- continue;
- }
- ids.add(checkTypeArtifactId("Prototype removal extension artifact", aid));
- }
- prototype.getArtifactExtensionRemovals().put(name, ids);
- } else {
- prototype.getExtensionRemovals().add(name);
- }
- }
- }
- }
- readRequirements(removalObj, prototype.getRequirementRemovals());
- readCapabilities(removalObj, prototype.getCapabilityRemovals());
-
- }
- }
- return prototype;
- }
- return null;
- }
-
- private void readRequirements(final JsonObject json, final List<MatchingRequirement> container)
- throws IOException {
- if ( json.containsKey(JSONConstants.FEATURE_REQUIREMENTS)) {
- for(final JsonValue req : checkTypeArray(JSONConstants.FEATURE_REQUIREMENTS, json.get(JSONConstants.FEATURE_REQUIREMENTS))) {
- final JsonObject obj = checkTypeObject("Requirement", req);
-
- if ( !obj.containsKey(JSONConstants.REQCAP_NAMESPACE) ) {
- throw new IOException(this.exceptionPrefix.concat("Namespace is missing for requirement"));
- }
- final String namespace = checkTypeString("Requirement namespace", obj.get(JSONConstants.REQCAP_NAMESPACE));
-
- Map<String, Object> attrMap = new HashMap<>();
- if ( obj.containsKey(JSONConstants.REQCAP_ATTRIBUTES) ) {
- final JsonObject attrs = checkTypeObject("Requirement attributes", obj.get(JSONConstants.REQCAP_ATTRIBUTES));
- attrs.forEach(rethrowBiConsumer((key, value) -> ManifestUtils.unmarshalAttribute(key, value, attrMap::put)));
- }
-
- Map<String, String> dirMap = new HashMap<>();
- if ( obj.containsKey(JSONConstants.REQCAP_DIRECTIVES) ) {
- final JsonObject dirs = checkTypeObject("Requirement directives", obj.get(JSONConstants.REQCAP_DIRECTIVES));
- dirs.forEach(rethrowBiConsumer((key, value) -> ManifestUtils.unmarshalDirective(key, value, dirMap::put)));
- }
-
- final MatchingRequirement r = new MatchingRequirementImpl(null,
- namespace, dirMap, attrMap);
- container.add(r);
- }
- }
- }
-
- private void readCapabilities(final JsonObject json, final List<Capability> container) throws IOException {
- if ( json.containsKey(JSONConstants.FEATURE_CAPABILITIES)) {
- for(final JsonValue cap : checkTypeArray(JSONConstants.FEATURE_REQUIREMENTS, json.get(JSONConstants.FEATURE_CAPABILITIES))) {
- final JsonObject obj = checkTypeObject("Capability", cap);
-
- if ( !obj.containsKey(JSONConstants.REQCAP_NAMESPACE) ) {
- throw new IOException(this.exceptionPrefix.concat("Namespace is missing for capability"));
- }
- final String namespace = checkTypeString("Capability namespace", obj.get(JSONConstants.REQCAP_NAMESPACE));
-
- Map<String, Object> attrMap = new HashMap<>();
- if ( obj.containsKey(JSONConstants.REQCAP_ATTRIBUTES) ) {
- final JsonObject attrs = checkTypeObject("Capability attributes", obj.get(JSONConstants.REQCAP_ATTRIBUTES));
- attrs.forEach(rethrowBiConsumer((key, value) -> ManifestUtils.unmarshalAttribute(key, value, attrMap::put)));
- }
-
- Map<String, String> dirMap = new HashMap<>();
- if ( obj.containsKey(JSONConstants.REQCAP_DIRECTIVES) ) {
- final JsonObject dirs = checkTypeObject("Capability directives", obj.get(JSONConstants.REQCAP_DIRECTIVES));
- dirs.forEach(rethrowBiConsumer((key, value) -> ManifestUtils.unmarshalDirective(key, value, dirMap::put)));
- }
-
- final Capability c = new CapabilityImpl(null, namespace, dirMap, attrMap);
- container.add(c);
- }
- }
- }
-
- @FunctionalInterface
- private interface BiConsumer_WithExceptions<T, V, E extends Exception> {
- void accept(T t, V u) throws E;
- }
-
- private static <T, V, E extends Exception> BiConsumer<T, V> rethrowBiConsumer(BiConsumer_WithExceptions<T, V, E> biConsumer) {
- return (t, u) -> {
- try {
- biConsumer.accept(t, u);
- } catch (Exception exception) {
- throwAsUnchecked(exception);
- }
- };
- }
-
- @SuppressWarnings ("unchecked")
- private static <E extends Throwable> void throwAsUnchecked(Exception exception) throws E {
- throw (E) exception;
- }
-
- private static class MatchingRequirementImpl extends RequirementImpl implements MatchingRequirement {
-
- public MatchingRequirementImpl(Resource res, String ns, Map<String, String> dirs, Map<String, Object> attrs) {
- super(res, ns, dirs, attrs);
- }
- }
-
- /**
- * Read a full feature
- * @param reader The reader
- * @return The feature object
- * @throws IOException If an IO error occurs or the JSON is not valid.
- */
- private Feature readFeature(final Reader reader)
- throws IOException {
- final JsonObject json = Json.createReader(org.apache.felix.cm.json.Configurations.jsonCommentAwareReader(reader)).readObject();
-
- checkModelVersion(json);
-
- final ArtifactId featureId = this.getFeatureId(json);
- this.feature = new Feature(featureId);
- this.feature.setLocation(this.location);
-
- // final flag
- if (json.containsKey(JSONConstants.FEATURE_FINAL)) {
- this.feature.setFinal(checkTypeBoolean(JSONConstants.FEATURE_FINAL, json.get(JSONConstants.FEATURE_FINAL)));
- }
-
- // complete flag
- if (json.containsKey(JSONConstants.FEATURE_COMPLETE)) {
- this.feature.setComplete(checkTypeBoolean(JSONConstants.FEATURE_COMPLETE, json.get(JSONConstants.FEATURE_COMPLETE)));
- }
-
- // title, description, vendor and license
- this.feature.setTitle(getProperty(json, JSONConstants.FEATURE_TITLE));
- this.feature.setDescription(getProperty(json, JSONConstants.FEATURE_DESCRIPTION));
- this.feature.setVendor(getProperty(json, JSONConstants.FEATURE_VENDOR));
- this.feature.setLicense(getProperty(json, JSONConstants.FEATURE_LICENSE));
-
- this.readVariables(json, feature.getVariables());
- this.readBundles(json, feature.getBundles(), feature.getConfigurations());
- this.readFrameworkProperties(json, feature.getFrameworkProperties());
- this.readConfigurations(json, feature.getConfigurations());
-
- this.readCapabilities(json, feature.getCapabilities());
- this.readRequirements(json, feature.getRequirements());
- this.feature.setPrototype(this.readPrototype(json));
-
- this.readExtensions(json,
- JSONConstants.FEATURE_KNOWN_PROPERTIES,
- this.feature.getExtensions(), this.feature.getConfigurations());
-
- return this.feature;
- }
-
- private void checkModelVersion(final JsonObject json) throws IOException {
- String modelVersion = getProperty(json, JSONConstants.FEATURE_MODEL_VERSION);
- if (modelVersion == null) {
- modelVersion = "1";
- }
- if (!"1".equals(modelVersion)) {
- throw new IOException(this.exceptionPrefix.concat("Unsupported model version: ").concat(modelVersion));
- }
- }
-}
-
-
diff --git a/src/main/java/org/apache/sling/feature/io/json/FeatureJSONWriter.java b/src/main/java/org/apache/sling/feature/io/json/FeatureJSONWriter.java
deleted file mode 100644
index cf33b13..0000000
--- a/src/main/java/org/apache/sling/feature/io/json/FeatureJSONWriter.java
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * 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.io.json;
-
-import java.io.FilterWriter;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-
-import javax.json.Json;
-import javax.json.stream.JsonGenerator;
-import javax.json.stream.JsonGeneratorFactory;
-
-import org.apache.felix.cm.json.ConfigurationResource;
-import org.apache.felix.cm.json.ConfigurationWriter;
-import org.apache.sling.feature.Artifact;
-import org.apache.sling.feature.ArtifactId;
-import org.apache.sling.feature.Bundles;
-import org.apache.sling.feature.Configuration;
-import org.apache.sling.feature.Configurations;
-import org.apache.sling.feature.Extension;
-import org.apache.sling.feature.ExtensionType;
-import org.apache.sling.feature.Feature;
-import org.apache.sling.feature.MatchingRequirement;
-import org.apache.sling.feature.Prototype;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-
-/**
- * This class offers a static method to write a feature using a writer.
- */
-public class FeatureJSONWriter {
-
- /**
- * Writes the feature to the writer.
- * The writer is not closed.
- * @param writer Writer
- * @param feature Feature
- * @throws IOException If writing fails
- */
- public static void write(final Writer writer, final Feature feature)
- throws IOException {
- final FeatureJSONWriter w = new FeatureJSONWriter();
- w.writeFeature(writer, feature);
- }
-
- private final JsonGeneratorFactory generatorFactory = Json.createGeneratorFactory(Collections.singletonMap(JsonGenerator.PRETTY_PRINTING, true));
-
- private final JsonGenerator newGenerator(final Writer writer) {
- // prevent closing of the underlying writer
- return generatorFactory.createGenerator(new FilterWriter(writer) {
-
- @Override
- public void close() throws IOException {
- super.flush();
- }
- });
- }
-
- private void writeBundles(final JsonGenerator generator,
- final Bundles bundles,
- final Configurations allConfigs) {
- // bundles
- if ( !bundles.isEmpty() ) {
- generator.writeStartArray(JSONConstants.FEATURE_BUNDLES);
-
- for(final Artifact artifact : bundles) {
- final Configurations cfgs = new Configurations();
- for(final Configuration cfg : allConfigs) {
- final String artifactProp = (String)cfg.getProperties().get(Configuration.PROP_ARTIFACT_ID);
- if ( artifact.getId().toMvnId().equals(artifactProp) ) {
- cfgs.add(cfg);
- }
- }
- Map<String,String> md = artifact.getMetadata();
- if ( md.isEmpty() && cfgs.isEmpty() ) {
- generator.write(artifact.getId().toMvnId());
- } else {
- generator.writeStartObject();
- generator.write(JSONConstants.ARTIFACT_ID, artifact.getId().toMvnId());
-
- Object runmodes = md.remove("runmodes");
- if (runmodes instanceof String) {
- md.put("run-modes", (String) runmodes);
- }
-
- for(final Map.Entry<String, String> me : md.entrySet()) {
- generator.write(me.getKey(), me.getValue());
- }
-
- generator.writeEnd();
- }
- }
-
- generator.writeEnd();
- }
- }
-
- /**
- * Write the list of configurations into a "configurations" element
- * @param generator The json generator
- * @param cfgs The list of configurations
- * @throws IOException
- */
- private void writeConfigurations(final JsonGenerator generator, final Configurations cfgs) throws IOException {
- if ( cfgs.isEmpty() ) {
- return;
- }
-
- generator.writeKey(JSONConstants.FEATURE_CONFIGURATIONS);
-
- final ConfigurationWriter cfgWriter = org.apache.felix.cm.json.Configurations
- .buildWriter()
- .build(generator);
-
- final ConfigurationResource rsrc = new ConfigurationResource();
- for(final Configuration cfg : cfgs) {
- final Hashtable<String, Object> properties;
- if ( cfg.getProperties() instanceof Hashtable && cfg.getProperties().get(Configuration.PROP_ARTIFACT_ID) == null ) {
- properties = (Hashtable<String, Object>)cfg.getProperties();
- } else {
- properties = org.apache.felix.cm.json.Configurations.newConfiguration();
- for(final String name : Collections.list(cfg.getProperties().keys()) ) {
- if ( !Configuration.PROP_ARTIFACT_ID.equals(name) ) {
- properties.put(name, cfg.getProperties().get(name));
- }
- }
- }
- rsrc.getConfigurations().put(cfg.getPid(), properties);
- }
- cfgWriter.writeConfigurationResource(rsrc);
- }
-
- private void writeVariables(final JsonGenerator generator, final Map<String,String> vars) {
- if ( !vars.isEmpty()) {
- generator.writeStartObject(JSONConstants.FEATURE_VARIABLES);
-
- for (final Map.Entry<String, String> entry : vars.entrySet()) {
- String val = entry.getValue();
- if (val != null)
- generator.write(entry.getKey(), val);
- else
- generator.writeNull(entry.getKey());
- }
-
- generator.writeEnd();
- }
- }
-
- private void writeFrameworkProperties(final JsonGenerator generator, final Map<String,String> props) {
- // framework properties
- if ( !props.isEmpty() ) {
- generator.writeStartObject(JSONConstants.FEATURE_FRAMEWORK_PROPERTIES);
- for(final Map.Entry<String, String> entry : props.entrySet()) {
- generator.write(entry.getKey(), entry.getValue());
- }
- generator.writeEnd();
- }
- }
-
- private void writeExtensions(final JsonGenerator generator,
- final List<Extension> extensions,
- final Configurations allConfigs) throws IOException {
- for(final Extension ext : extensions) {
- final String state;
- switch (ext.getState()) {
- case OPTIONAL:
- state = "false";
- break;
- case REQUIRED:
- state = "true";
- break;
- default:
- state = ext.getState().name();
- }
- final String key = ext.getName().concat(":").concat(ext.getType().name()).concat("|").concat(state);
- if ( ext.getType() == ExtensionType.JSON ) {
- generator.write(key, ext.getJSONStructure());
- } else if ( ext.getType() == ExtensionType.TEXT ) {
- generator.writeStartArray(key);
- for(String line : ext.getText().split("\n")) {
- generator.write(line);
- }
- generator.writeEnd();
- } else {
- generator.writeStartArray(key);
- for(final Artifact artifact : ext.getArtifacts()) {
- final Configurations artifactCfgs = new Configurations();
- for(final Configuration cfg : allConfigs) {
- final String artifactProp = (String)cfg.getProperties().get(Configuration.PROP_ARTIFACT_ID);
- if ( artifact.getId().toMvnId().equals(artifactProp) ) {
- artifactCfgs.add(cfg);
- }
- }
- if ( artifact.getMetadata().isEmpty() && artifactCfgs.isEmpty() ) {
- generator.write(artifact.getId().toMvnId());
- } else {
- generator.writeStartObject();
- generator.write(JSONConstants.ARTIFACT_ID, artifact.getId().toMvnId());
-
- for(final Map.Entry<String, String> me : artifact.getMetadata().entrySet()) {
- generator.write(me.getKey(), me.getValue());
- }
-
- writeConfigurations(generator, artifactCfgs);
-
- generator.writeEnd();
- }
- }
- generator.writeEnd();
- }
- }
- }
-
- private void writeProperty(final JsonGenerator generator, final String key, final String value) {
- if ( value != null ) {
- generator.write(key, value);
- }
- }
-
- private <T> void writeList(final JsonGenerator generator, final String name, final Collection<T> values) {
- if (!values.isEmpty()) {
- generator.writeStartArray(name);
- for (T value : values) {
- generator.write(value.toString());
- }
- generator.writeEnd();
- }
- }
-
- private void writePrototype(final JsonGenerator generator, final Prototype inc) {
- if (inc == null) {
- return;
- }
-
- if ( inc.getArtifactExtensionRemovals().isEmpty()
- && inc.getBundleRemovals().isEmpty()
- && inc.getConfigurationRemovals().isEmpty()
- && inc.getFrameworkPropertiesRemovals().isEmpty()
- && inc.getRequirementRemovals().isEmpty()
- && inc.getCapabilityRemovals().isEmpty() ) {
-
- generator.write(JSONConstants.FEATURE_PROTOTYPE, inc.getId().toMvnId());
- } else {
- generator.writeStartObject(JSONConstants.FEATURE_PROTOTYPE);
- writeProperty(generator, JSONConstants.ARTIFACT_ID, inc.getId().toMvnId());
-
- generator.writeStartObject(JSONConstants.PROTOTYPE_REMOVALS);
-
- if ( !inc.getArtifactExtensionRemovals().isEmpty()
- || inc.getExtensionRemovals().isEmpty() ) {
- generator.writeStartArray(JSONConstants.PROTOTYPE_EXTENSION_REMOVALS);
-
- for(final String id : inc.getExtensionRemovals()) {
- generator.write(id);
- }
- for(final Map.Entry<String, List<ArtifactId>> entry : inc.getArtifactExtensionRemovals().entrySet()) {
- generator.writeStartObject();
-
- writeList(generator, entry.getKey(), entry.getValue());
-
- generator.writeEnd();
- }
-
- generator.writeEnd();
- }
- writeList(generator, JSONConstants.FEATURE_CONFIGURATIONS, inc.getConfigurationRemovals());
- writeList(generator, JSONConstants.FEATURE_BUNDLES, inc.getBundleRemovals());
- writeList(generator, JSONConstants.FEATURE_FRAMEWORK_PROPERTIES, inc.getFrameworkPropertiesRemovals());
-
- writeRequirements(generator, inc.getRequirementRemovals());
- writeCapabilities(generator, inc.getCapabilityRemovals());
-
- generator.writeEnd().writeEnd();
- }
- }
-
- private void writeRequirements(final JsonGenerator generator, final List<MatchingRequirement> requirements) {
- if (requirements.isEmpty()) {
- return;
- }
-
- generator.writeStartArray(JSONConstants.FEATURE_REQUIREMENTS);
-
- for(final Requirement req : requirements) {
- generator.writeStartObject();
- writeProperty(generator, JSONConstants.REQCAP_NAMESPACE, req.getNamespace());
- if ( !req.getAttributes().isEmpty() ) {
- generator.writeStartObject(JSONConstants.REQCAP_ATTRIBUTES);
- req.getAttributes().forEach((key, value) -> ManifestUtils.marshalAttribute(key, value, generator::write));
- generator.writeEnd();
- }
- if ( !req.getDirectives().isEmpty() ) {
- generator.writeStartObject(JSONConstants.REQCAP_DIRECTIVES);
- req.getDirectives().forEach((key, value) -> ManifestUtils.marshalDirective(key, value, generator::write));
- generator.writeEnd();
- }
- generator.writeEnd();
- }
-
- generator.writeEnd();
- }
-
- private void writeCapabilities(final JsonGenerator generator, final List<Capability> capabilities) {
- if (capabilities.isEmpty()) {
- return;
- }
-
- generator.writeStartArray(JSONConstants.FEATURE_CAPABILITIES);
-
- for(final Capability cap : capabilities) {
- generator.writeStartObject();
- writeProperty(generator, JSONConstants.REQCAP_NAMESPACE, cap.getNamespace());
- if ( !cap.getAttributes().isEmpty() ) {
- generator.writeStartObject(JSONConstants.REQCAP_ATTRIBUTES);
- cap.getAttributes().forEach((key, value) -> ManifestUtils.marshalAttribute(key, value, generator::write));
- generator.writeEnd();
- }
- if ( !cap.getDirectives().isEmpty() ) {
- generator.writeStartObject(JSONConstants.REQCAP_DIRECTIVES);
- cap.getDirectives().forEach((key, value) -> ManifestUtils.marshalDirective(key, value, generator::write));
- generator.writeEnd();
- }
- generator.writeEnd();
- }
-
- generator.writeEnd();
- }
-
- /**
- * Writes the feature to the writer.
- * The writer is not closed.
- * @param writer Writer
- * @param feature Feature
- * @throws IOException If writing fails
- */
- private void writeFeature(final Writer writer, final Feature feature)
- throws IOException {
- JsonGenerator generator = newGenerator(writer);
- generator.writeStartObject();
-
- writeFeatureId(generator, feature);
-
- if (feature.isFinal()) {
- generator.write(JSONConstants.FEATURE_FINAL, true);
- }
-
- if (feature.isComplete()) {
- generator.write(JSONConstants.FEATURE_COMPLETE, true);
- }
-
- // title, description, vendor, license
- writeProperty(generator, JSONConstants.FEATURE_TITLE, feature.getTitle());
- writeProperty(generator, JSONConstants.FEATURE_DESCRIPTION, feature.getDescription());
- writeProperty(generator, JSONConstants.FEATURE_VENDOR, feature.getVendor());
- writeProperty(generator, JSONConstants.FEATURE_LICENSE, feature.getLicense());
-
- // variables
- writeVariables(generator, feature.getVariables());
-
- // prototype
- writePrototype(generator, feature.getPrototype());
-
- // requirements
- writeRequirements(generator, feature.getRequirements());
-
- // capabilities
- writeCapabilities(generator, feature.getCapabilities());
-
- // bundles
- writeBundles(generator, feature.getBundles(), feature.getConfigurations());
-
- // configurations
- final Configurations cfgs = new Configurations();
- for(final Configuration cfg : feature.getConfigurations()) {
- final String artifactProp = (String)cfg.getProperties().get(Configuration.PROP_ARTIFACT_ID);
- if ( artifactProp == null ) {
- cfgs.add(cfg);
- }
- }
- writeConfigurations(generator, cfgs);
-
- // framework properties
- writeFrameworkProperties(generator, feature.getFrameworkProperties());
-
- // extensions
- writeExtensions(generator, feature.getExtensions(), feature.getConfigurations());
-
- generator.writeEnd().close();
- }
-
- private void writeFeatureId(final JsonGenerator generator,
- final Feature feature) {
- writeProperty(generator, JSONConstants.FEATURE_ID, feature.getId().toMvnId());
- }
-
-}
diff --git a/src/main/java/org/apache/sling/feature/io/json/JSONConstants.java b/src/main/java/org/apache/sling/feature/io/json/JSONConstants.java
deleted file mode 100644
index 9d665fb..0000000
--- a/src/main/java/org/apache/sling/feature/io/json/JSONConstants.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.io.json;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.sling.feature.Configuration;
-
-public abstract class JSONConstants {
-
- static final String FEATURE_ID = "id";
-
- static final String FEATURE_VARIABLES = "variables";
-
- static final String FEATURE_BUNDLES = "bundles";
-
- static final String FEATURE_FRAMEWORK_PROPERTIES = "framework-properties";
-
- static final String FEATURE_CONFIGURATIONS = "configurations";
-
- static final String FEATURE_PROTOTYPE = "prototype";
-
- static final String FEATURE_REQUIREMENTS = "requirements";
-
- static final String FEATURE_CAPABILITIES = "capabilities";
-
- static final String FEATURE_TITLE = "title";
-
- static final String FEATURE_DESCRIPTION = "description";
-
- static final String FEATURE_VENDOR = "vendor";
-
- static final String FEATURE_LICENSE = "license";
-
- static final String FEATURE_FINAL = "final";
-
- static final String FEATURE_COMPLETE = "complete";
-
- static final String FEATURE_MODEL_VERSION = "model-version";
-
- static final List<String> FEATURE_KNOWN_PROPERTIES = Arrays.asList(FEATURE_ID,
- FEATURE_MODEL_VERSION,
- FEATURE_VARIABLES,
- FEATURE_BUNDLES,
- FEATURE_FRAMEWORK_PROPERTIES,
- FEATURE_CONFIGURATIONS,
- FEATURE_PROTOTYPE,
- FEATURE_REQUIREMENTS,
- FEATURE_CAPABILITIES,
- FEATURE_TITLE,
- FEATURE_DESCRIPTION,
- FEATURE_VENDOR,
- FEATURE_FINAL,
- FEATURE_COMPLETE,
- FEATURE_LICENSE);
-
- static final String ARTIFACT_ID = "id";
-
- static final List<String> ARTIFACT_KNOWN_PROPERTIES = Arrays.asList(ARTIFACT_ID,
- Configuration.PROP_ARTIFACT_ID,
- FEATURE_CONFIGURATIONS);
-
- static final String PROTOTYPE_REMOVALS = "removals";
-
- static final String PROTOTYPE_EXTENSION_REMOVALS = "extensions";
-
- static final String REQCAP_NAMESPACE = "namespace";
- static final String REQCAP_ATTRIBUTES = "attributes";
- static final String REQCAP_DIRECTIVES = "directives";
-}
diff --git a/src/main/java/org/apache/sling/feature/io/json/ManifestUtils.java b/src/main/java/org/apache/sling/feature/io/json/ManifestUtils.java
deleted file mode 100644
index dae75c8..0000000
--- a/src/main/java/org/apache/sling/feature/io/json/ManifestUtils.java
+++ /dev/null
@@ -1,518 +0,0 @@
-/*
- * 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.io.json;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.function.BiConsumer;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-import javax.json.JsonValue;
-
-import org.apache.felix.cm.json.Configurations;
-import org.apache.felix.utils.resource.CapabilityImpl;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Version;
-import org.osgi.resource.Capability;
-
-// This class can be picked up from Felix Utils once it has been moved there. At that point
-// this class can be removed.
-class ManifestUtils {
- public static void unmarshalAttribute(String key, JsonValue value, BiConsumer<String, Object> sink) throws IOException {
- unmarshal(key.concat("=").concat(Configurations.convertToObject(value).toString()), Capability::getAttributes, sink);
- }
-
- public static void unmarshalDirective(String key, JsonValue value, BiConsumer<String, String> sink) throws IOException {
- unmarshal(key.concat(":=").concat(Configurations.convertToObject(value).toString()), Capability::getDirectives, sink);
- }
-
- private static <T> void unmarshal(String header, Function<Capability, Map<String, T>> lookup, BiConsumer<String, T> sink) throws IOException {
- try {
- convertProvideCapabilities(
- normalizeCapabilityClauses(parseStandardHeader("foo;".concat(header)), "2"))
- .forEach(capability -> lookup.apply(capability).forEach(sink));
- } catch (Exception e) {
- throw new IOException(e);
- }
- }
-
- public static void marshalAttribute(String key, Object value, BiConsumer<String, String> sink) {
- marshal(key, value, sink);
- }
-
- public static void marshalDirective(String key, Object value, BiConsumer<String, String> sink) {
- marshal(key, value, sink);
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- private static void marshal(String key, Object value, BiConsumer<String, String> sink) {
- StringBuilder keyBuilder = new StringBuilder(key);
- if (value instanceof List) {
- List list = (List) value;
- keyBuilder.append(":List");
- if (!list.isEmpty()) {
- String type = type(list.get(0));
- if (!type.equals("String")) {
- keyBuilder.append('<').append(type).append('>');
- }
- value = list.stream().map(
- v -> v.toString().replace(",", "\\,")
- ).collect(Collectors.joining(","));
- }
- else {
- value = "";
- }
- }
- else {
- String type = type(value);
- if (!type.equals("String")) {
- keyBuilder.append(':').append(type);
- }
- }
- sink.accept(keyBuilder.toString(), value.toString());
- }
-
- private static String type(Object value) {
- if (value instanceof Long) {
- return "Long";
- }
- else if (value instanceof Double)
- {
- return "Double";
- }
- else if (value instanceof Version)
- {
- return "Version";
- }
- else
- {
- return "String";
- }
- }
-
- public static List<Capability> convertProvideCapabilities(
- List<ParsedHeaderClause> clauses)
- throws BundleException
- {
- List<Capability> capList = new ArrayList<>();
- for (ParsedHeaderClause clause : clauses)
- {
- for (String path : clause.m_paths)
- {
- if (path.startsWith("osgi.wiring."))
- {
- throw new BundleException("Manifest cannot use Provide-Capability for '"
- + path
- + "' namespace.");
- }
-
- Capability capability = new CapabilityImpl(null, path, clause.m_dirs, clause.m_attrs);
- // Create package capability and add to capability list.
- capList.add(capability);
- }
- }
-
- return capList;
- }
-
- public static List<ParsedHeaderClause> normalizeCapabilityClauses(
- List<ParsedHeaderClause> clauses, String mv)
- throws BundleException
- {
-
- if (!mv.equals("2") && !clauses.isEmpty())
- {
- // Should we error here if we are not an R4 bundle?
- }
-
- // Convert attributes into specified types.
- for (ParsedHeaderClause clause : clauses)
- {
- for (Entry<String, String> entry : clause.m_types.entrySet())
- {
- String type = entry.getValue();
- if (!type.equals("String"))
- {
- if (type.equals("Double"))
- {
- clause.m_attrs.put(
- entry.getKey(),
- new Double(clause.m_attrs.get(entry.getKey()).toString().trim()));
- }
- else if (type.equals("Version"))
- {
- clause.m_attrs.put(
- entry.getKey(),
- new Version(clause.m_attrs.get(entry.getKey()).toString().trim()));
- }
- else if (type.equals("Long"))
- {
- clause.m_attrs.put(
- entry.getKey(),
- new Long(clause.m_attrs.get(entry.getKey()).toString().trim()));
- }
- else if (type.startsWith("List"))
- {
- int startIdx = type.indexOf('<');
- int endIdx = type.indexOf('>');
- if (((startIdx > 0) && (endIdx <= startIdx))
- || ((startIdx < 0) && (endIdx > 0)))
- {
- throw new BundleException(
- "Invalid Provide-Capability attribute list type for '"
- + entry.getKey()
- + "' : "
- + type);
- }
-
- String listType = "String";
- if (endIdx > startIdx)
- {
- listType = type.substring(startIdx + 1, endIdx).trim();
- }
-
- List<String> tokens = parseDelimitedString(
- clause.m_attrs.get(entry.getKey()).toString(), ",", false);
- List<Object> values = new ArrayList<>(tokens.size());
- for (String token : tokens)
- {
- if (listType.equals("String"))
- {
- values.add(token);
- }
- else if (listType.equals("Double"))
- {
- values.add(new Double(token.trim()));
- }
- else if (listType.equals("Version"))
- {
- values.add(new Version(token.trim()));
- }
- else if (listType.equals("Long"))
- {
- values.add(new Long(token.trim()));
- }
- else
- {
- throw new BundleException(
- "Unknown Provide-Capability attribute list type for '"
- + entry.getKey()
- + "' : "
- + type);
- }
- }
- clause.m_attrs.put(
- entry.getKey(),
- values);
- }
- else
- {
- throw new BundleException(
- "Unknown Provide-Capability attribute type for '"
- + entry.getKey()
- + "' : "
- + type);
- }
- }
- }
- }
-
- return clauses;
- }
-
- private static final char EOF = (char) -1;
-
- private static char charAt(int pos, String headers, int length)
- {
- if (pos >= length)
- {
- return EOF;
- }
- return headers.charAt(pos);
- }
-
- private static final int CLAUSE_START = 0;
- private static final int PARAMETER_START = 1;
- private static final int KEY = 2;
- private static final int DIRECTIVE_OR_TYPEDATTRIBUTE = 4;
- private static final int ARGUMENT = 8;
- private static final int VALUE = 16;
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static List<ParsedHeaderClause> parseStandardHeader(String header)
- {
- List<ParsedHeaderClause> clauses = new ArrayList<>();
- if (header == null)
- {
- return clauses;
- }
- ParsedHeaderClause clause = null;
- String key = null;
- Map targetMap = null;
- int state = CLAUSE_START;
- int currentPosition = 0;
- int startPosition = 0;
- int length = header.length();
- boolean quoted = false;
- boolean escaped = false;
-
- char currentChar = EOF;
- do
- {
- currentChar = charAt(currentPosition, header, length);
- switch (state)
- {
- case CLAUSE_START:
- clause = new ParsedHeaderClause(
- new ArrayList<>(),
- new HashMap<>(),
- new HashMap<>(),
- new HashMap<>());
- clauses.add(clause);
- state = PARAMETER_START;
- case PARAMETER_START:
- startPosition = currentPosition;
- state = KEY;
- case KEY:
- switch (currentChar)
- {
- case ':':
- case '=':
- key = header.substring(startPosition, currentPosition).trim();
- startPosition = currentPosition + 1;
- targetMap = clause.m_attrs;
- state = currentChar == ':' ? DIRECTIVE_OR_TYPEDATTRIBUTE : ARGUMENT;
- break;
- case EOF:
- case ',':
- case ';':
- clause.m_paths.add(header.substring(startPosition, currentPosition).trim());
- state = currentChar == ',' ? CLAUSE_START : PARAMETER_START;
- break;
- default:
- break;
- }
- currentPosition++;
- break;
- case DIRECTIVE_OR_TYPEDATTRIBUTE:
- switch(currentChar)
- {
- case '=':
- if (startPosition != currentPosition)
- {
- clause.m_types.put(key, header.substring(startPosition, currentPosition).trim());
- }
- else
- {
- targetMap = clause.m_dirs;
- }
- state = ARGUMENT;
- startPosition = currentPosition + 1;
- break;
- default:
- break;
- }
- currentPosition++;
- break;
- case ARGUMENT:
- if (currentChar == '\"')
- {
- quoted = true;
- currentPosition++;
- }
- else
- {
- quoted = false;
- }
- if (!Character.isWhitespace(currentChar)) {
- state = VALUE;
- }
- else {
- currentPosition++;
- }
- break;
- case VALUE:
- if (escaped)
- {
- escaped = false;
- }
- else
- {
- if (currentChar == '\\' )
- {
- escaped = true;
- }
- else if (quoted && currentChar == '\"')
- {
- quoted = false;
- }
- else if (!quoted)
- {
- String value = null;
- switch(currentChar)
- {
- case EOF:
- case ';':
- case ',':
- value = header.substring(startPosition, currentPosition).trim();
- if (value.startsWith("\"") && value.endsWith("\""))
- {
- value = value.substring(1, value.length() - 1);
- }
- if (targetMap.put(key, value) != null)
- {
- throw new IllegalArgumentException(
- "Duplicate '" + key + "' in: " + header);
- }
- state = currentChar == ';' ? PARAMETER_START : CLAUSE_START;
- break;
- default:
- break;
- }
- }
- }
- currentPosition++;
- break;
- default:
- break;
- }
- } while ( currentChar != EOF);
-
- if (state > PARAMETER_START)
- {
- throw new IllegalArgumentException("Unable to parse header: " + header);
- }
- return clauses;
- }
-
- /**
- * Parses delimited string and returns an array containing the tokens. This
- * parser obeys quotes, so the delimiter character will be ignored if it is
- * inside of a quote. This method assumes that the quote character is not
- * included in the set of delimiter characters.
- * @param value the delimited string to parse.
- * @param delim the characters delimiting the tokens.
- * @return a list of string or an empty list if there are none.
- **/
- public static List<String> parseDelimitedString(String value, String delim, boolean trim)
- {
- if (value == null)
- {
- value = "";
- }
-
- List<String> list = new ArrayList<>();
-
- int CHAR = 1;
- int DELIMITER = 2;
- int STARTQUOTE = 4;
- int ENDQUOTE = 8;
-
- StringBuffer sb = new StringBuffer();
-
- int expecting = (CHAR | DELIMITER | STARTQUOTE);
-
- boolean isEscaped = false;
- for (int i = 0; i < value.length(); i++)
- {
- char c = value.charAt(i);
-
- boolean isDelimiter = (delim.indexOf(c) >= 0);
-
- if (!isEscaped && (c == '\\'))
- {
- isEscaped = true;
- continue;
- }
-
- if (isEscaped)
- {
- sb.append(c);
- }
- else if (isDelimiter && ((expecting & DELIMITER) > 0))
- {
- if (trim)
- {
- list.add(sb.toString().trim());
- }
- else
- {
- list.add(sb.toString());
- }
- sb.delete(0, sb.length());
- expecting = (CHAR | DELIMITER | STARTQUOTE);
- }
- else if ((c == '"') && ((expecting & STARTQUOTE) > 0))
- {
- sb.append(c);
- expecting = CHAR | ENDQUOTE;
- }
- else if ((c == '"') && ((expecting & ENDQUOTE) > 0))
- {
- sb.append(c);
- expecting = (CHAR | STARTQUOTE | DELIMITER);
- }
- else if ((expecting & CHAR) > 0)
- {
- sb.append(c);
- }
- else
- {
- throw new IllegalArgumentException("Invalid delimited string: " + value);
- }
-
- isEscaped = false;
- }
-
- if (sb.length() > 0)
- {
- if (trim)
- {
- list.add(sb.toString().trim());
- }
- else
- {
- list.add(sb.toString());
- }
- }
-
- return list;
- }
-
- static class ParsedHeaderClause
- {
- public final List<String> m_paths;
- public final Map<String, String> m_dirs;
- public final Map<String, Object> m_attrs;
- public final Map<String, String> m_types;
-
- public ParsedHeaderClause(
- List<String> paths, Map<String, String> dirs, Map<String, Object> attrs,
- Map<String, String> types)
- {
- m_paths = paths;
- m_dirs = dirs;
- m_attrs = attrs;
- m_types = types;
- }
- }
-}
diff --git a/src/main/java/org/apache/sling/feature/io/json/package-info.java b/src/main/java/org/apache/sling/feature/io/json/package-info.java
deleted file mode 100644
index 54ecf2e..0000000
--- a/src/main/java/org/apache/sling/feature/io/json/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.
- */
-
-@org.osgi.annotation.versioning.Version("1.1.0")
-package org.apache.sling.feature.io.json;
-
-
diff --git a/src/main/java/org/apache/sling/feature/io/package-info.java b/src/main/java/org/apache/sling/feature/io/package-info.java
deleted file mode 100644
index 81fdbf9..0000000
--- a/src/main/java/org/apache/sling/feature/io/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.
- */
-
-@org.osgi.annotation.versioning.Version("1.1.0")
-package org.apache.sling.feature.io;
-
-
diff --git a/src/main/resources/META-INF/feature/Feature-1.0.0.schema.json b/src/main/resources/META-INF/feature/Feature-1.0.0.schema.json
deleted file mode 100644
index 9021482..0000000
--- a/src/main/resources/META-INF/feature/Feature-1.0.0.schema.json
+++ /dev/null
@@ -1,226 +0,0 @@
-{
- "$schema": "http://json-schema.org/draft-07/schema#",
- "$id": "http://sling.apache.org/Feature/1.0.0",
- "type": "object",
- "properties": {
- "model-version": {
- "type": "string"
- },
- "id": {
- "type": "string",
- "pattern": "^(([^: ]+):([^: ]+)(:([^: ]*)(:([^: ]+))?)?:([^: ]+)|([^/ ]+)/([^/ ]+)(/([^/ ]+))?(/([^/ ]*)(/([^/ ]+))?)?)$"
- },
- "final": {
- "type": "boolean"
- },
- "complete": {
- "type": "boolean"
- },
- "title": {
- "type": "string"
- },
- "description": {
- "type": "string"
- },
- "vendor": {
- "type": "string"
- },
- "license": {
- "type": "string"
- },
- "variables": {
- "type": "object",
- "patternProperties": {
- "^(.+)$": {
- "type": ["string","null"]
- }
- }
- },
- "bundles": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/Bundle"
- }
- },
- "framework-properties": {
- "type": "object",
- "patternProperties": {
- "^(.+)$": {
- "type": [ "string", "number", "boolean" ]
- }
- }
- },
- "configurations": {
- "type": "object",
- "patternProperties": {
- "^(.+)$": {
- "$ref": "#/definitions/Configuration"
- }
- }
- },
- "prototype": {
- "$ref": "#/definitions/Prototype"
- },
- "requirements": {
- " type": "array",
- "items": {
- "$ref": "#/definitions/Requirement"
- }
- },
- "capabilities": {
- " type": "array",
- "items": {
- "$ref": "#/definitions/Capability"
- }
- }
- },
- "patternProperties": {
- "^[^:]+:ARTIFACTS\\|(true|false)$": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/Bundle"
- }
- },
- "^[^:]+:TEXT\\|(true|false)$": {
- "type": [ "string", "array" ],
- "items": {
- "type": "string"
- }
- },
- "^[^:]+:JSON\\|(true|false)$": {
- "type": [
- "object",
- "array"
- ]
- }
- },
- "definitions": {
- "Bundle": {
- "$id": "#Bundle",
- "type": [
- "string",
- "object"
- ],
- "properties": {
- "id": {
- "type": "string",
- "pattern": "^(([^: ]+):([^: ]+)(:([^: ]*)(:([^: ]+))?)?:([^: ]+)|(mvn:)?([^/ ]+)/([^/ ]+)(/([^/ ]+))?(/([^/ ]*)(/([^/ ]+))?)?)$"
- },
- "start-level": {
- "type": [ "string", "number" ],
- "pattern": "^\\d+$"
- },
- "run-modes": {
- "type": [
- "string",
- "array"
- ],
- "items": {
- "type": "string"
- }
- },
- "configurations": {
- "type": "object",
- "patternProperties": {
- "^(.+)$": {
- "$ref": "#/definitions/Configuration"
- }
- }
- }
- }
- },
- "Configuration": {
- "$id": "#Configuration",
- "patternProperties": {
- "^(.+)$": {
- "type": [
- "string",
- "number",
- "boolean",
- "array",
- "object"
- ]
- }
- }
- },
- "Prototype": {
- "$id": "#Prototype",
- "type": "object",
- "properties": {
- "id": {
- "type": "string",
- "pattern": "^(([^: ]+):([^: ]+)(:([^: ]*)(:([^: ]+))?)?:([^: ]+)|(mvn:)?([^/ ]+)/([^/ ]+)(/([^/ ]+))?(/([^/ ]*)(/([^/ ]+))?)?)$"
- },
- "removals": {
- "$ref": "#/definitions/Removals"
- }
- }
- },
- "Removals": {
- "$id": "#Removals",
- "type": "object",
- "properties": {
- "configurations": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "bundles": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "framework-properties": {
- "type": "array",
- "items": {
- "type": "string"
- }
- }
- }
- },
- "Requirement": {
- "$id": "#Requirement",
- "type": "object",
- "properties": {
- "namespace": {
- "type": "string"
- },
- "directives": {
- "type": "object",
- "patternProperties": {
- "^(.+)$": {
- "type": "string"
- }
- }
- }
- }
- },
- "Capability": {
- "$id": "#Capability",
- "type": "object",
- "properties": {
- "namespace": {
- "type": "string"
- },
- "directives": {
- "type": "object",
- "patternProperties": {
- "^(.+)$": {
- "type": "string"
- }
- }
- },
- "attributes": {
- "type": "object",
- "patternProperties": {
- "^(.+)$": {
- "type": [ "string", "number", "boolean" ]
- }
- }
- }
- }
- }
- }
-}
diff --git a/src/test/java/org/apache/sling/feature/io/ConfiguratorUtilTest.java b/src/test/java/org/apache/sling/feature/io/ConfiguratorUtilTest.java
deleted file mode 100644
index 4ad71eb..0000000
--- a/src/test/java/org/apache/sling/feature/io/ConfiguratorUtilTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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.io;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.util.Arrays;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Objects;
-
-import org.apache.felix.cm.json.Configurations;
-import org.hamcrest.Description;
-import org.hamcrest.TypeSafeDiagnosingMatcher;
-import org.hamcrest.core.Every;
-import org.junit.Assert;
-import org.junit.Test;
-import org.osgi.util.converter.Converter;
-import org.osgi.util.converter.Converters;
-import org.osgi.util.converter.TypeReference;
-
-public class ConfiguratorUtilTest {
-
- @Test
- public void testConfigurationWriteReadRoundtrip() throws IOException {
- Dictionary<String, Object> props = new Hashtable<>();
- props.put("Integer-simple", 1);
- props.put("Integer-array", new Integer[]{1,2});
- props.put("Integer-list", Arrays.asList(1, 2));
- props.put("int-array", new int[]{1,2});
- props.put("Long-simple", 1);
- props.put("Long-array", new Long[]{1L,2L});
- props.put("Long-list", Arrays.asList(1l, 2l));
- props.put("long-array", new long[]{1,2});
- props.put("Boolean-simple", Boolean.TRUE);
- props.put("Boolean-array", new Boolean[] {Boolean.TRUE, Boolean.FALSE});
- props.put("Boolean-list", Arrays.asList(Boolean.TRUE, Boolean.FALSE));
- props.put("bool-array", new boolean[] {true, false});
- props.put("Float-simple", 1.0d);
- props.put("Float-array", new Float[]{1.0f, 2.0f});
- props.put("Float-list", Arrays.asList(1.0f, 2.0f));
- props.put("float-array", new float[]{1.0f,2.0f});
- props.put("Double-simple", 1.0d);
- props.put("Double-array", new Double[]{1.0d,2.0d});
- props.put("Double-list", Arrays.asList(1.0d, 2.0d));
- props.put("double-array", new double[]{1.0d,2.0d});
- props.put("Byte-simple", new Byte((byte)1));
- props.put("Byte-array", new Byte[]{1,2});
- props.put("Byte-list", Arrays.asList((byte)1, (byte)2));
- props.put("byte-array", new byte[]{1,2});
- props.put("Short-simple", new Short((short) 1));
- props.put("Short-array", new Short[]{1,2});
- props.put("Short-list", Arrays.asList((short)1, (short)2));
- props.put("Short-array", new short[]{1,2});
- props.put("Character-simple", 1);
- props.put("Character-array", new Character[]{'a','b'});
- props.put("Character-list", Arrays.asList('a', 'b'));
- props.put("char-array", new char[]{'a','b'});
- props.put("String-simple", "test");
- props.put("String-array", new String[]{"test1", "test2"});
- props.put("String-list", Arrays.asList("test1", "test2"));
- StringWriter writer = new StringWriter();
- ConfiguratorUtil.writeConfiguration(writer, props);
- writer.close();
- assertConfigurationJson(writer.toString(), props);
- }
-
- protected void assertConfigurationJson(String json, Dictionary<String, Object> expectedProps) throws IOException {
- final Hashtable<String, Object> readProps = Configurations.buildReader().verifyAsBundleResource(true).build(new StringReader(json)).readConfiguration();
- // convert to maps for easier comparison
- Converter converter = Converters.standardConverter();
- Map<String, Object> expectedPropsMap = converter.convert(expectedProps).to(new TypeReference<Map<String,Object>>(){});
- Map<String, Object> actualPropsMap = converter.convert(readProps).to(new TypeReference<Map<String,Object>>(){});
- Assert.assertThat(actualPropsMap.entrySet(), Every.everyItem(new MapEntryMatcher<>(expectedPropsMap)));
- }
-
- public static class MapEntryMatcher<K, V> extends TypeSafeDiagnosingMatcher<Map.Entry<K, V>> {
-
- private final Map<K,V> expectedMap;
-
- public MapEntryMatcher(Map<K, V> expectedMap) {
- this.expectedMap = expectedMap;
- }
-
- @Override
- public void describeTo(Description description) {
- description.appendText("contained in the expected map");
- }
-
- @Override
- protected boolean matchesSafely(Map.Entry<K, V> item, Description description) {
- if (expectedMap.get(item.getKey()) == null){
- description.appendText("key '" + item.getKey() + "' is not present");
- return false;
- } else {
- boolean isEqual;
- if (item.getValue().getClass().isArray()) {
- isEqual = Objects.deepEquals(expectedMap.get(item.getKey()), item.getValue());
-
- } else {
- isEqual = expectedMap.get(item.getKey()).equals(item.getValue());
- }
- if (!isEqual) {
- description.appendText("has the wrong value for key '" + item.getKey() + "': Expected=" + expectedMap.get(item.getKey()) + " (" + expectedMap.get(item.getKey()).getClass() + ")" + ", Actual=" + item.getValue() + " (" + item.getValue().getClass() + ")");
- }
- return isEqual;
- }
- }
- }
-}
diff --git a/src/test/java/org/apache/sling/feature/io/IOUtilsTest.java b/src/test/java/org/apache/sling/feature/io/IOUtilsTest.java
deleted file mode 100644
index 08920a4..0000000
--- a/src/test/java/org/apache/sling/feature/io/IOUtilsTest.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * 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.io;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLStreamHandler;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.jar.JarOutputStream;
-
-import org.junit.Test;
-
-public class IOUtilsTest {
-
- @Test public void testFileSort() {
- final String[] files = new String[] {
- "/different/path/app.json",
- "/path/to/base.json",
- "/path/to/feature.json",
- "/path/to/amode/feature.json",
- "/path/to/later/feature.json",
- "http://sling.apache.org/features/one.json",
- "http://sling.apache.org/features/two.json",
- "http://sling.apache.org/features/amode/feature.json"
- };
-
- final List<String> l = new ArrayList<>(Arrays.asList(files));
- Collections.sort(l, IOUtils.FEATURE_PATH_COMP);
- for(int i=0; i<files.length; i++) {
- assertEquals(files[i], l.get(i));
- }
- }
-
- @Test public void testGetFileFromURL() throws IOException {
- File file = File.createTempFile("IOUtilsTest", ".test");
-
- try {
- try (PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"))) {
- writer.println("Hello");
- }
-
- assertEquals(file, IOUtils.getFileFromURL(file.toURI().toURL(), false, null));
-
- URL url = new URL(null,"bla:" + file.toURI().toURL(), new URLStreamHandler() {
- @Override
- protected URLConnection openConnection(URL u){
- return new URLConnection(u) {
- @Override
- public void connect()
- {
-
- }
-
- @Override
- public InputStream getInputStream() throws IOException
- {
- return new FileInputStream(file);
- }
- };
- }
- });
-
- assertNull(IOUtils.getFileFromURL(url, false, null));
- File tmp = IOUtils.getFileFromURL(url, true, null);
-
- assertNotEquals(file, tmp);
- try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(tmp), "UTF-8"))) {
- assertEquals("Hello", reader.readLine());
- }
- } finally {
- file.delete();
- }
- File jarFile = File.createTempFile("IOUtilsTes", ".jar");
- try {
-
- try (JarOutputStream output = new JarOutputStream(new FileOutputStream(jarFile))) {
- output.putNextEntry(new JarEntry("test"));
- output.write("Hello".getBytes());
- output.closeEntry();
- }
-
- assertEquals(jarFile, IOUtils.getFileFromURL(new URL("jar:" + jarFile.toURI().toURL() + "!/"), false, null));
- assertNull(IOUtils.getFileFromURL(new URL("jar:file:" + jarFile.getPath() + "!/test"), false, null));
- File tmpJar = IOUtils.getFileFromURL(new URL("jar:" + jarFile.toURI().toURL() + "!/test"), true, null);
- assertNotNull(tmpJar);
- assertNotEquals(jarFile, tmpJar);
- } finally {
- jarFile.delete();
- }
- }
-
- @Test public void testGetJarFileFromURL() throws IOException {
- File jarFile = File.createTempFile("IOUtilsTest", ".jar");
-
- try {
- try (JarOutputStream output = new JarOutputStream(new FileOutputStream(jarFile))) {
- output.putNextEntry(new JarEntry("test"));
- output.write("Hello".getBytes());
- output.closeEntry();
- output.putNextEntry(new JarEntry("test.jar"));
- try (JarOutputStream inner = new JarOutputStream(output)) {
- inner.putNextEntry(new JarEntry("inner"));
- inner.write("Hello".getBytes());
- inner.closeEntry();
- }
- }
-
- JarFile jar = IOUtils.getJarFileFromURL(new URL("jar:" + jarFile.toURI().toURL() + "!/"), true, null);
- assertNotNull(jar);
- jar = IOUtils.getJarFileFromURL(jarFile.toURI().toURL(), true, null);
- assertNotNull(jar);
-
- assertNull(IOUtils.getFileFromURL(new URL("jar:" + jarFile.toURI().toURL() + "!/test"), false, null));
-
- JarFile tmpJar = IOUtils.getJarFileFromURL(new URL("jar:" + jarFile.toURI().toURL() + "!/test.jar"), true, null);
- assertNotNull(tmpJar);
- assertNotNull(tmpJar.getEntry("inner"));
-
- try {
- IOUtils.getJarFileFromURL(new URL("jar:" + jarFile.toURI().toURL() + "!/test"), true, null);
- fail();
- } catch (IOException ex) {
- // Expected
- }
-
- try {
- IOUtils.getJarFileFromURL(new URL("jar:" + jarFile.toURI().toURL() + "!/test.jar"), false, null);
- fail();
- } catch (IOException ex) {
- // Expected
- }
- } finally {
- jarFile.delete();
- }
- }
-}
diff --git a/src/test/java/org/apache/sling/feature/io/archive/ArchiveWriterTest.java b/src/test/java/org/apache/sling/feature/io/archive/ArchiveWriterTest.java
deleted file mode 100644
index ee3fa71..0000000
--- a/src/test/java/org/apache/sling/feature/io/archive/ArchiveWriterTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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.io.archive;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.sling.feature.Artifact;
-import org.apache.sling.feature.ArtifactId;
-import org.apache.sling.feature.Feature;
-import org.apache.sling.feature.io.json.FeatureJSONReader;
-import org.junit.Test;
-
-public class ArchiveWriterTest {
-
- public static final String ARTIFACT = "/features/final.json";
-
- @Test
- public void testArchiveWrite() throws IOException {
- final Feature f = new Feature(ArtifactId.parse("g:f:1"));
- f.getBundles().add(new Artifact(ArtifactId.parse("g:a:2")));
-
- byte[] archive = null;
- final Set<ArtifactId> ids = new HashSet<>();
- try (final ByteArrayOutputStream out = new ByteArrayOutputStream()) {
- ArchiveWriter.write(out, null, id -> {
- ids.add(id);
- return ArchiveWriterTest.class.getResource(ARTIFACT);
- }, f).finish();
- out.flush();
- archive = out.toByteArray();
- }
- assertEquals(1, ids.size());
- assertTrue(ids.contains(ArtifactId.parse("g:a:2")));
-
- // read "artifact"
- final byte[] artifactBytes;
- try (final InputStream is = ArchiveWriterTest.class.getResourceAsStream(ARTIFACT)) {
- artifactBytes = readFromStream(is);
- }
-
- final Set<ArtifactId> readIds = new HashSet<>();
- final Set<ArtifactId> readFeatureIds = new HashSet<>();
-
- final List<Feature> features = new ArrayList<>();
- try (final InputStream in = new ByteArrayInputStream(archive)) {
- features.addAll(ArchiveReader.read(in, (id, is) -> {
-
- // read contents
- byte[] read = readFromStream(is);
-
- // is feature?
- if ( id.equals(f.getId()) ) {
- try ( final Reader reader = new StringReader(new String(read, StandardCharsets.UTF_8))) {
- final Feature readFeature = FeatureJSONReader.read(reader, id.toString());
- assertEquals(f.getId(), readFeature.getId());
- readFeatureIds.add(f.getId());
- }
- } else {
- readIds.add(id);
- assertEquals(artifactBytes.length, read.length);
- assertArrayEquals(artifactBytes, read);
- }
- }));
- }
-
- assertEquals(1, readFeatureIds.size());
- assertTrue(readFeatureIds.contains(f.getId()));
-
- assertEquals(1, readIds.size());
- assertTrue(readIds.contains(ArtifactId.parse("g:a:2")));
-
- assertEquals(1, features.size());
- final Feature g = features.get(0);
- assertEquals(f.getId(), g.getId());
- }
-
- private byte[] readFromStream(final InputStream is) throws IOException {
- byte[] read;
- try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
- byte[] buf = new byte[1024];
- int l;
- while ((l = is.read(buf)) > 0) {
- baos.write(buf, 0, l);
- }
- baos.flush();
- read = baos.toByteArray();
- }
- return read;
- }
-}
diff --git a/src/test/java/org/apache/sling/feature/io/artifacts/ArtifactManagerTest.java b/src/test/java/org/apache/sling/feature/io/artifacts/ArtifactManagerTest.java
deleted file mode 100644
index fd106d3..0000000
--- a/src/test/java/org/apache/sling/feature/io/artifacts/ArtifactManagerTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.io.artifacts;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.sling.feature.io.artifacts.spi.ArtifactProvider;
-import org.junit.Test;
-
-public class ArtifactManagerTest {
-
- private static final String METADATA = "<metadata modelVersion=\"1.1.0\">\n" +
- "<groupId>org.apache.sling.samples</groupId>\n" +
- "<artifactId>slingshot</artifactId>\n" +
- "<version>0-DEFAULT-SNAPSHOT</version>\n" +
- "<versioning>\n" +
- "<snapshot>\n" +
- "<timestamp>20160321.103951</timestamp>\n" +
- "<buildNumber>1</buildNumber>\n" +
- "</snapshot>\n" +
- "<lastUpdated>20160321103951</lastUpdated>\n" +
- "<snapshotVersions>\n" +
- "<snapshotVersion>\n" +
- "<extension>txt</extension>\n" +
- "<value>0-DEFAULT-20160321.103951-1</value>\n" +
- "<updated>20160321103951</updated>\n" +
- "</snapshotVersion>\n" +
- "<snapshotVersion>\n" +
- "<extension>pom</extension>\n" +
- "<value>0-DEFAULT-20160321.103951-1</value>\n" +
- "<updated>20160321103951</updated>\n" +
- "</snapshotVersion>\n" +
- "</snapshotVersions>\n" +
- "</versioning></metadata>";
-
- @Test public void testMetadataParsing() {
- final String version = ArtifactManager.getLatestSnapshot(METADATA);
- assertEquals("20160321.103951-1", version);
- }
-
- @Test public void testSnapshotHandling() throws IOException {
- final String REPO = "http://org.apache.sling";
- final ArtifactManagerConfig config = mock(ArtifactManagerConfig.class);
- when(config.getRepositoryUrls()).thenReturn(new String[] {REPO});
-
- final URL metadataFile = new URL("file:/maven-metadata.xml");
-
- final URL artifactFile = new URL("file:/artifact");
-
- final ArtifactProvider provider = mock(ArtifactProvider.class);
- when(provider.getArtifact(REPO + "/group/artifact/1.0.0-SNAPSHOT/artifact-1.0.0-SNAPSHOT.txt", "group/artifact/1.0.0-SNAPSHOT/artifact-1.0.0-SNAPSHOT.txt")).thenReturn(null);
- when(provider.getArtifact(REPO + "/group/artifact/1.0.0-SNAPSHOT/maven-metadata.xml", "org.apache.sling/group/artifact/1.0.0-SNAPSHOT/maven-metadata.xml")).thenReturn(metadataFile);
- when(provider.getArtifact(REPO + "/group/artifact/1.0.0-SNAPSHOT/artifact-1.0.0-20160321.103951-1.txt", "group/artifact/1.0.0-SNAPSHOT/artifact-1.0.0-SNAPSHOT.txt")).thenReturn(artifactFile);
-
- final Map<String, ArtifactProvider> providers = new HashMap<>();
- providers.put("*", provider);
-
- final ArtifactManager mgr = new ArtifactManager(config, providers) {
-
- @Override
- protected String getFileContents(final ArtifactHandler handler) throws IOException {
- final String path = handler.getLocalURL().getPath();
- if ( "/maven-metadata.xml".equals(path) ) {
- return METADATA;
- }
- return super.getFileContents(handler);
- }
- };
-
- final ArtifactHandler handler = mgr.getArtifactHandler("mvn:group/artifact/1.0.0-SNAPSHOT/txt");
- assertNotNull(handler);
- assertEquals(artifactFile, handler.getLocalURL());
- }
-}
diff --git a/src/test/java/org/apache/sling/feature/io/json/ArtifactsExtensions.java b/src/test/java/org/apache/sling/feature/io/json/ArtifactsExtensions.java
deleted file mode 100644
index e2ecc54..0000000
--- a/src/test/java/org/apache/sling/feature/io/json/ArtifactsExtensions.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.apache.sling.feature.io.json;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import org.apache.sling.feature.ArtifactId;
-import org.apache.sling.feature.Extension;
-import org.apache.sling.feature.ExtensionState;
-import org.apache.sling.feature.Extensions;
-import org.apache.sling.feature.Feature;
-
-/*
- * 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.
- */
-public class ArtifactsExtensions {
-
- public static void testReadArtifactsExtensions(Feature feature) {
- Extensions extensions = feature.getExtensions();
-
- assertEquals(2, extensions.size());
-
- Extension extension1 = extensions.getByName("my-extension1");
- assertNotNull(extension1);
- assertEquals(extension1.getName(), "my-extension1");
- assertEquals(extension1.getState(), ExtensionState.OPTIONAL);
- assertEquals(1, extension1.getArtifacts().size());
-
- ArtifactId artifactId1 = extension1.getArtifacts().get(0).getId();
- assertEquals(artifactId1.getGroupId(), "org.apache.sling");
- assertEquals(artifactId1.getArtifactId(), "my-extension1");
- assertEquals(artifactId1.getVersion(), "1.2.3");
-
- Extension extension2 = extensions.getByName("my-extension2");
- assertNotNull(extension2);
- assertEquals(extension2.getName(), "my-extension2");
- assertEquals(extension2.getState(), ExtensionState.REQUIRED);
- assertEquals(1, extension2.getArtifacts().size());
-
- ArtifactId artifactId2 = extension2.getArtifacts().get(0).getId();
- assertEquals(artifactId2.getGroupId(), "org.apache.sling");
- assertEquals(artifactId2.getArtifactId(), "my-extension2");
- assertEquals(artifactId2.getVersion(), "1.2.3");
- }
-}
diff --git a/src/test/java/org/apache/sling/feature/io/json/FeatureJSONReaderTest.java b/src/test/java/org/apache/sling/feature/io/json/FeatureJSONReaderTest.java
deleted file mode 100644
index d2f6872..0000000
--- a/src/test/java/org/apache/sling/feature/io/json/FeatureJSONReaderTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.io.json;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Arrays;
-
-import org.apache.sling.feature.ArtifactId;
-import org.apache.sling.feature.Bundles;
-import org.apache.sling.feature.Configuration;
-import org.apache.sling.feature.Extension;
-import org.apache.sling.feature.Extensions;
-import org.apache.sling.feature.Feature;
-import org.junit.Test;
-import org.osgi.resource.Capability;
-
-public class FeatureJSONReaderTest {
-
- @Test public void testRead() throws Exception {
- final Feature feature = U.readFeature("test");
- assertNotNull(feature);
- assertNotNull(feature.getId());
- assertEquals("org.apache.sling", feature.getId().getGroupId());
- assertEquals("test-feature", feature.getId().getArtifactId());
- assertEquals("1.1", feature.getId().getVersion());
- assertEquals("jar", feature.getId().getType());
- assertNull(feature.getId().getClassifier());
-
- assertEquals(2, feature.getConfigurations().size());
- final Configuration cfg1 = U.findConfiguration(feature.getConfigurations(), "my.pid");
- assertEquals(7, cfg1.getProperties().get("number"));
- final Configuration cfg2 = U.findConfiguration(feature.getConfigurations(), "my.factory.pid~name");
- assertEquals("yeah", cfg2.getProperties().get("a.value"));
-
- assertEquals(3, feature.getCapabilities().size());
- Capability capability = U.findCapability(feature.getCapabilities(),"osgi.service");
- assertNotNull(capability.getAttributes().get("objectClass"));
-
- assertEquals(Arrays.asList("org.osgi.service.http.runtime.HttpServiceRuntime"), capability.getAttributes().get("objectClass"));
-
- }
-
- @Test public void testReadRepoInitExtension() throws Exception {
- Feature feature = U.readFeature("repoinit");
- Extensions extensions = feature.getExtensions();
- assertEquals(1, extensions.size());
- Extension ext = extensions.iterator().next();
- assertEquals("some repo init\ntext", ext.getText());
- }
-
- @Test public void testReadRepoInitExtensionArray() throws Exception {
- Feature feature = U.readFeature("repoinit2");
- Extensions extensions = feature.getExtensions();
- assertEquals(1, extensions.size());
- Extension ext = extensions.iterator().next();
- assertEquals("some repo init\ntext\n", ext.getText());
- }
-
- @Test public void testReadArtifactsExtensions() throws Exception {
- final Feature feature = U.readFeature("artifacts-extension");
- ArtifactsExtensions.testReadArtifactsExtensions(feature);
- }
-
- @Test
- public void testFinalFlag() throws Exception {
- final Feature featureA = U.readFeature("test");
- assertFalse(featureA.isFinal());
-
- final Feature featureB = U.readFeature("final");
- assertTrue(featureB.isFinal());
- }
-
- @Test
- public void testCompleteFlag() throws Exception {
- final Feature featureA = U.readFeature("test");
- assertFalse(featureA.isComplete());
-
- final Feature featureB = U.readFeature("complete");
- assertTrue(featureB.isComplete());
- }
-
- @Test
- public void testReadMultiBSNVer() throws Exception {
- final Feature f = U.readFeature("test3");
- Bundles fb = f.getBundles();
- assertEquals(2, fb.size());
- assertTrue(fb.containsExact(ArtifactId.fromMvnId("org.apache.sling:foo:1.2.3")));
- assertTrue(fb.containsExact(ArtifactId.fromMvnId("org.apache.sling:foo:4.5.6")));
- assertFalse(fb.containsExact(ArtifactId.fromMvnId("org.apache.sling:foo:7.8.9")));
- }
-
- @Test
- public void readComments() throws Exception {
- // we only test whether the feature can be read without problems
- U.readFeature("feature-model");
- }
-}
diff --git a/src/test/java/org/apache/sling/feature/io/json/FeatureJSONWriterTest.java b/src/test/java/org/apache/sling/feature/io/json/FeatureJSONWriterTest.java
deleted file mode 100644
index 4d3feca..0000000
--- a/src/test/java/org/apache/sling/feature/io/json/FeatureJSONWriterTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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.io.json;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.io.InputStreamReader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.util.Arrays;
-
-import javax.json.Json;
-import javax.json.JsonArray;
-import javax.json.JsonObject;
-import javax.json.JsonValue;
-import javax.json.JsonValue.ValueType;
-
-import org.apache.sling.feature.Feature;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class FeatureJSONWriterTest {
-
- @Test public void testWrite() throws Exception {
- final Feature f = U.readFeature("test");
- final Feature rf;
- try ( final StringWriter writer = new StringWriter() ) {
- FeatureJSONWriter.write(writer, f);
- try ( final StringReader reader = new StringReader(writer.toString()) ) {
- rf = FeatureJSONReader.read(reader, null);
- }
- }
- assertEquals(f.getId(), rf.getId());
- assertEquals("org.apache.sling:test-feature:1.1", rf.getId().toMvnId());
- assertEquals("The feature description", rf.getDescription());
-
- assertEquals(Arrays.asList("org.osgi.service.http.runtime.HttpServiceRuntime"),
- U.findCapability(rf.getCapabilities(), "osgi.service").getAttributes().get("objectClass"));
- }
-
- @Test public void testWrite2() throws Exception {
- final Feature f = U.readFeature("test2");
-
- final Feature rf;
- try ( final StringWriter writer = new StringWriter() ) {
- FeatureJSONWriter.write(writer, f);
- try ( final StringReader reader = new StringReader(writer.toString()) ) {
- rf = FeatureJSONReader.read(reader, null);
- }
- }
-
- assertEquals(f.getVariables(), rf.getVariables());
- }
-
- @Test public void testExtensionsWriteRead() throws Exception {
- final Feature f = U.readFeature("artifacts-extension");
- final Feature rf;
- try ( final StringWriter writer = new StringWriter() ) {
- FeatureJSONWriter.write(writer, f);
- try ( final StringReader reader = new StringReader(writer.toString()) ) {
- rf = FeatureJSONReader.read(reader, null);
- }
- }
-
- ArtifactsExtensions.testReadArtifactsExtensions(rf);
- }
-
- @Test public void testPrototypeWriteRead() throws Exception {
- final Feature f = U.readFeature("test");
- assertNotNull(f.getPrototype());
-
- final Feature rf;
- try ( final StringWriter writer = new StringWriter() ) {
- FeatureJSONWriter.write(writer, f);
- try ( final StringReader reader = new StringReader(writer.toString()) ) {
- rf = FeatureJSONReader.read(reader, null);
- }
- }
- assertEquals(f.getPrototype().getId(), rf.getPrototype().getId());
- }
-
- @Test public void testRepoInitWrite() throws Exception {
- final Feature f = U.readFeature("repoinit2");
- try ( final StringWriter writer = new StringWriter() ) {
- FeatureJSONWriter.write(writer, f);
- final JsonObject refJson = Json.createReader(
- new InputStreamReader(U.class.getResourceAsStream("/features/repoinit2.json"))
- ).readObject();
- final JsonObject resultJson = Json.createReader(new StringReader(writer.toString())).readObject();
-
- JsonArray refJsonArray = refJson.getJsonArray("repoinit:TEXT|false");
- JsonArray resultJsonArray = resultJson.getJsonArray("repoinit:TEXT|false");
- Assert.assertEquals(refJsonArray, resultJsonArray);
- }
- }
-
- @Test
- public void testFinalFlag() throws Exception {
- // no final flag set in test feature
- final Feature featureA = U.readFeature("test");
- try (final StringWriter writer = new StringWriter()) {
- FeatureJSONWriter.write(writer, featureA);
- final JsonObject resultJson = Json.createReader(new StringReader(writer.toString())).readObject();
-
- assertNull(resultJson.get(JSONConstants.FEATURE_FINAL));
- }
-
- // final flag set in final feature
- final Feature featureB = U.readFeature("final");
- try (final StringWriter writer = new StringWriter()) {
- FeatureJSONWriter.write(writer, featureB);
- final JsonObject resultJson = Json.createReader(new StringReader(writer.toString())).readObject();
-
- final JsonValue val = resultJson.get(JSONConstants.FEATURE_FINAL);
- assertNotNull(val);
- assertEquals(ValueType.TRUE, val.getValueType());
- }
- }
-}
diff --git a/src/test/java/org/apache/sling/feature/io/json/U.java b/src/test/java/org/apache/sling/feature/io/json/U.java
deleted file mode 100644
index ee642c1..0000000
--- a/src/test/java/org/apache/sling/feature/io/json/U.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.io.json;
-
-import static org.junit.Assert.fail;
-
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.List;
-
-import org.apache.sling.feature.Configuration;
-import org.apache.sling.feature.Feature;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-
-/** Test utilities */
-public class U {
-
- /** Read the feature from the provided resource
- */
- public static Feature readFeature(final String name) throws Exception {
- try ( final Reader reader = new InputStreamReader(U.class.getResourceAsStream("/features/" + name + ".json"),
- "UTF-8") ) {
- return FeatureJSONReader.read(reader, name);
- }
- }
-
- public static Configuration findConfiguration(final List<Configuration> cfgs, final String pid) {
- for(final Configuration c : cfgs) {
- if (pid.equals(c.getPid())) {
- return c;
- }
- }
- fail("Configuration not found " + pid);
- return null;
- }
-
- public static Capability findCapability(List<Capability> capabilities, final String namespace) {
- for (Capability capability : capabilities) {
- if (capability.getNamespace().equals(namespace)) {
- return capability;
- }
- }
-
- fail(String.format("No Capability with namespace '%s' found", namespace));
- return null;
- }
-
- public static Requirement findRequirement(List<Requirement> requirements, final String namespace) {
- for (Requirement requirement : requirements) {
- if (requirement.getNamespace().equals(namespace)) {
- return requirement;
- }
- }
-
- fail(String.format("No Requirement with namespace '%s' found", namespace));
- return null;
- }
-}
diff --git a/src/test/resources/features/artifacts-extension.json b/src/test/resources/features/artifacts-extension.json
deleted file mode 100644
index 3bcd47a..0000000
--- a/src/test/resources/features/artifacts-extension.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "id": "test/artifacts-extension/1.0.0",
- "my-extension1:ARTIFACTS|false":[
- "org.apache.sling/my-extension1/1.2.3"
- ],
- "my-extension2:ARTIFACTS|true":[
- "org.apache.sling/my-extension2/1.2.3"
- ]
-}
\ No newline at end of file
diff --git a/src/test/resources/features/complete.json b/src/test/resources/features/complete.json
deleted file mode 100644
index dc4b141..0000000
--- a/src/test/resources/features/complete.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "id" : "org.apache.sling/test-feature-complete/1.0.0",
- "complete": true
-}
\ No newline at end of file
diff --git a/src/test/resources/features/feature-model.json b/src/test/resources/features/feature-model.json
deleted file mode 100644
index aff0e66..0000000
--- a/src/test/resources/features/feature-model.json
+++ /dev/null
@@ -1,123 +0,0 @@
-{
- // this is a comment
- "id": "org.apache.sling:my.app:slingosgifeature:my-classifier:1.0",
-
- "title": "A title for the feature. (optional)",
- "description": "A description for the feature. (optional)",
- "vendor": "The feature vendor, for example 'Apache Software Foundation'. (optional)",
- "license": "The license of this feature file, for example 'ASL-2'. (optional)",
-
- // A complete feature has no external dependencies
- "complete": true,
-
- // A final feature cannot be used as a prototype for another feature
- "final": false,
-
- // variables used in configuration and framework properties are substituted at launch time.
- "variables": {
- "cfgvar": "somedefault",
- "org.abc.xyz": "1.2.3",
-
- // When converting to provisioning model, if you need a special name
- "provisioning.model.name": ":boot"
- },
-
- // A prototype is another feature that is used as a prototype for this one
- // Bundles, configurations and framework properties can be removed from the
- //prototype. Bundles with the same artifact ID defined in the feature override
- // bundles with this artifact ID in the Prototype
- "prototype":
- {
- "id": "org.apache.sling:some-other-feature:1.2.3",
- "removals": {
- "configurations": [],
- "bundles": [],
- "framework-properties": []
- }
- },
-
- // Requirements over and above the requirements in the bundles referenced by
- // feature.
- "requirements": [
- {
- "namespace": "osgi.contract",
- "directives": {
- "filter": "(&(osgi.contract=JavaServlet)(version=3.1))"
- }
- }
- ],
-
- // Capabilities over and above the capabilities provided by the bundles referenced
- // by the feature.
- "capabilities": [
- {
- "namespace": "osgi.implementation",
- "attributes": {
- "osgi.implementation": "osgi.http",
- "version:Version": "1.1"
- },
- "directives": {
- "uses": "javax.servlet,javax.servlet.http,org.osgi.service.http.context,org.osgi.service.http.whiteboard"
- }
- },
- {
- "namespace": "osgi.service",
- "attributes": {
- "objectClass:List<String>": "org.osgi.service.http.runtime.HttpServiceRuntime"
- },
- "directives": {
- "uses": "org.osgi.service.http.runtime,org.osgi.service.http.runtime.dto"
- }
- }
- ],
-
- // Framework properties to be provided to the running OSGi Framework
- "framework-properties": {
- "foo": 1,
- "org.osgi.framework.storage": "${tempdir}",
- "org.apache.felix.scr.directory": "launchpad/scr"
- },
-
- // The bundles that are part of the feature. Bundles are referenced using Maven
- // coordinates and can have additional metadata associated with them. Bundles can
- // specified as either a simple string (the Maven coordinates of the bundle) or
- // as an object with 'id' and additional metadata.
- "bundles": [
- {
- "id": "org.apache.sling:security-server:2.2.0",
- "hash": "4632463464363646436",
-
- // This is the relative start order inside the feature
- "start-order": 5
- },
- {
- "id": "org.apache.sling:application-bundle:2.0.0",
- "start-order": 10
- },
- "org.apache.sling:foo-xyz:1.2.3"
- ],
-
- // The configurations are specified following the format defined by the OSGi Configurator
- // specification: https://osgi.org/specification/osgi.cmpn/7.0.0/service.configurator.html
- // Variables declared in the variables section can be used for late binding of variables
- // they can be specified with the Launcher, or the default from the variables section is used.
- // Factory configurations can be specified using the named factory syntax, which separates
- // The factory PID and the name with a tilde '~'
- "configurations": {
- "my.pid": {
- "foo": 5,
- "something-enabled": false,
- "bar": "${cfgvar}",
-
- // The tempdir variable is not specified at the variables section.
- // It needs to be provided at launch, otherwise the launch will stop.
- "tempdir": "${tempdir}",
-
-
- "number:Integer": 7
- },
- "my.factory.pid~name": {
- "a.value":"yeah"
- }
- }
-}
diff --git a/src/test/resources/features/final.json b/src/test/resources/features/final.json
deleted file mode 100644
index ff1d8a0..0000000
--- a/src/test/resources/features/final.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "id" : "org.apache.sling/final-feature/1.1",
- "description": "The feature description",
- "final" : true
-}
\ No newline at end of file
diff --git a/src/test/resources/features/repoinit.json b/src/test/resources/features/repoinit.json
deleted file mode 100644
index 2177702..0000000
--- a/src/test/resources/features/repoinit.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "id": "test/repoinit/1.0.0",
- "repoinit:TEXT|false": "some repo init\ntext"
-}
diff --git a/src/test/resources/features/repoinit2.json b/src/test/resources/features/repoinit2.json
deleted file mode 100644
index beef986..0000000
--- a/src/test/resources/features/repoinit2.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "id": "test/repoinit2/1.0.0",
- "repoinit:TEXT|false": [
- "some repo init",
- "text"
- ]
-}
diff --git a/src/test/resources/features/test.json b/src/test/resources/features/test.json
deleted file mode 100644
index 42d4c4d..0000000
--- a/src/test/resources/features/test.json
+++ /dev/null
@@ -1,92 +0,0 @@
-{
- "id" : "org.apache.sling/test-feature/1.1",
- "description": "The feature description",
-
- "prototype" :
- {
- "id" : "org.apache.sling/sling/9",
- "removals" : {
- "configurations" : [
- ],
- "bundles" : [
- ],
- "framework-properties" : [
- ]
- }
- }
- ,
- "requirements" : [
- {
- "namespace" : "osgi.contract",
- "directives" : {
- "filter" : "(&(osgi.contract=JavaServlet)(&(version>=3.0)(!(version>=4.0))))"
- }
- }
- ],
- "capabilities" : [
- {
- "namespace" : "osgi.implementation",
- "attributes" : {
- "osgi.implementation" : "osgi.http",
- "version:Version" : "1.1"
- },
- "directives" : {
- "uses" : "javax.servlet,javax.servlet.http,org.osgi.service.http.context,org.osgi.service.http.whiteboard"
- }
- },
- {
- "namespace" : "osgi.service",
- "attributes" : {
- "objectClass:List<String>" : "org.osgi.service.http.runtime.HttpServiceRuntime"
- },
- "directives" : {
- "uses" : "org.osgi.service.http.runtime,org.osgi.service.http.runtime.dto"
- }
- },
- {
- "namespace" : "osgi.contract",
- "attributes" : {
- "osgi.contract" : "JavaServlet",
- "osgi.implementation" : "osgi.http",
- "version:Version" : "3.1"
- },
- "directives" : {
- "uses" : "org.osgi.service.http.runtime,org.osgi.service.http.runtime.dto"
- }
- }
- ],
- "framework-properties" : {
- "foo" : 1,
- "brave" : "something",
- "org.apache.felix.scr.directory" : "launchpad/scr"
- },
- "bundles" :[
- {
- "id" : "org.apache.sling/oak-server/1.0.0",
- "hash" : "4632463464363646436",
- "start-order" : 1
- },
- {
- "id" : "org.apache.sling/application-bundle/2.0.0",
- "start-order" : 1
- },
- {
- "id" : "org.apache.sling/another-bundle/2.1.0",
- "start-order" : 1
- },
- {
- "id" : "org.apache.sling/foo-xyz/1.2.3",
- "start-order" : 2
- }
- ],
- "configurations" : {
- "my.pid" : {
- "foo" : 5,
- "bar" : "test",
- "number:Integer" : 7
- },
- "my.factory.pid~name" : {
- "a.value" : "yeah"
- }
- }
-}
\ No newline at end of file
diff --git a/src/test/resources/features/test2.json b/src/test/resources/features/test2.json
deleted file mode 100644
index d89a051..0000000
--- a/src/test/resources/features/test2.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "id" : "org.apache.sling/test-feature2/1.0.0.0",
- "variables": {
- "foo": "bar",
- "zar": null
- }
-}
\ No newline at end of file
diff --git a/src/test/resources/features/test3.json b/src/test/resources/features/test3.json
deleted file mode 100644
index de143cc..0000000
--- a/src/test/resources/features/test3.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "id" : "org.apache.sling/test-feature3/2",
- "bundles": [
- "org.apache.sling/foo/1.2.3",
- "org.apache.sling/foo/4.5.6"
- ]
-}
\ No newline at end of file