提交 9cf5bf2b 编写于 作者: J jurgen

Dependency resolutin (repositories)

上级 f8570085
......@@ -31,6 +31,7 @@ import org.jkiss.dbeaver.model.impl.AbstractDescriptor;
import org.jkiss.dbeaver.model.impl.PropertyDescriptor;
import org.jkiss.dbeaver.model.navigator.meta.*;
import org.jkiss.dbeaver.registry.driver.DriverDescriptor;
import org.jkiss.dbeaver.registry.maven.MavenRegistry;
import org.jkiss.dbeaver.ui.UIIcon;
import org.jkiss.utils.ArrayUtils;
import org.jkiss.utils.CommonUtils;
......@@ -82,6 +83,11 @@ public class DataSourceProviderDescriptor extends AbstractDescriptor
this.icon = UIIcon.GEN_DATABASE_TYPE;
}
// Init maven registry.
// We have to init it before any maven library will be initiated.
// Otherwise artifact loading sequence can be broken.
MavenRegistry.getInstance();
// Load tree structure
IConfigurationElement[] trees = config.getChildren(RegistryConstants.TAG_TREE);
if (!ArrayUtils.isEmpty(trees)) {
......
......@@ -64,10 +64,12 @@ public class DriverDependencies implements DBPDriverDependencies
}
System.out.println(sb.toString());
*/
/*
System.out.println("---------------------------");
for (DependencyNode node : rootNodes) {
dumpNode(node, 0);
}
*/
}
} catch (IOException e) {
throw new DBException("IO error while resolving dependencies", e);
......
......@@ -94,7 +94,7 @@ public class DriverLibraryMavenArtifact extends DriverLibraryAbstract
@Nullable
protected MavenArtifactVersion getArtifactVersion(DBPDriverContext context) {
if (localVersion == null) {
localVersion = MavenRegistry.getInstance().findArtifact(context, reference);
localVersion = MavenRegistry.getInstance().findArtifact(context, null, reference);
}
return localVersion;
}
......@@ -139,6 +139,7 @@ public class DriverLibraryMavenArtifact extends DriverLibraryAbstract
List<DriverLibraryMavenDependency> dependencies = new ArrayList<>();
MavenArtifactVersion localVersion = resolveLocalVersion(context, false);
if (localVersion != null) {
List<MavenArtifactDependency> artifactDeps = localVersion.getDependencies(context);
if (!CommonUtils.isEmpty(artifactDeps)) {
for (MavenArtifactDependency dependency : artifactDeps) {
......@@ -146,7 +147,7 @@ public class DriverLibraryMavenArtifact extends DriverLibraryAbstract
continue;
}
MavenArtifactVersion depArtifact = MavenRegistry.getInstance().findArtifact(context, dependency);
MavenArtifactVersion depArtifact = MavenRegistry.getInstance().findArtifact(context, localVersion, dependency);
if (depArtifact != null) {
dependencies.add(
new DriverLibraryMavenDependency(
......@@ -197,7 +198,7 @@ public class DriverLibraryMavenArtifact extends DriverLibraryAbstract
//monitor.beginTask(taskName + " - update localVersion information", 1);
try {
MavenArtifactVersion localVersion = resolveLocalVersion(context, forceUpdate);
if (localVersion.getArtifact().getRepository().isLocal()) {
if (localVersion.getArtifact().getRepository().getType() == MavenRepository.RepositoryType.LOCAL) {
// No need to download local artifacts
return;
}
......
......@@ -33,9 +33,7 @@ import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.*;
/**
* Maven artifact version descriptor (POM).
......@@ -87,6 +85,7 @@ public class MavenArtifactVersion {
MavenArtifactVersion(@NotNull DBPDriverContext context, @NotNull MavenArtifact artifact, @NotNull String version, boolean readRemote) throws IOException {
this.artifact = artifact;
this.version = version;
loadPOM(context, readRemote);
}
......@@ -118,6 +117,10 @@ public class MavenArtifactVersion {
return licenses;
}
public List<MavenProfile> getProfiles() {
return profiles;
}
public List<MavenArtifactDependency> getDependencies(DBPDriverContext context) {
List<MavenArtifactDependency> dependencies = new ArrayList<>();
for (MavenProfile profile : profiles) {
......@@ -135,7 +138,7 @@ public class MavenArtifactVersion {
}
public File getCacheFile() {
if (artifact.getRepository().isLocal()) {
if (artifact.getRepository().getType() == MavenRepository.RepositoryType.LOCAL) {
String externalURL = getExternalURL(MavenArtifact.FILE_JAR);
try {
return new File(new URL(externalURL).toURI());
......@@ -161,7 +164,7 @@ public class MavenArtifactVersion {
}
private File getLocalPOM() {
if (artifact.getRepository().isLocal()) {
if (artifact.getRepository().getType() == MavenRepository.RepositoryType.LOCAL) {
try {
return new File(new URI(getRemotePOMLocation()));
} catch (URISyntaxException e) {
......@@ -177,6 +180,23 @@ public class MavenArtifactVersion {
return artifact.getFileURL(version, MavenArtifact.FILE_POM);
}
private void cachePOM(File localPOM) throws IOException {
if (artifact.getRepository().getType() == MavenRepository.RepositoryType.LOCAL) {
return;
}
String pomURL = getRemotePOMLocation();
try (InputStream is = RuntimeUtils.openConnectionStream(pomURL)) {
File folder = localPOM.getParentFile();
if (!folder.exists() && !folder.mkdirs()) {
throw new IOException("Can't create cache folder '" + folder.getAbsolutePath() + "'");
}
try (OutputStream os = new FileOutputStream(localPOM)) {
IOUtils.fastCopy(is, os);
}
}
}
private void loadPOM(DBPDriverContext context, boolean readRemote) throws IOException {
File localPOM = getLocalPOM();
if (!localPOM.exists()) {
......@@ -219,7 +239,7 @@ public class MavenArtifactVersion {
if (this.version == null) {
this.version = parentReference.getVersion();
}
parent = MavenRegistry.getInstance().findArtifact(context, parentReference);
parent = MavenRegistry.getInstance().findArtifact(context, this, parentReference);
if (parent == null) {
log.error("Artifact [" + this + "] parent [" + parentReference + "] not found");
}
......@@ -311,7 +331,7 @@ public class MavenArtifactVersion {
XMLUtils.getChildElementBody(repElement, "id"),
XMLUtils.getChildElementBody(repElement, "name"),
XMLUtils.getChildElementBody(repElement, "url"),
false);
MavenRepository.RepositoryType.EXTERNAL);
String layout = XMLUtils.getChildElementBody(repElement, "layout");
if ("legacy".equals(layout)) {
log.debug("Skip legacy repository [" + repository + "]");
......@@ -323,8 +343,9 @@ public class MavenArtifactVersion {
}
boolean enabled = CommonUtils.toBoolean(XMLUtils.getChildElementBody(releasesElement, "enabled"));
if (enabled) {
MavenContextInfo mci = context.getInfo(MavenContextInfo.class);
//mci.addRepositories();
repository.loadCache();
profile.addRepository(repository);
context.getInfo(MavenContextInfo.class).trackRepository(repository);
}
}
}
......@@ -339,23 +360,6 @@ public class MavenArtifactVersion {
}
}
private void cachePOM(File localPOM) throws IOException {
if (artifact.getRepository().isLocal()) {
return;
}
String pomURL = getRemotePOMLocation();
try (InputStream is = RuntimeUtils.openConnectionStream(pomURL)) {
File folder = localPOM.getParentFile();
if (!folder.exists() && !folder.mkdirs()) {
throw new IOException("Can't create cache folder '" + folder.getAbsolutePath() + "'");
}
try (OutputStream os = new FileOutputStream(localPOM)) {
IOUtils.fastCopy(is, os);
}
}
}
private List<MavenArtifactDependency> parseDependencies(DBPDriverContext context, Element element, boolean depManagement) {
List<MavenArtifactDependency> result = new ArrayList<>();
Element dependenciesElement = XMLUtils.getChildElement(element, "dependencies");
......@@ -386,7 +390,7 @@ public class MavenArtifactVersion {
groupId,
artifactId,
version);
MavenArtifactVersion importedVersion = MavenRegistry.getInstance().findArtifact(context, importReference);
MavenArtifactVersion importedVersion = MavenRegistry.getInstance().findArtifact(context, this, importReference);
if (importedVersion == null) {
log.error("Imported artifact [" + importReference + "] not found. Skip.");
}
......@@ -470,4 +474,21 @@ public class MavenArtifactVersion {
return GeneralUtils.replaceVariables(value, propertyResolver);
}
@NotNull
public Collection<MavenRepository> getActiveRepositories() {
Map<String, MavenRepository> repositories = new LinkedHashMap<>();
for (MavenArtifactVersion v = MavenArtifactVersion.this; v != null; v = v.parent) {
for (MavenProfile profile : v.profiles) {
if (profile.isActive()) {
List<MavenRepository> pr = profile.getRepositories();
if (pr != null) {
for (MavenRepository repository : pr) {
repositories.put(repository.getId(), repository);
}
}
}
}
}
return repositories.values();
}
}
\ No newline at end of file
......@@ -17,29 +17,90 @@
*/
package org.jkiss.dbeaver.registry.maven;
import org.jkiss.dbeaver.Log;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Driver resolve context
* MavenContextInfo
*/
public class MavenContextInfo {
public class MavenContextInfo implements AutoCloseable {
static final Log log = Log.getLog(MavenContextInfo.class);
private List<MavenRepository> repositoryStack = new ArrayList<>();
private Map<String, MavenRepository> externalRepositories = new LinkedHashMap<>();
public MavenRepository getCurrentRepository() {
return repositoryStack.isEmpty() ? null : repositoryStack.get(repositoryStack.size() - 1);
}
public void startRepositoryBrowse(MavenRepository repository) {
repositoryStack.add(repository);
}
public void endRepositoryBrowse(MavenRepository repository) {
MavenRepository removed = repositoryStack.remove(repositoryStack.size() - 1);
if (removed == null || removed != repository) {
log.error("Wrong artifact: " + repository);
}
}
public void trackRepository(MavenRepository repository) {
externalRepositories.put(repository.getUrl(), repository);
}
@Override
public void close() {
for (MavenRepository repository : externalRepositories.values()) {
repository.saveCache();
}
}
private final Map<MavenArtifactVersion, List<MavenRepository>> artifactRepositories = new LinkedHashMap<>();
private final List<MavenRepository> activeRepositories = new ArrayList<>();
/*
private final List<MavenArtifactVersion> artifactStack = new ArrayList<>();
public List<MavenRepository> getActiveRepositories() {
return activeRepositories;
public Collection<MavenRepository> getActiveRepositories() {
Map<String, MavenRepository> repositories = new LinkedHashMap<>();
for (int i = artifactStack.size(); i > 0; i--) {
for (MavenProfile profile : artifactStack.get(i - 1).getProfiles()) {
if (profile.isActive()) {
List<MavenRepository> profileRepositories = profile.getRepositories();
if (profileRepositories != null) {
for (MavenRepository repository : profileRepositories) {
repositories.put(repository.getId(), repository);
}
}
}
}
}
return repositories.values();
}
public void addRepositories(MavenArtifactVersion artifactVersion, List<MavenRepository> repositories) {
artifactRepositories.put(artifactVersion, repositories);
void beginArtifactProcessing(MavenArtifactVersion artifactVersion) {
artifactStack.add(artifactVersion);
}
public void removeRepositories(MavenArtifactVersion artifactVersion) {
artifactRepositories.remove(artifactVersion);
void endArtifactProcessing(MavenArtifactVersion artifactVersion) {
MavenArtifactVersion removed = artifactStack.remove(artifactStack.size() - 1);
if (removed == null || removed != artifactVersion) {
log.error("Wrong artifact: " + artifactVersion);
} else {
// Save repository cache immediately
for (MavenProfile profile : artifactVersion.getProfiles()) {
if (profile.isActive()) {
List<MavenRepository> profileRepositories = profile.getRepositories();
if (profileRepositories != null) {
for (MavenRepository repository : profileRepositories) {
repository.saveCache();
}
}
}
}
}
}
*/
}
......@@ -19,6 +19,7 @@ package org.jkiss.dbeaver.registry.maven;
import org.w3c.dom.Element;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
......@@ -32,6 +33,7 @@ public class MavenProfile {
Map<String, String> properties = new LinkedHashMap<>();
List<MavenArtifactDependency> dependencies;
List<MavenArtifactDependency> dependencyManagement;
List<MavenRepository> repositories;
boolean active;
......@@ -59,8 +61,20 @@ public class MavenProfile {
return active;
}
public List<MavenRepository> getRepositories() {
return repositories;
}
void addRepository(MavenRepository repository) {
if (repositories == null) {
repositories = new ArrayList<>();
}
repositories.add(repository);
}
@Override
public String toString() {
return id;
}
}
......@@ -24,6 +24,7 @@ import org.eclipse.core.runtime.Status;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBeaverPreferences;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.core.DBeaverCore;
import org.jkiss.dbeaver.model.connection.DBPDriverContext;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
......@@ -35,6 +36,8 @@ import java.util.*;
public class MavenRegistry
{
static final Log log = Log.getLog(MavenRegistry.class);
public static final String MAVEN_LOCAL_REPO_ID = "local";
public static final String MAVEN_LOCAL_REPO_NAME = "Local Repository";
public static final String MAVEN_LOCAL_REPO_FOLDER = "maven-local";
......@@ -90,7 +93,7 @@ public class MavenRegistry
MAVEN_LOCAL_REPO_ID,
MAVEN_LOCAL_REPO_NAME,
localRepoURL,
true);
MavenRepository.RepositoryType.LOCAL);
}
private void loadCache() {
......@@ -107,7 +110,7 @@ public class MavenRegistry
// Remove all custom repositories
for (Iterator<MavenRepository> iterator = repositories.iterator(); iterator.hasNext(); ) {
MavenRepository repository = iterator.next();
if (!repository.isPredefined()) {
if (repository.getType() == MavenRepository.RepositoryType.CUSTOM) {
iterator.remove();
}
}
......@@ -123,7 +126,7 @@ public class MavenRegistry
}
String repoID = repoInfo.substring(0, divPos);
String repoURL = repoInfo.substring(divPos + 1);
MavenRepository repo = new MavenRepository(repoID, repoID, repoURL, false);
MavenRepository repo = new MavenRepository(repoID, repoID, repoURL, MavenRepository.RepositoryType.CUSTOM);
repositories.add(repo);
}
}
......@@ -134,12 +137,12 @@ public class MavenRegistry
}
@Nullable
public MavenArtifactVersion findArtifact(@NotNull DBPDriverContext context, @NotNull MavenArtifactReference ref) {
public MavenArtifactVersion findArtifact(@NotNull DBPDriverContext context, @Nullable MavenArtifactVersion owner, @NotNull MavenArtifactReference ref) {
String fullId = ref.getId();
if (notFoundArtifacts.contains(fullId)) {
return null;
}
MavenArtifactVersion artifact = findInRepositories(context, ref);
MavenArtifactVersion artifact = findInRepositories(context, owner, ref);
if (artifact != null) {
return artifact;
}
......@@ -179,21 +182,59 @@ public class MavenRegistry
}
@Nullable
private MavenArtifactVersion findInRepositories(@NotNull DBPDriverContext context, @NotNull MavenArtifactReference ref) {
private MavenArtifactVersion findInRepositories(@NotNull DBPDriverContext context, MavenArtifactVersion owner, @NotNull MavenArtifactReference ref) {
//MavenContextInfo info = context.getInfo(MavenContextInfo.class);
MavenRepository currentRepository = owner == null ? null : owner.getArtifact().getRepository();
if (currentRepository != null) {
MavenArtifactVersion artifact = currentRepository.findArtifact(context, ref);
if (artifact != null) {
return artifact;
}
}
// Try all available repositories (without resolve)
for (MavenRepository repository : repositories) {
MavenArtifactVersion artifact = repository.findArtifact(context, ref);
if (repository != currentRepository) {
MavenArtifactVersion artifact = repository.findArtifact(context, ref);
if (artifact != null) {
return artifact;
}
}
}
if (owner != null) {
// Try context repositories
for (MavenRepository repository : owner.getActiveRepositories()) {
if (repository != currentRepository) {
MavenArtifactVersion artifact = repository.findArtifact(context, ref);
if (artifact != null) {
return artifact;
}
}
}
}
if (localRepository != currentRepository) {
MavenArtifactVersion artifact = localRepository.findArtifact(context, ref);
if (artifact != null) {
return artifact;
}
}
MavenArtifactVersion artifact = localRepository.findArtifact(context, ref);
if (artifact != null) {
return artifact;
}
log.warn("Maven artifact '" + ref + "' not found in any available repository.");
return null;
}
@Nullable
private MavenArtifactVersion findInRepository(@NotNull DBPDriverContext context, @NotNull MavenArtifactReference ref, MavenRepository repository) {
//info.startRepositoryBrowse(repository);
try {
return repository.findArtifact(context, ref);
} finally {
//info.endRepositoryBrowse(repository);
}
}
public MavenRepository findRepository(String id) {
for (MavenRepository repository : repositories) {
if (repository.getId().equals(id)) {
......
......@@ -34,6 +34,8 @@ import org.jkiss.utils.xml.XMLException;
import org.xml.sax.Attributes;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.Map;
......@@ -52,6 +54,7 @@ public class MavenRepository
public static final String TAG_ARTIFACT = "artifact";
public static final String TAG_VERSION = "version";
public static final String ATTR_ID = "id";
public static final String ATTR_NAME = "name";
public static final String ATTR_URL = "url";
public static final String ATTR_GROUP_ID = "groupId";
......@@ -59,11 +62,17 @@ public class MavenRepository
public static final String ATTR_ACTIVE_VERSION = "activeVersion";
public static final String ATTR_VERSION = "version";
private String id;
private String name;
private String url;
private boolean local;
private boolean predefined = false;
public enum RepositoryType {
GLOBAL, // Globally defined repositories (came from plugin.xml)
LOCAL, // Local (deployed locally) repository. It is singleton
CUSTOM, // User-defined repository
EXTERNAL // POM-defined repository
}
private final String id;
private final String name;
private final String url;
private final RepositoryType type;
private transient volatile boolean needsToSave = false;
......@@ -75,16 +84,15 @@ public class MavenRepository
config.getAttribute(RegistryConstants.ATTR_ID),
config.getAttribute(RegistryConstants.ATTR_NAME),
config.getAttribute(RegistryConstants.ATTR_URL),
false);
this.predefined = true;
RepositoryType.GLOBAL);
}
public MavenRepository(String id, String name, String url, boolean local) {
public MavenRepository(String id, String name, String url, RepositoryType type) {
this.id = id;
this.name = name;
this.name = CommonUtils.isEmpty(name) ? id : name;
if (!url.endsWith("/")) url += "/";
this.url = url;
this.local = local;
this.type = type;
}
public void flushCache() {
......@@ -103,12 +111,8 @@ public class MavenRepository
return url;
}
public boolean isPredefined() {
return predefined;
}
public boolean isLocal() {
return local;
public RepositoryType getType() {
return type;
}
@Nullable
......@@ -127,7 +131,7 @@ public class MavenRepository
}
return version;
} catch (IOException e) {
log.debug("Artifact version " + ref + " not found: " + e.getMessage());
// Generally it is ok. Artifact not present in this repository
return null;
}
}
......@@ -155,7 +159,21 @@ public class MavenRepository
File getLocalCacheDir()
{
File homeFolder = new File(DBeaverActivator.getInstance().getStateLocation().toFile(), "maven/" + id + "/");
String extPath;
switch (type) {
case EXTERNAL:
try {
URL repoUrl = new URL(this.url);
extPath = ".external/" + repoUrl.getHost() + "/" + repoUrl.getPath();
} catch (MalformedURLException e) {
extPath = ".external/" + id;
}
break;
default:
extPath = id;
break;
}
File homeFolder = new File(DBeaverActivator.getInstance().getStateLocation().toFile(), "maven/" + extPath);
if (!homeFolder.exists()) {
if (!homeFolder.mkdirs()) {
log.warn("Can't create maven repository '" + name + "' cache folder '" + homeFolder + "'");
......@@ -170,8 +188,7 @@ public class MavenRepository
if (!cacheFile.exists()) {
return;
}
final DBPDriverContext context = new DBPDriverContext(VoidProgressMonitor.INSTANCE);
try {
try (final DBPDriverContext context = new DBPDriverContext(VoidProgressMonitor.INSTANCE)) {
InputStream mdStream = new FileInputStream(cacheFile);
try {
SAXReader reader = new SAXReader(mdStream);
......@@ -230,7 +247,7 @@ public class MavenRepository
}
}
synchronized private void saveCache() {
synchronized void saveCache() {
try {
File cacheDir = getLocalCacheDir();
if (!cacheDir.exists()) {
......@@ -244,6 +261,7 @@ public class MavenRepository
XMLBuilder xml = new XMLBuilder(out, "utf-8");
xml.setButify(true);
try (XMLBuilder.Element e = xml.startElement(TAG_CACHE)) {
xml.addAttribute(ATTR_ID, id);
xml.addAttribute(ATTR_NAME, name);
xml.addAttribute(ATTR_URL, url);
......
......@@ -124,10 +124,8 @@ public class PrefPageDrivers extends PreferencePage implements IWorkbenchPrefere
boolean enabled = false;
TableItem[] selection = mavenRepoTable.getSelection();
if (selection.length == 1) {
enabled = true;
if (selection[0].getData() instanceof MavenRepository && ((MavenRepository)selection[0].getData()).isPredefined()) {
enabled = false;
}
enabled = selection[0].getData() instanceof MavenRepository &&
((MavenRepository) selection[0].getData()).getType() == MavenRepository.RepositoryType.CUSTOM;
}
removeButton.setEnabled(enabled);
}
......@@ -289,7 +287,7 @@ public class PrefPageDrivers extends PreferencePage implements IWorkbenchPrefere
String repoId = item.getText(0);
String repoURL = item.getText(1);
MavenRepository repository = MavenRegistry.getInstance().findRepository(repoId);
if (repository != null && repository.isPredefined()) {
if (repository != null && repository.getType() != MavenRepository.RepositoryType.CUSTOM) {
continue;
}
if (mavenRepos.length() > 0) mavenRepos.append('|');
......
......@@ -17,6 +17,7 @@
*/
package org.jkiss.dbeaver.model.connection;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
......@@ -32,7 +33,7 @@ public class DBPDriverContext implements AutoCloseable {
private final DBRProgressMonitor monitor;
private final Date initTime = new Date();
private final Map<String, String> properties = new HashMap<>();
private final Map<Class, Object> infoMap = new HashMap<>();
private final Map<Class, AutoCloseable> infoMap = new HashMap<>();
public DBPDriverContext(DBRProgressMonitor monitor) {
this.monitor = monitor;
......@@ -50,13 +51,14 @@ public class DBPDriverContext implements AutoCloseable {
return properties;
}
public <T> T getInfo(Class<T> type) {
Object o = infoMap.get(type);
@NotNull
public <T extends AutoCloseable> T getInfo(Class<T> type) {
AutoCloseable o = infoMap.get(type);
if (o == null) {
try {
o = type.newInstance();
} catch (Exception e) {
log.error("Can't create context info " + type.getName(), e);
throw new IllegalArgumentException("Can't create context info " + type.getName(), e);
}
infoMap.put(type, o);
}
......@@ -65,6 +67,12 @@ public class DBPDriverContext implements AutoCloseable {
@Override
public void close() {
for (AutoCloseable info : infoMap.values()) {
try {
info.close();
} catch (Exception e) {
log.error(e);
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册