All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.sling.feature.analyser.Analyser Maven / Gradle / Ivy

There is a newer version: 2.0.10
Show 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 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;

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;

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;

    /**
     * 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());
    }

    /**
     * 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());

        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());
        }
        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) {

            logger.info("- Executing {} [{}]...", task.getName(), task.getId());
            start = System.currentTimeMillis();
            final Map taskConfiguration = getConfiguration(task.getId());

            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 (analyserMetaDataExtension == null || analyserMetaDataExtension.reportWarning(feature.getId())) {
                        globalWarnings.add(new AnalyserResult.GlobalReport(message, task.getId()));
                    }
                }

                @Override
                public void reportArtifactWarning(ArtifactId artifactId, String 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 (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 (analyserMetaDataExtension == null || analyserMetaDataExtension.reportWarning(feature.getId())) {
                        configurationWarnings.add(new AnalyserResult.ConfigurationReport(cfg, message, task.getId()));
                    }
                }
            });
            logger.info("- Executed {} [{}] in {}ms", task.getName(), task.getId(), System.currentTimeMillis() - start);
        }

        int allWarnings = globalWarnings.size() + artifactWarnings.size() + extensionWarnings.size() + configurationWarnings.size();
        int allErrors = globalErrors.size() + artifactErrors.size() + extensionErrors.size()  + configurationErrors.size();
        logger.info("Analyzing feature '" + feature.getId() + "' finished : "
                + allWarnings + " warnings, "
                + allErrors + " errors.");

        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