| /* |
| * 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.cpconverter.maven.mojos; |
| |
| import org.apache.maven.artifact.Artifact; |
| import org.apache.maven.artifact.DefaultArtifact; |
| import org.apache.maven.plugin.MojoExecutionException; |
| import org.apache.maven.plugin.MojoFailureException; |
| import org.apache.maven.plugins.annotations.Mojo; |
| import org.apache.maven.plugins.annotations.Parameter; |
| import org.apache.maven.project.ProjectBuildingRequest; |
| import org.apache.maven.shared.transfer.artifact.install.ArtifactInstallerException; |
| import org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter; |
| import org.apache.sling.feature.cpconverter.acl.DefaultAclManager; |
| import org.apache.sling.feature.cpconverter.artifacts.DefaultArtifactsDeployer; |
| import org.apache.sling.feature.cpconverter.features.DefaultFeaturesManager; |
| import org.apache.sling.feature.cpconverter.handlers.DefaultEntryHandlersManager; |
| import org.apache.sling.feature.cpconverter.vltpkg.DefaultPackagesEventsEmitter; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.nio.file.Files; |
| import java.nio.file.StandardCopyOption; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import static org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter.PACKAGE_CLASSIFIER; |
| import static org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter.ZIP_TYPE; |
| |
| /** |
| * Converts the given Content Packages into Feature Models |
| * and places the converted Content Package into the local |
| * Maven Repository |
| */ |
| @Mojo( |
| name = "convert-cp", |
| requiresProject = true, |
| threadSafe = true |
| ) |
| public final class ConvertCPMojo |
| extends AbstractBaseMojo |
| { |
| public static final String CFG_STRICT_VALIDATION = "strictValidation"; |
| |
| public static final String CFG_MERGE_CONFIGURATIONS = "mergeConfigurations"; |
| |
| public static final String CFG_BUNDLE_START_ORDER = "bundleStartOrder"; |
| |
| public static final String CFG_ARTIFACT_ID_OVERRIDE = "artifactIdOverride"; |
| |
| public static final String CFG_INSTALL_CONVERTED_PACKAGE = "installConvertedContentPackage"; |
| |
| public static final String CFG_FM_OUTPUT_DIRECTORY = "featureModelsOutputDirectory"; |
| |
| public static final String CFG_CONVERTED_CP_OUTPUT_DIRECTORY = "convertedContentPackageOutputDirectory"; |
| |
| public static final String CFG_CONVERTED_CP_FM_PREFIX = "fmPrefix"; |
| |
| public static final String CFG_SYSTEM_PROPERTIES = "cpSystemProperties"; |
| |
| public static final String CFG_CONTENT_PACKAGES = "packages"; |
| |
| public static final boolean DEFAULT_STRING_VALIDATION = false; |
| |
| public static final boolean DEFAULT_MERGE_CONFIGURATIONS = false; |
| |
| public static final int DEFAULT_BUNDLE_START_ORDER = 20; |
| |
| public static final boolean DEFAULT_INSTALL_CONVERTED_PACKAGE = true; |
| |
| public static final String DEFAULT_CONVERTED_CP_OUTPUT_DIRECTORY = "${project.build.directory}/cp-conversion"; |
| |
| public static final String DEFAULT_FM_OUTPUT_DIRECTORY = DEFAULT_CONVERTED_CP_OUTPUT_DIRECTORY + "/fm.out"; |
| |
| /** |
| * If set to {@code true} the Content Package is strictly validated. |
| */ |
| @Parameter(property = CFG_STRICT_VALIDATION, defaultValue = DEFAULT_STRING_VALIDATION + "") |
| private boolean strictValidation; |
| |
| //AS TODO: Is that applicable to a single CP ? |
| /** |
| * If set to {@code true} the OSGi Configurations with same PID are merged. |
| */ |
| @Parameter(property = CFG_MERGE_CONFIGURATIONS, defaultValue = DEFAULT_MERGE_CONFIGURATIONS + "") |
| private boolean mergeConfigurations; |
| |
| /** |
| * If set to {@code true} the Content Package is strictly validated. |
| */ |
| @Parameter(property = CFG_BUNDLE_START_ORDER, defaultValue = DEFAULT_BUNDLE_START_ORDER + "") |
| private int bundleStartOrder; |
| |
| /** |
| * If set to {@code true} the Content Package is strictly validated. |
| */ |
| @Parameter(property = CFG_ARTIFACT_ID_OVERRIDE) |
| private String artifactIdOverride; |
| |
| /** |
| * Target directory for the converted Content Package Feature Model file |
| */ |
| @Parameter(property = CFG_FM_OUTPUT_DIRECTORY, defaultValue = DEFAULT_FM_OUTPUT_DIRECTORY) |
| private File fmOutput; |
| |
| /** |
| * Target directory for the Converted Content Package file |
| */ |
| @Parameter(property = CFG_CONVERTED_CP_OUTPUT_DIRECTORY, defaultValue = DEFAULT_CONVERTED_CP_OUTPUT_DIRECTORY) |
| private File convertedCPOutput; |
| |
| /** |
| * If set to {@code true} the converted Content Package will be installed in the local Maven Repository |
| */ |
| @Parameter(property = CFG_INSTALL_CONVERTED_PACKAGE, defaultValue = DEFAULT_INSTALL_CONVERTED_PACKAGE + "") |
| private boolean installConvertedCP; |
| |
| /** |
| * System Properties to hand over to the Content Package Converter |
| */ |
| @Parameter(property = CFG_CONVERTED_CP_FM_PREFIX) |
| private String fmPrefix; |
| |
| /** |
| * System Properties to hand over to the Content Package Converter |
| */ |
| @Parameter(property = CFG_SYSTEM_PROPERTIES) |
| private List<String> systemProperties; |
| |
| /** |
| * List of Content Packages to be converted |
| */ |
| @Parameter(property = CFG_CONTENT_PACKAGES) |
| private List<ContentPackage> contentPackages; |
| |
| @Override |
| public void execute() throws MojoExecutionException, MojoFailureException { |
| // Un-encode a given Artifact Override Id |
| if(artifactIdOverride != null) { |
| String old = artifactIdOverride; |
| artifactIdOverride = artifactIdOverride.replaceAll("\\$\\{\\{", "\\$\\{"); |
| artifactIdOverride = artifactIdOverride.replaceAll("}}", "}"); |
| getLog().info("Replaced Old Artifact Id Override: '" + old + "', with new one: '" + artifactIdOverride + "'"); |
| } |
| // Parse the System Properties if provided |
| Map<String,String> properties = new HashMap<>(); |
| if(systemProperties != null) { |
| for(String systemProperty: systemProperties) { |
| if(systemProperty != null) { |
| int index = systemProperty.indexOf("="); |
| if(index > 0 && index < systemProperty.length() - 1) { |
| String key = systemProperty.substring(0, index); |
| String value = systemProperty.substring(index + 1); |
| properties.put(key, value); |
| } |
| } |
| } |
| } |
| try { |
| ContentPackage2FeatureModelConverter converter = new ContentPackage2FeatureModelConverter(strictValidation) |
| .setFeaturesManager( |
| new DefaultFeaturesManager( |
| mergeConfigurations, |
| bundleStartOrder, |
| fmOutput, |
| artifactIdOverride, |
| // fmPrefix, |
| properties |
| ) |
| ) |
| .setBundlesDeployer( |
| new DefaultArtifactsDeployer( |
| convertedCPOutput |
| ) |
| ) |
| .setEntryHandlersManager( |
| new DefaultEntryHandlersManager() |
| ) |
| .setAclManager( |
| new DefaultAclManager() |
| ) |
| .setEmitter(DefaultPackagesEventsEmitter.open(fmOutput)); |
| |
| if(contentPackages == null || contentPackages.isEmpty()) { |
| getLog().info("Project Artifact File: " + project.getArtifact()); |
| String targetPath = project.getModel().getBuild().getDirectory() + "/" |
| + project.getModel().getBuild().getFinalName() |
| + "." + ZIP_TYPE; |
| File targetFile = new File(targetPath); |
| if (targetFile.exists() && targetFile.isFile() && targetFile.canRead()) { |
| converter.convert(project.getArtifact().getFile()); |
| // Artifact convertedPackage = new DefaultArtifact( |
| // project.getGroupId(), project.getArtifactId(), project.getVersion(), |
| // "compile", ZIP_TYPE, PACKAGE_CLASSIFIER, artifactHandlerManager.getArtifactHandler(ZIP_TYPE) |
| // ); |
| // installConvertedCP(convertedPackage); |
| } else { |
| getLog().error("Artifact is not found: " + targetPath); |
| } |
| } else { |
| for(ContentPackage contentPackage: contentPackages) { |
| getLog().info("Content Package Artifact File: " + contentPackage.toString()); |
| contentPackage.setExcludeTransitive(true); |
| final Collection<Artifact> artifacts = contentPackage.getMatchingArtifacts(project); |
| if (artifacts.isEmpty()) { |
| getLog().warn("No matching artifacts for " + contentPackage); |
| continue; |
| } |
| getLog().info("Target Convert CP of --- " + contentPackage + " ---"); |
| for (final Artifact artifact : artifacts) { |
| final File source = artifact.getFile(); |
| if (source.exists() && source.isFile() && source.canRead()) { |
| converter.convert(source); |
| Artifact convertedPackage = new DefaultArtifact( |
| artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), |
| "compile", ZIP_TYPE, PACKAGE_CLASSIFIER, artifactHandlerManager.getArtifactHandler(ZIP_TYPE) |
| ); |
| // installConvertedCP(convertedPackage); |
| } else { |
| getLog().error("Artifact is not found: " + artifact); |
| } |
| } |
| } |
| } |
| installGeneratedArtifacts(); |
| } catch (Throwable t) { |
| throw new MojoExecutionException("Content Package Converter Exception", t); |
| } |
| |
| } |
| |
| /** |
| * For now this is a hack to update the local Maven Repo (.m2/repository) correctly |
| * bypassing the Maven Installer as this is giving us grief |
| */ |
| private void installGeneratedArtifacts() { |
| if(installConvertedCP) { |
| File userHome = new File(System.getProperty("user.home")); |
| if(userHome.isDirectory()) { |
| File destFolder = new File(userHome, ".m2/repository"); |
| if(destFolder.isDirectory()) { |
| copyFiles(convertedCPOutput, destFolder); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Copies the local generated Maven Artifacts into the local Maven Repo |
| * recursively one folder at the time. |
| * Folder are created on the local Maven Repo if not found, missing files |
| * are copied over but only CP2FM Converted CP files are replaced on the |
| * target folders |
| * |
| * @param source Folder with the source files / folders |
| * @param destination Destination folder (inside the local Maven repo). This is the corresponding folder to the source |
| */ |
| private void copyFiles(File source, File destination) { |
| for(File file: source.listFiles()) { |
| String name = file.getName(); |
| if(file.isDirectory()) { |
| File newDest = new File(destination, name); |
| if(!newDest.exists()) { |
| newDest.mkdirs(); |
| } |
| if(newDest.isDirectory()) { |
| copyFiles(file, newDest); |
| } else { |
| getLog().warn("Source File: '" + file.getAbsolutePath() + "' is a folder but its counterpart is a file: " + newDest.getAbsolutePath()); |
| } |
| } else { |
| File newDest = new File(destination, name); |
| if(!newDest.exists()) { |
| // Copy File over |
| try { |
| Files.copy(file.toPath(), newDest.toPath(), StandardCopyOption.COPY_ATTRIBUTES); |
| } catch (IOException e) { |
| getLog().warn("Failed to copy File: '" + file.getAbsolutePath() + "' to File: " + newDest.getAbsolutePath(), e); |
| } |
| } else { |
| // We only overwrite converted files |
| if(name.endsWith(PACKAGE_CLASSIFIER + "." + ZIP_TYPE)) { |
| // Copy File over |
| try { |
| Files.copy(file.toPath(), newDest.toPath(), StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); |
| } catch (IOException e) { |
| getLog().warn("Failed to copy generated File: '" + file.getAbsolutePath() + "' to File: " + newDest.getAbsolutePath(), e); |
| } |
| } else { |
| getLog().info("Ignore File: '" + file.getAbsolutePath()); |
| } |
| } |
| } |
| } |
| } |
| |
| private void installConvertedCP(Artifact artifact) throws MojoFailureException, MojoExecutionException { |
| if(installConvertedCP) { |
| Collection<Artifact> artifacts = Collections.synchronizedCollection(new ArrayList<>()); |
| // Rebuild the converted package path |
| String convertedPackagePath = artifact.getGroupId().replaceAll("\\.", "/") |
| + "/" + artifact.getArtifactId() |
| + "/" + artifact.getVersion() |
| + "/" + artifact.getArtifactId() |
| + "-" + artifact.getVersion() |
| + "-" + PACKAGE_CLASSIFIER |
| + "." + ZIP_TYPE; |
| File convertedPackageFile = new File(convertedCPOutput, convertedPackagePath); |
| if(convertedPackageFile.exists() && convertedPackageFile.canRead()) { |
| artifact.setFile(convertedPackageFile); |
| artifacts.add(artifact); |
| installArtifact(mavenSession.getProjectBuildingRequest(), artifacts); |
| } else { |
| getLog().error("xCould not find Converted Package: " + convertedPackageFile); |
| } |
| } |
| } |
| |
| private void installArtifact(ProjectBuildingRequest pbr, Collection<Artifact> artifacts ) |
| throws MojoFailureException, MojoExecutionException |
| { |
| try |
| { |
| installer.install(pbr, artifacts); |
| } |
| catch ( ArtifactInstallerException e ) |
| { |
| throw new MojoExecutionException( "ArtifactInstallerException", e ); |
| } |
| } |
| |
| } |