Author: cziegeler
Date: Thu Jul 6 14:09:13 2017
New Revision: 1801057
URL: http://svn.apache.org/viewvc?rev=1801057&view=rev
Log:
Update scanner framework to scan features and applications
Added:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/FrameworkScanner.java
(with props)
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/impl/
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/impl/FelixFrameworkScanner.java
(with props)
Modified:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/Analyser.java
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/AnalyserTaskContext.java
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/main/Main.java
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/tasks/CheckBundleExportsImports.java
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/tasks/CheckBundlesForInitialContent.java
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/tasks/CheckBundlesForResources.java
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/ArtifactScanner.java
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/BundleDescriptor.java
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/Descriptor.java
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/ExtensionScanner.java
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/FeatureDescriptor.java
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/PackageInfo.java
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/Scanner.java
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Capability.java
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/KeyValueMap.java
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Requirement.java
Modified:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/Analyser.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/Analyser.java?rev=1801057&r1=1801056&r2=1801057&view=diff
==============================================================================
---
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/Analyser.java
(original)
+++
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/Analyser.java
Thu Jul 6 14:09:13 2017
@@ -21,18 +21,12 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
-import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
import org.apache.sling.feature.Application;
-import org.apache.sling.feature.KeyValueMap;
-import org.apache.sling.feature.scanner.ArtifactDescriptor;
-import org.apache.sling.feature.scanner.BundleDescriptor;
-import org.apache.sling.feature.scanner.PackageInfo;
+import org.apache.sling.feature.scanner.ApplicationDescriptor;
import org.apache.sling.feature.scanner.Scanner;
-import org.apache.sling.feature.support.ArtifactManager;
-import org.apache.sling.feature.support.ArtifactManagerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,32 +34,29 @@ public class Analyser {
private final AnalyserTask[] tasks;
- private final ArtifactManager artifactManager;
-
private final Scanner scanner;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
- public Analyser(final ArtifactManagerConfig amConfig,
+ public Analyser(final Scanner scanner,
final AnalyserTask...tasks)
throws IOException {
this.tasks = tasks;
- this.artifactManager = ArtifactManager.getArtifactManager(amConfig);
- this.scanner = new Scanner(amConfig);
+ this.scanner = scanner;
}
- public Analyser(final ArtifactManagerConfig amConfig,
+ public Analyser(final Scanner scanner,
final String... taskIds)
throws IOException {
- this(amConfig, getTasks(taskIds));
+ this(scanner, getTasks(taskIds));
if ( this.tasks.length != taskIds.length ) {
throw new IOException("Couldn't find all tasks " + taskIds);
}
}
- public Analyser(final ArtifactManagerConfig amConfig)
+ public Analyser(final Scanner scanner)
throws IOException {
- this(amConfig, getTasks((String[])null));
+ this(scanner, getTasks((String[])null));
}
private static AnalyserTask[] getTasks(final String... taskIds) {
@@ -84,18 +75,7 @@ public class Analyser {
throws Exception {
logger.info("Starting application analyzer...");
- // get framework properties and update application
- final KeyValueMap frameworkProps = scanner.getFrameworkProperties(app);
- for(final Map.Entry<String, String>entry : frameworkProps) {
- if ( app.getFrameworkProperties().get(entry.getKey()) == null ) {
- app.getFrameworkProperties().put(entry.getKey(),
entry.getValue());
- }
- }
-
- final List<PackageInfo> systemPackages =
scanner.calculateSystemPackages(app);
-
- final List<BundleDescriptor> bundleInfos = scanner.getBundleInfos(app);
- final List<ArtifactDescriptor> artifactInfos =
scanner.getArtifactInfos(app);
+ final ApplicationDescriptor appDesc = scanner.scan(app);
final List<String> warnings = new ArrayList<>();
final List<String> errors = new ArrayList<>();
@@ -111,18 +91,8 @@ public class Analyser {
}
@Override
- public List<BundleDescriptor> getBundleInfos() {
- return bundleInfos;
- }
-
- @Override
- public List<ArtifactDescriptor> getArtifactInfos() {
- return artifactInfos;
- }
-
- @Override
- public List<PackageInfo> getSystemPackages() {
- return systemPackages;
+ public ApplicationDescriptor getDescriptor() {
+ return appDesc;
}
@Override
Modified:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/AnalyserTaskContext.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/AnalyserTaskContext.java?rev=1801057&r1=1801056&r2=1801057&view=diff
==============================================================================
---
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/AnalyserTaskContext.java
(original)
+++
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/AnalyserTaskContext.java
Thu Jul 6 14:09:13 2017
@@ -16,12 +16,8 @@
*/
package org.apache.sling.feature.analyser;
-import java.util.List;
-
import org.apache.sling.feature.Application;
-import org.apache.sling.feature.scanner.ArtifactDescriptor;
-import org.apache.sling.feature.scanner.BundleDescriptor;
-import org.apache.sling.feature.scanner.PackageInfo;
+import org.apache.sling.feature.scanner.ApplicationDescriptor;
public interface AnalyserTaskContext {
@@ -32,22 +28,9 @@ public interface AnalyserTaskContext {
Application getApplication();
/**
- * The list of system packages exported by the framework itself
- * @return Unmodifiable list of system package.
- */
- List<PackageInfo> getSystemPackages();
-
- /**
- * Get the list of bundle infos.
- * @return The unmodifiable list of bundle infos
- */
- List<BundleDescriptor> getBundleInfos();
-
- /**
- * Get the list artifact infos
- * @return The unmodifiable list of artifact infos
+ * The application descriptor
*/
- List<ArtifactDescriptor> getArtifactInfos();
+ ApplicationDescriptor getDescriptor();
/**
* This method is invoked by a {@link AnalyserTask} to report
Modified:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/main/Main.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/main/Main.java?rev=1801057&r1=1801056&r2=1801057&view=diff
==============================================================================
---
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/main/Main.java
(original)
+++
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/main/Main.java
Thu Jul 6 14:09:13 2017
@@ -21,10 +21,11 @@ import java.io.FileReader;
import java.io.IOException;
import org.apache.sling.feature.Application;
-import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.analyser.Analyser;
import org.apache.sling.feature.json.ApplicationJSONReader;
+import org.apache.sling.feature.scanner.Scanner;
import org.apache.sling.feature.support.ArtifactManagerConfig;
+import org.apache.sling.feature.support.FeatureUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -58,14 +59,12 @@ public class Main {
System.exit(1);
}
if ( app.getFramework() == null ) {
- // use hard coded Apache Felix
- app.setFramework(new ArtifactId("org.apache.felix",
- "org.apache.felix.framework",
- "5.6.4", null, null));
+ app.setFramework(FeatureUtil.getFelixFrameworkId(null));
}
try {
- final Analyser analyser = new Analyser(new
ArtifactManagerConfig());
+ final Scanner scanner = new Scanner(new ArtifactManagerConfig());
+ final Analyser analyser = new Analyser(scanner);
analyser.analyse(app);
} catch ( final Exception e) {
logger.error("Unable to analyse application: {}", f, e);
Modified:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/tasks/CheckBundleExportsImports.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/tasks/CheckBundleExportsImports.java?rev=1801057&r1=1801056&r2=1801057&view=diff
==============================================================================
---
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/tasks/CheckBundleExportsImports.java
(original)
+++
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/tasks/CheckBundleExportsImports.java
Thu Jul 6 14:09:13 2017
@@ -70,7 +70,7 @@ public class CheckBundleExportsImports i
}
private void checkForVersionOnExportedPackages(final AnalyserTaskContext
ctx, final Map<BundleDescriptor, Report> reports) {
- for(final BundleDescriptor info : ctx.getBundleInfos()) {
+ for(final BundleDescriptor info :
ctx.getDescriptor().getBundleDescriptors()) {
if ( info.getExportedPackages() != null ) {
for(final PackageInfo i : info.getExportedPackages()) {
if ( i.getPackageVersion().compareTo(Version.emptyVersion)
== 0 ) {
@@ -82,7 +82,7 @@ public class CheckBundleExportsImports i
}
private void checkForVersionOnImportingPackages(final AnalyserTaskContext
ctx, final Map<BundleDescriptor, Report> reports) {
- for(final BundleDescriptor info : ctx.getBundleInfos()) {
+ for(final BundleDescriptor info :
ctx.getDescriptor().getBundleDescriptors()) {
if ( info.getImportedPackages() != null ) {
for(final PackageInfo i : info.getImportedPackages()) {
if ( i.getVersion() == null ) {
@@ -106,7 +106,7 @@ public class CheckBundleExportsImports i
checkForVersionOnImportingPackages(ctx, reports);
final SortedMap<Integer, List<BundleDescriptor>> bundlesMap = new
TreeMap<>();
- for(final BundleDescriptor bi : ctx.getBundleInfos()) {
+ for(final BundleDescriptor bi :
ctx.getDescriptor().getBundleDescriptors()) {
List<BundleDescriptor> list =
bundlesMap.get(bi.getBundleStartLevel());
if ( list == null ) {
list = new ArrayList<>();
@@ -116,7 +116,7 @@ public class CheckBundleExportsImports i
}
// create a synthetic bundle info for the system bundle
- final BundleDescriptor system = new BundleDescriptor(new
Artifact(ctx.getApplication().getFramework()), ctx.getSystemPackages());
+ final BundleDescriptor system = new BundleDescriptor(new
Artifact(ctx.getApplication().getFramework()),
ctx.getDescriptor().getFrameworkDescriptor().getExportedPackages());
// add all system packages
final List<BundleDescriptor> exportingBundles = new ArrayList<>();
Modified:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/tasks/CheckBundlesForInitialContent.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/tasks/CheckBundlesForInitialContent.java?rev=1801057&r1=1801056&r2=1801057&view=diff
==============================================================================
---
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/tasks/CheckBundlesForInitialContent.java
(original)
+++
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/tasks/CheckBundlesForInitialContent.java
Thu Jul 6 14:09:13 2017
@@ -51,7 +51,7 @@ public class CheckBundlesForInitialConte
@Override
public void execute(final AnalyserTaskContext ctx) {
// check for initial content
- for(final BundleDescriptor info : ctx.getBundleInfos()) {
+ for(final BundleDescriptor info :
ctx.getDescriptor().getBundleDescriptors()) {
final List<String> initialContent =
extractInitialContent(info.getManifest());
if ( !initialContent.isEmpty() ) {
Modified:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/tasks/CheckBundlesForResources.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/tasks/CheckBundlesForResources.java?rev=1801057&r1=1801056&r2=1801057&view=diff
==============================================================================
---
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/tasks/CheckBundlesForResources.java
(original)
+++
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/analyser/tasks/CheckBundlesForResources.java
Thu Jul 6 14:09:13 2017
@@ -51,7 +51,7 @@ public class CheckBundlesForResources im
@Override
public void execute(final AnalyserTaskContext ctx) {
// check for initial content
- for(final BundleDescriptor info : ctx.getBundleInfos()) {
+ for(final BundleDescriptor info :
ctx.getDescriptor().getBundleDescriptors()) {
final List<String> bundleResources =
extractBundleResources(info.getManifest());
if ( !bundleResources.isEmpty() ) {
ctx.reportWarning("Found bundle resources in " +
info.getArtifact() + " : " + bundleResources);
Modified:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/ArtifactScanner.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/ArtifactScanner.java?rev=1801057&r1=1801056&r2=1801057&view=diff
==============================================================================
---
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/ArtifactScanner.java
(original)
+++
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/ArtifactScanner.java
Thu Jul 6 14:09:13 2017
@@ -16,6 +16,7 @@
*/
package org.apache.sling.feature.scanner;
+import java.io.File;
import java.io.IOException;
import org.apache.sling.feature.Artifact;
@@ -34,8 +35,9 @@ public interface ArtifactScanner {
/**
* Try to scan the artifact
* @param artifact The artifact
+ * @param file The artifact file
* @return An artifact info or {@code null} if the scanner can't process
the artifact
* @throws IOException If an error occurs while scanning the artifact or
the artifact is invalid
*/
- ArtifactDescriptor scan(Artifact artifact) throws IOException;
+ ArtifactDescriptor scan(Artifact artifact, File file) throws IOException;
}
\ No newline at end of file
Modified:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/BundleDescriptor.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/BundleDescriptor.java?rev=1801057&r1=1801056&r2=1801057&view=diff
==============================================================================
---
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/BundleDescriptor.java
(original)
+++
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/BundleDescriptor.java
Thu Jul 6 14:09:13 2017
@@ -18,9 +18,9 @@ package org.apache.sling.feature.scanner
import java.io.File;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Collections;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
import java.util.jar.Manifest;
import org.apache.sling.feature.Artifact;
@@ -41,13 +41,13 @@ public class BundleDescriptor extends Ar
private final int startLevel;
/** Information about exported packages. */
- private final List<PackageInfo> exportedPackages = new ArrayList<>();
+ private final Set<PackageInfo> exportedPackages = new HashSet<>();
/** Information about imported packages. */
- private final List<PackageInfo> importedPackages = new ArrayList<>();
+ private final Set<PackageInfo> importedPackages = new HashSet<>();
/** Information about dynamic imported packages. */
- private final List<PackageInfo> dynamicImportedPackages = new
ArrayList<>();
+ private final Set<PackageInfo> dynamicImportedPackages = new HashSet<>();
/** Manifest */
private final Manifest manifest;
@@ -66,7 +66,7 @@ public class BundleDescriptor extends Ar
}
public BundleDescriptor(final Artifact artifact,
- final List<PackageInfo> pcks) throws IOException {
+ final Set<PackageInfo> pcks) throws IOException {
super(artifact, null);
this.startLevel = 0;
@@ -100,8 +100,9 @@ public class BundleDescriptor extends Ar
return startLevel;
}
- public List<PackageInfo> getExportedPackages() {
- return Collections.unmodifiableList(this.exportedPackages);
+ @Override
+ public Set<PackageInfo> getExportedPackages() {
+ return Collections.unmodifiableSet(this.exportedPackages);
}
@Override
@@ -133,13 +134,13 @@ public class BundleDescriptor extends Ar
}
@Override
- public List<PackageInfo> getImportedPackages() {
- return Collections.unmodifiableList(this.importedPackages);
+ public Set<PackageInfo> getImportedPackages() {
+ return Collections.unmodifiableSet(this.importedPackages);
}
@Override
- public List<PackageInfo> getDynamicImportedPackages() {
- return Collections.unmodifiableList(this.dynamicImportedPackages);
+ public Set<PackageInfo> getDynamicImportedPackages() {
+ return Collections.unmodifiableSet(this.dynamicImportedPackages);
}
protected void analyze() throws IOException {
Modified:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/Descriptor.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/Descriptor.java?rev=1801057&r1=1801056&r2=1801057&view=diff
==============================================================================
---
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/Descriptor.java
(original)
+++
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/Descriptor.java
Thu Jul 6 14:09:13 2017
@@ -17,7 +17,7 @@
package org.apache.sling.feature.scanner;
import java.util.Collections;
-import java.util.List;
+import java.util.Set;
import org.apache.sling.feature.Capability;
import org.apache.sling.feature.Requirement;
@@ -27,27 +27,31 @@ import org.apache.sling.feature.Requirem
*/
public class Descriptor {
- public List<PackageInfo> getImportedPackages() {
- return Collections.emptyList();
+ public Set<PackageInfo> getExportedPackages() {
+ return Collections.emptySet();
}
- public List<PackageInfo> getDynamicImportedPackages() {
- return Collections.emptyList();
+ public Set<PackageInfo> getImportedPackages() {
+ return Collections.emptySet();
+ }
+
+ public Set<PackageInfo> getDynamicImportedPackages() {
+ return Collections.emptySet();
}
/**
* Return the list of requirements.
* @return The list of requirements. The list might be empty.
*/
- public List<Requirement> getRequirements() {
- return Collections.emptyList();
+ public Set<Requirement> getRequirements() {
+ return Collections.emptySet();
}
/**
* Return the list of capabilities.
* @return The list of capabilities. The list might be empty.
*/
- public List<Capability> getCapabilities() {
- return Collections.emptyList();
+ public Set<Capability> getCapabilities() {
+ return Collections.emptySet();
}
}
\ No newline at end of file
Modified:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/ExtensionScanner.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/ExtensionScanner.java?rev=1801057&r1=1801056&r2=1801057&view=diff
==============================================================================
---
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/ExtensionScanner.java
(original)
+++
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/ExtensionScanner.java
Thu Jul 6 14:09:13 2017
@@ -20,6 +20,7 @@ import java.io.IOException;
import java.util.List;
import org.apache.sling.feature.Extension;
+import org.apache.sling.feature.support.ArtifactManager;
/**
* The extension scanner scans an extension.
@@ -36,8 +37,11 @@ public interface ExtensionScanner {
* Try to scan the extension and return a descriptor
* @param extension The extension
* @param descs A list of scanned artifact descriptors if the extension is
of type artifacts, {@code null} otherwise.
+ * @param manager Artifact manager
* @return The descriptor or {@code null} if the scanner does not know the
extension
* @throws IOException If an error occurs while scanning the extension or
the extension is invalid
*/
- Descriptor scan(Extension extension, List<ArtifactDescriptor> descs)
throws IOException;
+ Descriptor scan(Extension extension,
+ List<ArtifactDescriptor> descs,
+ ArtifactManager manager) throws IOException;
}
\ No newline at end of file
Modified:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/FeatureDescriptor.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/FeatureDescriptor.java?rev=1801057&r1=1801056&r2=1801057&view=diff
==============================================================================
---
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/FeatureDescriptor.java
(original)
+++
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/FeatureDescriptor.java
Thu Jul 6 14:09:13 2017
@@ -16,11 +16,62 @@
*/
package org.apache.sling.feature.scanner;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.sling.feature.Capability;
+import org.apache.sling.feature.Requirement;
+
/**
* Information about a feature.
* This is the aggregated information.
*/
public class FeatureDescriptor extends Descriptor {
+ private final Set<Requirement> requirements = new HashSet<>();
+
+ private final Set<Capability> capabilities = new HashSet<>();
+
+ private final Set<PackageInfo> exports = new HashSet<>();
+
+ private final Set<PackageInfo> imports = new HashSet<>();
+
+ private final Set<PackageInfo> dynamicImports = new HashSet<>();
+
+ private final Set<BundleDescriptor> bundles = new HashSet<>();
+
+ private final Set<ArtifactDescriptor> artifacts = new HashSet<>();
+
+ public Set<PackageInfo> getExportedPackages() {
+ return this.exports;
+ }
+
+ public Set<BundleDescriptor> getBundleDescriptors() {
+ return this.bundles;
+ }
+
+ public Set<ArtifactDescriptor> getArtifactDescriptors() {
+ return this.artifacts;
+ }
+
+ @Override
+ public Set<PackageInfo> getImportedPackages() {
+ return this.imports;
+ }
+
+ @Override
+ public Set<PackageInfo> getDynamicImportedPackages() {
+ return this.dynamicImports;
+ }
+
+ @Override
+ public Set<Requirement> getRequirements() {
+ return this.requirements;
+ }
+
+ @Override
+ public Set<Capability> getCapabilities() {
+ return this.capabilities;
+ }
}
\ No newline at end of file
Added:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/FrameworkScanner.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/FrameworkScanner.java?rev=1801057&view=auto
==============================================================================
---
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/FrameworkScanner.java
(added)
+++
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/FrameworkScanner.java
Thu Jul 6 14:09:13 2017
@@ -0,0 +1,41 @@
+/*
+ * 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.scanner;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.KeyValueMap;
+
+/**
+ * The framework scanner scans the framework
+ */
+public interface FrameworkScanner {
+
+ /**
+ * Try to scan the artifact
+ * @param framework The framework artifact id
+ * @param file The framework artifact
+ * @param frameworkProps framework properties to launch the framework
+ * @return A descriptor or {@code null}
+ * @throws IOException If an error occurs while scanning the platform or
the artifact is invalid
+ */
+ Descriptor scan(ArtifactId framework,
+ File platformFile,
+ KeyValueMap frameworkProps) throws IOException;
+}
\ No newline at end of file
Propchange:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/FrameworkScanner.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/FrameworkScanner.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Modified:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/PackageInfo.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/PackageInfo.java?rev=1801057&r1=1801056&r2=1801057&view=diff
==============================================================================
---
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/PackageInfo.java
(original)
+++
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/PackageInfo.java
Thu Jul 6 14:09:13 2017
@@ -55,4 +55,39 @@ public class PackageInfo {
public String toString() {
return "Package " + name + ";version=" + version;
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + (optional ? 1231 : 1237);
+ result = prime * result + ((version == null) ? 0 : version.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ PackageInfo other = (PackageInfo) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ if (optional != other.optional)
+ return false;
+ if (version == null) {
+ if (other.version != null)
+ return false;
+ } else if (!version.equals(other.version))
+ return false;
+ return true;
+ }
+
}
Modified:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/Scanner.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/Scanner.java?rev=1801057&r1=1801056&r2=1801057&view=diff
==============================================================================
---
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/Scanner.java
(original)
+++
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/Scanner.java
Thu Jul 6 14:09:13 2017
@@ -17,36 +17,99 @@
package org.apache.sling.feature.scanner;
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Properties;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
+import java.util.ServiceLoader;
-import org.apache.sling.commons.osgi.ManifestHeader;
import org.apache.sling.feature.Application;
import org.apache.sling.feature.Artifact;
+import org.apache.sling.feature.Bundles;
import org.apache.sling.feature.Extension;
import org.apache.sling.feature.ExtensionType;
+import org.apache.sling.feature.Extensions;
import org.apache.sling.feature.Feature;
-import org.apache.sling.feature.KeyValueMap;
import org.apache.sling.feature.support.ArtifactManager;
import org.apache.sling.feature.support.ArtifactManagerConfig;
-import org.osgi.framework.Constants;
+/**
+ * The scanner is a service that scans items and provides descriptions for
these.
+ * The following items can be scanned individually
+ * <ul>
+ * <li>A bundle artifact
+ * <li>An artifact (requires {@link ArtifactScannner}s)
+ * <li>An extension (requires {@link ExtensionScanner}s)
+ * <li>A feature (requires {@link ArtifactScannner}s and {@link
ExtensionScanner}s)
+ * <li>A framework (requires {@link FrameworkScanner}s
+ * <li>An application (requires all scanner types)
+ * </ul>
+ */
public class Scanner {
private final ArtifactManager artifactManager;
- public Scanner(final ArtifactManagerConfig amConfig)
+ private final List<ArtifactScanner> artifactScanners;
+
+ private final List<ExtensionScanner> extensionScanners;
+
+ private final List<FrameworkScanner> frameworkScanners;
+
+ /**
+ * Create a new scanner
+ *
+ * @param amConfig The artifact manager configuration
+ * @param artifactScanners A list of artifact scanners
+ * @param extensionScanners A list of extension scanners
+ * @param frameworkScanners A list of framework scanners
+ * @throws IOException If something goes wrong
+ */
+ public Scanner(final ArtifactManagerConfig amConfig,
+ final List<ArtifactScanner> artifactScanners,
+ final List<ExtensionScanner> extensionScanners,
+ final List<FrameworkScanner> frameworkScanners)
throws IOException {
this.artifactManager = ArtifactManager.getArtifactManager(amConfig);
+ this.artifactScanners = artifactScanners;
+ this.extensionScanners = extensionScanners;
+ this.frameworkScanners = frameworkScanners;
+ }
+
+ /**
+ * Create a new scanner and use the service loader to find the scanners
+ *
+ * @param amConfig The artifact manager configuration
+ * @throws IOException If something goes wrong
+ */
+ public Scanner(final ArtifactManagerConfig amConfig)
+ throws IOException {
+ this(amConfig, getServices(ArtifactScanner.class),
+ getServices(ExtensionScanner.class),
+ getServices(FrameworkScanner.class));
+ }
+
+ /**
+ * Get services from the service loader
+ *
+ * @param clazz The service class
+ * @return The list of services might be empty.
+ */
+ private static <T> List<T> getServices(final Class<T> clazz) {
+ final ServiceLoader<T> loader = ServiceLoader.load(clazz);
+ final List<T> list = new ArrayList<>();
+ for(final T task : loader) {
+ list.add(task);
+ }
+ return list;
}
+ /**
+ * Scan an artifact.
+ *
+ * @param artifact The artifact
+ * @return The artifact descriptor.
+ * @throws IOException If something goes wrong or no scanner could handle
the artifact
+ */
public ArtifactDescriptor scan(final Artifact artifact) throws IOException
{
final File file =
artifactManager.getArtifactHandler(artifact.getId().toMvnUrl()).getFile();
if ( file == null ) {
@@ -55,240 +118,156 @@ public class Scanner {
ArtifactDescriptor info = null;
- info = new ArtifactDescriptor(artifact, file);
+ for(final ArtifactScanner scanner : this.artifactScanners ) {
+ info = scanner.scan(artifact, file);
+ if ( info != null ) {
+ break;
+ }
+ }
+ if ( info == null ) {
+ throw new IOException("No artifact scanner found for " +
artifact.getId().toMvnId());
+ }
return info;
}
- public BundleDescriptor scanBundle(final Artifact artifact, final int
startLevel) throws IOException {
- final File file =
artifactManager.getArtifactHandler(artifact.getId().toMvnUrl()).getFile();
+ /**
+ * Scan a bundle
+ *
+ * @param bundle The bundle artifact
+ * @param startLevel The start level of the bundle
+ * @return The bundle descriptor
+ * @throws IOException If something goes wrong or the provided artifact is
not a bundle.
+ */
+ public BundleDescriptor scan(final Artifact bundle, final int startLevel)
throws IOException {
+ final File file =
artifactManager.getArtifactHandler(bundle.getId().toMvnUrl()).getFile();
if ( file == null ) {
- throw new IOException("Unable to find file for " +
artifact.getId());
+ throw new IOException("Unable to find file for " + bundle.getId());
}
- return new BundleDescriptor(artifact, file, startLevel);
+ return new BundleDescriptor(bundle, file, startLevel);
}
- public FeatureDescriptor scanFeature(final Feature feature) throws
IOException {
- return null; // TBD
- }
-
- public List<BundleDescriptor> getBundleInfos(final Application app)
throws Exception {
- final List<BundleDescriptor> bundleInfos = new ArrayList<>();
-
- for(final Map.Entry<Integer, List<Artifact>> entry :
app.getBundles().getBundlesByStartLevel().entrySet()) {
+ /**
+ * Get all bundle descriptors for a feature / application
+ * @param bundles The bundles
+ * @param desc The descriptor
+ * @throws IOException If something goes wrong or no suitable scanner is
found.
+ */
+ private void getBundleInfos(final Bundles bundles, final FeatureDescriptor
desc)
+ throws IOException {
+ for(final Map.Entry<Integer, List<Artifact>> entry :
bundles.getBundlesByStartLevel().entrySet()) {
for(final Artifact bundle : entry.getValue() ) {
- bundleInfos.add(scanBundle(bundle, entry.getKey()));
+ final BundleDescriptor bundleDesc = scan(bundle,
entry.getKey());
+ desc.getBundleDescriptors().add(bundleDesc);
+ // aggregate
+ desc.getRequirements().addAll(bundleDesc.getRequirements());
+ desc.getCapabilities().addAll(bundleDesc.getCapabilities());
+
desc.getExportedPackages().addAll(bundleDesc.getExportedPackages());
+
desc.getImportedPackages().addAll(bundleDesc.getImportedPackages());
+
desc.getDynamicImportedPackages().addAll(bundleDesc.getDynamicImportedPackages());
}
}
- return bundleInfos;
+ // TBD remove all import packages / dynamic import packages which are
resolved by this bundle set
+ // same with requirements
}
- public List<ArtifactDescriptor> getArtifactInfos(final Application app)
throws Exception {
- final List<ArtifactDescriptor> artifactInfos = new ArrayList<>();
-
- for(final Extension ext : app.getExtensions()) {
+ private void scan(final Extensions extensions, final FeatureDescriptor
desc)
+ throws IOException {
+ for(final Extension ext : extensions) {
+ final List<ArtifactDescriptor> infos;
if ( ext.getType() == ExtensionType.ARTIFACTS ) {
+ infos = new ArrayList<>();
for(final Artifact artifact : ext.getArtifacts()) {
- artifactInfos.add(scan(artifact));
+ final ArtifactDescriptor artifactDesc = scan(artifact);
+ infos.add(artifactDesc);
+ desc.getArtifactDescriptors().add(artifactDesc);
+ // aggregate
+
desc.getRequirements().addAll(artifactDesc.getRequirements());
+
desc.getCapabilities().addAll(artifactDesc.getCapabilities());
+
desc.getExportedPackages().addAll(artifactDesc.getExportedPackages());
+
desc.getImportedPackages().addAll(artifactDesc.getImportedPackages());
+
desc.getDynamicImportedPackages().addAll(artifactDesc.getDynamicImportedPackages());
}
+ } else {
+ infos = null;
}
- }
-
- return artifactInfos;
- }
-
- public List<PackageInfo> calculateSystemPackages(final Application app) {
- final String system =
app.getFrameworkProperties().get(Constants.FRAMEWORK_SYSTEMPACKAGES);
- final String extra =
app.getFrameworkProperties().get(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
- final List<PackageInfo> packages = new ArrayList<>();
- for(int i=0;i<2;i++) {
- final String value = (i == 0 ? system : extra);
- if ( value != null ) {
- final ManifestHeader header = ManifestHeader.parse(value);
- for(final ManifestHeader.Entry entry : header.getEntries()) {
- String version = entry.getAttributeValue("version");
- if ( version == null ) {
- version = "0.0.0";
- }
-
- final PackageInfo exportedPackageInfo = new
PackageInfo(entry.getValue(),
- version, false);
- packages.add(exportedPackageInfo);
+ Descriptor extDesc = null;
+ for(final ExtensionScanner scanner : this.extensionScanners) {
+ extDesc = scanner.scan(ext, infos, this.artifactManager);
+ if ( extDesc != null ) {
+ break;
}
}
- }
- return packages;
- }
-
- private static final String DEFAULT_PROPERTIES = "default.properties";
-
- public KeyValueMap getFrameworkProperties(final Application app)
- throws IOException {
- final File framework =
this.artifactManager.getArtifactHandler(app.getFramework().toMvnUrl()).getFile();
-
- final Map<String, Properties> propsMap = new HashMap<>();
- try (final ZipInputStream zis = new ZipInputStream(new
FileInputStream(framework)) ) {
- boolean done = false;
- while ( !done ) {
- final ZipEntry entry = zis.getNextEntry();
- if ( entry == null ) {
- done = true;
- } else {
- final String entryName = entry.getName();
- if ( entryName.endsWith(".properties") ) {
- final Properties props = new Properties();
- props.load(zis);
-
- propsMap.put(entryName, props);
- }
- zis.closeEntry();
- }
+ if ( extDesc == null ) {
+ throw new IOException("No extension scanner found for
extension named " + ext.getName() + " of type " + ext.getType().name());
}
+ desc.getRequirements().addAll(extDesc.getRequirements());
+ desc.getCapabilities().addAll(extDesc.getCapabilities());
+ desc.getExportedPackages().addAll(extDesc.getExportedPackages());
+ desc.getImportedPackages().addAll(extDesc.getImportedPackages());
+
desc.getDynamicImportedPackages().addAll(extDesc.getDynamicImportedPackages());
}
+ // TBD remove all import packages / dynamic import packages which are
resolved by this bundle set
+ // same with requirements
+ }
- final Properties defaultMap = propsMap.get(DEFAULT_PROPERTIES);
- if ( defaultMap == null ) {
- throw new IOException("Unable to find " + DEFAULT_PROPERTIES + "
in framework " + app.getFramework());
- }
+ /**
+ * Scan a feature
+ *
+ * @param feature The feature
+ * @return The feature descriptor
+ * @throws IOException If something goes wrong or a scanner is missing
+ */
+ public FeatureDescriptor scan(final Feature feature) throws IOException {
+ final FeatureDescriptor desc = new FeatureDescriptor();
- final KeyValueMap frameworkProps = new KeyValueMap();
- // replace variables
- defaultMap.put("java.specification.version",
- System.getProperty("java.specification.version", "1.8"));
- for(final Object name : defaultMap.keySet()) {
- final String value = (String)defaultMap.get(name);
- final String substValue = substVars(value, name.toString(), null,
defaultMap);
- frameworkProps.put(name.toString(), substValue);
- }
+ getBundleInfos(feature.getBundles(), desc);
- return frameworkProps;
+ scan(feature.getExtensions(), desc);
+ return desc;
}
- private static final String DELIM_START = "${";
- private static final String DELIM_STOP = "}";
-
/**
- * <p>
- * This method performs property variable substitution on the
- * specified value. If the specified value contains the syntax
- * <tt>${<prop-name>}</tt>, where <tt><prop-name></tt>
- * refers to either a configuration property or a system property,
- * then the corresponding property value is substituted for the variable
- * placeholder. Multiple variable place holders may exist in the
- * specified value as well as nested variable place holders, which
- * are substituted from inner most to outer most. Configuration
- * properties override system properties.
- * </p>
- * @param val The string on which to perform property substitution.
- * @param currentKey The key of the property being evaluated used to
- * detect cycles.
- * @param cycleMap Map of variable references used to detect nested cycles.
- * @param configProps Set of configuration properties.
- * @return The value of the specified string after system property
substitution.
- * @throws IllegalArgumentException If there was a syntax error in the
- * property placeholder syntax or a recursive variable reference.
- **/
- public static String substVars(String val, String currentKey,
- Map<String, String> cycleMap, Properties configProps)
- throws IllegalArgumentException
- {
- // If there is currently no cycle map, then create
- // one for detecting cycles for this invocation.
- if (cycleMap == null)
- {
- cycleMap = new HashMap<>();
- }
+ * Scan an application
+ *
+ * @param app The application
+ * @return The application descriptor
+ * @throws IOException If something goes wrong or a scanner is missing
+ */
+ public ApplicationDescriptor scan(final Application app) throws
IOException {
+ final ApplicationDescriptor desc = new ApplicationDescriptor();
- // Put the current key in the cycle map.
- cycleMap.put(currentKey, currentKey);
+ getBundleInfos(app.getBundles(), desc);
+ scan(app.getExtensions(), desc);
- // Assume we have a value that is something like:
- // "leading ${foo.${bar}} middle ${baz} trailing"
+ // framework
+ final File file =
artifactManager.getArtifactHandler(app.getFramework().toMvnUrl()).getFile();
+ if ( file == null ) {
+ throw new IOException("Unable to find file for " +
app.getFramework());
+ }
- // Find the first ending '}' variable delimiter, which
- // will correspond to the first deepest nested variable
- // placeholder.
- int stopDelim = -1;
- int startDelim = -1;
-
- do
- {
- stopDelim = val.indexOf(DELIM_STOP, stopDelim + 1);
- // If there is no stopping delimiter, then just return
- // the value since there is no variable declared.
- if (stopDelim < 0)
- {
- return val;
- }
- // Try to find the matching start delimiter by
- // looping until we find a start delimiter that is
- // greater than the stop delimiter we have found.
- startDelim = val.indexOf(DELIM_START);
- // If there is no starting delimiter, then just return
- // the value since there is no variable declared.
- if (startDelim < 0)
- {
- return val;
- }
- while (stopDelim >= 0)
- {
- int idx = val.indexOf(DELIM_START, startDelim +
DELIM_START.length());
- if ((idx < 0) || (idx > stopDelim))
- {
- break;
- }
- else if (idx < stopDelim)
- {
- startDelim = idx;
- }
+ Descriptor fwk = null;
+ for(final FrameworkScanner scanner : this.frameworkScanners) {
+ fwk = scanner.scan(app.getFramework(), file,
app.getFrameworkProperties());
+ if ( fwk != null ) {
+ break;
}
}
- while ((startDelim > stopDelim) && (stopDelim >= 0));
-
- // At this point, we have found a variable placeholder so
- // we must perform a variable substitution on it.
- // Using the start and stop delimiter indices, extract
- // the first, deepest nested variable placeholder.
- String variable =
- val.substring(startDelim + DELIM_START.length(), stopDelim);
-
- // Verify that this is not a recursive variable reference.
- if (cycleMap.get(variable) != null)
- {
- throw new IllegalArgumentException(
- "recursive variable reference: " + variable);
+ if ( fwk == null ) {
+ throw new IOException("No scanner found for framework " +
app.getFramework().toMvnId());
}
- // Get the value of the deepest nested variable placeholder.
- // Try to configuration properties first.
- String substValue = (configProps != null)
- ? configProps.getProperty(variable, null)
- : null;
- if (substValue == null)
- {
- // Ignore unknown property values.
- substValue = System.getProperty(variable, "");
- }
+ // aggregate
+ desc.getRequirements().addAll(fwk.getRequirements());
+ desc.getCapabilities().addAll(fwk.getCapabilities());
+ desc.getExportedPackages().addAll(fwk.getExportedPackages());
+ desc.getImportedPackages().addAll(fwk.getImportedPackages());
+
desc.getDynamicImportedPackages().addAll(fwk.getDynamicImportedPackages());
- // Remove the found variable from the cycle map, since
- // it may appear more than once in the value and we don't
- // want such situations to appear as a recursive reference.
- cycleMap.remove(variable);
-
- // Append the leading characters, the substituted value of
- // the variable, and the trailing characters to get the new
- // value.
- val = val.substring(0, startDelim)
- + substValue
- + val.substring(stopDelim + DELIM_STOP.length(), val.length());
-
- // Now perform substitution again, since there could still
- // be substitutions to make.
- val = substVars(val, currentKey, cycleMap, configProps);
+ desc.setFrameworkDescriptor(fwk);
- // Return the value.
- return val;
+ return desc;
}
}
Added:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/impl/FelixFrameworkScanner.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/impl/FelixFrameworkScanner.java?rev=1801057&view=auto
==============================================================================
---
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/impl/FelixFrameworkScanner.java
(added)
+++
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/impl/FelixFrameworkScanner.java
Thu Jul 6 14:09:13 2017
@@ -0,0 +1,254 @@
+/*
+ * 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.scanner.impl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.apache.sling.commons.osgi.ManifestHeader;
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.KeyValueMap;
+import org.apache.sling.feature.scanner.Descriptor;
+import org.apache.sling.feature.scanner.FrameworkScanner;
+import org.apache.sling.feature.scanner.PackageInfo;
+import org.osgi.framework.Constants;
+
+public class FelixFrameworkScanner implements FrameworkScanner {
+
+
+ @Override
+ public Descriptor scan(final ArtifactId framework,
+ final File platformFile,
+ final KeyValueMap frameworkProps)
+ throws IOException {
+ final KeyValueMap fwkProps = getFrameworkProperties(frameworkProps,
platformFile);
+ if ( fwkProps == null ) {
+ return null;
+ }
+ final Set<PackageInfo> pcks = calculateSystemPackages(fwkProps);
+ return new Descriptor() {
+
+ @Override
+ public Set<PackageInfo> getExportedPackages() {
+ return pcks;
+ }
+ };
+ }
+
+ private Set<PackageInfo> calculateSystemPackages(final KeyValueMap
fwkProps) {
+ final String system = fwkProps.get(Constants.FRAMEWORK_SYSTEMPACKAGES);
+ final String extra =
fwkProps.get(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
+ final Set<PackageInfo> packages = new HashSet<>();
+ for(int i=0;i<2;i++) {
+ final String value = (i == 0 ? system : extra);
+ if ( value != null ) {
+ final ManifestHeader header = ManifestHeader.parse(value);
+ for(final ManifestHeader.Entry entry : header.getEntries()) {
+ String version = entry.getAttributeValue("version");
+ if ( version == null ) {
+ version = "0.0.0";
+ }
+
+ final PackageInfo exportedPackageInfo = new
PackageInfo(entry.getValue(),
+ version, false);
+ packages.add(exportedPackageInfo);
+ }
+ }
+ }
+ return packages;
+ }
+
+ private static final String DEFAULT_PROPERTIES = "default.properties";
+
+ private KeyValueMap getFrameworkProperties(final KeyValueMap appProps,
final File framework)
+ throws IOException {
+ final Map<String, Properties> propsMap = new HashMap<>();
+ try (final ZipInputStream zis = new ZipInputStream(new
FileInputStream(framework)) ) {
+ boolean done = false;
+ while ( !done ) {
+ final ZipEntry entry = zis.getNextEntry();
+ if ( entry == null ) {
+ done = true;
+ } else {
+ final String entryName = entry.getName();
+ if ( entryName.endsWith(".properties") ) {
+ final Properties props = new Properties();
+ props.load(zis);
+
+ propsMap.put(entryName, props);
+ }
+ zis.closeEntry();
+ }
+ }
+ }
+
+ final Properties defaultMap = propsMap.get(DEFAULT_PROPERTIES);
+ if ( defaultMap == null ) {
+ return null;
+ }
+
+ final KeyValueMap frameworkProps = new KeyValueMap();
+ frameworkProps.putAll(appProps);
+
+ // replace variables
+ defaultMap.put("java.specification.version",
+ System.getProperty("java.specification.version", "1.8"));
+ for(final Object name : defaultMap.keySet()) {
+ if ( frameworkProps.get(name.toString()) == null ) {
+ final String value = (String)defaultMap.get(name);
+ final String substValue = substVars(value, name.toString(),
null, defaultMap);
+ frameworkProps.put(name.toString(), substValue);
+ }
+ }
+
+ return frameworkProps;
+ }
+
+ private static final String DELIM_START = "${";
+ private static final String DELIM_STOP = "}";
+
+ /**
+ * <p>
+ * This method performs property variable substitution on the
+ * specified value. If the specified value contains the syntax
+ * <tt>${<prop-name>}</tt>, where <tt><prop-name></tt>
+ * refers to either a configuration property or a system property,
+ * then the corresponding property value is substituted for the variable
+ * placeholder. Multiple variable place holders may exist in the
+ * specified value as well as nested variable place holders, which
+ * are substituted from inner most to outer most. Configuration
+ * properties override system properties.
+ * </p>
+ * @param val The string on which to perform property substitution.
+ * @param currentKey The key of the property being evaluated used to
+ * detect cycles.
+ * @param cycleMap Map of variable references used to detect nested cycles.
+ * @param configProps Set of configuration properties.
+ * @return The value of the specified string after system property
substitution.
+ * @throws IllegalArgumentException If there was a syntax error in the
+ * property placeholder syntax or a recursive variable reference.
+ **/
+ private static String substVars(String val, String currentKey,
+ Map<String, String> cycleMap, Properties configProps)
+ throws IllegalArgumentException
+ {
+ // If there is currently no cycle map, then create
+ // one for detecting cycles for this invocation.
+ if (cycleMap == null)
+ {
+ cycleMap = new HashMap<>();
+ }
+
+ // Put the current key in the cycle map.
+ cycleMap.put(currentKey, currentKey);
+
+ // Assume we have a value that is something like:
+ // "leading ${foo.${bar}} middle ${baz} trailing"
+
+ // Find the first ending '}' variable delimiter, which
+ // will correspond to the first deepest nested variable
+ // placeholder.
+ int stopDelim = -1;
+ int startDelim = -1;
+
+ do
+ {
+ stopDelim = val.indexOf(DELIM_STOP, stopDelim + 1);
+ // If there is no stopping delimiter, then just return
+ // the value since there is no variable declared.
+ if (stopDelim < 0)
+ {
+ return val;
+ }
+ // Try to find the matching start delimiter by
+ // looping until we find a start delimiter that is
+ // greater than the stop delimiter we have found.
+ startDelim = val.indexOf(DELIM_START);
+ // If there is no starting delimiter, then just return
+ // the value since there is no variable declared.
+ if (startDelim < 0)
+ {
+ return val;
+ }
+ while (stopDelim >= 0)
+ {
+ int idx = val.indexOf(DELIM_START, startDelim +
DELIM_START.length());
+ if ((idx < 0) || (idx > stopDelim))
+ {
+ break;
+ }
+ else if (idx < stopDelim)
+ {
+ startDelim = idx;
+ }
+ }
+ }
+ while ((startDelim > stopDelim) && (stopDelim >= 0));
+
+ // At this point, we have found a variable placeholder so
+ // we must perform a variable substitution on it.
+ // Using the start and stop delimiter indices, extract
+ // the first, deepest nested variable placeholder.
+ String variable =
+ val.substring(startDelim + DELIM_START.length(), stopDelim);
+
+ // Verify that this is not a recursive variable reference.
+ if (cycleMap.get(variable) != null)
+ {
+ throw new IllegalArgumentException(
+ "recursive variable reference: " + variable);
+ }
+
+ // Get the value of the deepest nested variable placeholder.
+ // Try to configuration properties first.
+ String substValue = (configProps != null)
+ ? configProps.getProperty(variable, null)
+ : null;
+ if (substValue == null)
+ {
+ // Ignore unknown property values.
+ substValue = System.getProperty(variable, "");
+ }
+
+ // Remove the found variable from the cycle map, since
+ // it may appear more than once in the value and we don't
+ // want such situations to appear as a recursive reference.
+ cycleMap.remove(variable);
+
+ // Append the leading characters, the substituted value of
+ // the variable, and the trailing characters to get the new
+ // value.
+ val = val.substring(0, startDelim)
+ + substValue
+ + val.substring(stopDelim + DELIM_STOP.length(), val.length());
+
+ // Now perform substitution again, since there could still
+ // be substitutions to make.
+ val = substVars(val, currentKey, cycleMap, configProps);
+
+ // Return the value.
+ return val;
+ }
+}
Propchange:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/impl/FelixFrameworkScanner.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/whiteboard/cziegeler/feature-analyser/src/main/java/org/apache/sling/feature/scanner/impl/FelixFrameworkScanner.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Modified:
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Capability.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Capability.java?rev=1801057&r1=1801056&r2=1801057&view=diff
==============================================================================
---
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Capability.java
(original)
+++
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Capability.java
Thu Jul 6 14:09:13 2017
@@ -70,4 +70,41 @@ public class Capability {
public KeyValueMap getDirectives() {
return directives;
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((attributes == null) ? 0 :
attributes.hashCode());
+ result = prime * result + ((directives == null) ? 0 :
directives.hashCode());
+ result = prime * result + ((namespace == null) ? 0 :
namespace.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Capability other = (Capability) obj;
+ if (attributes == null) {
+ if (other.attributes != null)
+ return false;
+ } else if (!attributes.equals(other.attributes))
+ return false;
+ if (directives == null) {
+ if (other.directives != null)
+ return false;
+ } else if (!directives.equals(other.directives))
+ return false;
+ if (namespace == null) {
+ if (other.namespace != null)
+ return false;
+ } else if (!namespace.equals(other.namespace))
+ return false;
+ return true;
+ }
}
Modified:
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/KeyValueMap.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/KeyValueMap.java?rev=1801057&r1=1801056&r2=1801057&view=diff
==============================================================================
---
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/KeyValueMap.java
(original)
+++
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/KeyValueMap.java
Thu Jul 6 14:09:13 2017
@@ -97,4 +97,29 @@ public class KeyValueMap
public void clear() {
this.properties.clear();
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((properties == null) ? 0 :
properties.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ KeyValueMap other = (KeyValueMap) obj;
+ if (properties == null) {
+ if (other.properties != null)
+ return false;
+ } else if (!properties.equals(other.properties))
+ return false;
+ return true;
+ }
}
Modified:
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Requirement.java
URL:
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Requirement.java?rev=1801057&r1=1801056&r2=1801057&view=diff
==============================================================================
---
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Requirement.java
(original)
+++
sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Requirement.java
Thu Jul 6 14:09:13 2017
@@ -70,4 +70,41 @@ public class Requirement {
public KeyValueMap getDirectives() {
return directives;
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((attributes == null) ? 0 :
attributes.hashCode());
+ result = prime * result + ((directives == null) ? 0 :
directives.hashCode());
+ result = prime * result + ((namespace == null) ? 0 :
namespace.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Requirement other = (Requirement) obj;
+ if (attributes == null) {
+ if (other.attributes != null)
+ return false;
+ } else if (!attributes.equals(other.attributes))
+ return false;
+ if (directives == null) {
+ if (other.directives != null)
+ return false;
+ } else if (!directives.equals(other.directives))
+ return false;
+ if (namespace == null) {
+ if (other.namespace != null)
+ return false;
+ } else if (!namespace.equals(other.namespace))
+ return false;
+ return true;
+ }
}