Skip to content

Commit 8992bd6

Browse files
committed
Merge branch 'develop' into feature-refactor-run-configuration
2 parents 781989b + 85efda2 commit 8992bd6

File tree

27 files changed

+1430
-552
lines changed

27 files changed

+1430
-552
lines changed

PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-database/src/main/java/com/microsoft/azure/toolkit/intellij/connector/database/DatabaseConnectionUtils.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,12 @@
99
import com.microsoft.azuretools.ActionConstants;
1010
import com.microsoft.azuretools.telemetrywrapper.EventType;
1111
import com.microsoft.azuretools.telemetrywrapper.EventUtil;
12-
import com.mysql.cj.jdbc.ConnectionImpl;
1312
import lombok.AllArgsConstructor;
1413
import lombok.Getter;
1514
import org.apache.commons.lang3.StringUtils;
1615
import org.apache.commons.lang3.reflect.FieldUtils;
1716

18-
import java.sql.Connection;
19-
import java.sql.DriverManager;
20-
import java.sql.ResultSet;
21-
import java.sql.SQLException;
22-
import java.sql.Statement;
17+
import java.sql.*;
2318
import java.util.Collections;
2419

2520
public class DatabaseConnectionUtils {
@@ -69,7 +64,8 @@ public static ConnectResult connectWithPing(JdbcUrl url, String username, String
6964
serverVersion = "unknown";
7065
}
7166
} else {
72-
serverVersion = ((ConnectionImpl) connection).getServerVersion().toString();
67+
final DatabaseMetaData meta = connection.getMetaData();
68+
serverVersion = meta == null ? "unknown" : String.format("%d.%d", meta.getDatabaseMajorVersion(), meta.getDatabaseMinorVersion());
7369
}
7470
} catch (final SQLException exception) {
7571
errorCode = exception.getErrorCode();
@@ -86,7 +82,7 @@ public static ConnectResult connectWithPing(JdbcUrl url, String username, String
8682
}
8783

8884
private static String getDriverClassName(JdbcUrl url) {
89-
String jdbcUrl = url.toString();
85+
final String jdbcUrl = url.toString();
9086
if (StringUtils.startsWith(jdbcUrl, SQL_SERVER_URL_PREFIX)) {
9187
return "com.microsoft.sqlserver.jdbc.SQLServerDriver";
9288
} else if (StringUtils.startsWith(jdbcUrl, POSTGRE_URL_PREFIX)) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*/
5+
6+
package com.microsoft.azure.toolkit.intellij.connector.database.component;
7+
8+
import com.microsoft.azure.toolkit.intellij.common.AzureComboBox;
9+
import com.microsoft.azure.toolkit.lib.database.entity.IDatabase;
10+
import com.microsoft.azure.toolkit.lib.database.entity.IDatabaseServer;
11+
import lombok.Getter;
12+
13+
import java.util.Objects;
14+
15+
public class DatabaseComboBoxV2 extends AzureComboBox<IDatabase> {
16+
17+
@Getter
18+
private IDatabaseServer server;
19+
20+
public void setServer(IDatabaseServer server) {
21+
if (Objects.equals(server, this.server)) {
22+
return;
23+
}
24+
this.server = server;
25+
if (server == null) {
26+
this.clear();
27+
return;
28+
}
29+
this.refreshItems();
30+
}
31+
32+
@Override
33+
protected String getItemText(Object item) {
34+
return Objects.nonNull(item) && item instanceof IDatabase ? ((IDatabase) item).getName() : super.getItemText(item);
35+
}
36+
37+
@Override
38+
public boolean isRequired() {
39+
return true;
40+
}
41+
}

PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-database/src/main/java/com/microsoft/azure/toolkit/intellij/database/postgre/IntellijPostgreSqlActionsContributor.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@
1010
import com.microsoft.azure.toolkit.ide.common.IActionsContributor;
1111
import com.microsoft.azure.toolkit.ide.common.action.ResourceCommonActionsContributor;
1212
import com.microsoft.azure.toolkit.ide.database.postgre.PostgreSqlActionsContributor;
13+
import com.microsoft.azure.toolkit.intellij.connector.ConnectorDialog;
1314
import com.microsoft.azure.toolkit.intellij.database.IntellijDatasourceService;
15+
import com.microsoft.azure.toolkit.intellij.database.postgre.connection.PostgreSqlDatabaseResource;
16+
import com.microsoft.azure.toolkit.intellij.database.postgre.connection.PostgreSqlResourceDefinition;
1417
import com.microsoft.azure.toolkit.intellij.database.postgre.creation.CreatePostgreSqlAction;
1518
import com.microsoft.azure.toolkit.lib.common.action.AzureActionManager;
1619
import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource;
1720
import com.microsoft.azure.toolkit.lib.common.entity.IAzureResource;
18-
import com.microsoft.azure.toolkit.lib.common.messager.AzureMessager;
1921
import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation;
2022
import com.microsoft.azure.toolkit.lib.common.task.AzureTaskManager;
2123
import com.microsoft.azure.toolkit.lib.database.JdbcUrl;
@@ -36,10 +38,14 @@ public void registerHandlers(AzureActionManager am) {
3638
final BiConsumer<Object, AnActionEvent> handler = (c, e) -> CreatePostgreSqlAction.create((e.getProject()));
3739
am.registerHandler(ResourceCommonActionsContributor.CREATE, condition, handler);
3840

39-
//TODO(andxu): add service link
4041
am.<IAzureResource<?>, AnActionEvent>registerHandler(ResourceCommonActionsContributor.CONNECT, (r, e) -> r instanceof PostgreSqlServer,
41-
(r, e) -> AzureTaskManager.getInstance().runLater(() -> {
42-
AzureMessager.getMessager().info("Connect to PostgreSQL is not supported yet.", "Function not supported");
42+
(o, e) -> AzureTaskManager.getInstance().runLater(() -> {
43+
final ConnectorDialog dialog = new ConnectorDialog(e.getProject());
44+
PostgreSqlServerEntity entity = ((PostgreSqlServer) o).entity();
45+
dialog.setResource(new PostgreSqlDatabaseResource(((PostgreSqlServer) o).databasesV2().get(0),
46+
entity.getAdministratorLoginName() + "@" + entity.getName(),
47+
PostgreSqlResourceDefinition.INSTANCE));
48+
dialog.show();
4349
}));
4450

4551
final BiConsumer<IAzureBaseResource<?, ?>, AnActionEvent> openDatabaseHandler = (c, e) -> openDatabaseTool(e.getProject(), (PostgreSqlServer) c);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*/
5+
package com.microsoft.azure.toolkit.intellij.database.postgre.connection;
6+
7+
import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId;
8+
import com.intellij.openapi.project.Project;
9+
import com.microsoft.azure.toolkit.intellij.connector.AzureServiceResource;
10+
import com.microsoft.azure.toolkit.intellij.connector.Password;
11+
import com.microsoft.azure.toolkit.intellij.connector.PasswordStore;
12+
import com.microsoft.azure.toolkit.intellij.connector.database.Database;
13+
import com.microsoft.azure.toolkit.intellij.connector.database.DatabaseConnectionUtils;
14+
import com.microsoft.azure.toolkit.intellij.connector.database.component.PasswordDialog;
15+
import com.microsoft.azure.toolkit.lib.common.messager.AzureMessager;
16+
import com.microsoft.azure.toolkit.lib.common.operation.AzureOperationBundle;
17+
import com.microsoft.azure.toolkit.lib.common.task.AzureTaskManager;
18+
import com.microsoft.azure.toolkit.lib.database.JdbcUrl;
19+
import com.microsoft.azure.toolkit.lib.postgre.PostgreSqlDatabase;
20+
import lombok.Getter;
21+
import lombok.Setter;
22+
import org.apache.commons.lang3.StringUtils;
23+
24+
import javax.annotation.Nonnull;
25+
import java.util.Objects;
26+
import java.util.Optional;
27+
import java.util.concurrent.atomic.AtomicReference;
28+
29+
import static com.microsoft.azure.toolkit.intellij.connector.database.DatabaseConnectionUtils.ACCESS_DENIED_ERROR_CODE;
30+
31+
@Setter
32+
@Getter
33+
public class PostgreSqlDatabaseResource extends AzureServiceResource<PostgreSqlDatabase> {
34+
35+
@Nonnull
36+
private final Database database;
37+
38+
@Override
39+
public String getName() {
40+
return database.getServerName() + "/" + database.getName();
41+
}
42+
43+
44+
public PostgreSqlDatabaseResource(PostgreSqlDatabase database, @Nonnull String username, @Nonnull Definition<PostgreSqlDatabase> definition) {
45+
super(database, definition);
46+
this.database = new Database(ResourceId.fromString(database.id()).parent().id(), database.getName());
47+
this.database.setUsername(username);
48+
}
49+
50+
public String loadPassword() {
51+
Password password = getPassword();
52+
if (Objects.nonNull(password) && password.saveType() == Password.SaveType.NEVER) {
53+
return null;
54+
}
55+
final String defName = PostgreSqlResourceDefinition.INSTANCE.getName();
56+
if (password.saveType() == Password.SaveType.FOREVER) {
57+
PasswordStore.migratePassword(this.getDataId(), this.getUsername(),
58+
defName, this.getDataId(), this.getUsername());
59+
}
60+
final String saved = PasswordStore.loadPassword(defName, this.getDataId(), this.getUsername(), password.saveType());
61+
if (password.saveType() == Password.SaveType.UNTIL_RESTART && StringUtils.isBlank(saved)) {
62+
return null;
63+
}
64+
final DatabaseConnectionUtils.ConnectResult result = DatabaseConnectionUtils.connectWithPing(this.getJdbcUrl(), this.getUsername(), saved);
65+
if (StringUtils.isNotBlank(saved) && result.isConnected()) {
66+
return saved;
67+
}
68+
if (result.getErrorCode() != ACCESS_DENIED_ERROR_CODE) {
69+
AzureMessager.getMessager().warning(result.getMessage(), "Azure Resource Connector");
70+
}
71+
return null;
72+
}
73+
74+
public String inputPassword(@Nonnull final Project project) {
75+
final AtomicReference<Password> passwordRef = new AtomicReference<>();
76+
AzureTaskManager.getInstance().runAndWait(AzureOperationBundle.title("postgre.update_password"), () -> {
77+
final PasswordDialog dialog = new PasswordDialog(project, this.database);
78+
if (dialog.showAndGet()) {
79+
final Password password = dialog.getValue();
80+
this.database.getPassword().saveType(password.saveType());
81+
PasswordStore.savePassword(this.getName(),
82+
this.getDataId(), this.database.getUsername(), password.password(), password.saveType());
83+
passwordRef.set(password);
84+
}
85+
});
86+
return Optional.ofNullable(passwordRef.get()).map(c -> String.valueOf(c.password())).orElse(null);
87+
}
88+
89+
public JdbcUrl getJdbcUrl() {
90+
return database.getJdbcUrl();
91+
}
92+
93+
public String getUsername() {
94+
return database.getUsername();
95+
}
96+
97+
public Password getPassword() {
98+
return database.getPassword();
99+
}
100+
101+
@Nonnull
102+
public Database getDatabase() {
103+
return database;
104+
}
105+
106+
public void setJdbcUrl(JdbcUrl url) {
107+
this.database.setJdbcUrl(url);
108+
}
109+
110+
public void setPassword(Password password) {
111+
this.database.setPassword(password);
112+
}
113+
114+
public void setUsername(String username) {
115+
this.database.setUsername(username);
116+
}
117+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*/
5+
6+
package com.microsoft.azure.toolkit.intellij.database.postgre.connection;
7+
8+
import com.intellij.openapi.application.PreloadingActivity;
9+
import com.intellij.openapi.progress.ProgressIndicator;
10+
import com.intellij.openapi.project.Project;
11+
import com.microsoft.azure.arm.resources.ResourceId;
12+
import com.microsoft.azure.toolkit.intellij.common.AzureFormJPanel;
13+
import com.microsoft.azure.toolkit.intellij.connector.*;
14+
import com.microsoft.azure.toolkit.intellij.connector.spring.SpringSupported;
15+
import com.microsoft.azure.toolkit.lib.Azure;
16+
import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException;
17+
import com.microsoft.azure.toolkit.lib.database.JdbcUrl;
18+
import com.microsoft.azure.toolkit.lib.postgre.AzurePostgreSql;
19+
import com.microsoft.azure.toolkit.lib.postgre.PostgreSqlDatabase;
20+
import com.microsoft.azure.toolkit.lib.postgre.PostgreSqlServer;
21+
import org.apache.commons.lang3.ArrayUtils;
22+
import org.apache.commons.lang3.StringUtils;
23+
import org.apache.commons.lang3.tuple.Pair;
24+
import org.jdom.Attribute;
25+
import org.jdom.Element;
26+
import org.jetbrains.annotations.NotNull;
27+
28+
import javax.annotation.Nonnull;
29+
import java.util.*;
30+
31+
32+
public class PostgreSqlResourceDefinition extends AzureServiceResource.Definition<PostgreSqlDatabase> implements SpringSupported<PostgreSqlDatabase> {
33+
public static final PostgreSqlResourceDefinition INSTANCE = new PostgreSqlResourceDefinition();
34+
35+
36+
private PostgreSqlResourceDefinition() {
37+
super("Azure.PostgreSQL", "Azure Database for PostgreSQL", "/icons/postgre.svg");
38+
}
39+
40+
@Override
41+
public Map<String, String> initEnv(AzureServiceResource<PostgreSqlDatabase> data, Project project) {
42+
PostgreSqlDatabaseResource resource = (PostgreSqlDatabaseResource) data;
43+
final HashMap<String, String> env = new HashMap<>();
44+
env.put(String.format("%s_URL", Connection.ENV_PREFIX), resource.getJdbcUrl().toString());
45+
env.put(String.format("%s_USERNAME", Connection.ENV_PREFIX), resource.getUsername());
46+
env.put(String.format("%s_PASSWORD", Connection.ENV_PREFIX), Optional.ofNullable(resource.loadPassword()).or(() -> Optional.ofNullable(resource.inputPassword(project))).orElse(""));
47+
return env;
48+
}
49+
50+
@Override
51+
public List<Pair<String, String>> getSpringProperties() {
52+
final List<Pair<String, String>> properties = new ArrayList<>();
53+
properties.add(Pair.of("spring.datasource.url", String.format("${%s_URL}", Connection.ENV_PREFIX)));
54+
properties.add(Pair.of("spring.datasource.username", String.format("${%s_USERNAME}", Connection.ENV_PREFIX)));
55+
properties.add(Pair.of("spring.datasource.password", String.format("${%s_PASSWORD}", Connection.ENV_PREFIX)));
56+
return properties;
57+
}
58+
59+
@Override
60+
public boolean write(@Nonnull Element resourceEle, @Nonnull Resource<PostgreSqlDatabase> paramResource) {
61+
PostgreSqlDatabaseResource resource = (PostgreSqlDatabaseResource) paramResource;
62+
final String defName = resource.getDefinition().getName();
63+
64+
final Password.SaveType saveType = resource.getPassword().saveType();
65+
resourceEle.addContent(new Element("url").setText(resource.getJdbcUrl().toString()));
66+
resourceEle.addContent(new Element("username").setText(resource.getUsername()));
67+
resourceEle.addContent(new Element("passwordSave").setText(saveType.name()));
68+
final char[] password = resource.getPassword().password();
69+
final String storedPassword = PasswordStore.loadPassword(defName, resource.getDataId(), resource.getUsername(), saveType);
70+
if (ArrayUtils.isNotEmpty(password) && !StringUtils.equals(String.valueOf(password), storedPassword)) {
71+
PasswordStore.savePassword(defName, resource.getDataId(), resource.getUsername(), resource.getPassword().password(), saveType);
72+
}
73+
74+
resourceEle.setAttribute(new Attribute("id", resource.getId()));
75+
resourceEle.addContent(new Element("dataId").addContent(resource.getDataId()));
76+
77+
return true;
78+
}
79+
80+
@Override
81+
public Resource<PostgreSqlDatabase> read(@Nonnull Element resourceEle) {
82+
final String dataId = resourceEle.getChildTextTrim("dataId");
83+
84+
if (StringUtils.isBlank(dataId)) {
85+
throw new AzureToolkitRuntimeException("Missing required dataId for postgre SQL database in service link.");
86+
}
87+
PostgreSqlDatabaseResource resource = new PostgreSqlDatabaseResource(getResource(dataId), resourceEle.getChildTextTrim("username"), this);
88+
89+
final String defName = this.getName();
90+
resource.setJdbcUrl(JdbcUrl.from(resourceEle.getChildTextTrim("url")));
91+
92+
resource.setPassword(new Password().saveType(Password.SaveType.valueOf(resourceEle.getChildTextTrim("passwordSave"))));
93+
if (resource.getPassword().saveType() == Password.SaveType.FOREVER) {
94+
PasswordStore.migratePassword(resource.getId(), resource.getUsername(), defName, resource.getId(), resource.getUsername());
95+
}
96+
final String savedPassword = PasswordStore.loadPassword(defName, resource.getId(), resource.getUsername(), resource.getPassword().saveType());
97+
if (StringUtils.isNotBlank(savedPassword)) {
98+
resource.getPassword().password(savedPassword.toCharArray());
99+
}
100+
return resource;
101+
}
102+
103+
@Override
104+
public Resource<PostgreSqlDatabase> define(PostgreSqlDatabase resource) {
105+
return new PostgreSqlDatabaseResource(resource, null, this);
106+
}
107+
108+
@Override
109+
public Resource<PostgreSqlDatabase> define(String dataId) {
110+
throw new UnsupportedOperationException("xx");
111+
}
112+
113+
@Override
114+
public PostgreSqlDatabase getResource(String dataId) {
115+
final ResourceId resourceId = ResourceId.fromString(dataId);
116+
final ResourceId serverId = resourceId.parent();
117+
final String databaseName = resourceId.name();
118+
final PostgreSqlServer postgreSqlServer = Azure.az(AzurePostgreSql.class).get(serverId.id());
119+
return postgreSqlServer.database(databaseName);
120+
}
121+
122+
@Override
123+
public AzureFormJPanel<Resource<PostgreSqlDatabase>> getResourcePanel(Project project) {
124+
return new PostgreSqlResourcePanel();
125+
}
126+
127+
public static class RegisterActivity extends PreloadingActivity {
128+
@Override
129+
public void preload(@NotNull ProgressIndicator progressIndicator) {
130+
ResourceManager.registerDefinition(INSTANCE);
131+
}
132+
}
133+
}

0 commit comments

Comments
 (0)