diff --git a/headless-services/boot-java-language-server/pom.xml b/headless-services/boot-java-language-server/pom.xml
index d1c813b6c..33a4cf809 100644
--- a/headless-services/boot-java-language-server/pom.xml
+++ b/headless-services/boot-java-language-server/pom.xml
@@ -84,7 +84,7 @@
commons-io
commons-io
- 2.4
+ ${commons-io-version}
diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/AutowiredHoverProvider.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/AutowiredHoverProvider.java
index 9dc13e806..36e3aa6d8 100644
--- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/AutowiredHoverProvider.java
+++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/AutowiredHoverProvider.java
@@ -25,6 +25,8 @@ import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.springframework.ide.vscode.boot.java.handlers.HoverProvider;
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
+import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBean;
+import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -54,8 +56,8 @@ public class AutowiredHoverProvider implements HoverProvider {
for (SpringBootAppProvider bootApp : runningApps) {
try {
- String liveBeans = bootApp.getBeans();
- if (liveBeans != null && liveBeans.length() > 0) {
+ LiveBeansModel liveBeans = bootApp.getBeans();
+ if (liveBeans != null && !liveBeans.isEmpty()) {
addLiveHoverContent(annotation, doc, liveBeans, bootApp, hoverContent);
}
}
@@ -85,8 +87,8 @@ public class AutowiredHoverProvider implements HoverProvider {
try {
for (SpringBootApp bootApp : runningApps) {
try {
- String liveBeans = bootApp.getBeans();
- if (liveBeans != null && liveBeans.length() > 0) {
+ LiveBeansModel liveBeans = bootApp.getBeans();
+ if (liveBeans != null && !liveBeans.isEmpty()) {
Range range = getLiveHoverHint(annotation, doc, liveBeans);
if (range != null) {
return ImmutableList.of(range);
@@ -105,14 +107,11 @@ public class AutowiredHoverProvider implements HoverProvider {
return null;
}
- public Range getLiveHoverHint(Annotation annotation, TextDocument doc, String liveBeansJSON) {
+ public Range getLiveHoverHint(Annotation annotation, TextDocument doc, LiveBeansModel beansModel) {
try {
String type = findDeclaredType(annotation);
- if (type != null && liveBeansJSON != null) {
-
- LiveBeansModel beansModel = LiveBeansModel.parse(liveBeansJSON);
+ if (type != null && beansModel != null) {
LiveBean[] beansOfType = beansModel.getBeansOfType(type);
-
if (beansOfType.length > 0) {
Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength());
return hoverRange;
@@ -126,11 +125,9 @@ public class AutowiredHoverProvider implements HoverProvider {
return null;
}
- public void addLiveHoverContent(Annotation annotation, TextDocument doc, String liveBeansJSON, SpringBootAppProvider bootApp, List> hoverContent) {
+ public void addLiveHoverContent(Annotation annotation, TextDocument doc, LiveBeansModel beansModel, SpringBootAppProvider bootApp, List> hoverContent) {
String type = findDeclaredType(annotation);
- if (type != null && liveBeansJSON != null) {
-
- LiveBeansModel beansModel = LiveBeansModel.parse(liveBeansJSON);
+ if (type != null && beansModel != null) {
LiveBean[] beansOfType = beansModel.getBeansOfType(type);
if (beansOfType.length > 0) {
diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/LiveBeansModel.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/LiveBeansModel.java
deleted file mode 100644
index 85071675c..000000000
--- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/LiveBeansModel.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2017 Pivotal, Inc.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Pivotal, Inc. - initial API and implementation
- *******************************************************************************/
-package org.springframework.ide.vscode.boot.java.autowired;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-/**
- * @author Martin Lippert
- */
-public class LiveBeansModel {
-
- public static LiveBeansModel parse(String json) {
- LiveBeansModel model = new LiveBeansModel();
-
- try {
- JSONArray mainArray = new JSONArray(json);
-
- for (int i = 0; i < mainArray.length(); i++) {
- JSONObject appContext = mainArray.getJSONObject(i);
- if (appContext == null) continue;
-
- JSONArray beansArray = appContext.optJSONArray("beans");
- if (beansArray == null) continue;
-
- for (int j = 0; j < beansArray.length(); j++) {
- JSONObject beanObject = beansArray.getJSONObject(j);
- if (beanObject == null) continue;
-
- LiveBean bean = LiveBean.parse(beanObject);
- if (bean != null) {
- model.add(bean);
- }
- }
- }
- }
- catch (JSONException e) {
- e.printStackTrace();
- }
-
- return model;
- }
-
- private final ConcurrentMap> beansViaType;
- private final ConcurrentMap> beansViaName;
-
- protected LiveBeansModel() {
- this.beansViaType = new ConcurrentHashMap<>();
- this.beansViaName = new ConcurrentHashMap<>();
- }
-
- public LiveBean[] getBeansOfType(String fullyQualifiedType) {
- List result = beansViaType.get(fullyQualifiedType);
- return result != null ? result.toArray(new LiveBean[result.size()]) : new LiveBean[0];
- }
-
- public LiveBean[] getBeansOfName(String beanName) {
- List result = beansViaName.get(beanName);
- return result != null ? result.toArray(new LiveBean[result.size()]) : new LiveBean[0];
- }
-
- protected void add(LiveBean bean) {
- String type = bean.getType();
- if (type != null) {
- beansViaType.computeIfAbsent(type, (t) -> new ArrayList<>()).add(bean);
- }
-
- String name = bean.getId();
- if (name != null) {
- beansViaName.computeIfAbsent(name, (n) -> new ArrayList<>()).add(bean);
- }
- }
-
-}
diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/SpringBootAppProvider.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/SpringBootAppProvider.java
index 9a4a64d3e..5bf1fda5d 100644
--- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/SpringBootAppProvider.java
+++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/SpringBootAppProvider.java
@@ -10,12 +10,14 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.autowired;
+import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
+
/**
* @author Martin Lippert
*/
public interface SpringBootAppProvider {
- public String getBeans() throws Exception;
+ public LiveBeansModel getBeans() throws Exception;
public String getProcessID();
public String getProcessName();
diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/SpringBootAppProviderImpl.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/SpringBootAppProviderImpl.java
index af8e94c16..3563d0376 100644
--- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/SpringBootAppProviderImpl.java
+++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/SpringBootAppProviderImpl.java
@@ -11,6 +11,7 @@
package org.springframework.ide.vscode.boot.java.autowired;
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
+import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
/**
* @author Martin Lippert
@@ -24,7 +25,7 @@ public class SpringBootAppProviderImpl implements SpringBootAppProvider {
}
@Override
- public String getBeans() throws Exception {
+ public LiveBeansModel getBeans() throws Exception {
return bootApp.getBeans();
}
diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentHoverProvider.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentHoverProvider.java
index 4a09f215b..4852b1d0d 100644
--- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentHoverProvider.java
+++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentHoverProvider.java
@@ -26,12 +26,12 @@ import org.eclipse.lsp4j.MarkedString;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.springframework.ide.vscode.boot.java.autowired.Constants;
-import org.springframework.ide.vscode.boot.java.autowired.LiveBean;
-import org.springframework.ide.vscode.boot.java.autowired.LiveBeansModel;
import org.springframework.ide.vscode.boot.java.autowired.SpringBootAppProvider;
import org.springframework.ide.vscode.boot.java.autowired.SpringBootAppProviderImpl;
import org.springframework.ide.vscode.boot.java.handlers.HoverProvider;
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
+import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBean;
+import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -68,8 +68,8 @@ public class ComponentHoverProvider implements HoverProvider {
List> hoverContent = new ArrayList<>();
for (SpringBootAppProvider bootApp : runningApps) {
try {
- String liveBeans = bootApp.getBeans();
- if (liveBeans != null && liveBeans.length() > 0) {
+ LiveBeansModel liveBeans = bootApp.getBeans();
+ if (liveBeans != null && !liveBeans.isEmpty()) {
addLiveHoverContent(typeDecl, doc, liveBeans, bootApp, hoverContent);
}
}
@@ -101,8 +101,8 @@ public class ComponentHoverProvider implements HoverProvider {
try {
for (SpringBootApp bootApp : runningApps) {
try {
- String liveBeans = bootApp.getBeans();
- if (liveBeans != null && liveBeans.length() > 0) {
+ LiveBeansModel liveBeans = bootApp.getBeans();
+ if (liveBeans != null && !liveBeans.isEmpty()) {
Range range = getLiveHoverHint(annotation, doc, liveBeans);
if (range != null) {
return ImmutableList.of(range);
@@ -121,13 +121,11 @@ public class ComponentHoverProvider implements HoverProvider {
return null;
}
- public Range getLiveHoverHint(Annotation annotation, TextDocument doc, String liveBeansJSON) {
+ public Range getLiveHoverHint(Annotation annotation, TextDocument doc, LiveBeansModel beansModel) {
try {
TypeDeclaration type = findDeclaredType(annotation);
- if (type != null && liveBeansJSON != null) {
+ if (type != null && beansModel != null) {
String typeName = type.resolveBinding().getQualifiedName();
-
- LiveBeansModel beansModel = LiveBeansModel.parse(liveBeansJSON);
LiveBean[] beansOfType = beansModel.getBeansOfType(typeName);
if (beansOfType.length > 0) {
@@ -160,11 +158,9 @@ public class ComponentHoverProvider implements HoverProvider {
}
- public void addLiveHoverContent(TypeDeclaration declaringType, TextDocument doc, String liveBeansJSON, SpringBootAppProvider bootApp, List> hoverContent) {
+ public void addLiveHoverContent(TypeDeclaration declaringType, TextDocument doc, LiveBeansModel beansModel, SpringBootAppProvider bootApp, List> hoverContent) {
String type = declaringType.resolveBinding().getQualifiedName();
- if (type != null && liveBeansJSON != null) {
-
- LiveBeansModel beansModel = LiveBeansModel.parse(liveBeansJSON);
+ if (type != null && beansModel != null) {
LiveBean[] beansOfType = beansModel.getBeansOfType(type);
if (beansOfType.length > 0) {
diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/conditionals/ConditionalsLiveHoverProvider.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/conditionals/ConditionalsLiveHoverProvider.java
index 83a256ba8..a5a1b1c45 100644
--- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/conditionals/ConditionalsLiveHoverProvider.java
+++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/conditionals/ConditionalsLiveHoverProvider.java
@@ -96,9 +96,20 @@ public class ConditionalsLiveHoverProvider implements HoverProvider {
private void addHoverContent(List conditions,
List> hoverContent) throws Exception {
- for (RunningAppConditional condition : conditions) {
+ for (int i = 0; i < conditions.size(); i++) {
+ RunningAppConditional condition = conditions.get(i);
hoverContent.add(Either.forLeft("Condition: " + condition.condition));
hoverContent.add(Either.forLeft("Message: " + condition.message));
+
+ // If there is more than one instances show process information
+ if (conditions.size() > 1) {
+ hoverContent.add(Either.forLeft("Process ID: " + condition.app.getProcessID()));
+ hoverContent.add(Either.forLeft("Process Name: " + condition.app.getProcessName()));
+ }
+
+ if (i < conditions.size() - 1) {
+ hoverContent.add(Either.forLeft("---"));
+ }
}
}
@@ -117,16 +128,21 @@ public class ConditionalsLiveHoverProvider implements HoverProvider {
public Optional> parse(Annotation annotation, SpringBootApp[] runningApps) {
try {
+ List allConditionals = new ArrayList<>();
for (SpringBootApp app : runningApps) {
String autoConfigRecord = app.getAutoConfigReport();
if (autoConfigRecord != null) {
JSONObject autoConfigJson = new JSONObject(autoConfigRecord);
- List conditionalsFromPositiveMatches = getConditionals(annotation, autoConfigJson);
- if(!conditionalsFromPositiveMatches.isEmpty()) {
- return Optional.of(conditionalsFromPositiveMatches);
+ List conditionalsFromPositiveMatches = getConditionals(app, annotation,
+ autoConfigJson);
+ if (!conditionalsFromPositiveMatches.isEmpty()) {
+ allConditionals.addAll(conditionalsFromPositiveMatches);
}
}
}
+ if (!allConditionals.isEmpty()) {
+ return Optional.of(allConditionals);
+ }
} catch (Exception e) {
Log.log(e);
}
@@ -135,12 +151,13 @@ public class ConditionalsLiveHoverProvider implements HoverProvider {
/**
*
+ * @param app
* @param annotation
* @param autoConfigJson
* @return non-null list of conditionals parsed from an autoconfig report. List
* may be empty.
*/
- private List getConditionals(Annotation annotation,
+ private List getConditionals(SpringBootApp app, Annotation annotation,
JSONObject autoConfigJson) {
List conditions = new ArrayList<>();
@@ -152,7 +169,7 @@ public class ConditionalsLiveHoverProvider implements HoverProvider {
JSONArray matchList = (JSONArray) positiveMatches.get(positiveMatchKey);
matchList.forEach((match) -> {
if (match instanceof JSONObject) {
- getMatchedCondition((JSONObject) match, annotation)
+ getMatchedCondition(app, (JSONObject) match, annotation)
.ifPresent((condition) -> conditions.add(condition));
}
});
@@ -203,13 +220,14 @@ public class ConditionalsLiveHoverProvider implements HoverProvider {
return false;
}
- protected Optional getMatchedCondition(JSONObject conditionJson, Annotation annotation) {
+ protected Optional getMatchedCondition(SpringBootApp app, JSONObject conditionJson,
+ Annotation annotation) {
if (conditionJson != null) {
String condition = (String) conditionJson.get("condition");
String message = (String) conditionJson.get("message");
String annotationName = annotation.resolveTypeBinding().getName();
if (message.contains(annotationName)) {
- return Optional.of(new RunningAppConditional(condition, message));
+ return Optional.of(new RunningAppConditional(app, condition, message));
}
}
return Optional.empty();
@@ -220,10 +238,12 @@ public class ConditionalsLiveHoverProvider implements HoverProvider {
public final String condition;
public final String message;
+ public final SpringBootApp app;
- public RunningAppConditional(String condition, String message) {
+ public RunningAppConditional(SpringBootApp app, String condition, String message) {
this.condition = condition;
this.message = message;
+ this.app = app;
}
}
}
diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java
index d39e0baff..87930d291 100644
--- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java
+++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingHoverProvider.java
@@ -13,27 +13,15 @@ package org.springframework.ide.vscode.boot.java.requestmapping;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.HashSet;
import java.util.List;
-import java.util.Objects;
import java.util.Optional;
-import java.util.Set;
import java.util.concurrent.CompletableFuture;
-import java.util.stream.Collectors;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
-import org.eclipse.jdt.core.dom.ArrayInitializer;
-import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
-import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.MethodDeclaration;
-import org.eclipse.jdt.core.dom.NormalAnnotation;
-import org.eclipse.jdt.core.dom.QualifiedName;
-import org.eclipse.jdt.core.dom.SimpleName;
-import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
-import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.MarkedString;
@@ -66,7 +54,7 @@ public class RequestMappingHoverProvider implements HoverProvider {
public Collection getLiveHoverHints(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) {
try {
if (runningApps.length > 0) {
- Optional> val = getRequestMappingMethodFromRunningApp(annotation, runningApps);
+ Optional>> val = getRequestMappingMethodFromRunningApp(annotation, runningApps);
if (val.isPresent()) {
Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength());
return ImmutableList.of(hoverRange);
@@ -85,7 +73,7 @@ public class RequestMappingHoverProvider implements HoverProvider {
try {
List> hoverContent = new ArrayList<>();
- Optional> val = getRequestMappingMethodFromRunningApp(annotation, runningApps);
+ Optional>> val = getRequestMappingMethodFromRunningApp(annotation, runningApps);
if (val.isPresent()) {
addHoverContent(val.get(), hoverContent);
@@ -105,20 +93,22 @@ public class RequestMappingHoverProvider implements HoverProvider {
return null;
}
- private Optional> getRequestMappingMethodFromRunningApp(Annotation annotation,
+ private Optional>> getRequestMappingMethodFromRunningApp(Annotation annotation,
SpringBootApp[] runningApps) {
try {
+ List> results = new ArrayList<>();
for (SpringBootApp app : runningApps) {
Collection mappings = app.getRequestMappings();
- if (mappings!=null && !mappings.isEmpty()) {
- return mappings.stream()
- .filter(rm -> matchesAnnotation(annotation, rm))
+ if (mappings != null && !mappings.isEmpty()) {
+ mappings.stream()
+// .filter(rm -> matchesAnnotation(annotation, rm))
.filter(rm -> methodMatchesAnnotation(annotation, rm))
.map(rm -> Tuples.of(rm, app))
- .findFirst();
+ .findFirst().ifPresent(t -> results.add(t));
}
}
+ return Optional.of(results);
} catch (Exception e) {
Log.log(e);
}
@@ -135,7 +125,7 @@ public class RequestMappingHoverProvider implements HoverProvider {
return binding.getDeclaringClass().getQualifiedName().equals(rqClassName)
&& binding.getName().equals(rm.getMethodName())
&& Arrays.equals(Arrays.stream(binding.getParameterTypes())
- .map(t -> t.getQualifiedName())
+ .map(t -> t.getTypeDeclaration().getQualifiedName())
.toArray(String[]::new),
rm.getMethodParameters());
} else if (parent instanceof TypeDeclaration) {
@@ -145,157 +135,154 @@ public class RequestMappingHoverProvider implements HoverProvider {
return false;
}
- private void addHoverContent(Tuple2 mappingMethod, List> hoverContent) throws Exception {
- String processId = mappingMethod.getT2().getProcessID();
- String processName = mappingMethod.getT2().getProcessName();
- String port = mappingMethod.getT2().getPort();
- String host = mappingMethod.getT2().getHost();
- StringBuilder builder = new StringBuilder();
+ private void addHoverContent(List> mappingMethods, List> hoverContent) throws Exception {
+ for (int i = 0; i < mappingMethods.size(); i++) {
+ Tuple2 mappingMethod = mappingMethods.get(i);
- Arrays.stream(mappingMethod.getT1().getSplitPath()).forEach(path -> {
+ String processId = mappingMethod.getT2().getProcessID();
+ String processName = mappingMethod.getT2().getProcessName();
+ String port = mappingMethod.getT2().getPort();
+ String host = mappingMethod.getT2().getHost();
+ StringBuilder builder = new StringBuilder();
- String url = UrlUtil.createUrl(host, port, path);
+ Arrays.stream(mappingMethod.getT1().getSplitPath()).forEach(path -> {
- if (builder.length() > 0) {
- builder.append("\n");
- }
- builder.append("Path: ");
- builder.append("[");
- builder.append(path);
- builder.append("]");
- builder.append("(");
- builder.append(url);
- builder.append(")");
+ String url = UrlUtil.createUrl(host, port, path);
- });
-
- hoverContent.add(Either.forLeft(builder.toString()));
- hoverContent.add(Either.forLeft("Process ID: " + processId));
- hoverContent.add(Either.forLeft("Process Name: " + processName));
- }
-
- protected String getRequestMethod(SingleMemberAnnotation annotation) {
- ITypeBinding type = annotation.resolveTypeBinding();
- if (type != null) {
- switch (type.getQualifiedName()) {
- case Constants.SPRING_GET_MAPPING:
- return "GET";
- case Constants.SPRING_POST_MAPPING:
- return "POST";
- case Constants.SPRING_DELETE_MAPPING:
- return "DELETE";
- case Constants.SPRING_PUT_MAPPING:
- return "PUT";
- case Constants.SPRING_PATCH_MAPPING:
- return "PATCH";
- }
- }
- return null;
- }
-
- private boolean matchesAnnotation(Annotation annotation, RequestMapping rm) {
- String[] mappingPath = null;
- Set methods = null;
- if (annotation instanceof SingleMemberAnnotation) {
- SingleMemberAnnotation singleAnnotation = (SingleMemberAnnotation) annotation;
- Expression valueContent = singleAnnotation.getValue();
- if (valueContent instanceof StringLiteral) {
- mappingPath = new String[] { ((StringLiteral)valueContent).getLiteralValue() };
- }
- String method = getRequestMethod(singleAnnotation);
- if (method != null) {
- methods = new HashSet<>();
- methods.add(method);
- }
- }
- else if (annotation instanceof NormalAnnotation) {
- List> values = ((NormalAnnotation) annotation).values();
- for (Object value : values) {
- if (value instanceof MemberValuePair) {
- MemberValuePair pair = (MemberValuePair)value;
- String name = pair.getName().toString();
- switch (name) {
- case "value":
- case "path":
- mappingPath = getPaths(pair.getValue());
- break;
- case "method":
- methods = getRequestMethod(pair.getValue());
- break;
- }
+ if (builder.length() > 0) {
+ builder.append("\n");
}
+ builder.append("[");
+ builder.append(url);
+ builder.append("]");
+ builder.append("(");
+ builder.append(url);
+ builder.append(")");
+
+ });
+
+ hoverContent.add(Either.forLeft(builder.toString()));
+ hoverContent.add(Either.forLeft("Process ID: " + processId));
+ hoverContent.add(Either.forLeft("Process Name: " + processName));
+ if (i < mappingMethods.size() - 1) {
+ // Three dashes == line separator in Markdown
+ hoverContent.add(Either.forLeft("---"));
}
}
-
- if (mappingPath != null) {
- if (Arrays.equals(mappingPath, rm.getSplitPath())) {
- if (methods == null || methods.isEmpty()) {
- return true;
- } else {
- return methods.equals(rm.getRequestMethods());
- }
- }
- }
- return false;
-
}
- private static String getExpressionValueAsString(Expression exp) {
- if (exp instanceof StringLiteral) {
- return ((StringLiteral)exp).getLiteralValue();
- } else if (exp instanceof QualifiedName) {
- return getExpressionValueAsString(((QualifiedName)exp).getName());
- } else if (exp instanceof SimpleName) {
- return ((SimpleName)exp).getIdentifier();
- } else {
- return null;
- }
- }
+// protected String getRequestMethod(SingleMemberAnnotation annotation) {
+// ITypeBinding type = annotation.resolveTypeBinding();
+// if (type != null) {
+// switch (type.getQualifiedName()) {
+// case Constants.SPRING_GET_MAPPING:
+// return "GET";
+// case Constants.SPRING_POST_MAPPING:
+// return "POST";
+// case Constants.SPRING_DELETE_MAPPING:
+// return "DELETE";
+// case Constants.SPRING_PUT_MAPPING:
+// return "PUT";
+// case Constants.SPRING_PATCH_MAPPING:
+// return "PATCH";
+// }
+// }
+// return null;
+// }
+//
+// private boolean matchesAnnotation(Annotation annotation, RequestMapping rm) {
+// String[] mappingPath = null;
+// Set methods = null;
+// if (annotation instanceof SingleMemberAnnotation) {
+// SingleMemberAnnotation singleAnnotation = (SingleMemberAnnotation) annotation;
+// Expression valueContent = singleAnnotation.getValue();
+// if (valueContent instanceof StringLiteral) {
+// mappingPath = new String[] { ((StringLiteral)valueContent).getLiteralValue() };
+// }
+// String method = getRequestMethod(singleAnnotation);
+// if (method != null) {
+// methods = new HashSet<>();
+// methods.add(method);
+// }
+// }
+// else if (annotation instanceof NormalAnnotation) {
+// List> values = ((NormalAnnotation) annotation).values();
+// for (Object value : values) {
+// if (value instanceof MemberValuePair) {
+// MemberValuePair pair = (MemberValuePair)value;
+// String name = pair.getName().toString();
+// switch (name) {
+// case "value":
+// case "path":
+// mappingPath = getPaths(pair.getValue());
+// break;
+// case "method":
+// methods = getRequestMethod(pair.getValue());
+// break;
+// }
+// }
+// }
+//
+// }
+//
+// if (mappingPath != null) {
+// if (Arrays.equals(mappingPath, rm.getSplitPath())) {
+// if (methods == null || methods.isEmpty()) {
+// return true;
+// } else {
+// return methods.equals(rm.getRequestMethods());
+// }
+// }
+// }
+// return false;
+// }
+//
+// private static String getExpressionValueAsString(Expression exp) {
+// if (exp instanceof StringLiteral) {
+// return ((StringLiteral)exp).getLiteralValue();
+// } else if (exp instanceof QualifiedName) {
+// return getExpressionValueAsString(((QualifiedName)exp).getName());
+// } else if (exp instanceof SimpleName) {
+// return ((SimpleName)exp).getIdentifier();
+// } else {
+// return null;
+// }
+// }
+//
+// @SuppressWarnings("unchecked")
+// private static String[] getPaths(Expression exp) {
+// if (exp instanceof ArrayInitializer) {
+// ArrayInitializer array = (ArrayInitializer) exp;
+// return ((List)array.expressions()).stream()
+// .map(e -> getExpressionValueAsString(e))
+// .filter(Objects::nonNull)
+// .toArray(String[]::new);
+// } else {
+// String rm = getExpressionValueAsString(exp);
+// if (rm != null) {
+// return new String[] { rm };
+// }
+// }
+// return null;
+// }
+//
+// @SuppressWarnings("unchecked")
+// private static Set getRequestMethod(Expression exp) {
+// if (exp instanceof ArrayInitializer) {
+// ArrayInitializer array = (ArrayInitializer) exp;
+// return ((List)array.expressions()).stream()
+// .map(e -> getExpressionValueAsString(e))
+// .filter(Objects::nonNull)
+// .collect(Collectors.toSet());
+// } else {
+// String rm = getExpressionValueAsString(exp);
+// if (rm != null) {
+// HashSet methods = new HashSet<>();
+// methods.add(rm);
+// }
+// }
+// return null;
+// }
- @SuppressWarnings("unchecked")
- private static String[] getPaths(Expression exp) {
- if (exp instanceof ArrayInitializer) {
- ArrayInitializer array = (ArrayInitializer) exp;
- return ((List)array.expressions()).stream()
- .map(e -> getExpressionValueAsString(e))
- .filter(Objects::nonNull)
- .toArray(String[]::new);
- } else {
- String rm = getExpressionValueAsString(exp);
- if (rm != null) {
- return new String[] { rm };
- }
- }
- return null;
- }
-
- @SuppressWarnings("unchecked")
- private static Set getRequestMethod(Expression exp) {
- if (exp instanceof ArrayInitializer) {
- ArrayInitializer array = (ArrayInitializer) exp;
- return ((List)array.expressions()).stream()
- .map(e -> getExpressionValueAsString(e))
- .filter(Objects::nonNull)
- .collect(Collectors.toSet());
- } else {
- String rm = getExpressionValueAsString(exp);
- if (rm != null) {
- HashSet methods = new HashSet<>();
- methods.add(rm);
- }
- }
- return null;
- }
-
- static class RequestMappingMethod {
-
- public final SpringBootApp app;
- public final RequestMapping requestMapping;
-
- public RequestMappingMethod(RequestMapping requestMapping, SpringBootApp app) {
- this.requestMapping = requestMapping;
- this.app = app;
- }
- }
}
diff --git a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/AutowiredHoverProviderTest.java b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/AutowiredHoverProviderTest.java
index 92224fc0a..8e0d05537 100644
--- a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/AutowiredHoverProviderTest.java
+++ b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/AutowiredHoverProviderTest.java
@@ -42,6 +42,7 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.ide.vscode.boot.java.autowired.AutowiredHoverProvider;
import org.springframework.ide.vscode.boot.java.autowired.SpringBootAppProvider;
+import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
@@ -82,7 +83,7 @@ public class AutowiredHoverProviderTest {
AutowiredHoverProvider provider = new AutowiredHoverProvider();
String beansJSON = new String(Files.readAllBytes(new File(directory, "runtime-bean-information.json").toPath()));
- Range hint = provider.getLiveHoverHint((Annotation)node, document, beansJSON);
+ Range hint = provider.getLiveHoverHint((Annotation)node, document, LiveBeansModel.parse(beansJSON));
assertNotNull(hint);
assertEquals(11, hint.getStart().getLine());
@@ -106,7 +107,7 @@ public class AutowiredHoverProviderTest {
ASTNode node = NodeFinder.perform(cu, offset, 0).getParent();
AutowiredHoverProvider provider = new AutowiredHoverProvider();
- Range hint = provider.getLiveHoverHint((Annotation)node, document, (String)null);
+ Range hint = provider.getLiveHoverHint((Annotation)node, document, LiveBeansModel.parse(null));
assertNull(hint);
}
@@ -127,7 +128,7 @@ public class AutowiredHoverProviderTest {
AutowiredHoverProvider provider = new AutowiredHoverProvider();
String beansJSON = new String(Files.readAllBytes(new File(directory, "wrong-runtime-bean-information.json").toPath()));
- Range hint = provider.getLiveHoverHint((Annotation)node, document, beansJSON);
+ Range hint = provider.getLiveHoverHint((Annotation)node, document, LiveBeansModel.parse(beansJSON));
assertNull(hint);
}
@@ -146,7 +147,7 @@ public class AutowiredHoverProviderTest {
ASTNode node = NodeFinder.perform(cu, offset, 0).getParent();
AutowiredHoverProvider provider = new AutowiredHoverProvider();
- String beansJSON = new String(Files.readAllBytes(new File(directory, "runtime-bean-information.json").toPath()));
+ LiveBeansModel beansModel = LiveBeansModel.parse(new String(Files.readAllBytes(new File(directory, "runtime-bean-information.json").toPath())));
SpringBootAppProvider bootApp = new SpringBootAppProvider() {
@Override
@@ -160,8 +161,8 @@ public class AutowiredHoverProviderTest {
}
@Override
- public String getBeans() throws Exception {
- return beansJSON;
+ public LiveBeansModel getBeans() throws Exception {
+ return beansModel;
}
};
CompletableFuture hoverFuture = provider.provideHover(null, (Annotation)node, null, offset, document, new SpringBootAppProvider[] {bootApp});
diff --git a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/ComponentHoverProviderTest.java b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/ComponentHoverProviderTest.java
index 397f0aa2c..2130f9d06 100644
--- a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/ComponentHoverProviderTest.java
+++ b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/ComponentHoverProviderTest.java
@@ -42,6 +42,7 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.ide.vscode.boot.java.autowired.SpringBootAppProvider;
import org.springframework.ide.vscode.boot.java.beans.ComponentHoverProvider;
+import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
@@ -82,7 +83,7 @@ public class ComponentHoverProviderTest {
ComponentHoverProvider provider = new ComponentHoverProvider();
String beansJSON = new String(Files.readAllBytes(new File(directory, "runtime-bean-information-automatically-wired.json").toPath()));
- Range hint = provider.getLiveHoverHint((Annotation)node, document, beansJSON);
+ Range hint = provider.getLiveHoverHint((Annotation)node, document, LiveBeansModel.parse(beansJSON));
assertNotNull(hint);
assertEquals(10, hint.getStart().getLine());
@@ -108,7 +109,7 @@ public class ComponentHoverProviderTest {
ComponentHoverProvider provider = new ComponentHoverProvider();
String beansJSON = new String(Files.readAllBytes(new File(directory, "runtime-bean-information.json").toPath()));
- Range hint = provider.getLiveHoverHint((Annotation)node, document, beansJSON);
+ Range hint = provider.getLiveHoverHint((Annotation)node, document, LiveBeansModel.parse(beansJSON));
assertNull(hint);
}
@@ -127,7 +128,7 @@ public class ComponentHoverProviderTest {
ASTNode node = NodeFinder.perform(cu, offset, 0).getParent();
ComponentHoverProvider provider = new ComponentHoverProvider();
- String beansJSON = new String(Files.readAllBytes(new File(directory, "runtime-bean-information-automatically-wired.json").toPath()));
+ LiveBeansModel beansModel = LiveBeansModel.parse(new String(Files.readAllBytes(new File(directory, "runtime-bean-information-automatically-wired.json").toPath())));
SpringBootAppProvider bootApp = new SpringBootAppProvider() {
@Override
@@ -141,8 +142,8 @@ public class ComponentHoverProviderTest {
}
@Override
- public String getBeans() throws Exception {
- return beansJSON;
+ public LiveBeansModel getBeans() throws Exception {
+ return beansModel;
}
};
CompletableFuture hoverFuture = provider.provideHover(null, (Annotation) node, null, 0, document, new SpringBootAppProvider[] {bootApp});
diff --git a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/conditionals/test/ConditionalsLiveHoverTest.java b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/conditionals/test/ConditionalsLiveHoverTest.java
index 5eaa0c273..cb887f67c 100644
--- a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/conditionals/test/ConditionalsLiveHoverTest.java
+++ b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/conditionals/test/ConditionalsLiveHoverTest.java
@@ -136,6 +136,66 @@ public class ConditionalsLiveHoverTest {
+ "Message: @ConditionalOnExpression (#{true}) resulted in true");
}
+
+ @Test
+ public void testMultipleAppsLiveHover() throws Exception {
+
+ File directory = new File(
+ ProjectsHarness.class.getResource("/test-projects/test-conditionals-live-hover/").toURI());
+ String docUri = "file://" + directory.getAbsolutePath()
+ + "/src/main/java/example/ConditionalOnMissingBeanConfig.java";
+
+ // Build a mock running boot app
+ mockAppProvider.builder().isSpringBootApp(true).port("1000").processId("70000").host("cfapps.io")
+ .processName("test-conditionals-live-hover")
+ .getAutoConfigReport(
+ "{\"positiveMatches\":{\"ConditionalOnMissingBeanConfig#missing\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\"}]}}")
+ .build();
+
+ mockAppProvider.builder().isSpringBootApp(true).port("1001").processId("80000").host("cfapps.io")
+ .processName("test-conditionals-live-hover")
+ .getAutoConfigReport(
+ "{\"positiveMatches\":{\"ConditionalOnMissingBeanConfig#missing\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\"}]}}")
+ .build();
+
+ mockAppProvider.builder().isSpringBootApp(true).port("1002").processId("90000").host("cfapps.io")
+ .processName("test-conditionals-live-hover")
+ .getAutoConfigReport(
+ "{\"positiveMatches\":{\"ConditionalOnMissingBeanConfig#missing\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\"}]}}")
+ .build();
+
+ harness.intialize(directory);
+
+ Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
+
+
+ editor.assertHoverContains("@ConditionalOnMissingBean", "Condition: OnBeanCondition\n" + "\n"
+ + "Message: @ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\n" +
+ "\n" +
+ "Process ID: 70000\n" +
+ "\n" +
+ "Process Name: test-conditionals-live-hover\n" +
+ "\n" +
+ "---\n" +
+ "\n" +
+ "Condition: OnBeanCondition\n" + "\n"
+ + "Message: @ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\n" +
+ "\n" +
+ "Process ID: 80000\n" +
+ "\n" +
+ "Process Name: test-conditionals-live-hover\n" +
+ "\n" +
+ "---\n" +
+ "\n" +
+ "Condition: OnBeanCondition\n" + "\n"
+ + "Message: @ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\n" +
+ "\n" +
+ "Process ID: 90000\n" +
+ "\n" +
+ "Process Name: test-conditionals-live-hover");
+
+ }
+
// @Test
// public void testMultipleLiveHoverHints() throws Exception {
//
diff --git a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingLiveHoverTest.java b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingLiveHoverTest.java
index 8ab9ea978..dd3455556 100644
--- a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingLiveHoverTest.java
+++ b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/requestmapping/test/RequestMappingLiveHoverTest.java
@@ -62,7 +62,7 @@ public class RequestMappingLiveHoverTest {
harness.intialize(directory);
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
- editor.assertHoverContains("@RequestMapping(\"/hello-world\")", "Path: [/hello-world](http://cfapps.io:1111/hello-world)\n" +
+ editor.assertHoverContains("@RequestMapping(\"/hello-world\")", "[http://cfapps.io:1111/hello-world](http://cfapps.io:1111/hello-world)\n" +
"\n" +
"Process ID: 22022\n" +
"\n" +
@@ -94,13 +94,13 @@ public class RequestMappingLiveHoverTest {
harness.intialize(directory);
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
- editor.assertHoverContains("@RequestMapping(\"/hello\")", "Path: [/hello](http://cfapps.io:999/hello)\n" +
+ editor.assertHoverContains("@RequestMapping(\"/hello\")", "[http://cfapps.io:999/hello](http://cfapps.io:999/hello)\n" +
"\n" +
"Process ID: 76543\n" +
"\n" +
"Process Name: test-request-mapping-live-hover");
- editor.assertHoverContains("@RequestMapping(\"/goodbye\")", "Path: [/goodbye](http://cfapps.io:999/goodbye)\n" +
+ editor.assertHoverContains("@RequestMapping(\"/goodbye\")", "[http://cfapps.io:999/goodbye](http://cfapps.io:999/goodbye)\n" +
"\n" +
"Process ID: 76543\n" +
"\n" +
@@ -133,7 +133,7 @@ public class RequestMappingLiveHoverTest {
}
@Test
- public void testDeleteMappingHoverHintMethod1() throws Exception {
+ public void testSimpleMethodHoverHintMethod1() throws Exception {
File directory = new File(
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
@@ -171,7 +171,7 @@ public class RequestMappingLiveHoverTest {
"}",
docUri);
- editor.assertHoverContains("@DeleteMapping(\"/greetings\")", "Path: [/greetings](http://cfapps.io:999/greetings)\n" +
+ editor.assertHoverContains("@DeleteMapping(\"/greetings\")", "[http://cfapps.io:999/greetings](http://cfapps.io:999/greetings)\n" +
"\n" +
"Process ID: 76543\n" +
"\n" +
@@ -198,7 +198,7 @@ public class RequestMappingLiveHoverTest {
// Ugly, but this is real JSON copied from a real live running app. We want the
// mock app to return realistic results if possible
.getRequestMappings(
- "{\"{[/greetings],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.deleteGreetings()\"}}")
+ "{\"{[/greetings],methods=[DELETE]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public void com.example.RestApi.deleteGreetings()\"}}")
. build();
harness.intialize(directory);
@@ -213,7 +213,7 @@ public class RequestMappingLiveHoverTest {
"public class RestApi {\n" +
"\n" +
"@DeleteMapping(\"/greetings\")\n" +
- "public void deleteGreetings() {\n" +
+ "public void deleteGreetings(int n) {\n" +
"}\n" +
"\n" +
"}",
@@ -223,8 +223,11 @@ public class RequestMappingLiveHoverTest {
}
+
+
+
@Test
- public void testGetMappingHoverHintMethod1() throws Exception {
+ public void testNoHoverHintMethod() throws Exception {
File directory = new File(
ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
@@ -241,56 +244,7 @@ public class RequestMappingLiveHoverTest {
// Ugly, but this is real JSON copied from a real live running app. We want the
// mock app to return realistic results if possible
.getRequestMappings(
- "{\"{[/greetings],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.greetings()\"}}")
- . build();
-
- harness.intialize(directory);
-
- Editor editor = harness.newEditor(LanguageId.JAVA,
- "package com.example;\n" +
- "\n" +
- "import java.lang.String;\n" +
- "import org.springframework.stereotype.Controller;\n" +
- "import org.springframework.web.bind.annotation.GetMapping;\n" +
- "\n" +
- "@Controller\n" +
- "public class RestApi {\n" +
- "\n" +
- "@GetMapping(\"/greetings\")\n" +
- "public String greetings() {\n" +
- "return \"Greetings!\";\n" +
- "}\n" +
- "\n" +
- "}",
- docUri);
-
- editor.assertHoverContains("@GetMapping(\"/greetings\")", "Path: [/greetings](http://cfapps.io:999/greetings)\n" +
- "\n" +
- "Process ID: 76543\n" +
- "\n" +
- "Process Name: test-request-mapping-live-hover");
-
- }
-
- @Test
- public void testGetMappingHoverHintMethod2() throws Exception {
-
- File directory = new File(
- ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
- String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
-
-
- // Build a mock running boot app
- mockAppProvider.builder()
- .isSpringBootApp(true)
- .port("999")
- .processId("76543")
- .host("cfapps.io")
- .processName("test-request-mapping-live-hover")
- // Ugly, but this is real JSON copied from a real live running app. We want the
- // mock app to return realistic results if possible
- .getRequestMappings(
- "{\"{[/greetings],methods=[DELETE]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.greetings()\"}}")
+ "{\"{[/greetings],methods=[PUT]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.updateGreetings()\"}}")
. build();
harness.intialize(directory);
@@ -300,194 +254,13 @@ public class RequestMappingLiveHoverTest {
"\n" +
"import java.lang.String;\n" +
"import org.springframework.stereotype.Controller;\n" +
- "import org.springframework.web.bind.annotation.GetMapping;\n" +
- "\n" +
- "@Controller\n" +
- "public class RestApi {\n" +
- "\n" +
- "@GetMapping(\"/greetings\")\n" +
- "public String greetings() {\n" +
- "return \"Greetings!\";\n" +
- "}\n" +
- "\n" +
- "}",
- docUri);
-
- editor.assertNoHover("@GetMapping(\"/greetings\")");
-
- }
-
- @Test
- public void testPostMappingHoverHintMethod1() throws Exception {
-
- File directory = new File(
- ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
- String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
-
-
- // Build a mock running boot app
- mockAppProvider.builder()
- .isSpringBootApp(true)
- .port("999")
- .processId("76543")
- .host("cfapps.io")
- .processName("test-request-mapping-live-hover")
- // Ugly, but this is real JSON copied from a real live running app. We want the
- // mock app to return realistic results if possible
- .getRequestMappings(
- "{\"{[/greetings],methods=[POST]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public void com.example.RestApi.createGreetings()\"}}")
- . build();
-
- harness.intialize(directory);
-
- Editor editor = harness.newEditor(LanguageId.JAVA,
- "package com.example;\n" +
- "\n" +
- "import org.springframework.stereotype.Controller;\n" +
- "import org.springframework.web.bind.annotation.PostMapping;\n" +
- "\n" +
- "@Controller\n" +
- "public class RestApi {\n" +
- "\n" +
- "@PostMapping(\"/greetings\")\n" +
- "public void createGreetings() {\n" +
- "}\n" +
- "\n" +
- "}",
- docUri);
-
- editor.assertHoverContains("@PostMapping(\"/greetings\")", "Path: [/greetings](http://cfapps.io:999/greetings)\n" +
- "\n" +
- "Process ID: 76543\n" +
- "\n" +
- "Process Name: test-request-mapping-live-hover");
-
- }
-
- @Test
- public void testPostMappingHoverHintMethod2() throws Exception {
-
- File directory = new File(
- ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
- String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
-
-
- // Build a mock running boot app
- mockAppProvider.builder()
- .isSpringBootApp(true)
- .port("999")
- .processId("76543")
- .host("cfapps.io")
- .processName("test-request-mapping-live-hover")
- // Ugly, but this is real JSON copied from a real live running app. We want the
- // mock app to return realistic results if possible
- .getRequestMappings(
- "{\"{[/greetings],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.createGreetings()\"}}")
- . build();
-
- harness.intialize(directory);
-
- Editor editor = harness.newEditor(LanguageId.JAVA,
- "package com.example;\n" +
- "\n" +
- "import org.springframework.stereotype.Controller;\n" +
- "import org.springframework.web.bind.annotation.PostMapping;\n" +
- "\n" +
- "@Controller\n" +
- "public class RestApi {\n" +
- "\n" +
- "@PostMapping(\"/greetings\")\n" +
- "public void createGreetings() {\n" +
- "}\n" +
- "\n" +
- "}",
- docUri);
-
- editor.assertNoHover("@PostMapping(\"/greetings\")");
-
- }
-
- @Test
- public void testPutMappingHoverHintMethod1() throws Exception {
-
- File directory = new File(
- ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
- String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
-
-
- // Build a mock running boot app
- mockAppProvider.builder()
- .isSpringBootApp(true)
- .port("999")
- .processId("76543")
- .host("cfapps.io")
- .processName("test-request-mapping-live-hover")
- // Ugly, but this is real JSON copied from a real live running app. We want the
- // mock app to return realistic results if possible
- .getRequestMappings(
- "{\"{[/greetings],methods=[PUT]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public void com.example.RestApi.updateGreetings()\"}}")
- . build();
-
- harness.intialize(directory);
-
- Editor editor = harness.newEditor(LanguageId.JAVA,
- "package com.example;\n" +
- "\n" +
- "import org.springframework.stereotype.Controller;\n" +
"import org.springframework.web.bind.annotation.PutMapping;\n" +
"\n" +
"@Controller\n" +
"public class RestApi {\n" +
"\n" +
"@PutMapping(\"/greetings\")\n" +
- "public void updateGreetings() {\n" +
- "}\n" +
- "\n" +
- "}",
- docUri);
-
- editor.assertHoverContains("@PutMapping(\"/greetings\")", "Path: [/greetings](http://cfapps.io:999/greetings)\n" +
- "\n" +
- "Process ID: 76543\n" +
- "\n" +
- "Process Name: test-request-mapping-live-hover");
-
- }
-
- @Test
- public void testPutMappingHoverHintMethod2() throws Exception {
-
- File directory = new File(
- ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
- String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
-
-
- // Build a mock running boot app
- mockAppProvider.builder()
- .isSpringBootApp(true)
- .port("999")
- .processId("76543")
- .host("cfapps.io")
- .processName("test-request-mapping-live-hover")
- // Ugly, but this is real JSON copied from a real live running app. We want the
- // mock app to return realistic results if possible
- .getRequestMappings(
- "{\"{[/greetings],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.updateGreetings()\"}}")
- . build();
-
- harness.intialize(directory);
-
- Editor editor = harness.newEditor(LanguageId.JAVA,
- "package com.example;\n" +
- "\n" +
- "import org.springframework.stereotype.Controller;\n" +
- "import org.springframework.web.bind.annotation.PutMapping;\n" +
- "\n" +
- "@Controller\n" +
- "public class RestApi {\n" +
- "\n" +
- "@PutMapping(\"/greetings\")\n" +
- "public void updateGreetings() {\n" +
+ "public String updateGreetings(int n) {\n" +
"}\n" +
"\n" +
"}",
@@ -497,188 +270,6 @@ public class RequestMappingLiveHoverTest {
}
- @Test
- public void testPatchMappingHoverHintMethod1() throws Exception {
-
- File directory = new File(
- ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
- String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
-
-
- // Build a mock running boot app
- mockAppProvider.builder()
- .isSpringBootApp(true)
- .port("999")
- .processId("76543")
- .host("cfapps.io")
- .processName("test-request-mapping-live-hover")
- // Ugly, but this is real JSON copied from a real live running app. We want the
- // mock app to return realistic results if possible
- .getRequestMappings(
- "{\"{[/greetings],methods=[PATCH]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public void com.example.RestApi.patchGreetings()\"}}")
- . build();
-
- harness.intialize(directory);
-
- Editor editor = harness.newEditor(LanguageId.JAVA,
- "package com.example;\n" +
- "\n" +
- "import org.springframework.stereotype.Controller;\n" +
- "import org.springframework.web.bind.annotation.PatchMapping;\n" +
- "\n" +
- "@Controller\n" +
- "public class RestApi {\n" +
- "\n" +
- "@PatchMapping(\"/greetings\")\n" +
- "public void patchGreetings() {\n" +
- "}\n" +
- "\n" +
- "}",
- docUri);
-
- editor.assertHoverContains("@PatchMapping(\"/greetings\")", "Path: [/greetings](http://cfapps.io:999/greetings)\n" +
- "\n" +
- "Process ID: 76543\n" +
- "\n" +
- "Process Name: test-request-mapping-live-hover");
-
- }
-
- @Test
- public void testPatchMappingHoverHintMethod2() throws Exception {
-
- File directory = new File(
- ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
- String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
-
-
- // Build a mock running boot app
- mockAppProvider.builder()
- .isSpringBootApp(true)
- .port("999")
- .processId("76543")
- .host("cfapps.io")
- .processName("test-request-mapping-live-hover")
- // Ugly, but this is real JSON copied from a real live running app. We want the
- // mock app to return realistic results if possible
- .getRequestMappings(
- "{\"{[/greetings],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.patchGreetings()\"}}")
- . build();
-
- harness.intialize(directory);
-
- Editor editor = harness.newEditor(LanguageId.JAVA,
- "package com.example;\n" +
- "\n" +
- "import org.springframework.stereotype.Controller;\n" +
- "import org.springframework.web.bind.annotation.PatchMapping;\n" +
- "\n" +
- "@Controller\n" +
- "public class RestApi {\n" +
- "\n" +
- "@PatchMapping(\"/greetings\")\n" +
- "public void patchGreetings() {\n" +
- "}\n" +
- "\n" +
- "}",
- docUri);
-
- editor.assertNoHover("@PatchMapping(\"/greetings\")");
-
- }
-
- @Test
- public void testMultiRequestMethodMappingHoverHintMethod1() throws Exception {
-
- File directory = new File(
- ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
- String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
-
-
- // Build a mock running boot app
- mockAppProvider.builder()
- .isSpringBootApp(true)
- .port("999")
- .processId("76543")
- .host("cfapps.io")
- .processName("test-request-mapping-live-hover")
- // Ugly, but this is real JSON copied from a real live running app. We want the
- // mock app to return realistic results if possible
- .getRequestMappings(
- "{\"{[/greetings],methods=[POST,PUT]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public void com.example.RestApi.updateGreetings()\"}}")
- . build();
-
- harness.intialize(directory);
-
- Editor editor = harness.newEditor(LanguageId.JAVA,
- "package com.example;\n" +
- "\n" +
- "import org.springframework.stereotype.Controller;\n" +
- "import org.springframework.web.bind.annotation.RequestMapping;\n" +
- "import org.springframework.web.bind.annotation.RequestMethod.*;\n" +
- "\n" +
- "@Controller\n" +
- "public class RestApi {\n" +
- "\n" +
- "@RequestMapping(value=\"/greetings\", method={POST, PUT})\n" +
- "public void updateGreetings() {\n" +
- "}\n" +
- "\n" +
- "}",
- docUri);
-
- editor.assertHoverContains("@RequestMapping(value=\"/greetings\", method={POST, PUT})", "Path: [/greetings](http://cfapps.io:999/greetings)\n" +
- "\n" +
- "Process ID: 76543\n" +
- "\n" +
- "Process Name: test-request-mapping-live-hover");
-
- }
-
- @Test
- public void testMultiRequestMethodMappingHoverHintMethod2() throws Exception {
-
- File directory = new File(
- ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
- String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
-
-
- // Build a mock running boot app
- mockAppProvider.builder()
- .isSpringBootApp(true)
- .port("999")
- .processId("76543")
- .host("cfapps.io")
- .processName("test-request-mapping-live-hover")
- // Ugly, but this is real JSON copied from a real live running app. We want the
- // mock app to return realistic results if possible
- .getRequestMappings(
- "{\"{[/greetings],methods=[POST,PUT,PATCH]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.updateGreetings()\"}}")
- . build();
-
- harness.intialize(directory);
-
- Editor editor = harness.newEditor(LanguageId.JAVA,
- "package com.example;\n" +
- "\n" +
- "import org.springframework.stereotype.Controller;\n" +
- "import org.springframework.web.bind.annotation.RequestMapping;\n" +
- "import org.springframework.web.bind.annotation.RequestMethod.*;\n" +
- "\n" +
- "@Controller\n" +
- "public class RestApi {\n" +
- "\n" +
- "@RequestMapping(value=\"/greetings\", method={POST, PUT})\n" +
- "public void updateGreetings() {\n" +
- "}\n" +
- "\n" +
- "}",
- docUri);
-
- editor.assertNoHover("@RequestMapping(value=\"/greetings\", method={POST, PUT})");
-
- }
-
@Test
public void testMultiPathMappingHoverHintMethod1() throws Exception {
@@ -719,8 +310,8 @@ public class RequestMappingLiveHoverTest {
"}",
docUri);
- editor.assertHoverContains("@RequestMapping(value={\"/greetings\", \"/hello\"}, method=GET)", "Path: [/greetings](http://cfapps.io:999/greetings)\n" +
- "Path: [/hello](http://cfapps.io:999/hello)\n" +
+ editor.assertHoverContains("@RequestMapping(value={\"/greetings\", \"/hello\"}, method=GET)", "[http://cfapps.io:999/greetings](http://cfapps.io:999/greetings)\n" +
+ "[http://cfapps.io:999/hello](http://cfapps.io:999/hello)\n" +
"\n" +
"Process ID: 76543\n" +
"\n" +
@@ -728,50 +319,6 @@ public class RequestMappingLiveHoverTest {
}
- @Test
- public void testMultiPathMappingHoverHintMethod2() throws Exception {
-
- File directory = new File(
- ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
- String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
-
-
- // Build a mock running boot app
- mockAppProvider.builder()
- .isSpringBootApp(true)
- .port("999")
- .processId("76543")
- .host("cfapps.io")
- .processName("test-request-mapping-live-hover")
- // Ugly, but this is real JSON copied from a real live running app. We want the
- // mock app to return realistic results if possible
- .getRequestMappings(
- "{\"{[/greetings || /hello || /helloAgain],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.String com.example.RestApi.greetings()\"}}")
- . build();
-
- harness.intialize(directory);
-
- Editor editor = harness.newEditor(LanguageId.JAVA,
- "package com.example;\n" +
- "\n" +
- "import org.springframework.stereotype.Controller;\n" +
- "import org.springframework.web.bind.annotation.RequestMapping;\n" +
- "import org.springframework.web.bind.annotation.RequestMethod.*;\n" +
- "\n" +
- "@Controller\n" +
- "public class RestApi {\n" +
- "\n" +
- "@RequestMapping(value={\"/greetings\", \"/hello\"}, method=GET)\n" +
- "public String greetings() {\n" +
- "}\n" +
- "\n" +
- "}",
- docUri);
-
- editor.assertNoHover("@RequestMapping(value={\"/greetings\", \"/hello\"}, method=GET)");
-
- }
-
@Test
public void testMethodMatchingHoverHintMethod1() throws Exception {
@@ -816,7 +363,7 @@ public class RequestMappingLiveHoverTest {
"}",
docUri);
- editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "Path: [/find](http://cfapps.io:999/find)\n" +
+ editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "[http://cfapps.io:999/find](http://cfapps.io:999/find)\n" +
"\n" +
"Process ID: 76543\n" +
"\n" +
@@ -868,7 +415,7 @@ public class RequestMappingLiveHoverTest {
"}",
docUri);
- editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "Path: [/find](http://cfapps.io:999/find)\n" +
+ editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "[http://cfapps.io:999/find](http://cfapps.io:999/find)\n" +
"\n" +
"Process ID: 76543\n" +
"\n" +
@@ -921,7 +468,7 @@ public class RequestMappingLiveHoverTest {
"}",
docUri);
- editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "Path: [/find](http://cfapps.io:999/find)\n" +
+ editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "[http://cfapps.io:999/find](http://cfapps.io:999/find)\n" +
"\n" +
"Process ID: 76543\n" +
"\n" +
@@ -929,5 +476,280 @@ public class RequestMappingLiveHoverTest {
}
+ @Test
+ public void testWildCardMethodMatchingHoverHint() throws Exception {
+
+ File directory = new File(
+ ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
+ String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
+
+
+ // Build a mock running boot app
+ mockAppProvider.builder()
+ .isSpringBootApp(true)
+ .port("999")
+ .processId("76543")
+ .host("cfapps.io")
+ .processName("test-request-mapping-live-hover")
+ // Ugly, but this is real JSON copied from a real live running app. We want the
+ // mock app to return realistic results if possible
+ .getRequestMappings(
+ "{\"{[/find],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.Object com.example.RestApi.set(java.lang.String,java.util.Map>)\"}}")
+ . build();
+
+ harness.intialize(directory);
+
+ Editor editor = harness.newEditor(LanguageId.JAVA,
+ "package com.example;\n" +
+ "\n" +
+ "import org.springframework.http.ResponseEntity;\n" +
+ "import java.lang.String;\n" +
+ "import java.lang.Integer;\n" +
+ "import java.util.Map;\n" +
+ "import org.springframework.stereotype.Controller;\n" +
+ "import org.springframework.web.bind.annotation.RequestMapping;\n" +
+ "import org.springframework.web.bind.annotation.RequestMethod.*;\n" +
+ "\n" +
+ "@Controller\n" +
+ "public class RestApi {\n" +
+ "\n" +
+ "@RequestMapping(value=\"/find\", method=GET)\n" +
+ "public Object set(String p1, Map> p2) {\n" +
+ "return null;\n" +
+ "}\n" +
+ "\n" +
+ "}",
+ docUri);
+
+ editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "[http://cfapps.io:999/find](http://cfapps.io:999/find)\n" +
+ "\n" +
+ "Process ID: 76543\n" +
+ "\n" +
+ "Process Name: test-request-mapping-live-hover");
+
+ }
+
+ @Test
+ public void testArrayMethodMatchingHoverHint() throws Exception {
+
+ File directory = new File(
+ ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
+ String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
+
+
+ // Build a mock running boot app
+ mockAppProvider.builder()
+ .isSpringBootApp(true)
+ .port("999")
+ .processId("76543")
+ .host("cfapps.io")
+ .processName("test-request-mapping-live-hover")
+ // Ugly, but this is real JSON copied from a real live running app. We want the
+ // mock app to return realistic results if possible
+ .getRequestMappings(
+ "{\"{[/find],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.Object com.example.RestApi.set(java.lang.String[])\"}}")
+ . build();
+
+ harness.intialize(directory);
+
+ Editor editor = harness.newEditor(LanguageId.JAVA,
+ "package com.example;\n" +
+ "\n" +
+ "import org.springframework.http.ResponseEntity;\n" +
+ "import java.lang.String;\n" +
+ "import org.springframework.stereotype.Controller;\n" +
+ "import org.springframework.web.bind.annotation.RequestMapping;\n" +
+ "import org.springframework.web.bind.annotation.RequestMethod.*;\n" +
+ "\n" +
+ "@Controller\n" +
+ "public class RestApi {\n" +
+ "\n" +
+ "@RequestMapping(value=\"/find\", method=GET)\n" +
+ "public Object set(String[] p) {\n" +
+ "return null;\n" +
+ "}\n" +
+ "\n" +
+ "}",
+ docUri);
+
+ editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "[http://cfapps.io:999/find](http://cfapps.io:999/find)\n" +
+ "\n" +
+ "Process ID: 76543\n" +
+ "\n" +
+ "Process Name: test-request-mapping-live-hover");
+
+ }
+
+ @Test
+ public void testMultiDimensionalArrayMethodMatchingHoverHint() throws Exception {
+
+ File directory = new File(
+ ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
+ String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
+
+
+ // Build a mock running boot app
+ mockAppProvider.builder()
+ .isSpringBootApp(true)
+ .port("999")
+ .processId("76543")
+ .host("cfapps.io")
+ .processName("test-request-mapping-live-hover")
+ // Ugly, but this is real JSON copied from a real live running app. We want the
+ // mock app to return realistic results if possible
+ .getRequestMappings(
+ "{\"{[/find],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.Object com.example.RestApi.set(java.lang.String[][])\"}}")
+ . build();
+
+ harness.intialize(directory);
+
+ Editor editor = harness.newEditor(LanguageId.JAVA,
+ "package com.example;\n" +
+ "\n" +
+ "import org.springframework.http.ResponseEntity;\n" +
+ "import java.lang.String;\n" +
+ "import org.springframework.stereotype.Controller;\n" +
+ "import org.springframework.web.bind.annotation.RequestMapping;\n" +
+ "import org.springframework.web.bind.annotation.RequestMethod.*;\n" +
+ "\n" +
+ "@Controller\n" +
+ "public class RestApi {\n" +
+ "\n" +
+ "@RequestMapping(value=\"/find\", method=GET)\n" +
+ "public Object set(String[][] p) {\n" +
+ "return null;\n" +
+ "}\n" +
+ "\n" +
+ "}",
+ docUri);
+
+ editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "[http://cfapps.io:999/find](http://cfapps.io:999/find)\n" +
+ "\n" +
+ "Process ID: 76543\n" +
+ "\n" +
+ "Process Name: test-request-mapping-live-hover");
+
+ }
+
+ @Test
+ public void testVarArgsMethodMatchingHoverHint() throws Exception {
+
+ File directory = new File(
+ ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
+ String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
+
+
+ // Build a mock running boot app
+ mockAppProvider.builder()
+ .isSpringBootApp(true)
+ .port("999")
+ .processId("76543")
+ .host("cfapps.io")
+ .processName("test-request-mapping-live-hover")
+ // Ugly, but this is real JSON copied from a real live running app. We want the
+ // mock app to return realistic results if possible
+ .getRequestMappings(
+ "{\"{[/find],methods=[GET]}\": {\"bean\": \"requestMappingHandlerMapping\", \"method\":\"public java.lang.Object com.example.RestApi.set(java.lang.String...)\"}}")
+ . build();
+
+ harness.intialize(directory);
+
+ Editor editor = harness.newEditor(LanguageId.JAVA,
+ "package com.example;\n" +
+ "\n" +
+ "import org.springframework.http.ResponseEntity;\n" +
+ "import java.lang.String;\n" +
+ "import org.springframework.stereotype.Controller;\n" +
+ "import org.springframework.web.bind.annotation.RequestMapping;\n" +
+ "import org.springframework.web.bind.annotation.RequestMethod.*;\n" +
+ "\n" +
+ "@Controller\n" +
+ "public class RestApi {\n" +
+ "\n" +
+ "@RequestMapping(value=\"/find\", method=GET)\n" +
+ "public Object set(String... p) {\n" +
+ "return null;\n" +
+ "}\n" +
+ "\n" +
+ "}",
+ docUri);
+
+ editor.assertHoverContains("@RequestMapping(value=\"/find\", method=GET)", "[http://cfapps.io:999/find](http://cfapps.io:999/find)\n" +
+ "\n" +
+ "Process ID: 76543\n" +
+ "\n" +
+ "Process Name: test-request-mapping-live-hover");
+
+ }
+
+ @Test
+ public void testMultipleAppsLiveHover() throws Exception {
+
+ File directory = new File(
+ ProjectsHarness.class.getResource("/test-projects/test-request-mapping-live-hover/").toURI());
+ String docUri = "file://" +directory.getAbsolutePath() + "/src/main/java/example/RestApi.java";
+
+ // Build three different instances of the same app running on different ports with different process IDs
+ mockAppProvider.builder()
+ .isSpringBootApp(true)
+ .port("1000")
+ .processId("70000")
+ .host("cfapps.io")
+ .processName("test-request-mapping-live-hover")
+ // Ugly, but this is real JSON copied from a real live running app. We want the
+ // mock app to return realistic results if possible
+ .getRequestMappings(
+ "{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
+ . build();
+
+ mockAppProvider.builder()
+ .isSpringBootApp(true)
+ .port("1001")
+ .processId("80000")
+ .host("cfapps.io")
+ .processName("test-request-mapping-live-hover")
+ // Ugly, but this is real JSON copied from a real live running app. We want the
+ // mock app to return realistic results if possible
+ .getRequestMappings(
+ "{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
+ . build();
+
+ mockAppProvider.builder()
+ .isSpringBootApp(true)
+ .port("1002")
+ .processId("90000")
+ .host("cfapps.io")
+ .processName("test-request-mapping-live-hover")
+ // Ugly, but this is real JSON copied from a real live running app. We want the
+ // mock app to return realistic results if possible
+ .getRequestMappings(
+ "{\"/webjars/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**\":{\"bean\":\"resourceHandlerMapping\"},\"/**/favicon.ico\":{\"bean\":\"faviconHandlerMapping\"},\"{[/hello-world],methods=[GET]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public example.Greeting example.HelloWorldController.sayHello(java.lang.String)\"},\"{[/goodbye]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.goodbye()\"},\"{[/hello]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public java.lang.String example.RestApi.hello()\"},\"{[/error]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.http.ResponseEntity> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)\"},\"{[/error],produces=[text/html]}\":{\"bean\":\"requestMappingHandlerMapping\",\"method\":\"public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)\"}}")
+ . build();
+ harness.intialize(directory);
+
+ Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
+ editor.assertHoverContains("@RequestMapping(\"/hello\")", "[http://cfapps.io:1000/hello](http://cfapps.io:1000/hello)\n" +
+ "\n" +
+ "Process ID: 70000\n" +
+ "\n" +
+ "Process Name: test-request-mapping-live-hover\n" +
+ "\n" +
+ "---\n" +
+ "\n" +
+ "[http://cfapps.io:1001/hello](http://cfapps.io:1001/hello)\n" +
+ "\n" +
+ "Process ID: 80000\n" +
+ "\n" +
+ "Process Name: test-request-mapping-live-hover\n" +
+ "\n" +
+ "---\n" +
+ "\n" +
+ "[http://cfapps.io:1002/hello](http://cfapps.io:1002/hello)\n" +
+ "\n" +
+ "Process ID: 90000\n" +
+ "\n" +
+ "Process Name: test-request-mapping-live-hover");
+
+ }
}
diff --git a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/project/harness/MockRunningAppProvider.java b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/project/harness/MockRunningAppProvider.java
index 718e6319f..7710f8c01 100644
--- a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/project/harness/MockRunningAppProvider.java
+++ b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/project/harness/MockRunningAppProvider.java
@@ -20,6 +20,7 @@ import org.mockito.Mockito;
import org.springframework.ide.vscode.boot.java.handlers.RunningAppProvider;
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
import org.springframework.ide.vscode.commons.boot.app.cli.requestmappings.RequestMapping;
+import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
import com.google.common.collect.ImmutableList;
@@ -67,7 +68,7 @@ public class MockRunningAppProvider {
}
public MockAppBuilder beans(String beans) throws Exception {
- when(app.getBeans()).thenReturn(beans);
+ when(app.getBeans()).thenReturn(LiveBeansModel.parse(beans));
return this;
}
diff --git a/headless-services/commons/commons-boot-app-cli/pom.xml b/headless-services/commons/commons-boot-app-cli/pom.xml
index d5c478053..d1ce1a918 100644
--- a/headless-services/commons/commons-boot-app-cli/pom.xml
+++ b/headless-services/commons/commons-boot-app-cli/pom.xml
@@ -24,6 +24,11 @@
jackson-databind
2.8.8.1
+
+ commons-io
+ commons-io
+ ${commons-io-version}
+
com.sun
diff --git a/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/SpringBootApp.java b/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/SpringBootApp.java
index d69e5d1d2..8433882ee 100644
--- a/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/SpringBootApp.java
+++ b/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/SpringBootApp.java
@@ -34,7 +34,9 @@ import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.ide.vscode.commons.boot.app.cli.requestmappings.RequestMapping;
import org.springframework.ide.vscode.commons.boot.app.cli.requestmappings.RequestMappingImpl1;
+import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
import org.springframework.ide.vscode.commons.util.Log;
+import org.springframework.ide.vscode.commons.util.StringUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableList;
@@ -174,7 +176,7 @@ public class SpringBootApp {
return null;
}
- public String getBeans() throws Exception {
+ private String getBeansJson() throws Exception {
Object result = getActuatorDataFromAttribute("org.springframework.boot:type=Endpoint,name=beansEndpoint", "Data");
if (result != null) {
String beans = new ObjectMapper().writeValueAsString(result);
@@ -190,6 +192,14 @@ public class SpringBootApp {
return null;
}
+ public LiveBeansModel getBeans() throws Exception {
+ String json = getBeansJson();
+ if (StringUtil.hasText(json)) {
+ return LiveBeansModel.parse(json);
+ }
+ return null;
+ }
+
public static Collection parseRequestMappingsJson(String json) {
JSONObject obj = new JSONObject(json);
Iterator keys = obj.keys();
diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/LiveBean.java b/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/livebean/LiveBean.java
similarity index 62%
rename from headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/LiveBean.java
rename to headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/livebean/LiveBean.java
index 6e7b29cde..2b20ad27a 100644
--- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/autowired/LiveBean.java
+++ b/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/livebean/LiveBean.java
@@ -8,37 +8,17 @@
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
-package org.springframework.ide.vscode.boot.java.autowired;
+package org.springframework.ide.vscode.commons.boot.app.cli.livebean;
import org.json.JSONArray;
import org.json.JSONObject;
/**
* @author Martin Lippert
+ * @author Kris De Volder
*/
public class LiveBean {
- public static LiveBean parse(JSONObject beansJSON) {
- String id = beansJSON.optString("bean");
- String type = beansJSON.optString("type");
- String scope = beansJSON.optString("scope");
- String resource = beansJSON.optString("resource");
-
- JSONArray aliasesJSON = beansJSON.getJSONArray("aliases");
- String[] aliases = new String[aliasesJSON.length()];
- for (int i = 0; i < aliasesJSON.length(); i++) {
- aliases[i] = aliasesJSON.optString(i);
- }
-
- JSONArray dependenciesJSON = beansJSON.getJSONArray("dependencies");
- String[] dependencies = new String[dependenciesJSON.length()];
- for (int i = 0; i < dependenciesJSON.length(); i++) {
- dependencies[i] = dependenciesJSON.optString(i);
- }
-
- return new LiveBean(id, aliases, scope, type, resource, dependencies);
- }
-
private final String id;
private final String[] aliases;
private final String scope;
diff --git a/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/livebean/LiveBeansModel.java b/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/livebean/LiveBeansModel.java
new file mode 100644
index 000000000..5ea7cbf83
--- /dev/null
+++ b/headless-services/commons/commons-boot-app-cli/src/main/java/org/springframework/ide/vscode/commons/boot/app/cli/livebean/LiveBeansModel.java
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springframework.ide.vscode.commons.boot.app.cli.livebean;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.stream.Stream;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.springframework.ide.vscode.commons.util.Log;
+import org.springframework.ide.vscode.commons.util.StringUtil;
+
+/**
+ * @author Martin Lippert
+ */
+public class LiveBeansModel {
+
+ interface Parser {
+ LiveBeansModel parse(String json) throws Exception;
+ }
+
+ private static class Boot15Parser implements Parser {
+ @Override
+ public LiveBeansModel parse(String json) throws Exception {
+ LiveBeansModel model = new LiveBeansModel();
+ JSONArray mainArray = new JSONArray(json);
+ for (int i = 0; i < mainArray.length(); i++) {
+ JSONObject appContext = mainArray.getJSONObject(i);
+ if (appContext == null) continue;
+
+ JSONArray beansArray = appContext.optJSONArray("beans");
+ if (beansArray == null) continue;
+
+ for (int j = 0; j < beansArray.length(); j++) {
+ JSONObject beanObject = beansArray.getJSONObject(j);
+ if (beanObject == null) continue;
+
+ LiveBean bean = parseBean(beanObject);
+ if (bean != null) {
+ model.add(bean);
+ }
+ }
+ }
+ return model;
+ }
+ private LiveBean parseBean(JSONObject beansJSON) {
+ String id = beansJSON.optString("bean");
+ String type = beansJSON.optString("type");
+ String scope = beansJSON.optString("scope");
+ String resource = beansJSON.optString("resource");
+
+ JSONArray aliasesJSON = beansJSON.getJSONArray("aliases");
+ String[] aliases = new String[aliasesJSON.length()];
+ for (int i = 0; i < aliasesJSON.length(); i++) {
+ aliases[i] = aliasesJSON.optString(i);
+ }
+
+ JSONArray dependenciesJSON = beansJSON.getJSONArray("dependencies");
+ String[] dependencies = new String[dependenciesJSON.length()];
+ for (int i = 0; i < dependenciesJSON.length(); i++) {
+ dependencies[i] = dependenciesJSON.optString(i);
+ }
+
+ return new LiveBean(id, aliases, scope, type, resource, dependencies);
+ }
+
+ }
+
+ private static class Boot20Parser implements Parser {
+ @Override
+ public LiveBeansModel parse(String json) throws Exception {
+ LiveBeansModel model = new LiveBeansModel();
+ JSONObject mainObject = new JSONObject(json);
+ JSONObject beansObject = mainObject.getJSONObject("beans");
+ for (String id : beansObject.keySet()) {
+ JSONObject beanObject = beansObject.getJSONObject(id);
+ System.out.println(beanObject.toString(3));
+ LiveBean bean = parseBean(id, beanObject);
+ if (bean!=null) {
+ model.add(bean);
+ }
+ }
+ return model;
+ }
+
+ private LiveBean parseBean(String id, JSONObject beansJSON) {
+ String type = beansJSON.optString("type");
+ String scope = beansJSON.optString("scope");
+ String resource = beansJSON.optString("resource");
+
+ JSONArray aliasesJSON = beansJSON.getJSONArray("aliases");
+ String[] aliases = new String[aliasesJSON.length()];
+ for (int i = 0; i < aliasesJSON.length(); i++) {
+ aliases[i] = aliasesJSON.optString(i);
+ }
+
+ JSONArray dependenciesJSON = beansJSON.getJSONArray("dependencies");
+ String[] dependencies = new String[dependenciesJSON.length()];
+ for (int i = 0; i < dependenciesJSON.length(); i++) {
+ dependencies[i] = dependenciesJSON.optString(i);
+ }
+
+ return new LiveBean(id, aliases, scope, type, resource, dependencies);
+ }
+ }
+
+ private static final Parser[] PARSERS = {
+ new Boot15Parser(),
+ new Boot20Parser(),
+ };
+
+ public static LiveBeansModel parse(String json) {
+ List exceptions = new ArrayList<>(PARSERS.length);
+ if (StringUtil.hasText(json)) {
+ for (Parser parser : PARSERS) {
+ try {
+ LiveBeansModel model = parser.parse(json);
+ if (model==null) {
+ throw new NullPointerException("Parser returned a null model (it should not!)");
+ }
+ return model; //good!
+ } catch (Exception e) {
+ exceptions.add(e);
+ }
+ }
+ }
+ //Only getting here if none of the parsers worked... So if at least one parser works,
+ // we won't log any exceptions.
+ for (Exception e : exceptions) {
+ Log.log(e);
+ }
+ return new LiveBeansModel(); // allways return at least an empty model.
+ }
+
+ private final ConcurrentMap> beansViaType;
+ private final ConcurrentMap> beansViaName;
+
+ protected LiveBeansModel() {
+ this.beansViaType = new ConcurrentHashMap<>();
+ this.beansViaName = new ConcurrentHashMap<>();
+ }
+
+ public LiveBean[] getBeansOfType(String fullyQualifiedType) {
+ List result = beansViaType.get(fullyQualifiedType);
+ return result != null ? result.toArray(new LiveBean[result.size()]) : new LiveBean[0];
+ }
+
+ public LiveBean[] getBeansOfName(String beanName) {
+ List result = beansViaName.get(beanName);
+ return result != null ? result.toArray(new LiveBean[result.size()]) : new LiveBean[0];
+ }
+
+ protected void add(LiveBean bean) {
+ String type = bean.getType();
+ if (type != null) {
+ beansViaType.computeIfAbsent(type, (t) -> new ArrayList<>()).add(bean);
+ }
+
+ String name = bean.getId();
+ if (name != null) {
+ beansViaName.computeIfAbsent(name, (n) -> new ArrayList<>()).add(bean);
+ }
+ }
+
+ public Stream getAllBeans() {
+ return beansViaName.values().stream().flatMap(Collection::stream);
+ }
+
+ public boolean isEmpty() {
+ return !getAllBeans().findAny().isPresent();
+ }
+
+}
diff --git a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/LiveBeansModelTest.java b/headless-services/commons/commons-boot-app-cli/src/test/java/org/springframework/ide/vscode/commons/boot/app/cli/LiveBeansModelTest.java
similarity index 75%
rename from headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/LiveBeansModelTest.java
rename to headless-services/commons/commons-boot-app-cli/src/test/java/org/springframework/ide/vscode/commons/boot/app/cli/LiveBeansModelTest.java
index 5c08df184..e7372bd27 100644
--- a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/autowired/test/LiveBeansModelTest.java
+++ b/headless-services/commons/commons-boot-app-cli/src/test/java/org/springframework/ide/vscode/commons/boot/app/cli/LiveBeansModelTest.java
@@ -8,15 +8,16 @@
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
-package org.springframework.ide.vscode.boot.java.autowired.test;
+package org.springframework.ide.vscode.commons.boot.app.cli;
import static org.junit.Assert.assertEquals;
+import java.io.InputStream;
+
import org.apache.commons.io.IOUtils;
import org.junit.Test;
-import org.springframework.ide.vscode.boot.java.autowired.LiveBean;
-import org.springframework.ide.vscode.boot.java.autowired.LiveBeansModel;
-import org.springframework.ide.vscode.project.harness.ProjectsHarness;
+import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBean;
+import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
/**
* @author Martin Lippert
@@ -25,7 +26,7 @@ public class LiveBeansModelTest {
@Test
public void testSimpleModel() throws Exception {
- String json = IOUtils.toString(ProjectsHarness.class.getResourceAsStream("/live-beans-models/simple-live-beans-model.json"));
+ String json = IOUtils.toString(getResourceAsStream("/live-beans-models/simple-live-beans-model.json"));
LiveBeansModel model = LiveBeansModel.parse(json);
LiveBean[] bean = model.getBeansOfType("org.test.DependencyA");
@@ -49,7 +50,7 @@ public class LiveBeansModelTest {
@Test
public void testEmptyModel() throws Exception {
- String json = IOUtils.toString(ProjectsHarness.class.getResourceAsStream("/live-beans-models/empty-live-beans-model.json"));
+ String json = IOUtils.toString(getResourceAsStream("/live-beans-models/empty-live-beans-model.json"));
LiveBeansModel model = LiveBeansModel.parse(json);
LiveBean[] bean = model.getBeansOfType("org.test.DependencyA");
@@ -58,11 +59,15 @@ public class LiveBeansModelTest {
@Test
public void testTotallyEmptyModel() throws Exception {
- String json = IOUtils.toString(ProjectsHarness.class.getResourceAsStream("/live-beans-models/totally-empty-live-beans-model.json"));
+ String json = IOUtils.toString(getResourceAsStream("/live-beans-models/totally-empty-live-beans-model.json"));
LiveBeansModel model = LiveBeansModel.parse(json);
LiveBean[] bean = model.getBeansOfType("org.test.DependencyA");
assertEquals(0, bean.length);
}
+ private InputStream getResourceAsStream(String string) {
+ return LiveBeansModelTest.class.getResourceAsStream(string);
+ }
+
}
diff --git a/headless-services/commons/commons-boot-app-cli/src/test/java/org/springframework/ide/vscode/commons/boot/app/cli/SpringBootAppTest.java b/headless-services/commons/commons-boot-app-cli/src/test/java/org/springframework/ide/vscode/commons/boot/app/cli/SpringBootAppTest.java
index 29ef8566e..d48f34cde 100644
--- a/headless-services/commons/commons-boot-app-cli/src/test/java/org/springframework/ide/vscode/commons/boot/app/cli/SpringBootAppTest.java
+++ b/headless-services/commons/commons-boot-app-cli/src/test/java/org/springframework/ide/vscode/commons/boot/app/cli/SpringBootAppTest.java
@@ -12,23 +12,27 @@ package org.springframework.ide.vscode.commons.boot.app.cli;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.net.URL;
import java.time.Duration;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.stream.Collectors;
import org.json.JSONObject;
import org.junit.AfterClass;
import org.junit.BeforeClass;
+import org.junit.Ignore;
import org.junit.Test;
+import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
import org.springframework.ide.vscode.commons.boot.app.cli.requestmappings.RequestMapping;
import org.springframework.ide.vscode.commons.util.AsyncProcess;
+import org.springframework.ide.vscode.commons.util.ExceptionUtil;
import org.springframework.ide.vscode.commons.util.ExternalCommand;
import org.springframework.ide.vscode.commons.util.StringUtil;
import org.springframework.ide.vscode.commons.util.test.ACondition;
@@ -37,25 +41,36 @@ import com.google.common.collect.ImmutableList;
public class SpringBootAppTest {
-// private static final String appName = "actuator-client-15-test-subject"; // Boot 1.5 test app
- private static final String appName = "actuator-client-20-test-subject"; //Boot 2.0 test app
-// private static final String appName = "actuator-client-20-thin-test-subject"; //Boot 2.0 test app with THIN launcher
+ private static final String[] appNames = {
+ "actuator-client-15-test-subject", // Boot 1.5 test app
+ "actuator-client-20-test-subject", //Boot 2.0 test app
+ "actuator-client-20-thin-test-subject", // Like the Boot 2.0 app, but packaged with thin launcher instead of fatjar
+ };
- private static final Duration TIMEOUT = Duration.ofSeconds(30); // in CI build starting the app takes longer than 10s sometimes.
- //Output from CI build: Started ActuatorClientTestSubjectApplication in 22.962 seconds (JVM running for 26.028)
+ private static final Duration TIMEOUT = Duration.ofSeconds(60); // in CI build starting the app takes a while, starting several in parallel takes even longer
private static final List TEST_PROFILES = ImmutableList.of("testing", "funny", "cameleon");
- private static AsyncProcess testAppRunner;
- private static SpringBootApp testApp;
+ private static List testAppRunners;
@BeforeClass
public static void setupClass() throws Exception {
- testAppRunner = startTestApplication(SpringBootAppTest.class.getResource("/"+appName+"-0.0.1-SNAPSHOT.jar"));
- ACondition.waitFor(TIMEOUT, () -> {
- testApp = getAppContaining(appName);
- assertNotNull(testApp);
- });
+ testAppRunners = Arrays.asList(appNames).stream().map(appName -> {
+ try {
+ return startTestApplication(SpringBootAppTest.class.getResource("/boot-apps/"+appName+"-0.0.1-SNAPSHOT.jar"));
+ } catch (Exception e) {
+ throw ExceptionUtil.unchecked(e);
+ }
+ })
+ .collect(Collectors.toList());
+ }
+
+ @AfterClass
+ public static void tearDownClass() throws Exception {
+ for (AsyncProcess process : testAppRunners) {
+ process.kill();
+ }
+ testAppRunners = null;
}
private static AsyncProcess startTestApplication(URL jarUrl) throws Exception {
@@ -73,95 +88,127 @@ public class SpringBootAppTest {
);
}
- private static SpringBootApp getAppContaining(String nameFragment) throws Exception {
- return SpringBootApp.getAllRunningJavaApps().values().stream().filter(app -> app.getProcessName().contains(nameFragment)).findAny().get();
+ private SpringBootApp getAppContaining(String nameFragment) {
+ try {
+ return SpringBootApp.getAllRunningJavaApps().values().stream().filter(app -> app.getProcessName().contains(nameFragment)).findAny().get();
+ } catch (Exception e) {
+ throw ExceptionUtil.unchecked(e);
+ }
}
- @AfterClass
- public static void tearDownClass() throws Exception {
- testAppRunner.kill();
+ @Ignore @Test public void dumpJvmInfo() throws Exception {
+ //Ignored because this test may have timing issues. Still useful to
+ // run locally and inspect dump results, but may need some tweaking.
+ for (String appName : appNames) {
+ SpringBootApp testApp = getAppContaining(appName);
+ testApp.dumpJvmInfo();
+ System.out.println("======================================");
+ }
}
- @Test
- public void getAllJavaApps() throws Exception {
+ @Test public void getAllJavaApps() throws Exception {
Map allApps = SpringBootApp.getAllRunningJavaApps();
- Optional myProcess = allApps.values().stream().filter(app -> app.getProcessName().contains(appName)).findAny();
- assertTrue(myProcess.isPresent());
- }
-
- @Test public void dumpJvmInfo() throws Exception {
- ACondition.waitFor(TIMEOUT, this::getRequestMappings);
- testApp.dumpJvmInfo();
-// SpringBootApp app = getAppContaining("language-server.jar");
-// app.dumpJvmInfo();
+ for (String appName : appNames) {
+ Optional myProcess = allApps.values().stream().filter(app -> app.getProcessName().contains(appName)).findAny();
+ assertTrue(appName, myProcess.isPresent());
+ }
}
@Test public void getAllBootApps() throws Exception {
Map allApps = SpringBootApp.getAllRunningSpringApps();
- Optional myProcess = allApps.values().stream().filter(app -> app.getProcessName().contains(appName)).findAny();
- assertTrue(myProcess.isPresent());
+ for (String appName : appNames) {
+ Optional myProcess = allApps.values().stream().filter(app -> app.getProcessName().contains(appName)).findAny();
+ assertTrue(myProcess.isPresent());
+ }
}
@Test
public void getPort() throws Exception {
- ACondition.waitFor(TIMEOUT, () -> {
- int port = Integer.parseInt(testApp.getPort());
- assertTrue(port > 0);
-// System.out.println("port = "+port);
- });
+ for (SpringBootApp testApp : getTestApps()) {
+ ACondition.waitFor(TIMEOUT, () -> {
+ int port = Integer.parseInt(testApp.getPort());
+ assertTrue(port > 0);
+// System.out.println("port = "+port);
+ });
+ }
+ }
+
+ private Collection getTestApps() throws Exception {
+ return ACondition.waitForValue(TIMEOUT, () -> Arrays.asList(appNames).stream()
+ .map(this::getAppContaining)
+ .collect(Collectors.toList())
+ );
}
@Test
public void getHost() throws Exception {
- ACondition.waitFor(TIMEOUT, () -> {
- String host = testApp.getHost();
- assertTrue(StringUtil.hasText(host));
-// System.out.println("host = "+host);
- });
+ for (SpringBootApp testApp : getTestApps()) {
+ System.err.println("getHost for "+testApp);
+ ACondition.waitFor(TIMEOUT, () -> {
+ String host = testApp.getHost();
+ assertTrue(StringUtil.hasText(host));
+ System.out.println("host = "+host);
+ });
+ }
}
@Test
public void getEnvironment() throws Exception {
- ACondition.waitFor(TIMEOUT, () -> {
- String env = testApp.getEnvironment();
- assertNonEmptyJsonObject(env);
- System.out.println("env = "+new JSONObject(env).toString(3));
- });
+ for (SpringBootApp testApp : getTestApps()) {
+ ACondition.waitFor(TIMEOUT, () -> {
+ String env = testApp.getEnvironment();
+ assertNonEmptyJsonObject(env);
+ System.out.println("env = "+new JSONObject(env).toString(3));
+ });
+ }
}
@Test
public void getBeans() throws Exception {
- ACondition.waitFor(TIMEOUT, () -> {
- String beans = testApp.getBeans();
- assertNonEmptyJsonObject(beans);
-// System.out.println("beans = "+beans);
- });
+ for (SpringBootApp testApp : getTestApps()) {
+ try {
+ ACondition.waitFor(TIMEOUT, () -> {
+ LiveBeansModel beansModel = testApp.getBeans();
+ assertTrue(beansModel.getAllBeans().findAny().isPresent());
+ // System.out.println("beans = "+beans);
+ });
+ } catch (Throwable e) {
+ //Make it easier to identify the culprit of failing test
+ throw new RuntimeException("Failed for: "+testApp.getProcessName(), e);
+ }
+ }
}
@Test
public void getRequestMappings() throws Exception {
- ACondition.waitFor(TIMEOUT, () -> {
- Collection result = testApp.getRequestMappings();
- assertTrue(result != null && !result.isEmpty());
-// System.out.println("requestMappings = "+result);
- });
+ for (SpringBootApp testApp : getTestApps()) {
+ ACondition.waitFor(TIMEOUT, () -> {
+ Collection result = testApp.getRequestMappings();
+ assertTrue(result != null && !result.isEmpty());
+// System.out.println("requestMappings = "+result);
+ });
+ }
}
@Test
public void getAutoConfigReport() throws Exception {
- ACondition.waitFor(TIMEOUT, () -> {
- String result = testApp.getAutoConfigReport();
- assertNonEmptyJsonObject(result);
-// System.out.println("autoconfreport = "+result);
- });
+ for (SpringBootApp testApp : getTestApps()) {
+ ACondition.waitFor(TIMEOUT, () -> {
+ String result = testApp.getAutoConfigReport();
+ assertNonEmptyJsonObject(result);
+ // System.out.println("autoconfreport = "+result);
+ });
+ }
}
@Test
public void getProfiles() throws Exception {
- ACondition.waitFor(TIMEOUT, () -> {
- List result = testApp.getActiveProfiles();
- assertEquals(ImmutableList.copyOf(TEST_PROFILES), result);
- });
+ for (SpringBootApp testApp : getTestApps()) {
+ ACondition.waitFor(TIMEOUT, () -> {
+ List result = testApp.getActiveProfiles();
+ assertEquals(ImmutableList.copyOf(TEST_PROFILES), result);
+ });
+ }
}
private void assertNonEmptyJsonObject(String jsonData) {
diff --git a/headless-services/commons/commons-boot-app-cli/src/test/resources/actuator-client-15-test-subject-0.0.1-SNAPSHOT.jar b/headless-services/commons/commons-boot-app-cli/src/test/resources/boot-apps/actuator-client-15-test-subject-0.0.1-SNAPSHOT.jar
similarity index 100%
rename from headless-services/commons/commons-boot-app-cli/src/test/resources/actuator-client-15-test-subject-0.0.1-SNAPSHOT.jar
rename to headless-services/commons/commons-boot-app-cli/src/test/resources/boot-apps/actuator-client-15-test-subject-0.0.1-SNAPSHOT.jar
diff --git a/headless-services/commons/commons-boot-app-cli/src/test/resources/actuator-client-20-test-subject-0.0.1-SNAPSHOT.jar b/headless-services/commons/commons-boot-app-cli/src/test/resources/boot-apps/actuator-client-20-test-subject-0.0.1-SNAPSHOT.jar
similarity index 100%
rename from headless-services/commons/commons-boot-app-cli/src/test/resources/actuator-client-20-test-subject-0.0.1-SNAPSHOT.jar
rename to headless-services/commons/commons-boot-app-cli/src/test/resources/boot-apps/actuator-client-20-test-subject-0.0.1-SNAPSHOT.jar
diff --git a/headless-services/commons/commons-boot-app-cli/src/test/resources/actuator-client-20-thin-test-subject-0.0.1-SNAPSHOT.jar b/headless-services/commons/commons-boot-app-cli/src/test/resources/boot-apps/actuator-client-20-thin-test-subject-0.0.1-SNAPSHOT.jar
similarity index 100%
rename from headless-services/commons/commons-boot-app-cli/src/test/resources/actuator-client-20-thin-test-subject-0.0.1-SNAPSHOT.jar
rename to headless-services/commons/commons-boot-app-cli/src/test/resources/boot-apps/actuator-client-20-thin-test-subject-0.0.1-SNAPSHOT.jar
diff --git a/headless-services/boot-java-language-server/src/test/resources/live-beans-models/empty-live-beans-model.json b/headless-services/commons/commons-boot-app-cli/src/test/resources/live-beans-models/empty-live-beans-model.json
similarity index 100%
rename from headless-services/boot-java-language-server/src/test/resources/live-beans-models/empty-live-beans-model.json
rename to headless-services/commons/commons-boot-app-cli/src/test/resources/live-beans-models/empty-live-beans-model.json
diff --git a/headless-services/boot-java-language-server/src/test/resources/live-beans-models/simple-live-beans-model.json b/headless-services/commons/commons-boot-app-cli/src/test/resources/live-beans-models/simple-live-beans-model.json
similarity index 100%
rename from headless-services/boot-java-language-server/src/test/resources/live-beans-models/simple-live-beans-model.json
rename to headless-services/commons/commons-boot-app-cli/src/test/resources/live-beans-models/simple-live-beans-model.json
diff --git a/headless-services/boot-java-language-server/src/test/resources/live-beans-models/totally-empty-live-beans-model.json b/headless-services/commons/commons-boot-app-cli/src/test/resources/live-beans-models/totally-empty-live-beans-model.json
similarity index 100%
rename from headless-services/boot-java-language-server/src/test/resources/live-beans-models/totally-empty-live-beans-model.json
rename to headless-services/commons/commons-boot-app-cli/src/test/resources/live-beans-models/totally-empty-live-beans-model.json
diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/parser/JLRMethodParser.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/parser/JLRMethodParser.java
index 970480e8c..b151b37d9 100644
--- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/parser/JLRMethodParser.java
+++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/parser/JLRMethodParser.java
@@ -108,15 +108,24 @@ public class JLRMethodParser {
}
break;
default:
- if (Character.isJavaIdentifierPart(ch)) {
- currentParameter.append(ch);
- }
+ currentParameter.append(ch);
}
}
if (currentParameter.length() > 0) {
parameters.add(currentParameter.toString());
}
- return parameters.toArray(new String[parameters.size()]);
+ return parameters.stream()
+ .map(p -> {
+ int genericStart = p.indexOf('<');
+ int genericEnd = p.lastIndexOf('>');
+ if (genericStart < genericEnd) {
+ return p.substring(0, genericStart) + p.substring(genericEnd + 1);
+ } else {
+ return p;
+ }
+ })
+ .map(p -> p.replaceAll("\\.\\.\\.", "[]"))
+ .toArray(String[]::new);
}
@Override
diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/CompositeJavaProjectFinder.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/CompositeJavaProjectFinder.java
index b32937259..fbeb5921a 100644
--- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/CompositeJavaProjectFinder.java
+++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/languageserver/java/CompositeJavaProjectFinder.java
@@ -14,14 +14,13 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import java.util.Objects;
import java.util.Optional;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.springframework.ide.vscode.commons.java.IJavaProject;
/**
- * Composite project manager that acts a single project manager but consissts of many project managers
+ * Composite project manager that acts a single project manager but consists of many project managers
*
* @author Alex Boyko
*
@@ -48,7 +47,7 @@ public class CompositeJavaProjectFinder implements JavaProjectFinder {
@Override
public Optional find(TextDocumentIdentifier doc) {
- return projectFinders.stream().map(finder -> finder.find(doc)).filter(Optional::isPresent).findFirst().orElse(null);
+ return projectFinders.stream().map(finder -> finder.find(doc)).filter(Optional::isPresent).findFirst().orElseGet(() -> Optional.empty());
}
}
diff --git a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/test/ACondition.java b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/test/ACondition.java
index 034447d17..2d6599557 100644
--- a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/test/ACondition.java
+++ b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/test/ACondition.java
@@ -11,6 +11,8 @@
package org.springframework.ide.vscode.commons.util.test;
import java.time.Duration;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicReference;
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
@@ -44,5 +46,14 @@ public class ACondition {
} while (System.currentTimeMillis()-startTime < timeout_millis);
throw ExceptionUtil.exception(lastException);
}
+
+ /**
+ * Retries fecthing a value until it succeeds without an error, or until timeout exceeded.
+ */
+ public static T waitForValue(Duration timeout, Callable provider) throws Exception {
+ AtomicReference result = new AtomicReference<>(null);
+ waitFor(timeout, () -> result.set(provider.call()));
+ return result.get();
+ }
}
diff --git a/headless-services/commons/pom.xml b/headless-services/commons/pom.xml
index 51fa1730a..55e8c8007 100644
--- a/headless-services/commons/pom.xml
+++ b/headless-services/commons/pom.xml
@@ -85,6 +85,7 @@
3.0.5.RELEASE
0.6.0.RELEASE
2.4.0.RELEASE
+ 2.4