From 231f4a4f6336484863859fe343f1eacba87c8682 Mon Sep 17 00:00:00 2001 From: mastern2k3 Date: Wed, 24 Feb 2016 16:28:49 +0200 Subject: [PATCH] initial --- .gitignore | 4 + intelli-qs-plugin.iml | 13 ++ resources/META-INF/plugin.xml | 36 +++++ resources/qs-icon.png | Bin 0 -> 744 bytes .../DriverPublisherSettings.java | 44 ++++++ .../QualiPublishDriverAction.java | 120 ++++++++++++++++ .../ResourceManagementService.java | 133 ++++++++++++++++++ .../pythonDriverPlugin/ZipHelper.java | 99 +++++++++++++ 8 files changed, 449 insertions(+) create mode 100644 .gitignore create mode 100644 intelli-qs-plugin.iml create mode 100644 resources/META-INF/plugin.xml create mode 100644 resources/qs-icon.png create mode 100644 src/com/qualisystems/pythonDriverPlugin/DriverPublisherSettings.java create mode 100644 src/com/qualisystems/pythonDriverPlugin/QualiPublishDriverAction.java create mode 100644 src/com/qualisystems/pythonDriverPlugin/ResourceManagementService.java create mode 100644 src/com/qualisystems/pythonDriverPlugin/ZipHelper.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5304ebd --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ + +.idea/ +out/ +*.jar diff --git a/intelli-qs-plugin.iml b/intelli-qs-plugin.iml new file mode 100644 index 0000000..e025b20 --- /dev/null +++ b/intelli-qs-plugin.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml new file mode 100644 index 0000000..ca37f41 --- /dev/null +++ b/resources/META-INF/plugin.xml @@ -0,0 +1,36 @@ + + com.qualisystems.pythonDriverPlugin + Quali Python Driver Uploader + 1.0 + QualiSystems + + + Make sure you have a `deployment.xml` file present in your project root. + + ]]> + + + + + + com.intellij.modules.lang + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/qs-icon.png b/resources/qs-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c652538cbe0e1dea965c2bddd0e5588800e99f60 GIT binary patch literal 744 zcmVP)lA^VeI@wQh^2b80t_8@}5l$BG-14Fm-Z zytvAgynT!mt=woF-Rlt?k4~Y|TZwK$#4eijKP@?&s}HN1ixB-=oo8oSB#BONS1;gc zyAzX5G$SrJ(~C8khH@;zcB3%0ekh`L literal 0 HcmV?d00001 diff --git a/src/com/qualisystems/pythonDriverPlugin/DriverPublisherSettings.java b/src/com/qualisystems/pythonDriverPlugin/DriverPublisherSettings.java new file mode 100644 index 0000000..bc8c499 --- /dev/null +++ b/src/com/qualisystems/pythonDriverPlugin/DriverPublisherSettings.java @@ -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; + } +} diff --git a/src/com/qualisystems/pythonDriverPlugin/QualiPublishDriverAction.java b/src/com/qualisystems/pythonDriverPlugin/QualiPublishDriverAction.java new file mode 100644 index 0000000..a6b22a9 --- /dev/null +++ b/src/com/qualisystems/pythonDriverPlugin/QualiPublishDriverAction.java @@ -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; + } +} diff --git a/src/com/qualisystems/pythonDriverPlugin/ResourceManagementService.java b/src/com/qualisystems/pythonDriverPlugin/ResourceManagementService.java new file mode 100644 index 0000000..efbc617 --- /dev/null +++ b/src/com/qualisystems/pythonDriverPlugin/ResourceManagementService.java @@ -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 = + "\n" + + "%s\n" + + "%s\n" + + "%s\n" + + ""; + + private static final String UpdateDriverEndpointPath = "ResourceManagerApiService/UpdateDriver"; + private static final String UpdateDriverRequestFormat = + "\n" + + "%s\n" + + "%s\n" + + "%s\n" + + ""; + + 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; + } +} diff --git a/src/com/qualisystems/pythonDriverPlugin/ZipHelper.java b/src/com/qualisystems/pythonDriverPlugin/ZipHelper.java new file mode 100644 index 0000000..e975995 --- /dev/null +++ b/src/com/qualisystems/pythonDriverPlugin/ZipHelper.java @@ -0,0 +1,99 @@ +package com.qualisystems.pythonDriverPlugin; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +class ZipHelper { + + private final String[] _filters; + + public ZipHelper(String... filters) { + + if (filters == null) + filters = new String[0]; + + _filters = filters; + } + + public void zipDir(String dirName, String nameZipFile) throws IOException { + + ZipOutputStream zip = null; + FileOutputStream fW = null; + + Files.createDirectories(Paths.get(new File(nameZipFile).getParent())); + + fW = new FileOutputStream(nameZipFile); + zip = new ZipOutputStream(fW); + + initialAddFolderToZip(dirName, zip); + + zip.close(); + fW.close(); + } + + private void initialAddFolderToZip(String srcFolder, ZipOutputStream zip) throws IOException { + + File folder = new File(srcFolder); + + for (String fileName : folder.list()) { + addFileToZip("", srcFolder + "/" + fileName, zip, false); + } + } + + private void addFolderToZip(String path, String srcFolder, ZipOutputStream zip) throws IOException { + File folder = new File(srcFolder); + if (folder.list().length == 0) { + addFileToZip(path , srcFolder, zip, true); + } + else { + for (String fileName : folder.list()) { + if (path.equals("")) { + addFileToZip(folder.getName(), srcFolder + "/" + fileName, zip, false); + } + else { + addFileToZip(path + "/" + folder.getName(), srcFolder + "/" + fileName, zip, false); + } + } + } + } + + private void addFileToZip(String path, String srcFile, ZipOutputStream zip, boolean flag) throws IOException { + + File folder = new File(srcFile); + + if (flag) { + + zip.putNextEntry(new ZipEntry(path + "/" +folder.getName() + "/")); + + } else { + + String nameInZip = (path.isEmpty() ? path : path + "/") + folder.getName(); + + for (String filter : _filters) + if (nameInZip.equalsIgnoreCase(filter)) + return; + + if (folder.isDirectory()) { + + addFolderToZip(path, srcFile, zip); + + } else { + + byte[] buf = new byte[1024]; + int len; + + FileInputStream in = new FileInputStream(srcFile); + zip.putNextEntry(new ZipEntry(nameInZip)); + + while ((len = in.read(buf)) > 0) + zip.write(buf, 0, len); + } + } + } +}