Refactor base classes for EnvironmentRepository implementations
Allows us to re-use the Scm features independent of the repository abstraction.
This commit is contained in:
@@ -34,7 +34,7 @@ import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.config.server.AbstractScmEnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.AbstractScmAccessor;
|
||||
import org.springframework.cloud.config.server.NativeEnvironmentRepository;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
@@ -66,7 +66,7 @@ public class FileMonitorConfiguration implements SmartLifecycle, ResourceLoaderA
|
||||
PropertyPathEndpoint endpoint;
|
||||
|
||||
@Autowired(required = false)
|
||||
AbstractScmEnvironmentRepository scmRepository;
|
||||
AbstractScmAccessor scmRepository;
|
||||
|
||||
@Autowired(required = false)
|
||||
NativeEnvironmentRepository nativeEnvironmentRepository;
|
||||
|
||||
@@ -1,171 +1,158 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.cloud.config.server;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.eclipse.jgit.util.FileUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.environment.PropertySource;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Michael Prankl
|
||||
*/
|
||||
public abstract class AbstractScmEnvironmentRepository implements EnvironmentRepository,
|
||||
InitializingBean {
|
||||
private static Log logger = LogFactory.getLog(AbstractScmEnvironmentRepository.class);
|
||||
|
||||
private File basedir;
|
||||
private String uri;
|
||||
private ConfigurableEnvironment environment;
|
||||
private String username;
|
||||
private String password;
|
||||
private String[] searchPaths = new String[0];
|
||||
|
||||
public AbstractScmEnvironmentRepository(ConfigurableEnvironment environment) {
|
||||
this.environment = environment;
|
||||
this.basedir = createBaseDir();
|
||||
}
|
||||
|
||||
private File createBaseDir() {
|
||||
try {
|
||||
final File basedir = Files.createTempDirectory("config-repo-").toFile();
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
FileUtils.delete(basedir, FileUtils.RECURSIVE);
|
||||
}
|
||||
catch (IOException e) {
|
||||
logger.warn("Failed to delete temporary directory on exit: " + e);
|
||||
}
|
||||
}
|
||||
});
|
||||
return basedir;
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException("Cannot create temp dir", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected ConfigurableEnvironment getEnvironment() {
|
||||
return environment;
|
||||
}
|
||||
|
||||
protected void setEnvironment(ConfigurableEnvironment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
public void setUri(String uri) {
|
||||
while (uri.endsWith("/")) {
|
||||
uri = uri.substring(0, uri.length() - 1);
|
||||
}
|
||||
int index = uri.indexOf("://");
|
||||
if (index>0 && !uri.substring(index+"://".length()).contains("/")) {
|
||||
// If there's no context path add one
|
||||
uri = uri + "/";
|
||||
}
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
public void setBasedir(File basedir) {
|
||||
this.basedir = basedir.getAbsoluteFile();
|
||||
}
|
||||
|
||||
public File getBasedir() {
|
||||
return basedir;
|
||||
}
|
||||
|
||||
public void setSearchPaths(String... searchPaths) {
|
||||
this.searchPaths = searchPaths;
|
||||
}
|
||||
|
||||
public String[] getSearchPaths() {
|
||||
return searchPaths;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
protected File getWorkingDirectory() {
|
||||
if (uri.startsWith("file:")) {
|
||||
try {
|
||||
return new UrlResource(StringUtils.cleanPath(uri)).getFile();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException("Cannot convert uri to file: " + uri);
|
||||
}
|
||||
}
|
||||
return basedir;
|
||||
}
|
||||
|
||||
protected String[] getSearchLocations(File dir) {
|
||||
List<String> locations = new ArrayList<String>();
|
||||
locations.add(dir.toURI().toString());
|
||||
String[] list = dir.list();
|
||||
if (list!=null) {
|
||||
for (String path : list) {
|
||||
File file = new File(dir, path);
|
||||
if (file.isDirectory() && PatternMatchUtils.simpleMatch(searchPaths, path)) {
|
||||
locations.add(file.toURI().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
return locations.toArray(new String[0]);
|
||||
}
|
||||
|
||||
protected Environment clean(Environment value) {
|
||||
Environment result = new Environment(value.getName(), value.getProfiles(), value.getLabel());
|
||||
for (PropertySource source : value.getPropertySources()) {
|
||||
String name = source.getName().replace(
|
||||
getWorkingDirectory().toURI().toString(), "");
|
||||
name = name.replace("applicationConfig: [", "");
|
||||
name = uri + "/" + name.replace("]", "");
|
||||
result.add(new PropertySource(name, source.getSource()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.cloud.config.server;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.eclipse.jgit.util.FileUtils;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Base class for components that want to access a source control management system.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class AbstractScmAccessor {
|
||||
|
||||
protected Log logger = LogFactory.getLog(getClass());
|
||||
private File basedir;
|
||||
private String uri;
|
||||
private ConfigurableEnvironment environment;
|
||||
private String username;
|
||||
private String password;
|
||||
private String[] searchPaths = new String[0];
|
||||
|
||||
public AbstractScmAccessor(ConfigurableEnvironment environment) {
|
||||
this.environment = environment;
|
||||
this.basedir = createBaseDir();
|
||||
}
|
||||
|
||||
protected File createBaseDir() {
|
||||
try {
|
||||
final File basedir = Files.createTempDirectory("config-repo-").toFile();
|
||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
FileUtils.delete(basedir, FileUtils.RECURSIVE);
|
||||
}
|
||||
catch (IOException e) {
|
||||
AbstractScmAccessor.this.logger.warn("Failed to delete temporary directory on exit: " + e);
|
||||
}
|
||||
}
|
||||
});
|
||||
return basedir;
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException("Cannot create temp dir", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected ConfigurableEnvironment getEnvironment() {
|
||||
return this.environment;
|
||||
}
|
||||
|
||||
protected void setEnvironment(ConfigurableEnvironment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
public void setUri(String uri) {
|
||||
while (uri.endsWith("/")) {
|
||||
uri = uri.substring(0, uri.length() - 1);
|
||||
}
|
||||
int index = uri.indexOf("://");
|
||||
if (index>0 && !uri.substring(index+"://".length()).contains("/")) {
|
||||
// If there's no context path add one
|
||||
uri = uri + "/";
|
||||
}
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return this.uri;
|
||||
}
|
||||
|
||||
public void setBasedir(File basedir) {
|
||||
this.basedir = basedir.getAbsoluteFile();
|
||||
}
|
||||
|
||||
public File getBasedir() {
|
||||
return this.basedir;
|
||||
}
|
||||
|
||||
public void setSearchPaths(String... searchPaths) {
|
||||
this.searchPaths = searchPaths;
|
||||
}
|
||||
|
||||
public String[] getSearchPaths() {
|
||||
return this.searchPaths;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return this.password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
protected File getWorkingDirectory() {
|
||||
if (this.uri.startsWith("file:")) {
|
||||
try {
|
||||
return new UrlResource(StringUtils.cleanPath(this.uri)).getFile();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException("Cannot convert uri to file: " + this.uri);
|
||||
}
|
||||
}
|
||||
return this.basedir;
|
||||
}
|
||||
|
||||
protected String[] getSearchLocations(File dir) {
|
||||
List<String> locations = new ArrayList<String>();
|
||||
locations.add(dir.toURI().toString());
|
||||
String[] list = dir.list();
|
||||
if (list!=null) {
|
||||
for (String path : list) {
|
||||
File file = new File(dir, path);
|
||||
if (file.isDirectory() && PatternMatchUtils.simpleMatch(this.searchPaths, path)) {
|
||||
locations.add(file.toURI().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
return locations.toArray(new String[0]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.cloud.config.server;
|
||||
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.environment.PropertySource;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Michael Prankl
|
||||
*/
|
||||
public class EnvironmentCleaner {
|
||||
|
||||
public Environment clean(Environment value, String workingDir, String uri) {
|
||||
Environment result = new Environment(value.getName(), value.getProfiles(),
|
||||
value.getLabel());
|
||||
for (PropertySource source : value.getPropertySources()) {
|
||||
String name = source.getName().replace(workingDir, "");
|
||||
name = name.replace("applicationConfig: [", "");
|
||||
name = uri + "/" + name.replace("]", "");
|
||||
result.add(new PropertySource(name, source.getSource()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,8 +22,6 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.eclipse.jgit.api.CheckoutCommand;
|
||||
import org.eclipse.jgit.api.CloneCommand;
|
||||
import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
|
||||
@@ -40,6 +38,7 @@ import org.eclipse.jgit.transport.OpenSshConfig.Host;
|
||||
import org.eclipse.jgit.transport.SshSessionFactory;
|
||||
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
|
||||
import org.eclipse.jgit.util.FileUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
@@ -54,9 +53,7 @@ import com.jcraft.jsch.Session;
|
||||
* @author Dave Syer
|
||||
* @author Roy Clarkson
|
||||
*/
|
||||
public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository {
|
||||
|
||||
private static Log logger = LogFactory.getLog(JGitEnvironmentRepository.class);
|
||||
public class JGitEnvironmentRepository extends AbstractScmAccessor implements EnvironmentRepository, InitializingBean {
|
||||
|
||||
private static final String DEFAULT_LABEL = "master";
|
||||
private static final String FILE_URI_PREFIX = "file:";
|
||||
@@ -74,6 +71,8 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
*/
|
||||
private boolean cloneOnStart = false;
|
||||
|
||||
private EnvironmentCleaner cleaner = new EnvironmentCleaner();
|
||||
|
||||
private JGitEnvironmentRepository.JGitFactory gitFactory = new JGitEnvironmentRepository.JGitFactory();
|
||||
|
||||
public JGitEnvironmentRepository(ConfigurableEnvironment environment) {
|
||||
@@ -133,7 +132,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.warn("Could not close git repository", e);
|
||||
this.logger.warn("Could not close git repository", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,7 +172,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
environment.setSearchLocations(getSearchLocations(getWorkingDirectory()));
|
||||
Environment result = environment.findOne(application, profile, "");
|
||||
result.setLabel(label);
|
||||
return clean(result);
|
||||
return this.cleaner.clean(result, getWorkingDirectory().toURI().toString(), getUri());
|
||||
}
|
||||
|
||||
private Ref checkout(Git git, String label) throws GitAPIException {
|
||||
@@ -210,7 +209,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
pull.call();
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.warn("Could not pull remote for " + label + " (current ref=" + ref
|
||||
this.logger.warn("Could not pull remote for " + label + " (current ref=" + ref
|
||||
+ "), remote: " + git.getRepository().getConfig().getString("remote",
|
||||
"origin", "url"));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,10 +15,18 @@
|
||||
*/
|
||||
package org.springframework.cloud.config.server;
|
||||
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.internal.wc.DefaultSVNAuthenticationManager;
|
||||
@@ -26,32 +34,28 @@ import org.tmatesoft.svn.core.wc2.SvnCheckout;
|
||||
import org.tmatesoft.svn.core.wc2.SvnOperationFactory;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
import org.tmatesoft.svn.core.wc2.SvnUpdate;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
/**
|
||||
* Subversion-backed {@link EnvironmentRepository}.
|
||||
*
|
||||
*
|
||||
* @author Michael Prankl
|
||||
* @author Roy Clarkson
|
||||
* @author Roy Clarkson
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.config.server.svn")
|
||||
public class SvnKitEnvironmentRepository extends AbstractScmEnvironmentRepository {
|
||||
public class SvnKitEnvironmentRepository extends AbstractScmAccessor
|
||||
implements EnvironmentRepository, InitializingBean {
|
||||
|
||||
private static Log logger = LogFactory.getLog(SvnKitEnvironmentRepository.class);
|
||||
|
||||
private static final String DEFAULT_LABEL = "trunk";
|
||||
|
||||
@Override
|
||||
public String getDefaultLabel() {
|
||||
return DEFAULT_LABEL;
|
||||
}
|
||||
|
||||
private static final String DEFAULT_LABEL = "trunk";
|
||||
|
||||
private EnvironmentCleaner cleaner = new EnvironmentCleaner();
|
||||
|
||||
@Override
|
||||
public String getDefaultLabel() {
|
||||
return DEFAULT_LABEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Environment findOne(String application, String profile, String label) {
|
||||
SvnOperationFactory svnOperationFactory = new SvnOperationFactory();
|
||||
@@ -67,7 +71,8 @@ public class SvnKitEnvironmentRepository extends AbstractScmEnvironmentRepositor
|
||||
else {
|
||||
checkout(svnOperationFactory);
|
||||
}
|
||||
return clean(loadEnvironment(application, profile, label));
|
||||
return this.cleaner.clean(loadEnvironment(application, profile, label),
|
||||
getWorkingDirectory().toURI().toString(), getUri());
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new IllegalStateException("Cannot checkout repository", e);
|
||||
@@ -77,14 +82,15 @@ public class SvnKitEnvironmentRepository extends AbstractScmEnvironmentRepositor
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized Environment loadEnvironment(String application, String profile, String label) {
|
||||
private synchronized Environment loadEnvironment(String application, String profile,
|
||||
String label) {
|
||||
final NativeEnvironmentRepository environmentRepository = new NativeEnvironmentRepository(
|
||||
getEnvironment());
|
||||
String[] locations = getSearchLocations(getSvnPath(
|
||||
getWorkingDirectory(), label));
|
||||
String[] locations = getSearchLocations(getSvnPath(getWorkingDirectory(), label));
|
||||
boolean exists = false;
|
||||
for (String location : locations) {
|
||||
location = location.startsWith("file:") ? location.substring("file:".length()) : location;
|
||||
location = location.startsWith("file:") ? location.substring("file:".length())
|
||||
: location;
|
||||
location = StringUtils.cleanPath(location);
|
||||
if (new File(location).exists()) {
|
||||
exists = true;
|
||||
@@ -116,8 +122,7 @@ public class SvnKitEnvironmentRepository extends AbstractScmEnvironmentRepositor
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.state(
|
||||
getUri() != null,
|
||||
Assert.state(getUri() != null,
|
||||
"You need to configure a uri for the subversion repository (e.g. 'http://example.com/svn/')");
|
||||
resolveRelativeFileUri();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user