io.fabric8.forge.camel.commands.project.AbstractCamelProjectCommand Maven / Gradle / Ivy
/**
* Copyright 2005-2015 Red Hat, Inc.
*
* Red Hat 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 io.fabric8.forge.camel.commands.project;
import java.io.File;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.function.Function;
import javax.inject.Inject;
import io.fabric8.forge.addon.utils.CamelProjectHelper;
import io.fabric8.forge.camel.commands.project.completer.CurrentLineCompleter;
import io.fabric8.forge.camel.commands.project.completer.RouteBuilderCompleter;
import io.fabric8.forge.camel.commands.project.completer.RouteBuilderEndpointsCompleter;
import io.fabric8.forge.camel.commands.project.completer.SpringBootConfigurationFileCompleter;
import io.fabric8.forge.camel.commands.project.completer.XmlEndpointsCompleter;
import io.fabric8.forge.camel.commands.project.completer.XmlFileCompleter;
import io.fabric8.forge.camel.commands.project.dto.ComponentDto;
import io.fabric8.forge.camel.commands.project.dto.ContextDto;
import io.fabric8.forge.camel.commands.project.dto.NodeDto;
import io.fabric8.forge.camel.commands.project.dto.NodeDtos;
import io.fabric8.forge.camel.commands.project.helper.CamelCommandsHelper;
import io.fabric8.forge.camel.commands.project.helper.CamelXmlHelper;
import io.fabric8.forge.camel.commands.project.helper.PoorMansLogger;
import io.fabric8.utils.Strings;
import org.apache.camel.catalog.CamelCatalog;
import org.jboss.forge.addon.convert.Converter;
import org.jboss.forge.addon.convert.ConverterFactory;
import org.jboss.forge.addon.dependencies.Coordinate;
import org.jboss.forge.addon.dependencies.Dependency;
import org.jboss.forge.addon.dependencies.builder.CoordinateBuilder;
import org.jboss.forge.addon.maven.projects.facets.MavenDependencyFacet;
import org.jboss.forge.addon.parser.java.facets.JavaSourceFacet;
import org.jboss.forge.addon.projects.Project;
import org.jboss.forge.addon.projects.ProjectFactory;
import org.jboss.forge.addon.projects.Projects;
import org.jboss.forge.addon.projects.facets.ResourcesFacet;
import org.jboss.forge.addon.projects.facets.WebResourcesFacet;
import org.jboss.forge.addon.projects.ui.AbstractProjectCommand;
import org.jboss.forge.addon.resource.FileResource;
import org.jboss.forge.addon.ui.context.UIContext;
import org.jboss.forge.addon.ui.context.UIExecutionContext;
import org.jboss.forge.addon.ui.context.UIRegion;
import org.jboss.forge.addon.ui.input.UISelectOne;
import org.jboss.forge.addon.ui.input.ValueChangeListener;
import org.jboss.forge.addon.ui.input.events.ValueChangeEvent;
import org.jboss.forge.addon.ui.metadata.UICommandMetadata;
import org.jboss.forge.addon.ui.util.Categories;
import org.jboss.forge.addon.ui.util.Metadata;
import org.w3c.dom.Element;
import static io.fabric8.forge.addon.utils.VersionHelper.loadText;
import static io.fabric8.forge.camel.commands.project.helper.CollectionHelper.first;
public abstract class AbstractCamelProjectCommand extends AbstractProjectCommand {
private static final PoorMansLogger LOG = new PoorMansLogger(false);
public static String CATEGORY = "Camel";
public static int MAX_OPTIONS = 20;
@Inject
protected ProjectFactory projectFactory;
@Inject
protected ConverterFactory converterFactory;
@Inject
protected CamelCatalog camelCatalog;
@Override
protected boolean isProjectRequired() {
return true;
}
@Override
public UICommandMetadata getMetadata(UIContext context) {
return Metadata.forCommand(CamelDeleteNodeXmlCommand.class).name(
"Camel: Delete Node XML").category(Categories.create(CATEGORY))
.description("Deletes a node from a Camel XML file");
}
@Override
public boolean isEnabled(UIContext context) {
boolean enabled = super.isEnabled(context);
if (!enabled) {
return false;
}
if (requiresCamelSetup()) {
// requires camel is already setup
Project project = getSelectedProjectOrNull(context);
if (project != null) {
return findCamelCoreDependency(project) != null;
}
}
return false;
}
protected Project getSelectedProjectOrNull(UIContext context) {
return Projects.getSelectedProject(this.getProjectFactory(), context);
}
protected boolean isRunningInGui(UIContext context) {
return context.getProvider().isGUI();
}
protected boolean requiresCamelSetup() {
return true;
}
protected List configureXmlNodes(final UIContext context, final Project project, final String selected,
final UISelectOne xml, final UISelectOne node) throws Exception {
// because the UISelectOne must be unique we need to use a running number
int index = 1;
List nodes;
String xmlResourceName = xml.getValue();
if (Strings.isNullOrBlank(xmlResourceName)) {
xmlResourceName = selected;
}
if (Strings.isNotBlank(xmlResourceName)) {
List camelContexts = CamelXmlHelper.loadCamelContext(camelCatalog, context, project, xmlResourceName);
nodes = NodeDtos.toNodeList(camelContexts);
// if there is one CamelContext then pre-select the first node (which is the route)
if (camelContexts.size() == 1 && nodes.size() > 1) {
node.setDefaultValue("1 " + nodes.get(1).getLabel());
}
} else {
nodes = Collections.EMPTY_LIST;
}
final List answer = nodes;
List choices = new ArrayList<>();
for (NodeDto dto : nodes) {
choices.add(index + " " + dto.getLabel());
index++;
}
node.setValueChoices(choices);
// to convert from key to label (with number)
// this converter is needed for the web console as it uses the key to select which node to edit
// and we need to be able to convert from the key to the correct node in the list
node.setValueConverter(s -> {
for (int i = 0; i < answer.size(); i++) {
NodeDto dto = answer.get(i);
if (dto.getKey().equals(s)) {
int number = i + 1;
return number + " " + dto.getLabel();
}
}
return s;
});
return answer;
}
@Override
protected ProjectFactory getProjectFactory() {
return projectFactory;
}
protected ConverterFactory getConverterFactory() {
return converterFactory;
}
protected CamelCatalog getCamelCatalog() {
return camelCatalog;
}
protected PrintStream getOutput(UIExecutionContext context) {
return context.getUIContext().getProvider().getOutput().out();
}
protected boolean isCamelProject(Project project) {
// is there any camel dependency?
return !findCamelArtifacts(project).isEmpty();
}
protected boolean isSpringBootProject(Project project) {
return CamelProjectHelper.hasDependency(project, "org.springframework.boot");
}
protected Dependency findCamelCoreDependency(Project project) {
return CamelProjectHelper.findCamelCoreDependency(project);
}
protected Set findCamelArtifacts(Project project) {
return CamelProjectHelper.findCamelArtifacts(project);
}
protected Coordinate createCoordinate(String groupId, String artifactId, String version) {
CoordinateBuilder builder = CoordinateBuilder.create()
.setGroupId(groupId)
.setArtifactId(artifactId);
if (version != null) {
builder = builder.setVersion(version);
}
return builder;
}
protected Coordinate createCamelCoordinate(String artifactId, String version) {
return createCoordinate("org.apache.camel", artifactId, version);
}
protected RouteBuilderCompleter createRouteBuilderCompleter(Project project) {
JavaSourceFacet facet = project.getFacet(JavaSourceFacet.class);
return new RouteBuilderCompleter(facet);
}
protected RouteBuilderEndpointsCompleter createRouteBuilderEndpointsCompleter(UIContext context, Function filter) {
Project project = getSelectedProject(context);
return createRouteBuilderEndpointsCompleter(project, filter);
}
protected RouteBuilderEndpointsCompleter createRouteBuilderEndpointsCompleter(Project project, Function filter) {
JavaSourceFacet facet = project.getFacet(JavaSourceFacet.class);
return new RouteBuilderEndpointsCompleter(facet, filter);
}
protected XmlEndpointsCompleter createXmlEndpointsCompleter(UIContext context, Function filter) {
Project project = getSelectedProject(context);
return createXmlEndpointsCompleter(project, filter);
}
protected XmlEndpointsCompleter createXmlEndpointsCompleter(Project project, Function filter) {
ResourcesFacet resourcesFacet = null;
WebResourcesFacet webResourcesFacet = null;
if (project.hasFacet(ResourcesFacet.class)) {
resourcesFacet = project.getFacet(ResourcesFacet.class);
}
if (project.hasFacet(WebResourcesFacet.class)) {
webResourcesFacet = project.getFacet(WebResourcesFacet.class);
}
return new XmlEndpointsCompleter(resourcesFacet, webResourcesFacet, filter);
}
protected XmlFileCompleter createXmlFileCompleter(Project project, Function filter) {
ResourcesFacet resourcesFacet = null;
WebResourcesFacet webResourcesFacet = null;
if (project.hasFacet(ResourcesFacet.class)) {
resourcesFacet = project.getFacet(ResourcesFacet.class);
}
if (project.hasFacet(WebResourcesFacet.class)) {
webResourcesFacet = project.getFacet(WebResourcesFacet.class);
}
return new XmlFileCompleter(resourcesFacet, webResourcesFacet, filter);
}
protected XmlFileCompleter createXmlFileCompleter(UIContext context, Function filter) {
Project project = getSelectedProject(context);
return createXmlFileCompleter(project, filter);
}
protected SpringBootConfigurationFileCompleter createSpringBootConfigurationFileCompleter(UIContext context, Function filter) {
Project project = getSelectedProject(context);
ResourcesFacet resourcesFacet = null;
if (project.hasFacet(ResourcesFacet.class)) {
resourcesFacet = project.getFacet(ResourcesFacet.class);
}
return new SpringBootConfigurationFileCompleter(resourcesFacet, filter);
}
protected CurrentLineCompleter createCurrentLineCompleter(int lineNumber, String file, UIContext context) throws Exception {
Project project = getSelectedProject(context);
JavaSourceFacet sourceFacet = null;
ResourcesFacet resourcesFacet = null;
WebResourcesFacet webResourcesFacet = null;
if (project.hasFacet(JavaSourceFacet.class)) {
sourceFacet = project.getFacet(JavaSourceFacet.class);
}
if (project.hasFacet(ResourcesFacet.class)) {
resourcesFacet = project.getFacet(ResourcesFacet.class);
}
if (project.hasFacet(WebResourcesFacet.class)) {
webResourcesFacet = project.getFacet(WebResourcesFacet.class);
}
String relativeFile = asRelativeFile(context, file);
return new CurrentLineCompleter(lineNumber, relativeFile, sourceFacet, resourcesFacet, webResourcesFacet);
}
protected FileResource getXmlResourceFile(Project project, String xmlResourceName) {
if (xmlResourceName == null) {
return null;
}
ResourcesFacet facet = null;
WebResourcesFacet webResourcesFacet = null;
if (project.hasFacet(ResourcesFacet.class)) {
facet = project.getFacet(ResourcesFacet.class);
}
if (project.hasFacet(WebResourcesFacet.class)) {
webResourcesFacet = project.getFacet(WebResourcesFacet.class);
}
FileResource file = facet != null ? facet.getResource(xmlResourceName) : null;
if (file == null || !file.exists()) {
file = webResourcesFacet != null ? webResourcesFacet.getWebResource(xmlResourceName) : null;
}
return file;
}
protected String configureXml(Project project, UISelectOne xml, String currentFile) {
XmlFileCompleter xmlFileCompleter = createXmlFileCompleter(project, null);
Set files = xmlFileCompleter.getFiles();
// use value choices instead of completer as that works better in web console
final String first = first(files);
String answer = first;
xml.setValueChoices(files);
if (files.size() == 1) {
// lets default the value if there's only one choice
xml.setDefaultValue(first);
} else if (currentFile != null) {
// lets default to the current file
for (String name : files) {
if (currentFile.endsWith(name)) {
xml.setDefaultValue(name);
answer = name;
break;
}
}
}
return answer;
}
protected String configureRouteBuilder(Project project, UISelectOne routeBuilders, String currentFile) {
RouteBuilderCompleter completer = createRouteBuilderCompleter(project);
Set builders = completer.getRouteBuilders();
// use value choices instead of completer as that works better in web console
final String first = first(builders);
String answer = first;
routeBuilders.setValueChoices(builders);
if (builders.size() == 1) {
// lets default the value if there's only one choice
routeBuilders.setDefaultValue(first);
} else if (currentFile != null) {
// lets default to the current file
if (currentFile.endsWith(".java")) {
currentFile = currentFile.substring(0, currentFile.length() - 5);
}
for (String name : builders) {
if (currentFile.endsWith(name)) {
routeBuilders.setDefaultValue(name);
answer = name;
break;
}
}
}
return answer;
}
protected void configureComponentName(Project project, final UISelectOne componentName, boolean consumerOnly, boolean producerOnly) throws Exception {
// filter the list of components based on consumer and producer only
Iterable it = CamelCommandsHelper.createComponentDtoValues(project, getCamelCatalog(), null, false, consumerOnly, producerOnly, false).call();
final Map components = new LinkedHashMap<>();
for (ComponentDto dto : it) {
components.put(dto.getScheme(), dto);
}
componentName.setValueChoices(components.values());
// include converter from string->dto
componentName.setValueConverter(new Converter() {
@Override
public ComponentDto convert(String text) {
return components.get(text);
}
});
// show note about the chosen component
componentName.addValueChangeListener(new ValueChangeListener() {
@Override
public void valueChanged(ValueChangeEvent event) {
ComponentDto component = (ComponentDto) event.getNewValue();
if (component != null) {
String description = component.getDescription();
componentName.setNote(description != null ? description : "");
} else {
componentName.setNote("");
}
}
});
}
protected Element getSelectedCamelElementNode(Project project, String xmlResourceName, String key) throws Exception {
FileResource file = getXmlResourceFile(project, xmlResourceName);
if (file != null) {
InputStream resourceInputStream = file.getResourceInputStream();
return CamelXmlHelper.getSelectedCamelElementNode(key, resourceInputStream);
} else {
return null;
}
}
protected String getSelectedFile(UIContext context) {
String currentFile = null;
// get selected file
Optional> region = context.getSelection().getRegion();
if (region.isPresent()) {
Object resource = region.get().getResource();
currentFile = resource.toString();
}
return currentFile;
}
protected boolean isSelectedFileJava(UIContext context) {
Optional> region = context.getSelection().getRegion();
if (region.isPresent()) {
Object resource = region.get().getResource();
if (resource instanceof FileResource) {
return ((FileResource) resource).getFullyQualifiedName().endsWith(".java");
}
}
return false;
}
protected boolean isSelectedFileXml(UIContext context) {
Optional> region = context.getSelection().getRegion();
if (region.isPresent()) {
Object resource = region.get().getResource();
if (resource instanceof FileResource) {
return ((FileResource) resource).getFullyQualifiedName().endsWith(".xml");
}
}
return false;
}
protected int getCurrentCursorLine(UIContext context) {
int answer = -1;
Optional> region = context.getSelection().getRegion();
if (region.isPresent()) {
answer = region.get().getStartLine();
}
return answer;
}
protected int getCurrentCursorPosition(UIContext context) {
int answer = -1;
Optional> region = context.getSelection().getRegion();
if (region.isPresent()) {
answer = region.get().getStartPosition();
}
return answer;
}
protected String asRelativeFile(UIContext context, String currentFile) {
Project project = getSelectedProject(context);
JavaSourceFacet javaSourceFacet = null;
ResourcesFacet resourcesFacet = null;
WebResourcesFacet webResourcesFacet = null;
if (project.hasFacet(JavaSourceFacet.class)) {
javaSourceFacet = project.getFacet(JavaSourceFacet.class);
}
if (project.hasFacet(ResourcesFacet.class)) {
resourcesFacet = project.getFacet(ResourcesFacet.class);
}
if (project.hasFacet(WebResourcesFacet.class)) {
webResourcesFacet = project.getFacet(WebResourcesFacet.class);
}
return asRelativeFile(currentFile, javaSourceFacet, resourcesFacet, webResourcesFacet);
}
public static String asRelativeFile(String currentFile, JavaSourceFacet javaSourceFacet, ResourcesFacet resourcesFacet, WebResourcesFacet webResourcesFacet) {
boolean javaFile = currentFile != null && currentFile.endsWith(".java");
// if its not a java file, then we need to have the relative path name
String target = null;
if (javaFile && javaSourceFacet != null) {
// we only want the relative dir name from the source directory, eg src/main/java
String baseDir = javaSourceFacet.getSourceDirectory().getFullyQualifiedName();
String fqn = currentFile;
if (fqn != null && fqn.startsWith(baseDir) && fqn.length() > baseDir.length()) {
target = fqn.substring(baseDir.length() + 1);
}
// could be in test directory
if (target == null) {
// we only want the relative dir name from the source directory, eg src/test/java
baseDir = javaSourceFacet.getTestSourceDirectory().getFullyQualifiedName();
fqn = currentFile;
if (fqn != null && fqn.startsWith(baseDir) && fqn.length() > baseDir.length()) {
target = fqn.substring(baseDir.length() + 1);
}
}
} else if (resourcesFacet != null || webResourcesFacet != null) {
if (resourcesFacet != null) {
// we only want the relative dir name from the resource directory, eg src/main/resources
String baseDir = resourcesFacet.getResourceDirectory().getFullyQualifiedName();
String fqn = currentFile;
if (fqn != null && fqn.startsWith(baseDir) && fqn.length() > baseDir.length()) {
target = fqn.substring(baseDir.length() + 1);
}
}
if (target == null && webResourcesFacet != null) {
// we only want the relative dir name from the web resource directory, eg WEB-INF/foo.xml
String baseDir = webResourcesFacet.getWebRootDirectory().getFullyQualifiedName();
String fqn = currentFile;
if (fqn != null && fqn.startsWith(baseDir) && fqn.length() > baseDir.length()) {
target = fqn.substring(baseDir.length() + 1);
}
}
}
return target != null ? target : currentFile;
}
protected Set discoverCustomCamelComponentsOnClasspathAndAddToCatalog(CamelCatalog camelCatalog, Project project) {
Set answer = new LinkedHashSet<>();
// find the dependency again because forge don't associate artifact on the returned dependency when installed
MavenDependencyFacet facet = project.getFacet(MavenDependencyFacet.class);
List list = facet.getEffectiveDependencies();
for (Dependency dep : list) {
Properties properties = loadComponentProperties(dep);
if (properties != null) {
String components = (String) properties.get("components");
if (components != null) {
String[] part = components.split("\\s");
for (String scheme : part) {
if (!camelCatalog.findComponentNames().contains(scheme)) {
// find the class name
String javaType = extractComponentJavaType(dep, scheme);
if (javaType != null) {
String json = loadComponentJSonSchema(dep, scheme);
if (json != null) {
camelCatalog.addComponent(scheme, javaType, json);
answer.add(scheme);
}
}
}
}
}
}
}
return answer;
}
public static Properties loadComponentProperties(Dependency dependency) {
Properties answer = new Properties();
try {
// is it a JAR file
File file = dependency.getArtifact().getUnderlyingResourceObject();
if (file != null && file.getName().toLowerCase().endsWith(".jar")) {
URL url = new URL("file:" + file.getAbsolutePath());
URLClassLoader child = new URLClassLoader(new URL[]{url});
InputStream is = child.getResourceAsStream("META-INF/services/org/apache/camel/component.properties");
if (is != null) {
answer.load(is);
}
}
} catch (Throwable e) {
// ignore
}
return answer;
}
public static String loadComponentJSonSchema(Dependency dependency, String scheme) {
String answer = null;
String path = null;
String javaType = extractComponentJavaType(dependency, scheme);
if (javaType != null) {
int pos = javaType.lastIndexOf(".");
path = javaType.substring(0, pos);
path = path.replace('.', '/');
path = path + "/" + scheme + ".json";
}
if (path != null) {
try {
// is it a JAR file
File file = dependency.getArtifact().getUnderlyingResourceObject();
if (file != null && file.getName().toLowerCase().endsWith(".jar")) {
URL url = new URL("file:" + file.getAbsolutePath());
URLClassLoader child = new URLClassLoader(new URL[]{url});
InputStream is = child.getResourceAsStream(path);
if (is != null) {
answer = loadText(is);
}
}
} catch (Throwable e) {
// ignore
}
}
return answer;
}
public static String extractComponentJavaType(Dependency dependency, String scheme) {
try {
// is it a JAR file
File file = dependency.getArtifact().getUnderlyingResourceObject();
if (file != null && file.getName().toLowerCase().endsWith(".jar")) {
URL url = new URL("file:" + file.getAbsolutePath());
URLClassLoader child = new URLClassLoader(new URL[]{url});
InputStream is = child.getResourceAsStream("META-INF/services/org/apache/camel/component/" + scheme);
if (is != null) {
Properties props = new Properties();
props.load(is);
return (String) props.get("class");
}
}
} catch (Throwable e) {
// ignore
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy