blob: 90d89684f439899cdca29f2fa08905969271f925 [file] [log] [blame]
/*
* 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.maven.mojos;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.Feature;
import org.apache.sling.feature.maven.ProjectHelper;
import org.codehaus.plexus.util.AbstractScanner;
public abstract class AbstractIncludingFeatureMojo extends AbstractFeatureMojo {
protected Map<String, Feature> getSelectedFeatures(final FeatureSelectionConfig config)
throws MojoExecutionException {
final Map<String, Feature> result = new LinkedHashMap<>();
boolean hasFileInclude = false;
for(final FeatureSelectionConfig.Selection selection : config.getSelections()) {
switch ( selection.type ) {
case FILE_INCLUDE:
hasFileInclude = true;
selectFeatureFiles(selection.instruction, config.getFilesExcludes(), result);
break;
case AGGREGATE_CLASSIFIER:
selectFeatureClassifier(selection.instruction, result);
break;
case ARTIFACT:
selectFeatureArtifact(selection.instruction, result);
break;
}
}
if (!hasFileInclude && !config.getFilesExcludes().isEmpty()) {
throw new MojoExecutionException("filesExclude configured without filesInclude in " + config);
}
return result;
}
protected Map<String, Feature> selectAllFeatureFiles() throws MojoExecutionException {
final FeatureSelectionConfig config = new FeatureSelectionConfig();
config.setFilesInclude("**/*.*");
return this.getSelectedFeatures(config);
}
protected Map<String, Feature> selectAllFeatureFilesAndAggregates() throws MojoExecutionException {
final FeatureSelectionConfig config = new FeatureSelectionConfig();
config.setFilesInclude("**/*.*");
config.setIncludeClassifier("*");
return this.getSelectedFeatures(config);
}
private void selectFeatureClassifier(final String selection, final Map<String, Feature> result)
throws MojoExecutionException {
final Map<String, Feature> projectFeatures = ProjectHelper.getAssembledFeatures(this.project);
boolean includeAll = "*".equals(selection);
boolean found = false;
for (final Map.Entry<String, Feature> entry : projectFeatures.entrySet()) {
final String classifier = entry.getValue().getId().getClassifier();
boolean include = includeAll;
if (!include) {
if (selection.trim().length() == 0 && classifier == null) {
include = true;
} else if (selection.equals(classifier)) {
include = true;
}
}
if (include) {
result.put(entry.getKey(), entry.getValue());
found = true;
}
}
if (!found) {
throw new MojoExecutionException("Aggregate Classifier " + selection + " not found.");
}
}
private void selectFeatureFiles(final String include, final List<String> excludes,
final Map<String, Feature> result)
throws MojoExecutionException {
final Map<String, Feature> projectFeatures = ProjectHelper.getAssembledFeatures(this.project);
final String prefix = this.features.toPath().normalize().toFile().getAbsolutePath().concat(File.separator);
final FeatureScanner scanner = new FeatureScanner(projectFeatures, prefix);
if (!excludes.isEmpty()) {
scanner.setExcludes(excludes.toArray(new String[excludes.size()]));
}
scanner.setIncludes(new String[] { include });
scanner.scan();
if (!include.contains("*") && scanner.getIncluded().isEmpty()) {
throw new MojoExecutionException("FeatureInclude " + include + " not found.");
}
for (Map.Entry<String, Feature> entry : scanner.getIncluded().entrySet()) {
if (!result.containsKey(entry.getKey())) {
result.put(entry.getKey(), entry.getValue());
}
}
if (!excludes.isEmpty()) {
for (final String exclude : excludes) {
if (!exclude.contains("*")) {
final FeatureScanner excludeScanner = new FeatureScanner(projectFeatures, prefix);
excludeScanner.setIncludes(new String[] { exclude });
excludeScanner.scan();
if (excludeScanner.getIncluded().isEmpty()) {
throw new MojoExecutionException("FeatureExclude " + exclude + " not found.");
}
}
}
}
}
private void selectFeatureArtifact(final String artifactId, final Map<String, Feature> result)
throws MojoExecutionException {
final ArtifactId id = ArtifactId.parse(artifactId);
if (ProjectHelper.isLocalProjectArtifact(this.project, id)) {
throw new MojoExecutionException(
"FeatureArtifact configuration is used to select a local feature: " + id.toMvnId());
}
final Feature feature = ProjectHelper.getOrResolveFeature(this.project, this.mavenSession,
this.artifactHandlerManager, this.artifactResolver, id);
result.put(id.toMvnUrl(), feature);
}
public static class FeatureScanner extends AbstractScanner {
private final Map<String, Feature> features;
private final Map<String, Feature> included = new TreeMap<>();
private final String prefix;
public FeatureScanner(final Map<String, Feature> features, final String prefix) {
this.features = features;
this.prefix = prefix;
}
@Override
public void scan() {
setupDefaultFilters();
setupMatchPatterns();
for (Map.Entry<String, Feature> entry : features.entrySet()) {
// skip aggregates
if (ProjectHelper.isAggregate(entry.getKey())) {
continue;
}
final String name = entry.getKey().substring(prefix.length());
final String[] tokenizedName = tokenizePathToString(name, File.separator);
if (isIncluded(name, tokenizedName)) {
if (!isExcluded(name, tokenizedName)) {
included.put(entry.getKey(), entry.getValue());
}
}
}
}
static String[] tokenizePathToString(String path, String separator) {
List<String> ret = new ArrayList<>();
StringTokenizer st = new StringTokenizer(path, separator);
while (st.hasMoreTokens()) {
ret.add(st.nextToken());
}
return ret.toArray(new String[ret.size()]);
}
public Map<String, Feature> getIncluded() {
return this.included;
}
@Override
public String[] getIncludedFiles() {
return null;
}
@Override
public String[] getIncludedDirectories() {
return null;
}
@Override
public File getBasedir() {
return null;
}
}
}