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