Skip to content

Commit d346014

Browse files
committed
Merge branch 'qianjin-sqlserver' of https://github.com/microsoft/azure-tools-for-java into qianjin-sqlserver
2 parents a0b9beb + bfc6d9a commit d346014

File tree

13 files changed

+371
-8
lines changed

13 files changed

+371
-8
lines changed

PluginsAndFeatures/azure-toolkit-for-intellij/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ dependencies {
211211
compile group: 'com.jcraft', name: 'jsch', version: '0.1.55'
212212
compile group: 'com.neovisionaries', name: 'nv-websocket-client', version: '2.9'
213213
compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.23'
214+
compile group: 'com.microsoft.sqlserver', name: 'mssql-jdbc', version: '9.3.1.jre8-preview'
214215

215216
testCompile 'junit:junit:4.13'
216217
testCompile 'info.cukes:cucumber-junit:1.2.6'

PluginsAndFeatures/azure-toolkit-for-intellij/resources/META-INF/plugin.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
<fileEditorProvider implementation="com.microsoft.azure.toolkit.intellij.arm.ResourceTemplateViewProvider"/>
9696
<fileEditorProvider implementation="com.microsoft.azure.toolkit.intellij.springcloud.properties.SpringCloudAppPropertiesEditorProvider"/>
9797
<fileEditorProvider implementation="com.microsoft.azure.toolkit.intellij.mysql.MySQLPropertyViewProvider"/>
98+
<fileEditorProvider implementation="com.microsoft.azure.toolkit.intellij.sqlserver.properties.SqlServerPropertyViewProvider"/>
9899
<toolWindow
99100
anchor="left"
100101
factoryClass="com.microsoft.intellij.ui.ServerExplorerToolWindowFactory"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
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.common;
7+
8+
import com.intellij.ide.plugins.PluginManagerCore;
9+
import com.intellij.openapi.extensions.PluginId;
10+
import com.intellij.openapi.project.Project;
11+
import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException;
12+
import lombok.Builder;
13+
import lombok.Getter;
14+
import org.apache.commons.lang3.reflect.MethodUtils;
15+
16+
import java.lang.reflect.Constructor;
17+
import java.lang.reflect.InvocationTargetException;
18+
19+
public class IntellijDatasourceService {
20+
21+
private static final String DATABASE_TOOLS_PLUGIN_ID = "com.intellij.database";
22+
private static final String NOT_SUPPORT_ERROR_MESSAGE = "detect database plugin in your IDE.";
23+
private static final String NOT_SUPPORT_ERROR_ACTION = "note this action is only supported in Intellij Ultimate edition.";
24+
private static final String ERROR_MESSAGE_PATTERN = "Failed to open datasource management dialog for %s";
25+
private static final String ERROR_ACTION = "please try again.";
26+
private static final IntellijDatasourceService instance = new IntellijDatasourceService();
27+
28+
public static IntellijDatasourceService getInstance() {
29+
return IntellijDatasourceService.instance;
30+
}
31+
32+
private IntellijDatasourceService() {
33+
}
34+
35+
public void openDataSourceManagerDialog(Project project, DatasourceProperties properties) {
36+
if (PluginManagerCore.getPlugin(PluginId.findId(DATABASE_TOOLS_PLUGIN_ID)) == null) {
37+
throw new AzureToolkitRuntimeException(NOT_SUPPORT_ERROR_MESSAGE, NOT_SUPPORT_ERROR_ACTION);
38+
}
39+
Object registry = getDataSourceRegistry(project, properties);
40+
Object dbPsiFacade = getDbPsiFacade(project, properties);
41+
try {
42+
Object builder = MethodUtils.invokeMethod(registry, "getBuilder");
43+
MethodUtils.invokeMethod(builder, true, "withName", properties.getName());
44+
MethodUtils.invokeMethod(builder, true, "withDriverClass", properties.getDriverClassName());
45+
MethodUtils.invokeMethod(builder, true, "withUrl", properties.getUrl());
46+
MethodUtils.invokeMethod(builder, true, "withUser", properties.getUsername());
47+
MethodUtils.invokeMethod(builder, true, "commit");
48+
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
49+
throw new AzureToolkitRuntimeException(String.format(ERROR_MESSAGE_PATTERN, properties.getName()), ERROR_ACTION);
50+
}
51+
showDataSourceManagerDialog(dbPsiFacade, registry, properties);
52+
}
53+
54+
private Object getDataSourceRegistry(Project project, DatasourceProperties properties) {
55+
try {
56+
Class[] parameterTypes = {Project.class};
57+
Class dataSourceRegistryClazz = Class.forName("com.intellij.database.autoconfig.DataSourceRegistry");
58+
Constructor constructor = dataSourceRegistryClazz.getConstructor(parameterTypes);
59+
return constructor.newInstance(project);
60+
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
61+
throw new AzureToolkitRuntimeException(String.format(ERROR_MESSAGE_PATTERN, properties.getName()), ERROR_ACTION);
62+
}
63+
}
64+
65+
private Object getDbPsiFacade(Object project, DatasourceProperties properties) {
66+
try {
67+
Class dbPsiFacadeClass = Class.forName("com.intellij.database.psi.DbPsiFacade");
68+
return MethodUtils.invokeStaticMethod(dbPsiFacadeClass, "getInstance", project);
69+
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
70+
throw new AzureToolkitRuntimeException(String.format(ERROR_MESSAGE_PATTERN, properties.getName()), ERROR_ACTION);
71+
}
72+
}
73+
74+
private void showDataSourceManagerDialog(Object dbPsiFacade, Object registry, DatasourceProperties properties) {
75+
try {
76+
Class dataSourceManagerDialogClazz = Class.forName("com.intellij.database.view.ui.DataSourceManagerDialog");
77+
MethodUtils.invokeStaticMethod(dataSourceManagerDialogClazz, "showDialog", dbPsiFacade, registry);
78+
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
79+
throw new AzureToolkitRuntimeException(String.format(ERROR_MESSAGE_PATTERN, properties.getName()), ERROR_ACTION);
80+
}
81+
}
82+
83+
@Builder
84+
@Getter
85+
public static class DatasourceProperties {
86+
private String name;
87+
@Builder.Default
88+
private String driverClassName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
89+
private String url;
90+
private String username;
91+
}
92+
}

PluginsAndFeatures/azure-toolkit-for-intellij/src/com/microsoft/azure/toolkit/intellij/sqlserver/CreateSqlServerAction.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation;
1313
import com.microsoft.azure.toolkit.lib.common.task.AzureTask;
1414
import com.microsoft.azure.toolkit.lib.common.task.AzureTaskManager;
15+
import com.microsoft.azure.toolkit.intellij.sqlserver.task.CreateSqlServerTask;
1516
import com.microsoft.azure.toolkit.lib.sqlserver.SqlServerConfig;
16-
import com.microsoft.azure.toolkit.lib.sqlserver.SqlServerService;
1717
import com.microsoft.azure.toolkit.lib.sqlserver.service.ISqlServer;
1818
import com.microsoft.azuretools.authmanage.AuthMethodManager;
1919
import com.microsoft.azuretools.utils.AzureUIRefreshCore;
@@ -74,7 +74,7 @@ private void createSqlServer(final SqlServerConfig config, SqlServerCreationDial
7474
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
7575
indicator.setIndeterminate(true);
7676
DefaultLoader.getIdeHelper().invokeLater(dialog::close);
77-
ISqlServer server = SqlServerService.getInstance().create(config);
77+
ISqlServer server = new CreateSqlServerTask(config).execute();
7878
refreshAzureExplorer(server);
7979
};
8080
String progressMessage = Node.getProgressMessage(AzureActionEnum.CREATE.getDoingName(), SqlServerModule.MODULE_NAME, config.getServerName());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
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.sqlserver;
7+
8+
import com.intellij.openapi.project.Project;
9+
import com.microsoft.azure.toolkit.intellij.common.IntellijDatasourceService;
10+
import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation;
11+
import com.microsoft.azure.toolkit.lib.common.utils.JdbcUrl;
12+
import com.microsoft.azure.toolkit.lib.sqlserver.model.SqlServerEntity;
13+
import com.microsoft.azuretools.ActionConstants;
14+
import com.microsoft.azuretools.authmanage.AuthMethodManager;
15+
import com.microsoft.intellij.AzurePlugin;
16+
import com.microsoft.intellij.actions.AzureSignInAction;
17+
import com.microsoft.intellij.util.AzureLoginHelper;
18+
import com.microsoft.tooling.msservices.components.DefaultLoader;
19+
import com.microsoft.tooling.msservices.helpers.Name;
20+
import com.microsoft.tooling.msservices.serviceexplorer.AzureIconSymbol;
21+
import com.microsoft.tooling.msservices.serviceexplorer.NodeActionEvent;
22+
import com.microsoft.tooling.msservices.serviceexplorer.NodeActionListener;
23+
import com.microsoft.tooling.msservices.serviceexplorer.azure.sqlserver.SqlServerNode;
24+
25+
import static com.microsoft.intellij.ui.messages.AzureBundle.message;
26+
27+
@Name(OpenSqlServerByToolsAction.ACTION_NAME)
28+
public class OpenSqlServerByToolsAction extends NodeActionListener {
29+
30+
public static final String ACTION_NAME = "Open by Database Tools";
31+
private static final String NAME_PREFIX = "SQL Server - %s";
32+
private static final String DEFAULT_DRIVER_CLASS_NAME = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
33+
34+
private final SqlServerNode node;
35+
private final Project project;
36+
37+
public OpenSqlServerByToolsAction(SqlServerNode node) {
38+
super();
39+
this.node = node;
40+
this.project = (Project) node.getProject();
41+
}
42+
43+
@Override
44+
public AzureIconSymbol getIconSymbol() {
45+
return AzureIconSymbol.SqlServer.CONNECT_TO_SERVER;
46+
}
47+
48+
@Override
49+
public void actionPerformed(NodeActionEvent e) {
50+
AzureSignInAction.doSignIn(AuthMethodManager.getInstance(), project).subscribe((isSuccess) -> {
51+
this.doActionPerformed(e, isSuccess, project);
52+
});
53+
}
54+
55+
@Override
56+
protected String getServiceName(NodeActionEvent event) {
57+
return ActionConstants.parse(ActionConstants.SqlServer.CONNECT_TO_SERVER).getServiceName();
58+
}
59+
60+
@Override
61+
protected String getOperationName(NodeActionEvent event) {
62+
return ActionConstants.parse(ActionConstants.SqlServer.CONNECT_TO_SERVER).getOperationName();
63+
}
64+
65+
@AzureOperation(name = ActionConstants.SqlServer.CONNECT_TO_SERVER, type = AzureOperation.Type.ACTION)
66+
private void doActionPerformed(NodeActionEvent e, boolean isLoggedIn, Project project) {
67+
try {
68+
if (!isLoggedIn ||
69+
!AzureLoginHelper.isAzureSubsAvailableOrReportError(message("common.error.signIn"))) {
70+
return;
71+
}
72+
} catch (final Exception ex) {
73+
AzurePlugin.log(message("common.error.signIn"), ex);
74+
DefaultLoader.getUIHelper().showException(message("common.error.signIn"), ex, message("common.error.signIn"), false, true);
75+
}
76+
SqlServerEntity entity = node.getServer().entity();
77+
IntellijDatasourceService.DatasourceProperties properties = IntellijDatasourceService.DatasourceProperties.builder()
78+
.name(String.format(NAME_PREFIX, entity.getName()))
79+
.driverClassName(DEFAULT_DRIVER_CLASS_NAME)
80+
.url(JdbcUrl.sqlserver(entity.getFullyQualifiedDomainName()).toString())
81+
.username(entity.getAdministratorLoginName() + "@" + entity.getName())
82+
.build();
83+
IntellijDatasourceService.getInstance().openDataSourceManagerDialog(project, properties);
84+
}
85+
86+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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.sqlserver.properties;
7+
8+
import com.intellij.openapi.fileEditor.FileEditor;
9+
import com.intellij.openapi.fileEditor.FileEditorPolicy;
10+
import com.intellij.openapi.fileEditor.FileEditorProvider;
11+
import com.intellij.openapi.project.DumbAware;
12+
import com.intellij.openapi.project.Project;
13+
import com.intellij.openapi.vfs.VirtualFile;
14+
import org.jetbrains.annotations.NotNull;
15+
16+
public class SqlServerPropertyViewProvider implements FileEditorProvider, DumbAware {
17+
18+
public static final String TYPE = "SQL_SERVER_PROPERTY_VIEW";
19+
20+
@Override
21+
public boolean accept(@NotNull Project project, @NotNull VirtualFile virtualFile) {
22+
return virtualFile.getFileType().getName().equals(TYPE);
23+
}
24+
25+
@NotNull
26+
@Override
27+
public FileEditor createEditor(@NotNull Project project, @NotNull VirtualFile virtualFile) {
28+
return new SqlServerPropertyView();
29+
}
30+
31+
@NotNull
32+
@Override
33+
public String getEditorTypeId() {
34+
return TYPE;
35+
}
36+
37+
@NotNull
38+
@Override
39+
public FileEditorPolicy getPolicy() {
40+
return FileEditorPolicy.HIDE_DEFAULT_EDITOR;
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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.sqlserver.task;
7+
8+
import com.microsoft.azure.toolkit.intellij.common.Draft;
9+
import com.microsoft.azure.toolkit.lib.Azure;
10+
import com.microsoft.azure.toolkit.lib.common.model.Region;
11+
import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation;
12+
import com.microsoft.azure.toolkit.lib.resource.AzureGroup;
13+
import com.microsoft.azure.toolkit.lib.resource.ResourceGroupEntity;
14+
import com.microsoft.azure.toolkit.lib.sqlserver.SqlServerConfig;
15+
import com.microsoft.azure.toolkit.lib.sqlserver.model.SqlServerEntity;
16+
import com.microsoft.azure.toolkit.lib.sqlserver.service.AzureSqlServer;
17+
import com.microsoft.azure.toolkit.lib.sqlserver.service.ISqlServer;
18+
import com.microsoft.azuretools.ActionConstants;
19+
import com.microsoft.azuretools.telemetry.TelemetryConstants;
20+
import com.microsoft.azuretools.telemetrywrapper.ErrorType;
21+
import com.microsoft.azuretools.telemetrywrapper.EventType;
22+
import com.microsoft.azuretools.telemetrywrapper.EventUtil;
23+
import com.microsoft.azuretools.telemetrywrapper.Operation;
24+
import com.microsoft.azuretools.telemetrywrapper.TelemetryManager;
25+
26+
import java.util.Collections;
27+
28+
public class CreateSqlServerTask {
29+
30+
private final SqlServerConfig config;
31+
32+
public CreateSqlServerTask(SqlServerConfig config) {
33+
this.config = config;
34+
}
35+
36+
@AzureOperation(
37+
name = "sqlserver.create",
38+
params = {
39+
"config.getServerName()",
40+
"config.getSubscription().displayName()"
41+
},
42+
type = AzureOperation.Type.SERVICE
43+
)
44+
public ISqlServer execute() {
45+
final Operation operation = TelemetryManager.createOperation(ActionConstants.MySQL.CREATE);
46+
try {
47+
operation.start();
48+
final String subscriptionId = config.getSubscription().subscriptionId();
49+
EventUtil.logEvent(EventType.info, operation, Collections.singletonMap(TelemetryConstants.SUBSCRIPTIONID, subscriptionId));
50+
// create resource group if necessary.
51+
if (config.getResourceGroup() instanceof Draft) {
52+
ResourceGroupEntity newResourceGroup = Azure.az(AzureGroup.class)
53+
.subscription(subscriptionId).create(config.getResourceGroup().name(), config.getRegion().getName());
54+
config.setResourceGroup(newResourceGroup);
55+
}
56+
// create sql server
57+
SqlServerEntity entity = this.fromConfig(this.config);
58+
return Azure.az(AzureSqlServer.class).sqlServer(entity).create()
59+
.withAdministratorLoginPassword(String.valueOf(config.getPassword()))
60+
.commit();
61+
} catch (final RuntimeException e) {
62+
EventUtil.logError(operation, ErrorType.systemError, e, null, null);
63+
throw e;
64+
} finally {
65+
operation.complete();
66+
}
67+
}
68+
69+
private SqlServerEntity fromConfig(SqlServerConfig config) {
70+
return SqlServerEntity.builder().name(config.getServerName()).subscriptionId(config.getSubscription().subscriptionId())
71+
.resourceGroup(config.getResourceGroup().name()).region(Region.fromName(config.getRegion().getName())).administratorLoginName(config.getAdminUsername())
72+
.enableAccessFromAzureServices(config.isAllowAccessFromAzureServices()).enableAccessFromLocalMachine(config.isAllowAccessFromLocalMachine())
73+
.build();
74+
}
75+
76+
}

PluginsAndFeatures/azure-toolkit-for-intellij/src/com/microsoft/intellij/helpers/UIHelperImpl.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
import com.microsoft.azure.toolkit.intellij.redis.RedisCachePropertyView;
3636
import com.microsoft.azure.toolkit.intellij.redis.RedisCachePropertyViewProvider;
3737
import com.microsoft.azure.toolkit.intellij.springcloud.properties.SpringCloudAppPropertiesEditorProvider;
38+
import com.microsoft.azure.toolkit.intellij.sqlserver.properties.SqlServerPropertyViewProvider;
39+
import com.microsoft.azure.toolkit.intellij.sqlserver.properties.SqlServerPropertyView;
3840
import com.microsoft.azure.toolkit.intellij.webapp.DeploymentSlotPropertyViewProvider;
3941
import com.microsoft.azure.toolkit.intellij.webapp.WebAppPropertyViewProvider;
4042
import com.microsoft.azure.toolkit.intellij.webapp.docker.ContainerRegistryPropertyView;
@@ -44,6 +46,7 @@
4446
import com.microsoft.azure.toolkit.lib.springcloud.AzureSpringCloud;
4547
import com.microsoft.azure.toolkit.lib.springcloud.SpringCloudApp;
4648
import com.microsoft.azure.toolkit.lib.springcloud.SpringCloudCluster;
49+
import com.microsoft.azure.toolkit.lib.sqlserver.model.SqlServerEntity;
4750
import com.microsoft.azuretools.ActionConstants;
4851
import com.microsoft.azuretools.azurecommons.helpers.AzureCmdException;
4952
import com.microsoft.azuretools.azurecommons.helpers.NotNull;
@@ -77,6 +80,7 @@
7780
import com.microsoft.tooling.msservices.serviceexplorer.azure.mysql.MySQLNode;
7881
import com.microsoft.tooling.msservices.serviceexplorer.azure.rediscache.RedisCacheNode;
7982
import com.microsoft.tooling.msservices.serviceexplorer.azure.springcloud.SpringCloudAppNode;
83+
import com.microsoft.tooling.msservices.serviceexplorer.azure.sqlserver.SqlServerNode;
8084
import com.microsoft.tooling.msservices.serviceexplorer.azure.webapp.WebAppNode;
8185
import com.microsoft.tooling.msservices.serviceexplorer.azure.webapp.deploymentslot.DeploymentSlotNode;
8286
import org.apache.commons.lang.ArrayUtils;
@@ -601,6 +605,31 @@ public void openMySQLPropertyView(@NotNull MySQLNode node) {
601605
});
602606
}
603607

608+
@Override
609+
public void openSqlServerPropertyView(@NotNull SqlServerNode node) {
610+
EventUtil.executeWithLog(ActionConstants.SqlServer.SHOW_PROPERTIES, (operation) -> {
611+
String name = node.getName();
612+
String subscriptionId = node.getSubscriptionId();
613+
String nodeId = node.getId();
614+
final FileEditorManager fileEditorManager = getFileEditorManager(subscriptionId, nodeId, (Project) node.getProject());
615+
if (fileEditorManager == null) {
616+
return;
617+
}
618+
LightVirtualFile itemVirtualFile = searchExistingFile(fileEditorManager, SqlServerPropertyViewProvider.TYPE, nodeId);
619+
if (itemVirtualFile == null) {
620+
itemVirtualFile = createVirtualFile(name, subscriptionId, nodeId);
621+
itemVirtualFile.setFileType(new AzureFileType(SqlServerPropertyViewProvider.TYPE, AzureIconLoader.loadIcon(AzureIconSymbol.SqlServer.MODULE)));
622+
}
623+
FileEditor[] editors = fileEditorManager.openFile(itemVirtualFile, true, true);
624+
for (FileEditor editor : editors) {
625+
if (editor.getName().equals(SqlServerPropertyView.ID) && editor instanceof SqlServerPropertyView) {
626+
SqlServerEntity entity = node.getServer().entity();
627+
((SqlServerPropertyView) editor).onReadProperty(subscriptionId, entity.getResourceGroup(), entity.getName());
628+
}
629+
}
630+
});
631+
}
632+
604633
@Nullable
605634
@Override
606635
public <T extends StorageServiceTreeItem> Object getOpenedFile(@NotNull Object projectObject,

0 commit comments

Comments
 (0)