blob: d6f8e060507580337ee1ee8080c72bf15aeeb62e [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.maven.packaging;
import java.io.File;
import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.FileSystemAlreadyExistsException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Stream;
import javax.xml.bind.annotation.XmlEnum;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.Indexer;
/**
* Analyses the Camel plugins in a project and generates extra descriptor information for easier auto-discovery in Camel.
*/
@Mojo(name = "generate-jaxb-list", threadSafe = true, defaultPhase = LifecyclePhase.PROCESS_CLASSES)
public class PackageJaxbMojo extends AbstractGeneratorMojo {
/**
* The output directory for generated components file
*/
@Parameter(defaultValue = "${project.build.directory}/generated/camel/jaxb")
protected File jaxbIndexOutDir;
/**
* 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 {
List<String> locations = new ArrayList<>();
locations.add(project.getBuild().getOutputDirectory());
processClasses(createIndex(locations));
Path path = jaxbIndexOutDir.toPath();
addResourceDirectory(path);
}
private void processClasses(IndexView index) {
Map<String, Set<String>> byPackage = new HashMap<>();
Stream.of(XmlRootElement.class, XmlEnum.class, XmlType.class)
.map(Class::getName)
.map(DotName::createSimple)
.map(index::getAnnotations)
.flatMap(Collection::stream)
.map(AnnotationInstance::target)
.map(AnnotationTarget::asClass)
.map(ClassInfo::name)
.map(DotName::toString)
.forEach(name -> {
int idx = name.lastIndexOf('.');
String p = name.substring(0, idx);
String c = name.substring(idx + 1);
byPackage.computeIfAbsent(p, s -> new TreeSet<>()).add(c);
});
Path jaxbIndexDir = jaxbIndexOutDir.toPath();
int count = 0;
for (Map.Entry<String, Set<String>> entry : byPackage.entrySet()) {
String fn = entry.getKey().replace('.', '/') + "/jaxb.index";
if (project.getCompileSourceRoots().stream()
.map(Paths::get)
.map(p -> p.resolve(fn))
.anyMatch(Files::isRegularFile)) {
continue;
}
Path file = jaxbIndexDir.resolve(fn);
StringBuilder sb = new StringBuilder();
sb.append("# " + GENERATED_MSG + NL);
for (String s : entry.getValue()) {
sb.append(s);
sb.append(NL);
}
updateResource(file, sb.toString());
}
getLog().info("Generated " + jaxbIndexOutDir + " containing " + count + " jaxb.index elements");
}
private IndexView createIndex(List<String> locations) throws MojoExecutionException {
try {
Indexer indexer = new Indexer();
locations.stream()
.map(this::asFolder)
.filter(Files::isDirectory)
.flatMap(this::walk)
.filter(Files::isRegularFile)
.filter(p -> p.getFileName().toString().endsWith(".class"))
.forEach(p -> index(indexer, p));
return indexer.complete();
} catch (IOError e) {
throw new MojoExecutionException("Error", e);
}
}
private Path asFolder(String p) {
if (p.endsWith(".jar")) {
File fp = new File(p);
try {
Map<String, String> env = new HashMap<>();
return FileSystems.newFileSystem(URI.create("jar:" + fp.toURI().toString()), env).getPath("/");
} catch (FileSystemAlreadyExistsException e) {
return FileSystems.getFileSystem(URI.create("jar:" + fp.toURI().toString())).getPath("/");
} catch (IOException e) {
throw new IOError(e);
}
} else {
return Paths.get(p);
}
}
private Stream<Path> walk(Path p) {
try {
return Files.walk(p);
} catch (IOException e) {
throw new IOError(e);
}
}
private void index(Indexer indexer, Path p) {
try (InputStream is = Files.newInputStream(p)) {
indexer.index(is);
} catch (IOException e) {
throw new IOError(e);
}
}
}