Skip to content

Commit c55a4b4

Browse files
committed
Merge pull request #2 from mastern2k3/master
initial
2 parents 9009a11 + 231f4a4 commit c55a4b4

File tree

8 files changed

+449
-0
lines changed

8 files changed

+449
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
.idea/
3+
out/
4+
*.jar

intelli-qs-plugin.iml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<module type="PLUGIN_MODULE" version="4">
3+
<component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/resources/META-INF/plugin.xml" />
4+
<component name="NewModuleRootManager" inherit-compiler-output="true">
5+
<exclude-output />
6+
<content url="file://$MODULE_DIR$">
7+
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
8+
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
9+
</content>
10+
<orderEntry type="inheritedJdk" />
11+
<orderEntry type="sourceFolder" forTests="false" />
12+
</component>
13+
</module>

resources/META-INF/plugin.xml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<idea-plugin version="2">
2+
<id>com.qualisystems.pythonDriverPlugin</id>
3+
<name>Quali Python Driver Uploader</name>
4+
<version>1.0</version>
5+
<vendor email="support@qualisystems.com" url="http://www.qualisystems.com/">QualiSystems</vendor>
6+
7+
<description><![CDATA[
8+
Publishes the driver project on a Quali server.<br>
9+
Make sure you have a `deployment.xml` file present in your project root.
10+
11+
]]></description>
12+
13+
<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -->
14+
<idea-version since-build="141.0"/>
15+
16+
<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html
17+
on how to target different products -->
18+
<depends>com.intellij.modules.lang</depends>
19+
20+
<extensions defaultExtensionNs="com.intellij">
21+
<!-- Add your extensions here -->
22+
</extensions>
23+
24+
<actions>
25+
<!-- Add your actions here -->
26+
<action id="QualiPublishDriverAction"
27+
class="com.qualisystems.pythonDriverPlugin.QualiPublishDriverAction"
28+
text="Publish Python Driver on CloudShell"
29+
description="Publishes the driver project on CloudShell"
30+
icon="/qs-icon.png">
31+
<add-to-group group-id="ProjectViewPopupMenu" anchor="first"/>
32+
<add-to-group group-id="RunnerActions" anchor="first"/>
33+
</action>
34+
</actions>
35+
36+
</idea-plugin>

resources/qs-icon.png

