-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from mastern2k3/master
initial
- Loading branch information
Showing
8 changed files
with
449 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
.idea/ | ||
out/ | ||
*.jar |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<module type="PLUGIN_MODULE" version="4"> | ||
<component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/resources/META-INF/plugin.xml" /> | ||
<component name="NewModuleRootManager" inherit-compiler-output="true"> | ||
<exclude-output /> | ||
<content url="file://$MODULE_DIR$"> | ||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> | ||
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" /> | ||
</content> | ||
<orderEntry type="inheritedJdk" /> | ||
<orderEntry type="sourceFolder" forTests="false" /> | ||
</component> | ||
</module> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<idea-plugin version="2"> | ||
<id>com.qualisystems.pythonDriverPlugin</id> | ||
<name>Quali Python Driver Uploader</name> | ||
<version>1.0</version> | ||
<vendor email="support@qualisystems.com" url="http://www.qualisystems.com/">QualiSystems</vendor> | ||
|
||
<description><![CDATA[ | ||
Publishes the driver project on a Quali server.<br> | ||
Make sure you have a `deployment.xml` file present in your project root. | ||
]]></description> | ||
|
||
<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description --> | ||
<idea-version since-build="141.0"/> | ||
|
||
<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html | ||
on how to target different products --> | ||
<depends>com.intellij.modules.lang</depends> | ||
|
||
<extensions defaultExtensionNs="com.intellij"> | ||
<!-- Add your extensions here --> | ||
</extensions> | ||
|
||
<actions> | ||
<!-- Add your actions here --> | ||
<action id="QualiPublishDriverAction" | ||
class="com.qualisystems.pythonDriverPlugin.QualiPublishDriverAction" | ||
text="Publish Python Driver on CloudShell" | ||
description="Publishes the driver project on CloudShell" | ||
icon="/qs-icon.png"> | ||
<add-to-group group-id="ProjectViewPopupMenu" anchor="first"/> | ||
<add-to-group group-id="RunnerActions" anchor="first"/> | ||
</action> | ||
</actions> | ||
|
||
</idea-plugin> |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions
44
src/com/qualisystems/pythonDriverPlugin/DriverPublisherSettings.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package com.qualisystems.pythonDriverPlugin; | ||
|
||
import org.apache.commons.lang.ArrayUtils; | ||
|
||
import java.util.Properties; | ||
|
||
public class DriverPublisherSettings { | ||
|
||
String serverRootAddress; | ||
int port; | ||
String driverUniqueName; | ||
String username; | ||
String password; | ||
String domain; | ||
String[] fileFilters; | ||
|
||
private static final String[] DefaultFileFilters = new String[] { ".idea", "deployment", "deployment.xml" }; | ||
|
||
public static DriverPublisherSettings fromProperties(Properties deploymentProperties) throws IllegalArgumentException { | ||
|
||
if (!deploymentProperties.containsKey("driverUniqueName")) | ||
throw new IllegalArgumentException("Missing `driverUniqueName` key in project's deployment.xml"); | ||
|
||
if (!deploymentProperties.containsKey("serverRootAddress")) | ||
throw new IllegalArgumentException("Missing `serverRootAddress` key in project's deployment.xml"); | ||
|
||
DriverPublisherSettings settings = new DriverPublisherSettings(); | ||
|
||
settings.serverRootAddress = deploymentProperties.getProperty("serverRootAddress"); | ||
settings.port = Integer.parseInt(deploymentProperties.getProperty("port", "8029")); | ||
settings.driverUniqueName = deploymentProperties.getProperty("driverUniqueName"); | ||
settings.username = deploymentProperties.getProperty("username", "admin"); | ||
settings.password = deploymentProperties.getProperty("password", "admin"); | ||
settings.domain = deploymentProperties.getProperty("domain", "Global"); | ||
|
||
String fileFiltersValue = deploymentProperties.getProperty("fileFilters", ""); | ||
|
||
String[] extraFilters = fileFiltersValue.isEmpty() ? new String[0] : fileFiltersValue.split(";"); | ||
|
||
settings.fileFilters = (String[])ArrayUtils.addAll(DefaultFileFilters, extraFilters); | ||
|
||
return settings; | ||
} | ||
} |
120 changes: 120 additions & 0 deletions
120
src/com/qualisystems/pythonDriverPlugin/QualiPublishDriverAction.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package com.qualisystems.pythonDriverPlugin; | ||
|
||
import com.intellij.openapi.actionSystem.AnAction; | ||
import com.intellij.openapi.actionSystem.AnActionEvent; | ||
import com.intellij.openapi.actionSystem.CommonDataKeys; | ||
import com.intellij.openapi.progress.ProgressIndicator; | ||
import com.intellij.openapi.progress.ProgressManager; | ||
import com.intellij.openapi.progress.Task; | ||
import com.intellij.openapi.project.Project; | ||
import com.intellij.openapi.ui.Messages; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
import java.io.*; | ||
import java.net.UnknownHostException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.util.Properties; | ||
|
||
public class QualiPublishDriverAction extends AnAction { | ||
|
||
public static final String DeploymentSettingsFileName = "deployment.xml"; | ||
|
||
@Override | ||
public void actionPerformed(AnActionEvent anActionEvent) { | ||
|
||
final Project project = anActionEvent.getData(CommonDataKeys.PROJECT); | ||
|
||
if (project == null) return; | ||
|
||
final File deploymentSettingsFile = new File(project.getBasePath(), DeploymentSettingsFileName); | ||
|
||
if (!deploymentSettingsFile.exists()) { | ||
|
||
Messages.showErrorDialog( | ||
project, | ||
"Could not find deployment.xml in the project folder, cannot upload driver.", | ||
"Missing Deployment Configuration File"); | ||
|
||
return; | ||
} | ||
|
||
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Publishing Python Driver on CloudShell") { | ||
|
||
public Exception _exception; | ||
public DriverPublisherSettings _settings; | ||
|
||
@Override | ||
public void onSuccess() { | ||
|
||
if (_exception != null) { | ||
|
||
_exception.printStackTrace(); | ||
|
||
if (_exception instanceof UnknownHostException) | ||
Messages.showErrorDialog( | ||
project, | ||
"Failed uploading new driver file:\n Unknown Host", | ||
"Publishing Python Driver on CloudShell"); | ||
else | ||
Messages.showErrorDialog( | ||
project, | ||
"Failed uploading new driver file:\n" + _exception.toString(), | ||
"Publishing Python Driver on CloudShell"); | ||
|
||
return; | ||
} | ||
|
||
if (_settings == null) return; | ||
|
||
Messages.showInfoMessage( | ||
project, | ||
String.format("Successfully uploaded new driver file for driver `%s`", _settings.driverUniqueName), | ||
"Publishing Python Driver on CloudShell"); | ||
} | ||
|
||
@Override | ||
public void run(@NotNull ProgressIndicator progressIndicator) { | ||
|
||
try { | ||
|
||
_settings = getDeploymentSettingsFromFile(deploymentSettingsFile); | ||
|
||
ResourceManagementService resourceManagementService = | ||
ResourceManagementService.OpenConnection(_settings.serverRootAddress, _settings.port, _settings.username, _settings.password, _settings.domain); | ||
|
||
File zippedProjectFile = zipProjectFolder(project.getBasePath(), _settings); | ||
|
||
resourceManagementService.updateDriver(_settings.driverUniqueName, zippedProjectFile); | ||
|
||
} catch (Exception e) { | ||
|
||
_exception = e; | ||
} | ||
} | ||
}); | ||
} | ||
|
||
private File zipProjectFolder(String directory, DriverPublisherSettings settings) throws IOException { | ||
|
||
ZipHelper zipHelper = new ZipHelper(settings.fileFilters); | ||
|
||
Path deploymentFilePath = Paths.get(directory, "deployment", settings.driverUniqueName + ".zip"); | ||
|
||
zipHelper.zipDir(directory, deploymentFilePath.toString()); | ||
|
||
return deploymentFilePath.toFile(); | ||
} | ||
|
||
private DriverPublisherSettings getDeploymentSettingsFromFile(File deploymentSettingsFile) throws IOException { | ||
|
||
Properties properties = new Properties(); | ||
|
||
properties.loadFromXML(Files.newInputStream(deploymentSettingsFile.toPath())); | ||
|
||
DriverPublisherSettings settings = DriverPublisherSettings.fromProperties(properties); | ||
|
||
return settings; | ||
} | ||
} |
133 changes: 133 additions & 0 deletions
133
src/com/qualisystems/pythonDriverPlugin/ResourceManagementService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package com.qualisystems.pythonDriverPlugin; | ||
|
||
import org.w3c.dom.Document; | ||
import org.w3c.dom.NodeList; | ||
|
||
import javax.xml.parsers.DocumentBuilder; | ||
import javax.xml.parsers.DocumentBuilderFactory; | ||
import java.io.DataOutputStream; | ||
import java.io.File; | ||
import java.net.HttpURLConnection; | ||
import java.net.URL; | ||
import java.net.InetAddress; | ||
import java.nio.file.Files; | ||
import java.util.Base64; | ||
|
||
public class ResourceManagementService { | ||
|
||
private static final String TargetServerURLFormat = "http://%s:%s/%s"; | ||
|
||
private static final String LoginEndpointPath = "ResourceManagerApiService/Logon"; | ||
private static final String LogonRequestFormat = | ||
"<Logon>\n" + | ||
"<username>%s</username>\n" + | ||
"<password>%s</password>\n" + | ||
"<domainName>%s</domainName>\n" + | ||
"</Logon>"; | ||
|
||
private static final String UpdateDriverEndpointPath = "ResourceManagerApiService/UpdateDriver"; | ||
private static final String UpdateDriverRequestFormat = | ||
"<UpdateDriver>\n" + | ||
"<driverName>%s</driverName>\n" + | ||
"<driverFile>%s</driverFile>\n" + | ||
"<driverFileName>%s</driverFileName>\n" + | ||
"</UpdateDriver>"; | ||
|
||
public static ResourceManagementService OpenConnection(String serverAddress, int port, String username, String password, String domain) throws Exception { | ||
|
||
ResourceManagementService resourceManagementService = new ResourceManagementService(serverAddress, port); | ||
|
||
resourceManagementService.login(username, password, domain); | ||
|
||
return resourceManagementService; | ||
} | ||
|
||
private void login(String username, String password, String domain) throws Exception { | ||
|
||
String serverURL = String.format(TargetServerURLFormat, _serverAddress, _port, LoginEndpointPath); | ||
|
||
Document doc = sendMessage(new URL(serverURL), String.format(LogonRequestFormat, username, password, domain)); | ||
|
||
NodeList tokenElement = doc.getElementsByTagName("Token"); | ||
|
||
if (tokenElement.getLength() != 1) | ||
throw new Exception("No token element in logon response"); | ||
|
||
_authToken = tokenElement.item(0).getAttributes().getNamedItem("Token").getTextContent(); | ||
} | ||
|
||
public void updateDriver(String driverName, File newDriverFile) throws Exception { | ||
|
||
String base64DriverFile = | ||
Base64.getEncoder().encodeToString(Files.readAllBytes(newDriverFile.toPath())); | ||
|
||
String serverURL = String.format(TargetServerURLFormat, _serverAddress, _port, UpdateDriverEndpointPath); | ||
|
||
sendMessage(new URL(serverURL), String.format(UpdateDriverRequestFormat, driverName, base64DriverFile, newDriverFile.getName())); | ||
} | ||
|
||
private Document sendMessage(URL requestURL, String message) throws Exception { | ||
|
||
HttpURLConnection con = (HttpURLConnection) requestURL.openConnection(); | ||
|
||
con.setRequestMethod("POST"); | ||
con.setRequestProperty("DateTimeFormat", "MM/dd/yyyy HH:mm"); | ||
con.setRequestProperty("ClientTimeZoneId", "UTC"); | ||
con.setRequestProperty("Content-Type", "text/xml"); | ||
con.setRequestProperty("Accept", "*/*"); | ||
con.setRequestProperty("Authorization", String.format("MachineName=%s;Token=%s", _hostname, _authToken)); | ||
con.setRequestProperty("Host", _serverAddress + ":" + Integer.toString(_port)); | ||
|
||
con.setDoOutput(true); | ||
|
||
DataOutputStream wr = new DataOutputStream(con.getOutputStream()); | ||
|
||
wr.writeBytes(message); | ||
|
||
wr.flush(); | ||
wr.close(); | ||
|
||
int responseCode = con.getResponseCode(); | ||
|
||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); | ||
DocumentBuilder builder = factory.newDocumentBuilder(); | ||
|
||
Document responseXml = builder.parse(con.getInputStream()); | ||
|
||
NodeList elements = responseXml.getElementsByTagName("Error"); | ||
|
||
if (elements.getLength() > 0) | ||
throw new Exception(String.format("API Message: %s", elements.item(0).getTextContent())); | ||
|
||
if (!isSuccessResponseCode(responseCode)) | ||
throw new Exception("Error making request, Response code: " + responseCode); | ||
|
||
return responseXml; | ||
} | ||
|
||
private boolean isSuccessResponseCode(int responseCode) { | ||
return responseCode >= 200 && responseCode < 300; | ||
} | ||
|
||
private final String _serverAddress; | ||
private final String _hostname; | ||
private final int _port; | ||
|
||
private String _authToken; | ||
|
||
private ResourceManagementService(String serverAddress, int port) { | ||
|
||
_serverAddress = serverAddress; | ||
_port = port; | ||
|
||
String hostname; | ||
|
||
try { | ||
hostname = InetAddress.getLocalHost().getHostName(); | ||
} catch (Exception ex) { | ||
hostname = "localhost"; | ||
} | ||
|
||
_hostname = hostname; | ||
} | ||
} |
Oops, something went wrong.