blob: 3a0d29b26136b8513252bc83b9cb0e8c4aafe1f8 [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.camel.karaf.maven;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.apache.camel.tooling.util.FileUtil;
import org.apache.camel.tooling.util.PackageHelper;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
/**
* Prepares the Karaf provider camel catalog to include component it supports
*/
@Mojo(name = "prepare-catalog-karaf", threadSafe = true)
public class PrepareCatalogKarafMojo extends AbstractMojo {
/**
* The maven project.
*/
@Parameter(property = "project", required = true, readonly = true)
protected MavenProject project;
/**
* The output directory for components catalog
*/
@Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/karaf/components")
protected File componentsOutDir;
/**
* The output directory for dataformats catalog
*/
@Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/karaf/dataformats")
protected File dataFormatsOutDir;
/**
* The output directory for languages catalog
*/
@Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/karaf/languages")
protected File languagesOutDir;
/**
* The output directory for others catalog
*/
@Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/karaf/others")
protected File othersOutDir;
/**
* The karaf features directory
*/
@Parameter(defaultValue = "${project.build.directory}/../../../platforms/karaf/features/src/main/resources/")
protected File featuresDir;
/**
* The components directory where all the Apache Camel components are from the camel-catalog
*/
@Parameter(defaultValue = "${project.build.directory}/sources/camel-catalog/org/apache/camel/catalog/components")
protected File componentsDir;
/**
* The components directory where there are karaf only components
*/
@Parameter(defaultValue = "${project.build.directory}/../../../components")
protected File karafComponentsDir;
/**
* The dataformats directory where all the Apache Camel components are from the camel-catalog
*/
@Parameter(defaultValue = "${project.build.directory}/sources/camel-catalog/org/apache/camel/catalog/dataformats")
protected File dataformatsDir;
/**
* The languages directory where all the Apache Camel components are from the camel-catalog
*/
@Parameter(defaultValue = "${project.build.directory}/sources/camel-catalog/org/apache/camel/catalog/languages")
protected File languagessDir;
/**
* The languages directory where all the Apache Camel components are from the camel-catalog
*/
@Parameter(defaultValue = "${project.build.directory}/sources/camel-catalog/org/apache/camel/catalog/others")
protected File otherssDir;
/**
* Maven ProjectHelper.
*/
@Component
private MavenProjectHelper projectHelper;
/**
* Execute goal.
*
* @throws MojoExecutionException execution of the main class or one of the
* threads it generated failed.
* @throws MojoFailureException something bad happened...
*/
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
Set<String> features = findKarafFeatures();
executeFeatures(features);
}
protected void executeFeatures(Set<String> features) throws MojoExecutionException, MojoFailureException {
// lets use sorted set/maps
Set<File> jsonFiles = new TreeSet<>();
if (componentsDir != null && componentsDir.isDirectory()) {
File[] files = componentsDir.listFiles();
if (files != null) {
for (File file : files) {
String name = stripExt(file);
if (features.contains("camel-" + name) || isCoreComponent(name)) {
jsonFiles.add(file);
}
}
}
}
// include paxlogging and eventadmin as regular components
jsonFiles.add(new File(karafComponentsDir, "camel-eventadmin/target/classes/org/apache/camel/component/eventadmin/eventadmin.json"));
jsonFiles.add(new File(karafComponentsDir, "camel-paxlogging/target/classes/org/apache/camel/component/paxlogging/paxlogging.json"));
if (!jsonFiles.isEmpty()) {
Path outDir = componentsOutDir.toPath();
copyFiles(outDir, jsonFiles);
generateJsonList(outDir, "../components.properties");
getLog().info("Copying " + jsonFiles.size() + " Camel component json descriptors");
}
jsonFiles.clear();
if (dataformatsDir != null && dataformatsDir.isDirectory()) {
File[] files = dataformatsDir.listFiles();
if (files != null) {
for (File file : files) {
// all dataformats are supported on karaf
jsonFiles.add(file);
}
}
}
if (!jsonFiles.isEmpty()) {
Path outDir = dataFormatsOutDir.toPath();
copyFiles(outDir, jsonFiles);
generateJsonList(outDir, "../dataformats.properties");
getLog().info("Copying " + jsonFiles.size() + " Camel dataformat json descriptors");
}
jsonFiles.clear();
if (languagessDir != null && languagessDir.isDirectory()) {
File[] files = languagessDir.listFiles();
if (files != null) {
for (File file : files) {
// all languages are supported on karaf
jsonFiles.add(file);
}
}
}
if (!jsonFiles.isEmpty()) {
Path outDir = languagesOutDir.toPath();
copyFiles(outDir, jsonFiles);
generateJsonList(outDir, "../languages.properties");
getLog().info("Copying " + jsonFiles.size() + " Camel language json descriptors");
}
jsonFiles.clear();
if (otherssDir != null && otherssDir.isDirectory()) {
File[] files = otherssDir.listFiles();
if (files != null) {
for (File file : files) {
if (features.contains("camel-" + stripExt(file))) {
jsonFiles.add(file);
}
}
}
}
// include others that are in camel-karaf only
jsonFiles.add(new File(karafComponentsDir, "camel-blueprint/target/classes/blueprint.json"));
jsonFiles.add(new File(karafComponentsDir, "camel-kura/target/classes/kura.json"));
jsonFiles.add(new File(karafComponentsDir, "camel-osgi-activator/target/classes/osgi-activator.json"));
if (!jsonFiles.isEmpty()) {
Path outDir = othersOutDir.toPath();
copyFiles(outDir, jsonFiles);
generateJsonList(outDir, "../others.properties");
getLog().info("Copying " + jsonFiles.size() + " Camel other json descriptors");
}
}
private static boolean isCoreComponent(String name) {
return ("bean,browse,controlbus,dataformat,dataset,direct,directvm,file,language,log,mock,ref"
+ ",rest,saga,scheduler,seda,stub,timer,validator,vm,xpath,xslt").contains(name);
}
private static String stripExt(File file) {
String name = file.getName();
return name.substring(0, name.indexOf("."));
}
public static void copyFiles(Path outDir, Collection<File> files) throws MojoFailureException {
for (File file : files) {
Path to = outDir.resolve(file.getName());
try {
FileUtil.updateFile(file.toPath(), to);
} catch (IOException e) {
throw new MojoFailureException("Cannot copy file from " + file + " -> " + to, e);
}
}
}
public static Set<String> generateJsonList(Path outDir, String outFile) throws MojoFailureException {
Path all = outDir.resolve(outFile);
try {
Set<String> answer = Files.list(outDir).filter(p -> p.getFileName().toString().endsWith(PackageHelper.JSON_SUFIX)).map(p -> p.getFileName().toString())
// strip out .json from the name
.map(n -> n.substring(0, n.length() - PackageHelper.JSON_SUFIX.length())).sorted().collect(LinkedHashSet::new, LinkedHashSet::add, LinkedHashSet::addAll);
String data = String.join("\n", answer) + "\n";
FileUtil.updateFile(all, data);
return answer;
} catch (IOException e) {
throw new MojoFailureException("Error writing to file " + all);
}
}
private Set<String> findKarafFeatures() throws MojoExecutionException, MojoFailureException {
// load features.xml file and parse it
Set<String> answer = new LinkedHashSet<>();
File file = new File(featuresDir, "features.xml");
try (InputStream is = new FileInputStream(file)) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setIgnoringComments(true);
dbf.setIgnoringElementContentWhitespace(true);
dbf.setNamespaceAware(false);
dbf.setValidating(false);
dbf.setXIncludeAware(false);
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
Document dom = dbf.newDocumentBuilder().parse(is);
NodeList children = dom.getElementsByTagName("features");
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
NodeList children2 = child.getChildNodes();
for (int j = 0; j < children2.getLength(); j++) {
Node child2 = children2.item(j);
if ("feature".equals(child2.getNodeName())) {
String artifactId = child2.getAttributes().getNamedItem("name").getTextContent();
if (artifactId != null && artifactId.startsWith("camel-")) {
answer.add(artifactId);
}
}
}
}
}
getLog().info("Found " + answer.size() + " Camel features in file: " + file);
} catch (Exception e) {
throw new MojoExecutionException("Error reading features.xml file", e);
}
return answer;
}
}