Add parsing of LiveBeanModel to actuator client

This commit is contained in:
Kris De Volder
2017-10-25 13:40:57 -07:00
parent 23d55a6d93
commit 136b98d215
22 changed files with 113 additions and 78 deletions

View File

@@ -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<Either<String, MarkedString>> hoverContent) {
public void addLiveHoverContent(Annotation annotation, TextDocument doc, LiveBeansModel beansModel, SpringBootAppProvider bootApp, List<Either<String, MarkedString>> 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) {

View File

@@ -1,83 +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 org.json.JSONArray;
import org.json.JSONObject;
/**
* @author Martin Lippert
*/
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;
private final String type;
private final String resource;
private final String[] dependencies;
protected LiveBean(String id, String[] aliases, String scope, String type, String resource, String[] dependencies) {
super();
this.id = id;
this.aliases = aliases;
this.scope = scope;
this.type = type;
this.resource = resource;
this.dependencies = dependencies;
}
public String getId() {
return id;
}
public String[] getAliases() {
return aliases;
}
public String getScope() {
return scope;
}
public String getType() {
return type;
}
public String getResource() {
return resource;
}
public String[] getDependencies() {
return dependencies;
}
}

View File

@@ -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<String, List<LiveBean>> beansViaType;
private final ConcurrentMap<String, List<LiveBean>> beansViaName;
protected LiveBeansModel() {
this.beansViaType = new ConcurrentHashMap<>();
this.beansViaName = new ConcurrentHashMap<>();
}
public LiveBean[] getBeansOfType(String fullyQualifiedType) {
List<LiveBean> result = beansViaType.get(fullyQualifiedType);
return result != null ? result.toArray(new LiveBean[result.size()]) : new LiveBean[0];
}
public LiveBean[] getBeansOfName(String beanName) {
List<LiveBean> 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);
}
}
}

View File

@@ -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();

View File

@@ -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();
}

View File

@@ -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<Either<String, MarkedString>> 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<Either<String, MarkedString>> hoverContent) {
public void addLiveHoverContent(TypeDeclaration declaringType, TextDocument doc, LiveBeansModel beansModel, SpringBootAppProvider bootApp, List<Either<String, MarkedString>> 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) {

View File

@@ -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<Hover> hoverFuture = provider.provideHover(null, (Annotation)node, null, offset, document, new SpringBootAppProvider[] {bootApp});

View File

@@ -1,68 +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.test;
import static org.junit.Assert.assertEquals;
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;
/**
* @author Martin Lippert
*/
public class LiveBeansModelTest {
@Test
public void testSimpleModel() throws Exception {
String json = IOUtils.toString(ProjectsHarness.class.getResourceAsStream("/live-beans-models/simple-live-beans-model.json"));
LiveBeansModel model = LiveBeansModel.parse(json);
LiveBean[] bean = model.getBeansOfType("org.test.DependencyA");
assertEquals(1, bean.length);
assertEquals("dependencyA", bean[0].getId());
assertEquals("singleton", bean[0].getScope());
assertEquals("org.test.DependencyA", bean[0].getType());
assertEquals("file [/test-projects/classes/org/test/DependencyA.class]", bean[0].getResource());
assertEquals(0, bean[0].getAliases().length);
assertEquals(0, bean[0].getDependencies().length);
bean = model.getBeansOfName("dependencyB");
assertEquals(1, bean.length);
assertEquals("dependencyB", bean[0].getId());
assertEquals("singleton", bean[0].getScope());
assertEquals("org.test.DependencyB", bean[0].getType());
assertEquals("file [/test-projects/classes/org/test/DependencyB.class]", bean[0].getResource());
assertEquals(0, bean[0].getAliases().length);
assertEquals(0, bean[0].getDependencies().length);
}
@Test
public void testEmptyModel() throws Exception {
String json = IOUtils.toString(ProjectsHarness.class.getResourceAsStream("/live-beans-models/empty-live-beans-model.json"));
LiveBeansModel model = LiveBeansModel.parse(json);
LiveBean[] bean = model.getBeansOfType("org.test.DependencyA");
assertEquals(0, bean.length);
}
@Test
public void testTotallyEmptyModel() throws Exception {
String json = IOUtils.toString(ProjectsHarness.class.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);
}
}

View File

@@ -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<Hover> hoverFuture = provider.provideHover(null, (Annotation) node, null, 0, document, new SpringBootAppProvider[] {bootApp});

View File

@@ -19,6 +19,7 @@ import java.util.Collection;
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.livebean.LiveBeansModel;
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness.Builder;
@@ -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;
}

View File

@@ -1,8 +0,0 @@
[
{
"context": "application",
"parent": null,
"beans": [
]
}
]

View File

@@ -1,35 +0,0 @@
[
{
"context": "application",
"parent": null,
"beans": [
{
"bean": "dependencyA",
"aliases": [],
"scope": "singleton",
"type": "org.test.DependencyA",
"resource": "file [/test-projects/classes/org/test/DependencyA.class]",
"dependencies": []
},
{
"bean": "dependencyB",
"aliases": [],
"scope": "singleton",
"type": "org.test.DependencyB",
"resource": "file [/test-projects/classes/org/test/DependencyB.class]",
"dependencies": []
},
{
"bean": "myAutowiredComponent",
"aliases": [],
"scope": "singleton",
"type": "org.test.MyAutowiredComponent",
"resource": "file [/test-projects/classes/org/test/MyAutowiredComponent.class]",
"dependencies": [
"dependencyA",
"dependencyB"
]
}
]
}
]