diff --git a/build.gradle b/build.gradle index 828b520b0..dabd60316 100644 --- a/build.gradle +++ b/build.gradle @@ -12,6 +12,9 @@ buildscript { maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } + maven { + url 'https://jitpack.io' + } } } @@ -63,6 +66,7 @@ checkSourceFormatting { dependencies { compile group: "biz.aQute.bnd", name: "biz.aQute.bndlib", version: "3.4.0" + compile group: "com.github.ballerina-platform", name: "lsp4intellij", version: "0.93.0" compile group: "commons-configuration", name: "commons-configuration", version: "1.10" compile group: "org.apache.ant", name: "ant", version: "1.10.1" compile group: "org.dom4j", name: "dom4j", version: "2.1.0" diff --git a/src/main/java/com/liferay/ide/idea/languageserver/LiferayLanguageServerPreloadingActivity.java b/src/main/java/com/liferay/ide/idea/languageserver/LiferayLanguageServerPreloadingActivity.java new file mode 100644 index 000000000..e7355195e --- /dev/null +++ b/src/main/java/com/liferay/ide/idea/languageserver/LiferayLanguageServerPreloadingActivity.java @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2000-present Liferay, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + */ + +package com.liferay.ide.idea.languageserver; + +import com.intellij.openapi.application.PreloadingActivity; +import com.intellij.openapi.progress.ProgressIndicator; + +import com.liferay.ide.idea.util.FileUtil; +import com.liferay.ide.idea.util.SocketSupport; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import java.net.JarURLConnection; +import java.net.URL; + +import java.nio.file.Files; +import java.nio.file.Paths; + +import java.util.Properties; +import java.util.jar.JarEntry; +import java.util.regex.Pattern; +import java.util.stream.Stream; + +import org.jetbrains.annotations.NotNull; + +import org.wso2.lsp4intellij.IntellijLanguageClient; +import org.wso2.lsp4intellij.client.languageserver.serverdefinition.RawCommandServerDefinition; + +/** + * @author Dominik Marks + * @author Terry Jia + */ +public class LiferayLanguageServerPreloadingActivity extends PreloadingActivity implements SocketSupport { + + @Override + public void preload(@NotNull ProgressIndicator progressIndicator) { + String[] args = { + _computeJavaPath(), "-DliferayLanguageServerStandardIO=true", "-jar", + _computeLiferayPropertiesServerJarPath() + }; + + RawCommandServerDefinition rawCommandServerDefinition = new RawCommandServerDefinition("properties", args); + + IntellijLanguageClient.addServerDefinition(rawCommandServerDefinition); + } + + private static String _computeJavaPath() { + String javaPath = "java"; + + String paths = System.getenv("PATH"); + + boolean existsInPath = Stream.of( + paths.split(Pattern.quote(File.pathSeparator)) + ).map( + Paths::get + ).anyMatch( + path -> Files.exists(path.resolve("java")) + ); + + if (!existsInPath) { + String javaHome = System.getProperty("java.home"); + + File file = new File(javaHome, "bin/java" + (_isWindows() ? ".exe" : "")); + + javaPath = file.getAbsolutePath(); + } + + return javaPath; + } + + private static String _computeLiferayPropertiesServerJarPath() { + Properties properties = System.getProperties(); + + File temp = new File(properties.getProperty("user.home"), ".liferay-intellij-plugin"); + + File liferayPropertiesServerJar = new File(temp, _PROPERTIES_LSP_JAR_FILE_NAME); + + boolean needToCopy = true; + + ClassLoader classLoader = LiferayLanguageServerPreloadingActivity.class.getClassLoader(); + + URL url = classLoader.getResource("/libs/" + _PROPERTIES_LSP_JAR_FILE_NAME); + + try (InputStream in = classLoader.getResourceAsStream("/libs/" + _PROPERTIES_LSP_JAR_FILE_NAME)) { + JarURLConnection jarURLConnection = (JarURLConnection)url.openConnection(); + + JarEntry jarEntry = jarURLConnection.getJarEntry(); + + Long bladeJarTimestamp = jarEntry.getTime(); + + if (liferayPropertiesServerJar.exists()) { + Long destTimestamp = liferayPropertiesServerJar.lastModified(); + + if (destTimestamp < bladeJarTimestamp) { + liferayPropertiesServerJar.delete(); + } + else { + needToCopy = false; + } + } + + if (needToCopy) { + FileUtil.writeFile(liferayPropertiesServerJar, in); + liferayPropertiesServerJar.setLastModified(bladeJarTimestamp); + } + } + catch (IOException ioe) { + } + + return liferayPropertiesServerJar.getAbsolutePath(); + } + + private static boolean _isWindows() { + String osName = System.getProperty("os.name"); + + osName = osName.toLowerCase(); + + return osName.contains("windows"); + } + + private static final String _PROPERTIES_LSP_JAR_FILE_NAME = "liferay-properties-server-all.jar"; + +} \ No newline at end of file diff --git a/src/main/java/com/liferay/ide/idea/util/SocketSupport.java b/src/main/java/com/liferay/ide/idea/util/SocketSupport.java new file mode 100644 index 000000000..7d8c57f7b --- /dev/null +++ b/src/main/java/com/liferay/ide/idea/util/SocketSupport.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2000-present Liferay, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + */ + +package com.liferay.ide.idea.util; + +import java.io.IOException; + +import java.net.ServerSocket; +import java.net.SocketException; + +import java.util.Random; + +/** + * @author Terry Jia + */ +public interface SocketSupport { + + public default int findUnusedPort(int low, int high) { + if (high < low) { + return -1; + } + + for (int i = 0; i < 10; ++i) { + int port = getRandomPort(low, high); + + if (!isPortInUse(port)) { + return port; + } + } + + return -1; + } + + public default int getRandomPort(int low, int high) { + return rand.nextInt(high - low) + low; + } + + public default boolean isPortInUse(int port) { + ServerSocket serverSocket = null; + + try { + serverSocket = new ServerSocket(port, 0, null); + } + catch (SocketException se) { + return true; + } + catch (IOException ioe) { + return true; + } + finally { + if (serverSocket != null) { + try { + serverSocket.close(); + } + catch (Exception e) { + } + } + } + + return false; + } + + public final Random rand = new Random(System.currentTimeMillis()); + +} \ No newline at end of file diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 438f70327..fc5c0ce28 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -204,5 +204,16 @@ + + + + + + + org.wso2.lsp4intellij.IntellijLanguageClient + + + + diff --git a/src/main/resources/libs/liferay-properties-server-all.jar b/src/main/resources/libs/liferay-properties-server-all.jar new file mode 100644 index 000000000..5b2e249cc Binary files /dev/null and b/src/main/resources/libs/liferay-properties-server-all.jar differ