744 Bytes
Loading
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.qualisystems.pythonDriverPlugin;
2+
3+
import org.apache.commons.lang.ArrayUtils;
4+
5+
import java.util.Properties;
6+
7+
public class DriverPublisherSettings {
8+
9+
String serverRootAddress;
10+
int port;
11+
String driverUniqueName;
12+
String username;
13+
String password;
14+
String domain;
15+
String[] fileFilters;
16+
17+
private static final String[] DefaultFileFilters = new String[] { ".idea", "deployment", "deployment.xml" };
18+
19+
public static DriverPublisherSettings fromProperties(Properties deploymentProperties) throws IllegalArgumentException {
20+
21+
if (!deploymentProperties.containsKey("driverUniqueName"))
22+
throw new IllegalArgumentException("Missing `driverUniqueName` key in project's deployment.xml");
23+
24+
if (!deploymentProperties.containsKey("serverRootAddress"))
25+
throw new IllegalArgumentException("Missing `serverRootAddress` key in project's deployment.xml");
26+
27+
DriverPublisherSettings settings = new DriverPublisherSettings();
28+
29+
settings.serverRootAddress = deploymentProperties.getProperty("serverRootAddress");
30+
settings.port = Integer.parseInt(deploymentProperties.getProperty("port", "8029"));
31+
settings.driverUniqueName = deploymentProperties.getProperty("driverUniqueName");
32+
settings.username = deploymentProperties.getProperty("username", "admin");
33+
settings.password = deploymentProperties.getProperty("password", "admin");
34+
settings.domain = deploymentProperties.getProperty("domain", "Global");
35+
36+
String fileFiltersValue = deploymentProperties.getProperty("fileFilters", "");
37+
38+
String[] extraFilters = fileFiltersValue.isEmpty() ? new String[0] : fileFiltersValue.split(";");
39+
40+
settings.fileFilters = (String[])ArrayUtils.addAll(DefaultFileFilters, extraFilters);
41+
42+
return settings;
43+
}
44+
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
package com.qualisystems.pythonDriverPlugin;
2+
3+
import com.intellij.openapi.actionSystem.AnAction;
4+
import com.intellij.openapi.actionSystem.AnActionEvent;
5+
import com.intellij.openapi.actionSystem.CommonDataKeys;
6+
import com.intellij.openapi.progress.ProgressIndicator;
7+
import com.intellij.openapi.progress.ProgressManager;
8+
import com.intellij.openapi.progress.Task;
9+
import com.intellij.openapi.project.Project;
10+
import com.intellij.openapi.ui.Messages;
11+
import org.jetbrains.annotations.NotNull;
12+
13+
import java.io.*;
14+
import java.net.UnknownHostException;
15+
import java.nio.file.Files;
16+
import java.nio.file.Path;
17+
import java.nio.file.Paths;
18+
import java.util.Properties;
19+
20+
public class QualiPublishDriverAction extends AnAction {
21+
22+
public static final String DeploymentSettingsFileName = "deployment.xml";
23+
24+
@Override
25+
public void actionPerformed(AnActionEvent anActionEvent) {
26+
27+
final Project project = anActionEvent.getData(CommonDataKeys.PROJECT);
28+
29+
if (project == null) return;
30+
31+
final File deploymentSettingsFile = new File(project.getBasePath(), DeploymentSettingsFileName);
32+
33+
if (!deploymentSettingsFile.exists()) {
34+
35+
Messages.showErrorDialog(
36+
project,
37+
"Could not find deployment.xml in the project folder, cannot upload driver.",
38+
"Missing Deployment Configuration File");
39+
40+
return;
41+
}
42+
43+
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Publishing Python Driver on CloudShell") {
44+
45+
public Exception _exception;
46+
public DriverPublisherSettings _settings;
47+
48+
@Override
49+
public void onSuccess() {
50+
51+
if (_exception != null) {
52+
53+
_exception.printStackTrace();
54+
55+
if (_exception instanceof UnknownHostException)
56+
Messages.showErrorDialog(
57+
project,
58+
"Failed uploading new driver file:\n Unknown Host",
59+
"Publishing Python Driver on CloudShell");
60+
else
61+
Messages.showErrorDialog(
62+
project,
63+
"Failed uploading new driver file:\n" + _exception.toString(),
64+
"Publishing Python Driver on CloudShell");
65+
66+
return;
67+
}
68+
69+
if (_settings == null) return;
70+
71+
Messages.showInfoMessage(
72+
project,
73+
String.format("Successfully uploaded new driver file for driver `%s`", _settings.driverUniqueName),
74+
"Publishing Python Driver on CloudShell");
75+
}
76+
77+
@Override
78+
public void run(@NotNull ProgressIndicator progressIndicator) {
79+
80+
try {
81+
82+
_settings = getDeploymentSettingsFromFile(deploymentSettingsFile);
83+
84+
ResourceManagementService resourceManagementService =
85+
ResourceManagementService.OpenConnection(_settings.serverRootAddress, _settings.port, _settings.username, _settings.password, _settings.domain);
86+
87+
File zippedProjectFile = zipProjectFolder(project.getBasePath(), _settings);
88+
89+
resourceManagementService.updateDriver(_settings.driverUniqueName, zippedProjectFile);
90+
91+
} catch (Exception e) {
92+
93+
_exception = e;
94+
}
95+
}
96+
});
97+
}
98+
99+
private File zipProjectFolder(String directory, DriverPublisherSettings settings) throws IOException {
100+
101+
ZipHelper zipHelper = new ZipHelper(settings.fileFilters);
102+
103+
Path deploymentFilePath = Paths.get(directory, "deployment", settings.driverUniqueName + ".zip");
104+
105+
zipHelper.zipDir(directory, deploymentFilePath.toString());
106+
107+
return deploymentFilePath.toFile();
108+
}
109+
110+
private DriverPublisherSettings getDeploymentSettingsFromFile(File deploymentSettingsFile) throws IOException {
111+
112+
Properties properties = new Properties();
113+
114+
properties.loadFromXML(Files.newInputStream(deploymentSettingsFile.toPath()));
115+
116+
DriverPublisherSettings settings = DriverPublisherSettings.fromProperties(properties);
117+
118+
return settings;
119+
}
120+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package com.qualisystems.pythonDriverPlugin;
2+
3+
import org.w3c.dom.Document;
4+
import org.w3c.dom.NodeList;
5+
6+
import javax.xml.parsers.DocumentBuilder;
7+
import javax.xml.parsers.DocumentBuilderFactory;
8+
import java.io.DataOutputStream;
9+
import java.io.File;
10+
import java.net.HttpURLConnection;
11+
import java.net.URL;
12+
import java.net.InetAddress;
13+
import java.nio.file.Files;
14+
import java.util.Base64;
15+
16+
public class ResourceManagementService {
17+
18+
private static final String TargetServerURLFormat = "http://%s:%s/%s";
19+
20+
private static final String LoginEndpointPath = "ResourceManagerApiService/Logon";
21+
private static final String LogonRequestFormat =
22+
"<Logon>\n" +
23+
"<username>%s</username>\n" +
24+
"<password>%s</password>\n" +
25+
"<domainName>%s</domainName>\n" +
26+
"</Logon>";
27+
28+
private static final String UpdateDriverEndpointPath = "ResourceManagerApiService/UpdateDriver";
29+
private static final String UpdateDriverRequestFormat =
30+
"<UpdateDriver>\n" +
31+
"<driverName>%s</driverName>\n" +
32+
"<driverFile>%s</driverFile>\n" +
33+
"<driverFileName>%s</driverFileName>\n" +
34+
"</UpdateDriver>";
35+
36+
public static ResourceManagementService OpenConnection(String serverAddress, int port, String username, String password, String domain) throws Exception {
37+
38+
ResourceManagementService resourceManagementService = new ResourceManagementService(serverAddress, port);
39+
40+
resourceManagementService.login(username, password, domain);
41+
42+
return resourceManagementService;
43+
}
44+
45+
private void login(String username, String password, String domain) throws Exception {
46+
47+
String serverURL = String.format(TargetServerURLFormat, _serverAddress, _port, LoginEndpointPath);
48+
49+
Document doc = sendMessage(new URL(serverURL), String.format(LogonRequestFormat, username, password, domain));
50+
51+
NodeList tokenElement = doc.getElementsByTagName("Token");
52+
53+
if (tokenElement.getLength() != 1)
54+
throw new Exception("No token element in logon response");
55+
56+
_authToken = tokenElement.item(0).getAttributes().getNamedItem("Token").getTextContent();
57+
}
58+
59+
public void updateDriver(String driverName, File newDriverFile) throws Exception {
60+
61+
String base64DriverFile =
62+
Base64.getEncoder().encodeToString(Files.readAllBytes(newDriverFile.toPath()));
63+
64+
String serverURL = String.format(TargetServerURLFormat, _serverAddress, _port, UpdateDriverEndpointPath);
65+
66+
sendMessage(new URL(serverURL), String.format(UpdateDriverRequestFormat, driverName, base64DriverFile, newDriverFile.getName()));
67+
}
68+
69+
private Document sendMessage(URL requestURL, String message) throws Exception {
70+
71+
HttpURLConnection con = (HttpURLConnection) requestURL.openConnection();
72+
73+
con.setRequestMethod("POST");
74+
con.setRequestProperty("DateTimeFormat", "MM/dd/yyyy HH:mm");
75+
con.setRequestProperty("ClientTimeZoneId", "UTC");
76+
con.setRequestProperty("Content-Type", "text/xml");
77+
con.setRequestProperty("Accept", "*/*");
78+
con.setRequestProperty("Authorization", String.format("MachineName=%s;Token=%s", _hostname, _authToken));
79+
con.setRequestProperty("Host", _serverAddress + ":" + Integer.toString(_port));
80+
81+
con.setDoOutput(true);
82+
83+
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
84+
85+
wr.writeBytes(message);
86+
87+
wr.flush();
88+
wr.close();
89+
90+
int responseCode = con.getResponseCode();
91+
92+
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
93+
DocumentBuilder builder = factory.newDocumentBuilder();
94+
95+
Document responseXml = builder.parse(con.getInputStream());
96+
97+
NodeList elements = responseXml.getElementsByTagName("Error");
98+
99+
if (elements.getLength() > 0)
100+
throw new Exception(String.format("API Message: %s", elements.item(0).getTextContent()));
101+
102+
if (!isSuccessResponseCode(responseCode))
103+
throw new Exception("Error making request, Response code: " + responseCode);
104+
105+
return responseXml;
106+
}
107+
108+
private boolean isSuccessResponseCode(int responseCode) {
109+
return responseCode >= 200 && responseCode < 300;
110+
}
111+
112+
private final String _serverAddress;
113+
private final String _hostname;
114+
private final int _port;
115+
116+
private String _authToken;
117+
118+
private ResourceManagementService(String serverAddress, int port) {
119+
120+
_serverAddress = serverAddress;
121+
_port = port;
122+
123+
String hostname;
124+
125+
try {
126+
hostname = InetAddress.getLocalHost().getHostName();
127+
} catch (Exception ex) {
128+
hostname = "localhost";
129+
}
130+
131+
_hostname = hostname;
132+
}
133+
}

0 commit comments

Comments
 (0)