|
| 1 | +package com.couchbase.intellij.listener; |
| 2 | + |
| 3 | +import com.couchbase.intellij.tools.CBTools; |
| 4 | +import com.couchbase.intellij.tools.ToolSpec; |
| 5 | +import com.couchbase.intellij.tools.ToolStatus; |
| 6 | +import com.intellij.openapi.application.PathManager; |
| 7 | + |
| 8 | +import java.io.File; |
| 9 | +import java.io.FileOutputStream; |
| 10 | +import java.net.URL; |
| 11 | +import java.nio.channels.Channels; |
| 12 | +import java.nio.channels.ReadableByteChannel; |
| 13 | +import java.nio.file.Files; |
| 14 | +import java.nio.file.Paths; |
| 15 | +import java.util.Arrays; |
| 16 | +import java.util.HashMap; |
| 17 | +import java.util.List; |
| 18 | +import java.util.Map; |
| 19 | +import java.util.concurrent.CompletableFuture; |
| 20 | + |
| 21 | +import static utils.FileUtils.*; |
| 22 | +import static utils.OSUtil.*; |
| 23 | + |
| 24 | +//TODO: This code is a little bit messy and definitely deserves some love in the future |
| 25 | +public class DependenciesDownloader { |
| 26 | + |
| 27 | + public static final String TOOL_SHELL = "shell"; |
| 28 | + public static final String TOOL_IMPORT_EXPORT = "import_export"; |
| 29 | + |
| 30 | + |
| 31 | + private String getToolInstallPath(String toolKey) { |
| 32 | + |
| 33 | + if (TOOL_SHELL.equals(toolKey)) { |
| 34 | + return "cbshell"; |
| 35 | + } else if (TOOL_IMPORT_EXPORT.equals(toolKey)) { |
| 36 | + return "cbimport_export"; |
| 37 | + } else { |
| 38 | + throw new IllegalStateException("Not Implemented yet"); |
| 39 | + } |
| 40 | + } |
| 41 | + |
| 42 | + private List<String> getToolsList(String toolKey, String os) { |
| 43 | + boolean unixBased = MACOS_64.equals(os) |
| 44 | + || MACOS_ARM.equals(os) |
| 45 | + || LINUX_64.equals(os) |
| 46 | + || LINUX_ARM.equals(os); |
| 47 | + |
| 48 | + if (TOOL_SHELL.equals(toolKey)) { |
| 49 | + if (unixBased) { |
| 50 | + return List.of("cbsh"); |
| 51 | + } else { |
| 52 | + return List.of("cbsh.exe"); |
| 53 | + } |
| 54 | + } else if (TOOL_IMPORT_EXPORT.equals(toolKey)) { |
| 55 | + String path = "bin" + File.separator; |
| 56 | + if (unixBased) { |
| 57 | + return Arrays.asList(path + "cbimport", path + "cbexport"); |
| 58 | + } else { |
| 59 | + return Arrays.asList(path + "cbimport.exe", path + "cbexport.exe"); |
| 60 | + } |
| 61 | + } else { |
| 62 | + throw new IllegalStateException("Not implemented yet"); |
| 63 | + } |
| 64 | + } |
| 65 | + |
| 66 | + private ToolSpec getToolSpec(String url, String toolKey, String os) { |
| 67 | + return new ToolSpec(url, getToolInstallPath(toolKey), getToolsList(toolKey, os)); |
| 68 | + } |
| 69 | + |
| 70 | + public Map<String, ToolSpec> getDownloadList(String os) { |
| 71 | + Map<String, ToolSpec> map = new HashMap<>(); |
| 72 | + |
| 73 | + if (MACOS_64.equals(os)) { |
| 74 | + map.put(TOOL_SHELL, getToolSpec("https://github.com/couchbaselabs/couchbase-shell/releases/download/v0.75.1/cbsh-x86_64-apple-darwin.zip", TOOL_SHELL, MACOS_64)); |
| 75 | + map.put(TOOL_IMPORT_EXPORT, getToolSpec("https://packages.couchbase.com/releases/7.2.0/couchbase-server-tools_7.2.0-macos_x86_64.zip", TOOL_IMPORT_EXPORT, MACOS_64)); |
| 76 | + |
| 77 | + } else if (MACOS_ARM.equals(os)) { |
| 78 | + map.put(TOOL_SHELL, getToolSpec("https://github.com/couchbaselabs/couchbase-shell/releases/download/v0.75.1/cbsh-aarch64-apple-darwin.zip", TOOL_SHELL, MACOS_ARM)); |
| 79 | + map.put(TOOL_IMPORT_EXPORT, getToolSpec("https://packages.couchbase.com/releases/7.2.0/couchbase-server-tools_7.2.0-macos_arm64.zip", TOOL_IMPORT_EXPORT, MACOS_ARM)); |
| 80 | + |
| 81 | + } else if (WINDOWS_64.equals(os)) { |
| 82 | + map.put(TOOL_SHELL, getToolSpec("https://github.com/couchbaselabs/couchbase-shell/releases/download/v0.75.1/cbsh-x86_64-pc-windows-msvc.zip", TOOL_SHELL, WINDOWS_64)); |
| 83 | + map.put(TOOL_IMPORT_EXPORT, getToolSpec("https://packages.couchbase.com/releases/7.2.0/couchbase-server-tools_7.2.0-windows_amd64.zip", TOOL_IMPORT_EXPORT, WINDOWS_64)); |
| 84 | + |
| 85 | + } else if (WINDOWS_ARM.equals(os)) { |
| 86 | + map.put(TOOL_SHELL, getToolSpec("https://github.com/couchbaselabs/couchbase-shell/releases/download/v0.75.1/cbsh-x86_64-pc-windows-msvc.zip", TOOL_SHELL, WINDOWS_ARM)); |
| 87 | + map.put(TOOL_IMPORT_EXPORT, getToolSpec("https://packages.couchbase.com/releases/7.2.0/couchbase-server-tools_7.2.0-windows_amd64.zip", TOOL_IMPORT_EXPORT, WINDOWS_ARM)); |
| 88 | + |
| 89 | + } else if (LINUX_64.equals(os)) { |
| 90 | + map.put(TOOL_SHELL, getToolSpec("https://github.com/couchbaselabs/couchbase-shell/releases/download/v0.75.1/cbsh-x86_64-unknown-linux-gnu.tar.gz", TOOL_SHELL, LINUX_64)); |
| 91 | + map.put(TOOL_IMPORT_EXPORT, getToolSpec("https://packages.couchbase.com/releases/7.2.0/couchbase-server-tools_7.2.0-linux_x86_64.tar.gz", TOOL_IMPORT_EXPORT, LINUX_64)); |
| 92 | + |
| 93 | + } else if (LINUX_ARM.equals(os)) { |
| 94 | + map.put(TOOL_SHELL, getToolSpec("https://github.com/couchbaselabs/couchbase-shell/releases/download/v0.75.1/cbsh-aarch64-unknown-linux-gnu.tar.gz", TOOL_SHELL, LINUX_ARM)); |
| 95 | + map.put(TOOL_IMPORT_EXPORT, getToolSpec("https://packages.couchbase.com/releases/7.2.0/couchbase-server-tools_7.2.0-linux_aarch64.tar.gz", TOOL_IMPORT_EXPORT, LINUX_ARM)); |
| 96 | + } else { |
| 97 | + throw new IllegalStateException("OS not supported."); |
| 98 | + } |
| 99 | + return map; |
| 100 | + } |
| 101 | + |
| 102 | + public void downloadDependencies() throws Exception { |
| 103 | + String toolsPath = PathManager.getConfigPath() + File.separator + "couchbase-intellij-plugin"; |
| 104 | + createFolder(toolsPath); |
| 105 | + toolsPath += File.separator + "tools"; |
| 106 | + createFolder(toolsPath); |
| 107 | + |
| 108 | + String os = getOSArch(); |
| 109 | + Map<String, ToolSpec> downloads = getDownloadList(os); |
| 110 | + |
| 111 | + ToolSpec shell = downloads.get(TOOL_SHELL); |
| 112 | + String shellPath = toolsPath + File.separator + shell.getInstallationPath(); |
| 113 | + if (CBTools.getShell().getStatus() == ToolStatus.NOT_AVAILABLE |
| 114 | + && !isInstalled(toolsPath, downloads.get(TOOL_SHELL))) { |
| 115 | + //avoiding 2 threads to install the same thing at the same time |
| 116 | + CBTools.getShell().setStatus(ToolStatus.DOWNLOADING); |
| 117 | + downloadAndUnzip(TOOL_SHELL, shellPath, shell); |
| 118 | + } else { |
| 119 | + setToolActive(TOOL_SHELL, ToolStatus.AVAILABLE, shellPath, shell); |
| 120 | + } |
| 121 | + |
| 122 | + ToolSpec cbImport = downloads.get(TOOL_IMPORT_EXPORT); |
| 123 | + String cbImportDir = toolsPath + File.separator + cbImport.getInstallationPath(); |
| 124 | + if (CBTools.getCbImport().getStatus() == ToolStatus.NOT_AVAILABLE |
| 125 | + && !isInstalled(toolsPath, downloads.get(TOOL_IMPORT_EXPORT))) { |
| 126 | + //avoiding 2 threads to install the same thing at the same time |
| 127 | + CBTools.getCbExport().setStatus(ToolStatus.DOWNLOADING); |
| 128 | + CBTools.getCbImport().setStatus(ToolStatus.DOWNLOADING); |
| 129 | + downloadAndUnzip(TOOL_IMPORT_EXPORT, cbImportDir, cbImport); |
| 130 | + } else { |
| 131 | + setToolActive(TOOL_IMPORT_EXPORT, ToolStatus.AVAILABLE, cbImportDir, cbImport); |
| 132 | + } |
| 133 | + } |
| 134 | + |
| 135 | + |
| 136 | + private void setToolActive(String toolKey, ToolStatus status, String path, ToolSpec spec) { |
| 137 | + if (TOOL_SHELL.equals(toolKey)) { |
| 138 | + CBTools.getShell().setStatus(status); |
| 139 | + if (status == ToolStatus.AVAILABLE) { |
| 140 | + CBTools.getShell().setPath(path + File.separator + spec.getToolsList().get(0)); |
| 141 | + } |
| 142 | + } else if (TOOL_IMPORT_EXPORT.equals(toolKey)) { |
| 143 | + CBTools.getCbImport().setStatus(status); |
| 144 | + CBTools.getCbExport().setStatus(status); |
| 145 | + |
| 146 | + if (status == ToolStatus.AVAILABLE) { |
| 147 | + for (String tool : spec.getToolsList()) { |
| 148 | + if (tool.contains("cbimport")) { |
| 149 | + CBTools.getCbImport().setPath(path + File.separator + tool); |
| 150 | + } else if (tool.contains("cbexport")) { |
| 151 | + CBTools.getCbExport().setPath(path + File.separator + tool); |
| 152 | + } |
| 153 | + } |
| 154 | + } |
| 155 | + } else { |
| 156 | + throw new IllegalStateException("Not Implemented Yet"); |
| 157 | + } |
| 158 | + } |
| 159 | + |
| 160 | + public void downloadAndUnzip(String toolKey, String targetDir, ToolSpec spec) { |
| 161 | + CompletableFuture.runAsync(() -> { |
| 162 | + try { |
| 163 | + createFolder(targetDir); |
| 164 | + String fileName = spec.getUrl().substring(spec.getUrl().lastIndexOf("/") + 1); |
| 165 | + String localFilePath = targetDir + File.separator + fileName; |
| 166 | + URL website = new URL(spec.getUrl()); |
| 167 | + ReadableByteChannel rbc = Channels.newChannel(website.openStream()); |
| 168 | + FileOutputStream fos = new FileOutputStream(localFilePath); |
| 169 | + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); |
| 170 | + |
| 171 | + unzipFile(localFilePath, targetDir); |
| 172 | + makeFilesExecutable(new File(targetDir)); |
| 173 | + setToolActive(toolKey, ToolStatus.AVAILABLE, targetDir, spec); |
| 174 | + } catch (Exception e) { |
| 175 | + setToolActive(toolKey, ToolStatus.NOT_AVAILABLE, null, null); |
| 176 | + e.printStackTrace(); |
| 177 | + } |
| 178 | + }); |
| 179 | + } |
| 180 | + |
| 181 | + |
| 182 | + //TODO: Keep this code until we have tested everything on windows |
| 183 | +// private void unzipFile(String zipFilePath, String destDir) throws IOException { |
| 184 | +// File dir = new File(destDir); |
| 185 | +// if (!dir.exists()) dir.mkdirs(); |
| 186 | +// File zipFile = new File(zipFilePath); |
| 187 | +// try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) { |
| 188 | +// ZipEntry entry = zis.getNextEntry(); |
| 189 | +// while (entry != null) { |
| 190 | +// String filePath = destDir + File.separator + entry.getName(); |
| 191 | +// if (!entry.isDirectory()) { |
| 192 | +// extractFile(zis, filePath); |
| 193 | +// } else { |
| 194 | +// File dir1 = new File(filePath); |
| 195 | +// dir1.mkdir(); |
| 196 | +// } |
| 197 | +// zis.closeEntry(); |
| 198 | +// entry = zis.getNextEntry(); |
| 199 | +// } |
| 200 | +// } |
| 201 | +// Files.delete(zipFile.toPath()); |
| 202 | +// } |
| 203 | +// |
| 204 | +// private void extractFile(ZipInputStream zis, String filePath) throws IOException { |
| 205 | +// try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath))) { |
| 206 | +// byte[] bytesIn = new byte[4096]; |
| 207 | +// int read; |
| 208 | +// while ((read = zis.read(bytesIn)) != -1) { |
| 209 | +// bos.write(bytesIn, 0, read); |
| 210 | +// } |
| 211 | +// } |
| 212 | +// } |
| 213 | + |
| 214 | + |
| 215 | + public boolean isInstalled(String pluginPath, ToolSpec spec) { |
| 216 | + return Files.exists(Paths.get(pluginPath + File.separator |
| 217 | + + spec.getInstallationPath() |
| 218 | + + File.separator |
| 219 | + + spec.getToolsList().get(0))); |
| 220 | + } |
| 221 | +} |
0 commit comments