org.apache.sling.feature.analyser.Analyser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.sling.feature.analyser Show documentation
Show all versions of org.apache.sling.feature.analyser Show documentation
A feature describes an OSGi system
The newest version!
/*
* 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.analyser;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.Configuration;
import org.apache.sling.feature.ExecutionEnvironmentExtension;
import org.apache.sling.feature.Feature;
import org.apache.sling.feature.analyser.extensions.AnalyserMetaDataExtension;
import org.apache.sling.feature.analyser.task.AnalyserTask;
import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
import org.apache.sling.feature.builder.FeatureProvider;
import org.apache.sling.feature.scanner.BundleDescriptor;
import org.apache.sling.feature.scanner.FeatureDescriptor;
import org.apache.sling.feature.scanner.Scanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.apache.sling.feature.analyser.task.AnalyzerTaskProvider.getTasks;
import static org.apache.sling.feature.analyser.task.AnalyzerTaskProvider.getTasksByClassName;
import static org.apache.sling.feature.analyser.task.AnalyzerTaskProvider.getTasksByIds;
public class Analyser {
/**
* Configurration key for configuration that applies to all tasks.
*/
static final String ALL_TASKS_KEY = "all";
private final AnalyserTask[] tasks;
private final Scanner scanner;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final Map> configurations;
private boolean outputTaskDetails = true;
/**
* Create new analyser with a provided scanner and the tasks to run
*
* @param scanner The scanner
* @param tasks The tasks to run
* @throws IOException If setting up the analyser fails
*/
public Analyser(final Scanner scanner, final AnalyserTask... tasks) throws IOException {
this(scanner, Collections.emptyMap(), tasks);
}
/**
* Create a new analyser with a provided scanner, tasks and configurations
*
* @param scanner The scanner
* @param configurations The configurations for the tasks
* @param tasks The tasks
* @throws IOException If setting up the analyser fails
*/
public Analyser(
final Scanner scanner, final Map> configurations, final AnalyserTask... tasks)
throws IOException {
this.tasks = tasks;
this.configurations = configurations;
this.scanner = scanner;
}
/**
* Create a new analyser with the provided scanner and task class names
*
* @param scanner The scanner
* @param taskClassNames The task class names
* @throws IOException If setting up the analyser fails
*/
public Analyser(final Scanner scanner, final String... taskClassNames) throws IOException {
this(scanner, Collections.emptyMap(), taskClassNames);
}
/**
* Create a new analyser with a provided scanner, task class names and
* configurations
*
* @param scanner The scanner
* @param configurations The configurations for the tasks
* @param taskClassNames The task class names
* @throws IOException If setting up the analyser fails
*/
public Analyser(
final Scanner scanner,
final Map> configurations,
final String... taskClassNames)
throws IOException {
this(scanner, configurations, getTasksByClassName(taskClassNames));
if (this.tasks.length != taskClassNames.length) {
throw new IOException("Couldn't find all tasks " + Arrays.toString(taskClassNames));
}
}
/**
* Create a new analyser with a provided scanner and includes/excludes for the
* task ids
*
* @param scanner The scanner
* @param includes The includes for the task ids - can be {@code null}
* @param excludes The excludes for the task ids - can be {@code null}
* @throws IOException If setting up the analyser fails
*/
public Analyser(final Scanner scanner, final Set includes, final Set excludes) throws IOException {
this(scanner, Collections.emptyMap(), includes, excludes);
}
/**
* Create a new analyser with a provided scanner and includes/excludes for the
* task ids and configuration
*
* @param scanner The scanner
* @param configurations The configurations for the tasks
* @param includes The includes for the task ids - can be {@code null}
* @param excludes The excludes for the task ids - can be {@code null}
* @throws IOException If setting up the analyser fails
*/
public Analyser(
final Scanner scanner,
final Map> configurations,
final Set includes,
final Set excludes)
throws IOException {
this(scanner, configurations, getTasksByIds(includes, excludes));
}
/**
* Create a new analyser with the provided scanner and use all available tasks
*
* @param scanner The scanner
* @throws IOException If setting up the analyser fails
*/
public Analyser(final Scanner scanner) throws IOException {
this(scanner, getTasks());
}
/**
* Enable/disable output of task details. By default the details are outputted.
* @param outputTaskDetails flag for enabling/disabling output of task details
* @since 1.6.0
*/
public void setOutputTaskDetails(final boolean outputTaskDetails) {
this.outputTaskDetails = outputTaskDetails;
}
/**
* Analyse the feature
*
* @param feature The feature to analyse
* @return The analyser result
* @throws Exception If analysing fails
*/
public AnalyserResult analyse(final Feature feature) throws Exception {
return this.analyse(feature, null);
}
/**
* Analyse the feature using the provided framework artifact
*
* @param feature The feature to analyse
* @param fwk The OSGi framework artifact
* @return The analyser result
* @throws Exception If analysing fails
*/
public AnalyserResult analyse(final Feature feature, final ArtifactId fwk) throws Exception {
return analyse(feature, fwk, null);
}
/**
* Analyse the feature using the provided framework artifact
*
* @param feature The feature to analyse
* @param fwk The OSGi framework artifact
* @param featureProvider Optional provider to resolve features (if required)
* @return The analyser result
* @throws Exception If analysing fails
*/
public AnalyserResult analyse(final Feature feature, final ArtifactId fwk, final FeatureProvider featureProvider)
throws Exception {
logger.info("Starting analyzing feature '{}'...", feature.getId());
final long start = System.currentTimeMillis();
final FeatureDescriptor featureDesc = scanner.scan(feature);
BundleDescriptor bd = null;
ArtifactId framework = fwk;
if (framework == null) {
final ExecutionEnvironmentExtension ext =
ExecutionEnvironmentExtension.getExecutionEnvironmentExtension(feature);
if (ext != null && ext.getFramework() != null) {
framework = ext.getFramework().getId();
}
}
if (framework != null) {
bd = scanner.scan(framework, feature.getFrameworkProperties());
}
if (this.outputTaskDetails) {
logger.info("- Scanned feature in {}ms", System.currentTimeMillis() - start);
}
final BundleDescriptor fwkDesc = bd;
final List globalWarnings = new ArrayList<>();
final List artifactWarnings = new ArrayList<>();
final List extensionWarnings = new ArrayList<>();
final List configurationWarnings = new ArrayList<>();
final List globalErrors = new ArrayList<>();
final List artifactErrors = new ArrayList<>();
final List extensionErrors = new ArrayList<>();
final List configurationErrors = new ArrayList<>();
AnalyserMetaDataExtension analyserMetaDataExtension =
AnalyserMetaDataExtension.getAnalyserMetaDataExtension(feature);
// execute analyser tasks
for (final AnalyserTask task : tasks) {
if (this.outputTaskDetails) {
logger.info("- Executing {} [{}]...", task.getName(), task.getId());
}
final long startTask = System.currentTimeMillis();
final Map taskConfiguration = getConfiguration(task.getId());
final boolean strict = Boolean.valueOf(taskConfiguration.getOrDefault("strict", "false"));
task.execute(new AnalyserTaskContext() {
private final FeatureProvider cachingFeatureProvider = featureProvider != null
? new FeatureProvider() {
private final ConcurrentHashMap cache = new ConcurrentHashMap<>();
@Override
public Feature provide(ArtifactId artifactId) {
return cache.computeIfAbsent(artifactId, key -> featureProvider.provide(artifactId));
}
}
: null;
@Override
public Feature getFeature() {
return feature;
}
@Override
public FeatureDescriptor getFeatureDescriptor() {
return featureDesc;
}
@Override
public FeatureProvider getFeatureProvider() {
return cachingFeatureProvider;
}
@Override
public BundleDescriptor getFrameworkDescriptor() {
return fwkDesc;
}
@Override
public Map getConfiguration() {
return taskConfiguration;
}
@Override
public void reportWarning(final String message) {
if (strict) {
reportError(message);
}
if (analyserMetaDataExtension == null || analyserMetaDataExtension.reportWarning(feature.getId())) {
globalWarnings.add(new AnalyserResult.GlobalReport(message, task.getId()));
}
}
@Override
public void reportArtifactWarning(ArtifactId artifactId, String message) {
if (strict) {
reportArtifactError(artifactId, message);
}
if (analyserMetaDataExtension == null
|| (analyserMetaDataExtension.reportWarning(artifactId)
&& analyserMetaDataExtension.reportWarning(feature.getId()))) {
artifactWarnings.add(new AnalyserResult.ArtifactReport(artifactId, message, task.getId()));
}
}
@Override
public void reportArtifactError(ArtifactId artifactId, String message) {
if (analyserMetaDataExtension == null
|| (analyserMetaDataExtension.reportError(artifactId)
&& analyserMetaDataExtension.reportError(feature.getId()))) {
artifactErrors.add(new AnalyserResult.ArtifactReport(artifactId, message, task.getId()));
}
}
@Override
public void reportExtensionWarning(String extension, String message) {
if (strict) {
reportExtensionError(extension, message);
}
if (analyserMetaDataExtension == null || analyserMetaDataExtension.reportWarning(feature.getId())) {
extensionWarnings.add(new AnalyserResult.ExtensionReport(extension, message, task.getId()));
}
}
@Override
public void reportExtensionError(String extension, String message) {
if (analyserMetaDataExtension == null || analyserMetaDataExtension.reportError(feature.getId())) {
extensionErrors.add(new AnalyserResult.ExtensionReport(extension, message, task.getId()));
}
}
@Override
public void reportError(final String message) {
if (analyserMetaDataExtension == null || analyserMetaDataExtension.reportError(feature.getId())) {
globalErrors.add(new AnalyserResult.GlobalReport(message, task.getId()));
}
}
@Override
public void reportConfigurationError(Configuration cfg, String message) {
if (analyserMetaDataExtension == null || analyserMetaDataExtension.reportWarning(feature.getId())) {
configurationErrors.add(new AnalyserResult.ConfigurationReport(cfg, message, task.getId()));
}
}
@Override
public void reportConfigurationWarning(Configuration cfg, String message) {
if (strict) {
reportConfigurationError(cfg, message);
}
if (analyserMetaDataExtension == null || analyserMetaDataExtension.reportWarning(feature.getId())) {
configurationWarnings.add(new AnalyserResult.ConfigurationReport(cfg, message, task.getId()));
}
}
});
if (this.outputTaskDetails) {
logger.info(
"- Executed {} [{}] in {}ms",
task.getName(),
task.getId(),
System.currentTimeMillis() - startTask);
}
}
final int allWarnings = globalWarnings.size()
+ artifactWarnings.size()
+ extensionWarnings.size()
+ configurationWarnings.size();
final int allErrors =
globalErrors.size() + artifactErrors.size() + extensionErrors.size() + configurationErrors.size();
logger.info(
"Finished analyzing feature '{}' in {}ms : {} warnings, {} errors.",
feature.getId(),
System.currentTimeMillis() - start,
allWarnings,
allErrors);
return new AnalyserResult() {
@Override
public List getGlobalWarnings() {
return globalWarnings;
}
@Override
public List getArtifactWarnings() {
return artifactWarnings;
}
@Override
public List getExtensionWarnings() {
return extensionWarnings;
}
@Override
public List getGlobalErrors() {
return globalErrors;
}
@Override
public List getArtifactErrors() {
return artifactErrors;
}
@Override
public List getExtensionErrors() {
return extensionErrors;
}
@Override
public FeatureDescriptor getFeatureDescriptor() {
return featureDesc;
}
@Override
public BundleDescriptor getFrameworkDescriptor() {
return fwkDesc;
}
@Override
public List getConfigurationErrors() {
return configurationErrors;
}
@Override
public List getConfigurationWarnings() {
return configurationWarnings;
}
};
}
Map getConfiguration(final String id) {
final Map result = new HashMap<>();
Map globalCfg = this.configurations.get(ALL_TASKS_KEY);
if (globalCfg != null) result.putAll(globalCfg);
Map specificCfg = this.configurations.get(id);
if (specificCfg != null) result.putAll(specificCfg);
return result;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy