Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CAMEL-18646] Provide custom configuration #8661

Merged
merged 1 commit into from Nov 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -31,6 +31,8 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj
case "exceptionHandler": target.setExceptionHandler(property(camelContext, org.apache.camel.spi.ExceptionHandler.class, value)); return true;
case "exchangepattern":
case "exchangePattern": target.setExchangePattern(property(camelContext, org.apache.camel.ExchangePattern.class, value)); return true;
case "gitconfigfile":
case "gitConfigFile": target.setGitConfigFile(property(camelContext, java.lang.String.class, value)); return true;
case "lazystartproducer":
case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
case "operation": target.setOperation(property(camelContext, java.lang.String.class, value)); return true;
Expand Down Expand Up @@ -62,6 +64,8 @@ public Class<?> getOptionType(String name, boolean ignoreCase) {
case "exceptionHandler": return org.apache.camel.spi.ExceptionHandler.class;
case "exchangepattern":
case "exchangePattern": return org.apache.camel.ExchangePattern.class;
case "gitconfigfile":
case "gitConfigFile": return java.lang.String.class;
case "lazystartproducer":
case "lazyStartProducer": return boolean.class;
case "operation": return java.lang.String.class;
Expand Down Expand Up @@ -94,6 +98,8 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
case "exceptionHandler": return target.getExceptionHandler();
case "exchangepattern":
case "exchangePattern": return target.getExchangePattern();
case "gitconfigfile":
case "gitConfigFile": return target.getGitConfigFile();
case "lazystartproducer":
case "lazyStartProducer": return target.isLazyStartProducer();
case "operation": return target.getOperation();
Expand Down
Expand Up @@ -21,12 +21,13 @@ public class GitEndpointUriFactory extends org.apache.camel.support.component.En
private static final Set<String> SECRET_PROPERTY_NAMES;
private static final Set<String> MULTI_VALUE_PREFIXES;
static {
Set<String> props = new HashSet<>(15);
Set<String> props = new HashSet<>(16);
props.add("allowEmpty");
props.add("branchName");
props.add("bridgeErrorHandler");
props.add("exceptionHandler");
props.add("exchangePattern");
props.add("gitConfigFile");
props.add("lazyStartProducer");
props.add("localPath");
props.add("operation");
Expand Down
Expand Up @@ -55,6 +55,7 @@
"tagName": { "kind": "parameter", "displayName": "Tag Name", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The tag name to work on" },
"targetBranchName": { "kind": "parameter", "displayName": "Target Branch Name", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "master", "description": "Name of target branch in merge operation. If not supplied will try to use init.defaultBranch git configs. If not configured will use default value" },
"username": { "kind": "parameter", "displayName": "Username", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Remote repository username" },
"lazyStartProducer": { "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }
"lazyStartProducer": { "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." },
"gitConfigFile": { "kind": "parameter", "displayName": "Git Config File", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "A String with path to a .gitconfig file" }
}
}
15 changes: 15 additions & 0 deletions components/camel-git/src/main/docs/git-component.adoc
Expand Up @@ -83,5 +83,20 @@ from("git:///tmp/testRepo?type=commit")
.to(....)
---------------------------------------

== Custom config file
By default camel-git will load ``.gitconfig`` file from user home folder. You
can override this by providing your own ``.gitconfig`` file.

[source,java]
---------------------------------------
from("git:///tmp/testRepo?type=commit&gitConfigFile=file:/tmp/configfile")
.to(....) //will load from os dirs

from("git:///tmp/testRepo?type=commit&gitConfigFile=classpath:configfile")
.to(....) //will load from resources dir

from("git:///tmp/testRepo?type=commit&gitConfigFile=http://somedomain.xyz/gitconfigfile")
.to(....) //will load from http. You could also use https
---------------------------------------

include::spring-boot:partial$starter.adoc[]
@@ -0,0 +1,85 @@
/*
* 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.component;

import java.io.File;

import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.SystemReader;

public class CustomConfigSystemReader extends SystemReader {
private static final SystemReader PROXY = SystemReader.getInstance();
private File userGitConfig;

public CustomConfigSystemReader(File userGitConfig) {
super();
this.userGitConfig = userGitConfig;
}

@Override
public String getenv(String variable) {
return PROXY.getenv(variable);
}

@Override
public String getHostname() {
return PROXY.getHostname();
}

@Override
public String getProperty(String key) {
return PROXY.getProperty(key);
}

@Override
public long getCurrentTime() {
return PROXY.getCurrentTime();
}

@Override
public int getTimezone(long when) {
return PROXY.getTimezone(when);
}

@Override
public FileBasedConfig openUserConfig(Config parent, FS fs) {
return new FileBasedConfig(parent, userGitConfig, fs);
}

@Override
public FileBasedConfig openJGitConfig(Config parent, FS fs) {
return PROXY.openJGitConfig(parent, fs);
}

// Return an empty system configuration, based on example in SystemReader.Default#openSystemConfig
@Override
public FileBasedConfig openSystemConfig(Config parent, FS fs) {
return new FileBasedConfig(parent, null, fs) {
@Override
public void load() {
}

@Override
public boolean isOutdated() {
return false;
}
};
}

}
@@ -0,0 +1,114 @@
/*
* 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.component;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;

import org.apache.camel.RuntimeCamelException;
import org.apache.camel.component.git.GitEndpoint;
import org.apache.camel.support.ResourceHelper;
import org.apache.camel.util.ObjectHelper;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.util.SystemReader;

public abstract class RepositoryFactory {

private static final SystemReader DEFAULT_INSTANCE;
private static final List<String> VALID_SCHEMES = Arrays.asList("classpath:", "file:", "http:", "https:");

static {
DEFAULT_INSTANCE = SystemReader.getInstance();
}

private RepositoryFactory() {
}

public static Repository of(GitEndpoint endpoint) {
if (ObjectHelper.isNotEmpty(endpoint.getGitConfigFile())) {
return resolveConfigFile(endpoint, endpoint.getGitConfigFile());
}
return getRepository(endpoint, DEFAULT_INSTANCE);
}

private static Repository resolveConfigFile(GitEndpoint endpoint, String uri) {
if (ObjectHelper.isEmpty(uri)) {
throw new IllegalArgumentException("URI to git config file must be supplied");
}

if (!ResourceHelper.hasScheme(uri) || !VALID_SCHEMES.contains(ResourceHelper.getScheme(uri))) {
throw new IllegalArgumentException(
"URI to git config file must have scheme:path pattern where scheme could be classpath, file, http or https");
}

String schema = ResourceHelper.getScheme(uri);
String path = uri.substring(schema.length());

File gitConfigFile;
if (ResourceHelper.isClasspathUri(uri)) {
gitConfigFile = new File(endpoint.getClass().getClassLoader().getResource(path).getFile());
} else if (ResourceHelper.isHttpUri(uri)) {
try {
gitConfigFile = getTempFileFromHttp(uri);
} catch (IOException e) {
throw new RuntimeCamelException(String.format("Something went wrong when loading: %s", uri), e);
}
} else { //load from system
gitConfigFile = new File(path);
if (Files.isDirectory(gitConfigFile.toPath()) || !Files.isReadable(gitConfigFile.toPath())) {
throw new IllegalArgumentException(
String.format(
"The configuration file at %s is unreadable (either missing, lacking proper access permission or is not a regular file)",
path));
}
}

return getRepository(endpoint, new CustomConfigSystemReader(gitConfigFile));
}

private static Repository getRepository(GitEndpoint endpoint, SystemReader instance) {
FileRepositoryBuilder builder = new FileRepositoryBuilder();
try {
SystemReader.setInstance(instance);
// scan environment GIT_* variables
return builder.setGitDir(new File(endpoint.getLocalPath(), ".git")).readEnvironment()
.findGitDir() // scan up the file system tree
.build();
} catch (IOException e) {
throw new RuntimeCamelException(
String.format("There was an error opening the repository at %s", endpoint.getLocalPath()), e);
}
}

private static File getTempFileFromHttp(String url) throws IOException {
Path tempFile = Files.createTempFile(null, null);
FileOutputStream outputStream = new FileOutputStream(tempFile.toString());
ReadableByteChannel byteChannel = Channels.newChannel(new URL(url).openStream());
outputStream.getChannel().transferFrom(byteChannel, 0, Long.MAX_VALUE);
return tempFile.toFile();
}

}
Expand Up @@ -77,6 +77,9 @@ public class GitEndpoint extends DefaultEndpoint {
label = "producer")
private String operation;

@UriParam(description = "A String with path to a .gitconfig file", label = "advanced")
private String gitConfigFile;

public GitEndpoint(String uri, GitComponent component) {
super(uri, component);
}
Expand Down Expand Up @@ -219,4 +222,15 @@ public String getTargetBranchName() {
public void setTargetBranchName(String targetBranchName) {
this.targetBranchName = targetBranchName;
}

/**
* A String with path to a .gitconfig file", label = "producer,consumer,advanced
*/
public String getGitConfigFile() {
return this.gitConfigFile;
}

public void setGitConfigFile(String gitConfigFile) {
this.gitConfigFile = gitConfigFile;
}
}
Expand Up @@ -16,15 +16,12 @@
*/
package org.apache.camel.component.git.consumer;

import java.io.File;
import java.io.IOException;

import org.apache.camel.Processor;
import org.apache.camel.component.RepositoryFactory;
import org.apache.camel.component.git.GitEndpoint;
import org.apache.camel.support.ScheduledPollConsumer;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -57,20 +54,11 @@ protected void doStop() throws Exception {
git.close();
}

private Repository getLocalRepository() throws IOException {
FileRepositoryBuilder builder = new FileRepositoryBuilder();
try {
// scan environment GIT_* variables
return builder.setGitDir(new File(endpoint.getLocalPath(), ".git")).readEnvironment()
.findGitDir() // scan up the file system tree
.build();
} catch (IOException e) {
LOG.error("There was an error, cannot open {} repository", endpoint.getLocalPath());
throw e;
}
private Repository getLocalRepository() {
return RepositoryFactory.of(endpoint);
}

protected Repository getRepository() {
public Repository getRepository() {
return repo;
}

Expand Down
Expand Up @@ -24,6 +24,7 @@
import java.util.Set;

import org.apache.camel.Exchange;
import org.apache.camel.component.RepositoryFactory;
import org.apache.camel.component.git.GitConstants;
import org.apache.camel.component.git.GitEndpoint;
import org.apache.camel.support.DefaultProducer;
Expand All @@ -46,7 +47,6 @@
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.URIish;
Expand Down Expand Up @@ -658,17 +658,8 @@ protected void doRemoteList(Exchange exchange, String operation) throws GitAPIEx
updateExchange(exchange, result);
}

private Repository getLocalRepository() throws IOException {
FileRepositoryBuilder builder = new FileRepositoryBuilder();
try {
// scan environment GIT_* variables
return builder.setGitDir(new File(endpoint.getLocalPath(), ".git")).readEnvironment()
.findGitDir() // scan up the file system tree
.build();
} catch (IOException e) {
LOG.error("There was an error, cannot open {} repository", endpoint.getLocalPath());
throw e;
}
private Repository getLocalRepository() {
return RepositoryFactory.of(endpoint);
}

private void updateExchange(Exchange exchange, Object body) {
Expand Down