Skip to content

Commit 5d2c549

Browse files
authored
Merge pull request #5200 from microsoft/file-explorer/node
[Track2-Kudu-2] Implement app service file node with app service library
2 parents 6c724b5 + 3f2b7c4 commit 5d2c549

File tree

10 files changed

+290
-75
lines changed

10 files changed

+290
-75
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public void runActivity(@NotNull Project project) {
9999
this.installationID = StringUtils.isNotEmpty(hasMac) ? hasMac : GetHashMac.hash(PermanentInstallationID.get());
100100
final String userAgent = String.format(USER_AGENT, PLUGIN_VERSION,
101101
TelemetryUtils.getMachieId(dataFile, message("prefVal"), message("instID")));
102-
Azure.az().config().setLogLevel(LogLevel.NONE);
102+
Azure.az().config().setLogLevel(LogLevel.NONE.name());
103103
Azure.az().config().setUserAgent(userAgent);
104104
CommonSettings.setUserAgent(userAgent);
105105

Utils/azure-explorer-common/src/com/microsoft/tooling/msservices/helpers/IDEHelper.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package com.microsoft.tooling.msservices.helpers;
77

88
import com.google.common.util.concurrent.ListenableFuture;
9+
import com.microsoft.azure.toolkit.lib.appservice.model.AppServiceFile;
910
import com.microsoft.azure.toolkit.lib.appservice.model.AppServiceFileLegacy;
1011
import com.microsoft.azuretools.azurecommons.helpers.AzureCmdException;
1112
import com.microsoft.azuretools.azurecommons.helpers.NotNull;
@@ -143,4 +144,12 @@ default void saveAppServiceFile(@NotNull final AppServiceFileLegacy file, @NotNu
143144
default void openAppServiceFile(final AppServiceFileLegacy file, Object context) {
144145
// do nothing in default
145146
}
147+
148+
default void saveAppServiceFile(@NotNull final AppServiceFile file, @NotNull Object context, @Nullable File dest) {
149+
// do nothing in default
150+
}
151+
152+
default void openAppServiceFile(final AppServiceFile file, Object context) {
153+
// do nothing in default
154+
}
146155
}

Utils/azure-explorer-common/src/com/microsoft/tooling/msservices/serviceexplorer/azure/appservice/file/AppServiceFileNode.java

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
package com.microsoft.tooling.msservices.serviceexplorer.azure.appservice.file;
77

88
import com.microsoft.azure.management.appservice.FunctionApp;
9-
import com.microsoft.azure.toolkit.lib.appservice.file.AppServiceFileService;
10-
import com.microsoft.azure.toolkit.lib.appservice.model.AppServiceFileLegacy;
9+
import com.microsoft.azure.toolkit.lib.appservice.model.AppServiceFile;
10+
import com.microsoft.azure.toolkit.lib.appservice.service.IAppService;
1111
import com.microsoft.azure.toolkit.lib.appservice.utils.Utils;
1212
import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation;
1313
import com.microsoft.azure.toolkit.lib.common.operation.AzureOperationBundle;
@@ -19,12 +19,7 @@
1919
import com.microsoft.azuretools.telemetry.TelemetryProperties;
2020
import com.microsoft.azuretools.telemetrywrapper.EventUtil;
2121
import com.microsoft.tooling.msservices.components.DefaultLoader;
22-
import com.microsoft.tooling.msservices.serviceexplorer.AzureRefreshableNode;
23-
import com.microsoft.tooling.msservices.serviceexplorer.Node;
24-
import com.microsoft.tooling.msservices.serviceexplorer.NodeActionEvent;
25-
import com.microsoft.tooling.msservices.serviceexplorer.NodeActionListener;
26-
import com.microsoft.tooling.msservices.serviceexplorer.Sortable;
27-
import com.microsoft.tooling.msservices.serviceexplorer.azure.webapp.WebAppModule;
22+
import com.microsoft.tooling.msservices.serviceexplorer.*;
2823
import lombok.extern.java.Log;
2924
import org.apache.commons.io.FileUtils;
3025

@@ -34,16 +29,16 @@
3429

3530
@Log
3631
public class AppServiceFileNode extends AzureRefreshableNode implements TelemetryProperties {
37-
private static final String MODULE_ID = WebAppModule.class.getName();
3832
private static final long SIZE_20MB = 20 * 1024 * 1024;
39-
private final AppServiceFileService fileService;
40-
private final AppServiceFileLegacy file;
4133

42-
public AppServiceFileNode(final AppServiceFileLegacy file, final Node parent, AppServiceFileService service) {
34+
private final AppServiceFile file;
35+
private final IAppService appService;
36+
37+
public AppServiceFileNode(final AppServiceFile file, final Node parent, IAppService webApp) {
4338
super(file.getName(), file.getName(), parent, null);
4439
this.file = file;
45-
this.fileService = service;
46-
if (this.file.getType() != AppServiceFileLegacy.Type.DIRECTORY) {
40+
this.appService = webApp;
41+
if (this.file.getType() != AppServiceFile.Type.DIRECTORY) {
4742
this.addDownloadAction();
4843
}
4944
}
@@ -66,11 +61,11 @@ private void download() {
6661
@AzureOperation(name = "appservice|file.refresh", params = {"this.file.getName()"}, type = AzureOperation.Type.ACTION)
6762
protected void refreshItems() {
6863
executeWithTelemetryWrapper(TelemetryConstants.REFRESH_FILE, () -> {
69-
if (this.file.getType() != AppServiceFileLegacy.Type.DIRECTORY) {
64+
if (this.file.getType() != AppServiceFile.Type.DIRECTORY) {
7065
return;
7166
}
72-
this.fileService.getFilesInDirectory(this.file.getPath()).stream()
73-
.map(file -> new AppServiceFileNode(file, this, fileService))
67+
appService.getFilesInDirectory(this.file.getPath()).stream()
68+
.map(file -> new AppServiceFileNode(file, this, appService))
7469
.forEach(this::addChildNode);
7570
});
7671
}
@@ -82,7 +77,7 @@ private void open(final Object context) {
8277

8378
@Override
8479
public void onNodeDblClicked(Object context) {
85-
if (this.file.getType() == AppServiceFileLegacy.Type.DIRECTORY) {
80+
if (this.file.getType() == AppServiceFile.Type.DIRECTORY) {
8681
return;
8782
} else if (this.file.getSize() > SIZE_20MB) {
8883
DefaultLoader.getUIHelper().showError("File is too large, please download it first", "File is Too Large");
@@ -95,17 +90,17 @@ public void onNodeDblClicked(Object context) {
9590

9691
@Override
9792
public int getPriority() {
98-
return this.file.getType() == AppServiceFileLegacy.Type.DIRECTORY ? Sortable.HIGH_PRIORITY : Sortable.DEFAULT_PRIORITY;
93+
return this.file.getType() == AppServiceFile.Type.DIRECTORY ? Sortable.HIGH_PRIORITY : Sortable.DEFAULT_PRIORITY;
9994
}
10095

10196
@Override
10297
public Icon getIcon() {
103-
return DefaultLoader.getIdeHelper().getFileTypeIcon(this.file.getName(), this.file.getType() == AppServiceFileLegacy.Type.DIRECTORY);
98+
return DefaultLoader.getIdeHelper().getFileTypeIcon(this.file.getName(), this.file.getType() == AppServiceFile.Type.DIRECTORY);
10499
}
105100

106101
@Override
107102
public String getToolTip() {
108-
return file.getType() == AppServiceFileLegacy.Type.DIRECTORY ?
103+
return file.getType() == AppServiceFile.Type.DIRECTORY ?
109104
String.format("Type: %s Date modified: %s", file.getMime(), file.getMtime()) :
110105
String.format("Type: %s Size: %s Date modified: %s", file.getMime(), FileUtils.byteCountToDisplaySize(file.getSize()), file.getMtime());
111106
}

Utils/azure-explorer-common/src/com/microsoft/tooling/msservices/serviceexplorer/azure/appservice/file/AppServiceLogFilesRootNode.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,18 @@
55

66
package com.microsoft.tooling.msservices.serviceexplorer.azure.appservice.file;
77

8-
import com.microsoft.azure.management.appservice.WebAppBase;
8+
import com.microsoft.azure.toolkit.lib.appservice.service.IAppService;
99
import com.microsoft.azuretools.azurecommons.helpers.NotNull;
1010
import com.microsoft.tooling.msservices.serviceexplorer.Node;
1111

12-
import java.util.function.Supplier;
13-
1412
public class AppServiceLogFilesRootNode extends AppServiceUserFilesRootNode {
1513
private static final String MODULE_NAME = "Logs";
1614
private static final String ROOT_PATH = "/LogFiles";
1715

18-
public AppServiceLogFilesRootNode(final Node parent, final String subscriptionId, final WebAppBase app) {
16+
public AppServiceLogFilesRootNode(final Node parent, final String subscriptionId, final IAppService app) {
1917
super(MODULE_NAME, parent, subscriptionId, app);
2018
}
2119

22-
public AppServiceLogFilesRootNode(final Node parent, final String subscriptionId, final Supplier<WebAppBase> supplier) {
23-
super(MODULE_NAME, parent, subscriptionId, supplier);
24-
}
25-
2620
@NotNull
2721
@Override
2822
protected String getRootPath() {

Utils/azure-explorer-common/src/com/microsoft/tooling/msservices/serviceexplorer/azure/appservice/file/AppServiceUserFilesRootNode.java

Lines changed: 10 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55

66
package com.microsoft.tooling.msservices.serviceexplorer.azure.appservice.file;
77

8-
import com.microsoft.azure.management.appservice.FunctionApp;
9-
import com.microsoft.azure.management.appservice.WebAppBase;
10-
import com.microsoft.azure.toolkit.lib.appservice.file.AppServiceFileService;
8+
import com.microsoft.azure.toolkit.lib.appservice.service.IAppService;
119
import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation;
1210
import com.microsoft.azuretools.azurecommons.helpers.NotNull;
1311
import com.microsoft.azuretools.azurecommons.helpers.Nullable;
@@ -23,39 +21,24 @@
2321
import javax.swing.*;
2422
import java.util.Collections;
2523
import java.util.Map;
26-
import java.util.Objects;
27-
import java.util.function.Supplier;
2824

2925
public class AppServiceUserFilesRootNode extends AzureRefreshableNode implements TelemetryProperties {
3026
private static final String MODULE_ID = WebAppModule.class.getName();
3127
private static final String MODULE_NAME = "Files";
3228
private static final String ROOT_PATH = "/site/wwwroot";
3329

34-
protected WebAppBase app;
35-
protected Supplier<WebAppBase> supplier;
36-
30+
protected IAppService appService;
3731
protected final String subscriptionId;
38-
private AppServiceFileService fileService;
39-
40-
public AppServiceUserFilesRootNode(final Node parent, final String subscriptionId, final WebAppBase app) {
41-
this(MODULE_NAME, parent, subscriptionId, app);
42-
}
43-
44-
public AppServiceUserFilesRootNode(final String name, final Node parent, final String subscriptionId, final WebAppBase app) {
45-
super(MODULE_ID, name, parent, null);
46-
this.subscriptionId = subscriptionId;
47-
this.app = app;
48-
}
4932

5033
// Lazy load for WebAppBase
51-
public AppServiceUserFilesRootNode(final Node parent, final String subscriptionId, final Supplier<WebAppBase> supplier) {
52-
this(MODULE_NAME, parent, subscriptionId, supplier);
34+
public AppServiceUserFilesRootNode(final Node parent, final String subscriptionId, final IAppService appService) {
35+
this(MODULE_NAME, parent, subscriptionId, appService);
5336
}
5437

55-
public AppServiceUserFilesRootNode(final String name, final Node parent, final String subscriptionId, final Supplier<WebAppBase> supplier) {
38+
public AppServiceUserFilesRootNode(final String name, final Node parent, final String subscriptionId, final IAppService appService) {
5639
super(MODULE_ID, name, parent, null);
5740
this.subscriptionId = subscriptionId;
58-
this.supplier = supplier;
41+
this.appService = appService;
5942
}
6043

6144
@Override
@@ -67,9 +50,8 @@ public void removeNode(final String sid, final String name, Node node) {
6750
protected void refreshItems() {
6851
EventUtil.executeWithLog(getServiceName(), TelemetryConstants.LIST_FILE, operation -> {
6952
operation.trackProperty(TelemetryConstants.SUBSCRIPTIONID, subscriptionId);
70-
final AppServiceFileService service = this.getFileService();
71-
service.getFilesInDirectory(getRootPath()).stream()
72-
.map(file -> new AppServiceFileNode(file, this, service))
53+
appService.getFilesInDirectory(getRootPath()).stream()
54+
.map(file -> new AppServiceFileNode(file, this, appService))
7355
.forEach(this::addChildNode);
7456
});
7557
}
@@ -79,23 +61,10 @@ protected String getRootPath() {
7961
return ROOT_PATH;
8062
}
8163

82-
public AppServiceFileService getFileService() {
83-
if (Objects.isNull(this.fileService)) {
84-
this.fileService = AppServiceFileService.forApp(getTargetAppService());
85-
}
86-
return this.fileService;
87-
}
88-
89-
private WebAppBase getTargetAppService() {
90-
if (app == null) {
91-
app = supplier.get();
92-
}
93-
return app;
94-
}
95-
9664
@Override
9765
public String getServiceName() {
98-
return (app != null && app instanceof FunctionApp) ? TelemetryConstants.FUNCTION : TelemetryConstants.WEBAPP;
66+
// todo: update after function track2 migration
67+
return TelemetryConstants.WEBAPP;
9968
}
10069

10170
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
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.tooling.msservices.serviceexplorer.azure.appservice.file.legacy;
7+
8+
import com.microsoft.azure.management.appservice.FunctionApp;
9+
import com.microsoft.azure.toolkit.lib.appservice.file.AppServiceFileService;
10+
import com.microsoft.azure.toolkit.lib.appservice.model.AppServiceFileLegacy;
11+
import com.microsoft.azure.toolkit.lib.appservice.utils.Utils;
12+
import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation;
13+
import com.microsoft.azure.toolkit.lib.common.operation.AzureOperationBundle;
14+
import com.microsoft.azure.toolkit.lib.common.operation.IAzureOperationTitle;
15+
import com.microsoft.azure.toolkit.lib.common.task.AzureTask;
16+
import com.microsoft.azure.toolkit.lib.common.task.AzureTaskManager;
17+
import com.microsoft.azuretools.telemetry.AppInsightsConstants;
18+
import com.microsoft.azuretools.telemetry.TelemetryConstants;
19+
import com.microsoft.azuretools.telemetry.TelemetryProperties;
20+
import com.microsoft.azuretools.telemetrywrapper.EventUtil;
21+
import com.microsoft.tooling.msservices.components.DefaultLoader;
22+
import com.microsoft.tooling.msservices.serviceexplorer.AzureRefreshableNode;
23+
import com.microsoft.tooling.msservices.serviceexplorer.Node;
24+
import com.microsoft.tooling.msservices.serviceexplorer.NodeActionEvent;
25+
import com.microsoft.tooling.msservices.serviceexplorer.NodeActionListener;
26+
import com.microsoft.tooling.msservices.serviceexplorer.Sortable;
27+
import com.microsoft.tooling.msservices.serviceexplorer.azure.webapp.WebAppModule;
28+
import lombok.extern.java.Log;
29+
import org.apache.commons.io.FileUtils;
30+
31+
import javax.swing.*;
32+
import java.util.Collections;
33+
import java.util.Map;
34+
35+
@Deprecated
36+
@Log
37+
public class AppServiceFileNode extends AzureRefreshableNode implements TelemetryProperties {
38+
private static final String MODULE_ID = WebAppModule.class.getName();
39+
private static final long SIZE_20MB = 20 * 1024 * 1024;
40+
private final AppServiceFileService fileService;
41+
private final AppServiceFileLegacy file;
42+
43+
public AppServiceFileNode(final AppServiceFileLegacy file, final Node parent, AppServiceFileService service) {
44+
super(file.getName(), file.getName(), parent, null);
45+
this.file = file;
46+
this.fileService = service;
47+
if (this.file.getType() != AppServiceFileLegacy.Type.DIRECTORY) {
48+
this.addDownloadAction();
49+
}
50+
}
51+
52+
private void addDownloadAction() {
53+
this.addAction("Download", new NodeActionListener() {
54+
@Override
55+
protected void actionPerformed(final NodeActionEvent e) {
56+
download();
57+
}
58+
});
59+
}
60+
61+
@AzureOperation(name = "appservice|file.download", params = {"this.file.getName()"}, type = AzureOperation.Type.ACTION)
62+
private void download() {
63+
DefaultLoader.getIdeHelper().saveAppServiceFile(file, getProject(), null);
64+
}
65+
66+
@Override
67+
@AzureOperation(name = "appservice|file.refresh", params = {"this.file.getName()"}, type = AzureOperation.Type.ACTION)
68+
protected void refreshItems() {
69+
executeWithTelemetryWrapper(TelemetryConstants.REFRESH_FILE, () -> {
70+
if (this.file.getType() != AppServiceFileLegacy.Type.DIRECTORY) {
71+
return;
72+
}
73+
this.fileService.getFilesInDirectory(this.file.getPath()).stream()
74+
.map(file -> new AppServiceFileNode(file, this, fileService))
75+
.forEach(this::addChildNode);
76+
});
77+
}
78+
79+
@AzureOperation(name = "appservice|file.open", params = {"this.file.getName()"}, type = AzureOperation.Type.ACTION)
80+
private void open(final Object context) {
81+
executeWithTelemetryWrapper(TelemetryConstants.OPEN_FILE, () -> DefaultLoader.getIdeHelper().openAppServiceFile(this.file, context));
82+
}
83+
84+
@Override
85+
public void onNodeDblClicked(Object context) {
86+
if (this.file.getType() == AppServiceFileLegacy.Type.DIRECTORY) {
87+
return;
88+
} else if (this.file.getSize() > SIZE_20MB) {
89+
DefaultLoader.getUIHelper().showError("File is too large, please download it first", "File is Too Large");
90+
return;
91+
}
92+
final Runnable runnable = () -> open(context);
93+
final IAzureOperationTitle title = AzureOperationBundle.title("appservice|file.get_content", file.getName(), file.getApp().name());
94+
AzureTaskManager.getInstance().runInBackground(new AzureTask(this.getProject(), title, false, runnable));
95+
}
96+
97+
@Override
98+
public int getPriority() {
99+
return this.file.getType() == AppServiceFileLegacy.Type.DIRECTORY ? Sortable.HIGH_PRIORITY : Sortable.DEFAULT_PRIORITY;
100+
}
101+
102+
@Override
103+
public Icon getIcon() {
104+
return DefaultLoader.getIdeHelper().getFileTypeIcon(this.file.getName(), this.file.getType() == AppServiceFileLegacy.Type.DIRECTORY);
105+
}
106+
107+
@Override
108+
public String getToolTip() {
109+
return file.getType() == AppServiceFileLegacy.Type.DIRECTORY ?
110+
String.format("Type: %s Date modified: %s", file.getMime(), file.getMtime()) :
111+
String.format("Type: %s Size: %s Date modified: %s", file.getMime(), FileUtils.byteCountToDisplaySize(file.getSize()), file.getMtime());
112+
}
113+
114+
@Override
115+
public String getServiceName() {
116+
return file.getApp() instanceof FunctionApp ? TelemetryConstants.FUNCTION : TelemetryConstants.WEBAPP;
117+
}
118+
119+
@Override
120+
public Map<String, String> toProperties() {
121+
return Collections.singletonMap(AppInsightsConstants.SubscriptionId, Utils.getSubscriptionId(file.getApp().id()));
122+
}
123+
124+
// todo: replace with AzureOperation when custom properties is supported for AzureOperation
125+
private void executeWithTelemetryWrapper(final String operationName, Runnable runnable) {
126+
EventUtil.executeWithLog(getServiceName(), operationName, operation -> {
127+
operation.trackProperty(TelemetryConstants.SUBSCRIPTIONID, Utils.getSubscriptionId(file.getApp().id()));
128+
runnable.run();
129+
});
130+
}
131+
}

0 commit comments

Comments
 (0)