You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2016/12/05 12:47:24 UTC
camel git commit: CAMEL-10559: maven plugin to validate using the
route parser. Donated from fabric8 project.
Repository: camel
Updated Branches:
refs/heads/parser 550186e97 -> a20439f24
CAMEL-10559: maven plugin to validate using the route parser. Donated from fabric8 project.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/a20439f2
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/a20439f2
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/a20439f2
Branch: refs/heads/parser
Commit: a20439f24de52a5e2ab4ee730b8196f61d3ef5f3
Parents: 550186e
Author: Claus Ibsen <da...@apache.org>
Authored: Mon Dec 5 13:45:55 2016 +0100
Committer: Claus Ibsen <da...@apache.org>
Committed: Mon Dec 5 13:45:55 2016 +0100
----------------------------------------------------------------------
tooling/maven/camel-maven-plugin/pom.xml | 34 +-
.../org/apache/camel/maven/ValidateMojo.java | 639 +++++++++++++++++++
.../camel/maven/helper/EndpointHelper.java | 105 +++
3 files changed, 777 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/a20439f2/tooling/maven/camel-maven-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-maven-plugin/pom.xml b/tooling/maven/camel-maven-plugin/pom.xml
index ec98c6b..fffc520 100644
--- a/tooling/maven/camel-maven-plugin/pom.xml
+++ b/tooling/maven/camel-maven-plugin/pom.xml
@@ -71,7 +71,39 @@
<groupId>org.apache.camel</groupId>
<artifactId>camel-cdi</artifactId>
</dependency>
-
+
+ <!-- camel-catalog -->
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-catalog</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-catalog-lucene</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-catalog-maven</artifactId>
+ </dependency>
+
+ <!-- camel route parser -->
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-route-parser</artifactId>
+ </dependency>
+
+ <!-- roaster java parser -->
+ <dependency>
+ <groupId>org.jboss.forge.roaster</groupId>
+ <artifactId>roaster-api</artifactId>
+ <version>${roaster-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.forge.roaster</groupId>
+ <artifactId>roaster-jdt</artifactId>
+ <version>${roaster-version}</version>
+ </dependency>
+
<!-- logging -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
http://git-wip-us.apache.org/repos/asf/camel/blob/a20439f2/tooling/maven/camel-maven-plugin/src/main/java/org/apache/camel/maven/ValidateMojo.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-maven-plugin/src/main/java/org/apache/camel/maven/ValidateMojo.java b/tooling/maven/camel-maven-plugin/src/main/java/org/apache/camel/maven/ValidateMojo.java
new file mode 100644
index 0000000..c5ed912
--- /dev/null
+++ b/tooling/maven/camel-maven-plugin/src/main/java/org/apache/camel/maven/ValidateMojo.java
@@ -0,0 +1,639 @@
+/**
+ * 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;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.camel.catalog.CamelCatalog;
+import org.apache.camel.catalog.DefaultCamelCatalog;
+import org.apache.camel.catalog.EndpointValidationResult;
+import org.apache.camel.catalog.SimpleValidationResult;
+import org.apache.camel.catalog.lucene.LuceneSuggestionStrategy;
+import org.apache.camel.catalog.maven.MavenVersionManager;
+import org.apache.camel.maven.helper.EndpointHelper;
+import org.apache.camel.parser.RouteBuilderParser;
+import org.apache.camel.parser.XmlRouteParser;
+import org.apache.camel.parser.model.CamelEndpointDetails;
+import org.apache.camel.parser.model.CamelSimpleExpressionDetails;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.Resource;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.mojo.exec.AbstractExecMojo;
+import org.jboss.forge.roaster.Roaster;
+import org.jboss.forge.roaster.model.JavaType;
+import org.jboss.forge.roaster.model.source.JavaClassSource;
+
+/**
+ * Parses the source code and validates the Camel routes has valid endpoint uris and simple expressions.
+ *
+ * @goal validate
+ * @requiresDependencyResolution compile+runtime
+ * @execute phase="process-test-classes"
+ */
+public class ValidateMojo extends AbstractExecMojo {
+
+ /**
+ * The maven project.
+ *
+ * @parameter property="project"
+ * @required
+ * @readonly
+ */
+ protected MavenProject project;
+
+ /**
+ * Whether to fail if invalid Camel endpoints was found. By default the plugin logs the errors at WARN level
+ *
+ * @parameter property="camel.failOnError"
+ * default-value="false"
+ */
+ private boolean failOnError;
+
+ /**
+ * Whether to log endpoint URIs which was un-parsable and therefore not possible to validate
+ *
+ * @parameter property="camel.logUnparseable"
+ * default-value="false"
+ */
+ private boolean logUnparseable;
+
+ /**
+ * Whether to include Java files to be validated for invalid Camel endpoints
+ *
+ * @parameter property="camel.includeJava"
+ * default-value="true"
+ */
+ private boolean includeJava;
+
+ /**
+ * Whether to include XML files to be validated for invalid Camel endpoints
+ *
+ * @parameter property="camel.includeXml"
+ * default-value="true"
+ */
+ private boolean includeXml;
+
+ /**
+ * Whether to include test source code
+ *
+ * @parameter property="camel.includeTest"
+ * default-value="false"
+ */
+ private boolean includeTest;
+
+ /**
+ * To filter the names of java and xml files to only include files matching any of the given list of patterns (wildcard and regular expression).
+ * Multiple values can be separated by comma.
+ *
+ * @parameter property="camel.includes"
+ */
+ private String includes;
+
+ /**
+ * To filter the names of java and xml files to exclude files matching any of the given list of patterns (wildcard and regular expression).
+ * Multiple values can be separated by comma.
+ *
+ * @parameter property="camel.excludes"
+ */
+ private String excludes;
+
+ /**
+ * Whether to ignore unknown components
+ *
+ * @parameter property="camel.ignoreUnknownComponent"
+ * default-value="true"
+ */
+ private boolean ignoreUnknownComponent;
+
+ /**
+ * Whether to ignore incapable of parsing the endpoint uri
+ *
+ * @parameter property="camel.ignoreIncapable"
+ * default-value="true"
+ */
+ private boolean ignoreIncapable;
+
+ /**
+ * Whether to ignore components that uses lenient properties. When this is true, then the uri validation is stricter
+ * but would fail on properties that are not part of the component but in the uri because of using lenient properties.
+ * For example using the HTTP components to provide query parameters in the endpoint uri.
+ *
+ * @parameter property="camel.ignoreLenientProperties"
+ * default-value="true"
+ */
+ private boolean ignoreLenientProperties;
+
+ /**
+ * Whether to show all endpoints and simple expressions (both invalid and valid).
+ *
+ * @parameter property="camel.showAll"
+ * default-value="false"
+ */
+ private boolean showAll;
+
+ /**
+ * Whether to allow downloading Camel catalog version from the internet. This is needed if the project
+ * uses a different Camel version than this plugin is using by default.
+ *
+ * @parameter property="camel.downloadVersion"
+ * default-value="true"
+ */
+ private boolean downloadVersion;
+
+ @Override
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ CamelCatalog catalog = new DefaultCamelCatalog();
+ // add activemq as known component
+ catalog.addComponent("activemq", "org.apache.activemq.camel.component.ActiveMQComponent");
+ // enable did you mean
+ catalog.setSuggestionStrategy(new LuceneSuggestionStrategy());
+ // enable loading other catalog versions dynamically
+ catalog.setVersionManager(new MavenVersionManager());
+ // enable caching
+ catalog.enableCache();
+
+ if (downloadVersion) {
+ String catalogVersion = catalog.getCatalogVersion();
+ String version = findCamelVersion(project);
+ if (version != null && !version.equals(catalogVersion)) {
+ // the project uses a different Camel version so attempt to load it
+ getLog().info("Downloading Camel version: " + version);
+ boolean loaded = catalog.loadVersion(version);
+ if (!loaded) {
+ getLog().warn("Error downloading Camel version: " + version);
+ }
+ }
+ }
+
+ // if using the same version as the fabric8-camel-maven-plugin we must still load it
+ if (catalog.getLoadedVersion() == null) {
+ catalog.loadVersion(catalog.getCatalogVersion());
+ }
+
+ if (catalog.getLoadedVersion() != null) {
+ getLog().info("Using Camel version: " + catalog.getLoadedVersion());
+ } else {
+ // force load version from the fabric8-camel-maven-plugin
+ getLog().info("Using Camel version: " + catalog.getCatalogVersion());
+ }
+
+ List<CamelEndpointDetails> endpoints = new ArrayList<>();
+ List<CamelSimpleExpressionDetails> simpleExpressions = new ArrayList<>();
+ Set<File> javaFiles = new LinkedHashSet<File>();
+ Set<File> xmlFiles = new LinkedHashSet<File>();
+
+ // find all java route builder classes
+ if (includeJava) {
+ List list = project.getCompileSourceRoots();
+ for (Object obj : list) {
+ String dir = (String) obj;
+ findJavaFiles(new File(dir), javaFiles);
+ }
+ if (includeTest) {
+ list = project.getTestCompileSourceRoots();
+ for (Object obj : list) {
+ String dir = (String) obj;
+ findJavaFiles(new File(dir), javaFiles);
+ }
+ }
+ }
+ // find all xml routes
+ if (includeXml) {
+ List list = project.getResources();
+ for (Object obj : list) {
+ Resource dir = (Resource) obj;
+ findXmlFiles(new File(dir.getDirectory()), xmlFiles);
+ }
+ if (includeTest) {
+ list = project.getTestResources();
+ for (Object obj : list) {
+ Resource dir = (Resource) obj;
+ findXmlFiles(new File(dir.getDirectory()), xmlFiles);
+ }
+ }
+ }
+
+ for (File file : javaFiles) {
+ if (matchFile(file)) {
+ try {
+ List<CamelEndpointDetails> fileEndpoints = new ArrayList<>();
+ List<CamelSimpleExpressionDetails> fileSimpleExpressions = new ArrayList<>();
+ List<String> unparsable = new ArrayList<>();
+
+ // parse the java source code and find Camel RouteBuilder classes
+ String fqn = file.getPath();
+ String baseDir = ".";
+ JavaType out = Roaster.parse(file);
+ // we should only parse java classes (not interfaces and enums etc)
+ if (out != null && out instanceof JavaClassSource) {
+ JavaClassSource clazz = (JavaClassSource) out;
+ RouteBuilderParser.parseRouteBuilderEndpoints(clazz, baseDir, fqn, fileEndpoints, unparsable, includeTest);
+ RouteBuilderParser.parseRouteBuilderSimpleExpressions(clazz, baseDir, fqn, fileSimpleExpressions);
+
+ // add what we found in this file to the total list
+ endpoints.addAll(fileEndpoints);
+ simpleExpressions.addAll(fileSimpleExpressions);
+
+ // was there any unparsable?
+ if (logUnparseable && !unparsable.isEmpty()) {
+ for (String uri : unparsable) {
+ getLog().warn("Cannot parse endpoint uri " + uri + " in java file " + file);
+ }
+ }
+ }
+ } catch (Exception e) {
+ getLog().warn("Error parsing java file " + file + " code due " + e.getMessage(), e);
+ }
+ }
+ }
+ for (File file : xmlFiles) {
+ if (matchFile(file)) {
+ try {
+ List<CamelEndpointDetails> fileEndpoints = new ArrayList<>();
+ List<CamelSimpleExpressionDetails> fileSimpleExpressions = new ArrayList<>();
+
+ // parse the xml source code and find Camel routes
+ String fqn = file.getPath();
+ String baseDir = ".";
+
+ InputStream is = new FileInputStream(file);
+ XmlRouteParser.parseXmlRouteEndpoints(is, baseDir, fqn, fileEndpoints);
+ is.close();
+ // need a new stream
+ is = new FileInputStream(file);
+ XmlRouteParser.parseXmlRouteSimpleExpressions(is, baseDir, fqn, fileSimpleExpressions);
+ is.close();
+
+ // add what we found in this file to the total list
+ endpoints.addAll(fileEndpoints);
+ simpleExpressions.addAll(fileSimpleExpressions);
+ } catch (Exception e) {
+ getLog().warn("Error parsing xml file " + file + " code due " + e.getMessage(), e);
+ }
+ }
+ }
+
+ int endpointErrors = 0;
+ int unknownComponents = 0;
+ int incapableErrors = 0;
+ for (CamelEndpointDetails detail : endpoints) {
+ EndpointValidationResult result = catalog.validateEndpointProperties(detail.getEndpointUri(), ignoreLenientProperties);
+
+ boolean ok = result.isSuccess();
+ if (!ok && ignoreUnknownComponent && result.getUnknownComponent() != null) {
+ // if we failed due unknown component then be okay if we should ignore that
+ unknownComponents++;
+ ok = true;
+ }
+ if (!ok && ignoreIncapable && result.getIncapable() != null) {
+ // if we failed due incapable then be okay if we should ignore that
+ incapableErrors++;
+ ok = true;
+ }
+ if (!ok) {
+ if (result.getUnknownComponent() != null) {
+ unknownComponents++;
+ } else if (result.getIncapable() != null) {
+ incapableErrors++;
+ } else {
+ endpointErrors++;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("Endpoint validation error at: ");
+ if (detail.getClassName() != null && detail.getLineNumber() != null) {
+ // this is from java code
+ sb.append(detail.getClassName());
+ if (detail.getMethodName() != null) {
+ sb.append(".").append(detail.getMethodName());
+ }
+ sb.append("(").append(asSimpleClassName(detail.getClassName())).append(".java:");
+ sb.append(detail.getLineNumber()).append(")");
+ } else if (detail.getLineNumber() != null) {
+ // this is from xml
+ String fqn = stripRootPath(asRelativeFile(detail.getFileName()));
+ if (fqn.endsWith(".xml")) {
+ fqn = fqn.substring(0, fqn.length() - 4);
+ fqn = asPackageName(fqn);
+ }
+ sb.append(fqn);
+ sb.append("(").append(asSimpleClassName(fqn)).append(".xml:");
+ sb.append(detail.getLineNumber()).append(")");
+ } else {
+ sb.append(detail.getFileName());
+ }
+ sb.append("\n\n");
+ String out = result.summaryErrorMessage(false);
+ sb.append(out);
+ sb.append("\n\n");
+
+ getLog().warn(sb.toString());
+ } else if (showAll) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Endpoint validation passsed at: ");
+ if (detail.getClassName() != null && detail.getLineNumber() != null) {
+ // this is from java code
+ sb.append(detail.getClassName());
+ if (detail.getMethodName() != null) {
+ sb.append(".").append(detail.getMethodName());
+ }
+ sb.append("(").append(asSimpleClassName(detail.getClassName())).append(".java:");
+ sb.append(detail.getLineNumber()).append(")");
+ } else if (detail.getLineNumber() != null) {
+ // this is from xml
+ String fqn = stripRootPath(asRelativeFile(detail.getFileName()));
+ if (fqn.endsWith(".xml")) {
+ fqn = fqn.substring(0, fqn.length() - 4);
+ fqn = asPackageName(fqn);
+ }
+ sb.append(fqn);
+ sb.append("(").append(asSimpleClassName(fqn)).append(".xml:");
+ sb.append(detail.getLineNumber()).append(")");
+ } else {
+ sb.append(detail.getFileName());
+ }
+ sb.append("\n");
+ sb.append("\n\t").append(result.getUri());
+ sb.append("\n\n");
+
+ getLog().info(sb.toString());
+ }
+ }
+ String endpointSummary;
+ if (endpointErrors == 0) {
+ int ok = endpoints.size() - endpointErrors - incapableErrors - unknownComponents;
+ endpointSummary = String.format("Endpoint validation success: (%s = passed, %s = invalid, %s = incapable, %s = unknown components)", ok, endpointErrors, incapableErrors, unknownComponents);
+ } else {
+ int ok = endpoints.size() - endpointErrors - incapableErrors - unknownComponents;
+ endpointSummary = String.format("Endpoint validation error: (%s = passed, %s = invalid, %s = incapable, %s = unknown components)", ok, endpointErrors, incapableErrors, unknownComponents);
+ }
+
+ if (endpointErrors > 0) {
+ getLog().warn(endpointSummary);
+ } else {
+ getLog().info(endpointSummary);
+ }
+
+ int simpleErrors = 0;
+ for (CamelSimpleExpressionDetails detail : simpleExpressions) {
+ SimpleValidationResult result = catalog.validateSimpleExpression(detail.getSimple());
+ if (!result.isSuccess()) {
+ simpleErrors++;
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("Simple validation error at: ");
+ if (detail.getClassName() != null && detail.getLineNumber() != null) {
+ // this is from java code
+ sb.append(detail.getClassName());
+ if (detail.getMethodName() != null) {
+ sb.append(".").append(detail.getMethodName());
+ }
+ sb.append("(").append(asSimpleClassName(detail.getClassName())).append(".java:");
+ sb.append(detail.getLineNumber()).append(")");
+ } else if (detail.getLineNumber() != null) {
+ // this is from xml
+ String fqn = stripRootPath(asRelativeFile(detail.getFileName()));
+ if (fqn.endsWith(".xml")) {
+ fqn = fqn.substring(0, fqn.length() - 4);
+ fqn = asPackageName(fqn);
+ }
+ sb.append(fqn);
+ sb.append("(").append(asSimpleClassName(fqn)).append(".xml:");
+ sb.append(detail.getLineNumber()).append(")");
+ } else {
+ sb.append(detail.getFileName());
+ }
+ sb.append("\n");
+ String[] lines = result.getError().split("\n");
+ for (String line : lines) {
+ sb.append("\n\t").append(line);
+ }
+ sb.append("\n");
+
+ getLog().warn(sb.toString());
+ } else if (showAll) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Simple validation passed at: ");
+ if (detail.getClassName() != null && detail.getLineNumber() != null) {
+ // this is from java code
+ sb.append(detail.getClassName());
+ if (detail.getMethodName() != null) {
+ sb.append(".").append(detail.getMethodName());
+ }
+ sb.append("(").append(asSimpleClassName(detail.getClassName())).append(".java:");
+ sb.append(detail.getLineNumber()).append(")");
+ } else if (detail.getLineNumber() != null) {
+ // this is from xml
+ String fqn = stripRootPath(asRelativeFile(detail.getFileName()));
+ if (fqn.endsWith(".xml")) {
+ fqn = fqn.substring(0, fqn.length() - 4);
+ fqn = asPackageName(fqn);
+ }
+ sb.append(fqn);
+ sb.append("(").append(asSimpleClassName(fqn)).append(".xml:");
+ sb.append(detail.getLineNumber()).append(")");
+ } else {
+ sb.append(detail.getFileName());
+ }
+ sb.append("\n");
+ sb.append("\n\t").append(result.getSimple());
+ sb.append("\n\n");
+
+ getLog().info(sb.toString());
+ }
+ }
+
+ String simpleSummary;
+ if (simpleErrors == 0) {
+ int ok = simpleExpressions.size() - simpleErrors;
+ simpleSummary = String.format("Simple validation success: (%s = passed, %s = invalid)", ok, simpleErrors);
+ } else {
+ int ok = simpleExpressions.size() - simpleErrors;
+ simpleSummary = String.format("Simple validation error: (%s = passed, %s = invalid)", ok, simpleErrors);
+ }
+
+ if (failOnError && (endpointErrors > 0 || simpleErrors > 0)) {
+ throw new MojoExecutionException(endpointSummary + "\n" + simpleSummary);
+ }
+
+ if (simpleErrors > 0) {
+ getLog().warn(simpleSummary);
+ } else {
+ getLog().info(simpleSummary);
+ }
+ }
+
+ private static String findCamelVersion(MavenProject project) {
+ Dependency candidate = null;
+
+ List list = project.getDependencies();
+ for (Object obj : list) {
+ Dependency dep = (Dependency) obj;
+ if ("org.apache.camel".equals(dep.getGroupId())) {
+ if ("camel-core".equals(dep.getArtifactId())) {
+ // favor camel-core
+ candidate = dep;
+ break;
+ } else {
+ candidate = dep;
+ }
+ }
+ }
+ if (candidate != null) {
+ return candidate.getVersion();
+ }
+
+ return null;
+ }
+
+ private void findJavaFiles(File dir, Set<File> javaFiles) {
+ File[] files = dir.isDirectory() ? dir.listFiles() : null;
+ if (files != null) {
+ for (File file : files) {
+ if (file.getName().endsWith(".java")) {
+ javaFiles.add(file);
+ } else if (file.isDirectory()) {
+ findJavaFiles(file, javaFiles);
+ }
+ }
+ }
+ }
+
+ private void findXmlFiles(File dir, Set<File> xmlFiles) {
+ File[] files = dir.isDirectory() ? dir.listFiles() : null;
+ if (files != null) {
+ for (File file : files) {
+ if (file.getName().endsWith(".xml")) {
+ xmlFiles.add(file);
+ } else if (file.isDirectory()) {
+ findXmlFiles(file, xmlFiles);
+ }
+ }
+ }
+ }
+
+ private boolean matchFile(File file) {
+ if (excludes == null && includes == null) {
+ return true;
+ }
+
+ // exclude take precedence
+ if (excludes != null) {
+ for (String exclude : excludes.split(",")) {
+ exclude = exclude.trim();
+ // try both with and without directory in the name
+ String fqn = stripRootPath(asRelativeFile(file.getAbsolutePath()));
+ boolean match = EndpointHelper.matchPattern(fqn, exclude) || EndpointHelper.matchPattern(file.getName(), exclude);
+ if (match) {
+ return false;
+ }
+ }
+ }
+
+ // include
+ if (includes != null) {
+ for (String include : includes.split(",")) {
+ include = include.trim();
+ // try both with and without directory in the name
+ String fqn = stripRootPath(asRelativeFile(file.getAbsolutePath()));
+ boolean match = EndpointHelper.matchPattern(fqn, include) || EndpointHelper.matchPattern(file.getName(), include);
+ if (match) {
+ return true;
+ }
+ }
+ // did not match any includes
+ return false;
+ }
+
+ // was not excluded nor failed include so its accepted
+ return true;
+ }
+
+ private String asRelativeFile(String name) {
+ String answer = name;
+
+ String base = project.getBasedir().getAbsolutePath();
+ if (name.startsWith(base)) {
+ answer = name.substring(base.length());
+ // skip leading slash for relative path
+ if (answer.startsWith(File.separator)) {
+ answer = answer.substring(1);
+ }
+ }
+ return answer;
+ }
+
+ private String stripRootPath(String name) {
+ // strip out any leading source / resource directory
+
+ List list = project.getCompileSourceRoots();
+ for (Object obj : list) {
+ String dir = (String) obj;
+ dir = asRelativeFile(dir);
+ if (name.startsWith(dir)) {
+ return name.substring(dir.length() + 1);
+ }
+ }
+ list = project.getTestCompileSourceRoots();
+ for (Object obj : list) {
+ String dir = (String) obj;
+ dir = asRelativeFile(dir);
+ if (name.startsWith(dir)) {
+ return name.substring(dir.length() + 1);
+ }
+ }
+ List resources = project.getResources();
+ for (Object obj : resources) {
+ Resource resource = (Resource) obj;
+ String dir = asRelativeFile(resource.getDirectory());
+ if (name.startsWith(dir)) {
+ return name.substring(dir.length() + 1);
+ }
+ }
+ resources = project.getTestResources();
+ for (Object obj : resources) {
+ Resource resource = (Resource) obj;
+ String dir = asRelativeFile(resource.getDirectory());
+ if (name.startsWith(dir)) {
+ return name.substring(dir.length() + 1);
+ }
+ }
+
+ return name;
+ }
+
+ private static String asPackageName(String name) {
+ return name.replace(File.separator, ".");
+ }
+
+ private static String asSimpleClassName(String className) {
+ int dot = className.lastIndexOf('.');
+ if (dot > 0) {
+ return className.substring(dot + 1);
+ } else {
+ return className;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/a20439f2/tooling/maven/camel-maven-plugin/src/main/java/org/apache/camel/maven/helper/EndpointHelper.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-maven-plugin/src/main/java/org/apache/camel/maven/helper/EndpointHelper.java b/tooling/maven/camel-maven-plugin/src/main/java/org/apache/camel/maven/helper/EndpointHelper.java
new file mode 100644
index 0000000..94bed8c
--- /dev/null
+++ b/tooling/maven/camel-maven-plugin/src/main/java/org/apache/camel/maven/helper/EndpointHelper.java
@@ -0,0 +1,105 @@
+/**
+ * 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.helper;
+
+import java.util.regex.PatternSyntaxException;
+
+public final class EndpointHelper {
+
+ /**
+ * Matches the name with the given pattern.
+ * <p/>
+ * The match rules are applied in this order:
+ * <ul>
+ * <li>exact match, returns true</li>
+ * <li>wildcard match (pattern ends with a * and the name starts with the pattern), returns true</li>
+ * <li>regular expression match, returns true</li>
+ * <li>otherwise returns false</li>
+ * </ul>
+ *
+ * @param name the name
+ * @param pattern a pattern to match
+ * @return <tt>true</tt> if match, <tt>false</tt> otherwise.
+ */
+ public static boolean matchPattern(String name, String pattern) {
+ if (name == null || pattern == null) {
+ return false;
+ }
+
+ if (name.equals(pattern)) {
+ // exact match
+ return true;
+ }
+
+ if (matchWildcard(name, pattern)) {
+ return true;
+ }
+
+ if (matchRegex(name, pattern)) {
+ return true;
+ }
+
+ // no match
+ return false;
+ }
+
+ /**
+ * Matches the name with the given pattern.
+ * <p/>
+ * The match rules are applied in this order:
+ * <ul>
+ * <li>wildcard match (pattern ends with a * and the name starts with the pattern), returns true</li>
+ * <li>otherwise returns false</li>
+ * </ul>
+ *
+ * @param name the name
+ * @param pattern a pattern to match
+ * @return <tt>true</tt> if match, <tt>false</tt> otherwise.
+ */
+ private static boolean matchWildcard(String name, String pattern) {
+ // we have wildcard support in that hence you can match with: file* to match any file endpoints
+ if (pattern.endsWith("*") && name.startsWith(pattern.substring(0, pattern.length() - 1))) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Matches the name with the given pattern.
+ * <p/>
+ * The match rules are applied in this order:
+ * <ul>
+ * <li>regular expression match, returns true</li>
+ * <li>otherwise returns false</li>
+ * </ul>
+ *
+ * @param name the name
+ * @param pattern a pattern to match
+ * @return <tt>true</tt> if match, <tt>false</tt> otherwise.
+ */
+ private static boolean matchRegex(String name, String pattern) {
+ // match by regular expression
+ try {
+ if (name.matches(pattern)) {
+ return true;
+ }
+ } catch (PatternSyntaxException e) {
+ // ignore
+ }
+ return false;
+ }
+}