Refine request mappings
This commit is contained in:
@@ -13,7 +13,9 @@ package org.springframework.ide.vscode.commons.boot.app.cli;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -30,6 +32,8 @@ import javax.management.remote.JMXServiceURL;
|
||||
|
||||
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.util.Log;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -186,17 +190,29 @@ public class SpringBootApp {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getRequestMappings() throws Exception {
|
||||
public static Collection<RequestMapping> parseRequestMappingsJson(String json) {
|
||||
JSONObject obj = new JSONObject(json);
|
||||
Iterator<String> keys = obj.keys();
|
||||
List<RequestMapping> result = new ArrayList<>();
|
||||
while (keys.hasNext()) {
|
||||
String rawKey = keys.next();
|
||||
JSONObject value = obj.getJSONObject(rawKey);
|
||||
result.add(new RequestMappingImpl1(rawKey, value));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Collection<RequestMapping> getRequestMappings() throws Exception {
|
||||
Object result = getActuatorDataFromAttribute("org.springframework.boot:type=Endpoint,name=requestMappingEndpoint", "Data");
|
||||
if (result != null) {
|
||||
String mappings = new ObjectMapper().writeValueAsString(result);
|
||||
return mappings;
|
||||
return parseRequestMappingsJson(mappings);
|
||||
}
|
||||
|
||||
result = getActuatorDataFromOperation("org.springframework.boot:type=Endpoint,name=Mappings", "mappings");
|
||||
if (result != null) {
|
||||
String mappings = new ObjectMapper().writeValueAsString(result);
|
||||
return mappings;
|
||||
return parseRequestMappingsJson(mappings);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*******************************************************************************
|
||||
* 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.requestmappings;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface RequestMapping {
|
||||
String getPath();
|
||||
String[] getSplitPath();
|
||||
String getFullyQualifiedClassName();
|
||||
String getMethodName();
|
||||
String[] getMethodParameters();
|
||||
String getMethodString();
|
||||
Set<String> getRequestMethods();
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*******************************************************************************
|
||||
* 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.requestmappings;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.ide.vscode.commons.java.parser.JLRMethodParser;
|
||||
import org.springframework.ide.vscode.commons.java.parser.JLRMethodParser.JLRMethod;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
|
||||
public class RequestMappingImpl1 implements RequestMapping {
|
||||
|
||||
private static final Pattern REQUEST_METHODS_PATTERN = Pattern.compile(".*methods=\\[(.*)\\].*");
|
||||
|
||||
/*
|
||||
There are two styles of entries:
|
||||
|
||||
1) key is a 'path' String. May contain patters like "**"
|
||||
"/** /favicon.ico":{
|
||||
"bean":"faviconHandlerMapping"
|
||||
}
|
||||
|
||||
2) key is a 'almost json' String
|
||||
"{[/bye],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}":{
|
||||
"bean":"requestMappingHandlerMapping",
|
||||
"method":"public java.lang.String demo.MyController.bye()"
|
||||
}
|
||||
*/
|
||||
|
||||
private JSONObject beanInfo;
|
||||
private String pathKey;
|
||||
private Supplier<JLRMethod> methodDataSupplier;
|
||||
private Supplier<Set<String>> requestMethodsSupplier;
|
||||
private Supplier<String> requestPathSupplier;
|
||||
|
||||
public RequestMappingImpl1(String pathKey, JSONObject beanInfo) {
|
||||
this.pathKey = pathKey;
|
||||
this.beanInfo = beanInfo;
|
||||
this.requestMethodsSupplier = Suppliers.memoize(() -> parseRequestMethods());
|
||||
this.requestPathSupplier = Suppliers.memoize(() -> parseRequestPath());
|
||||
this.methodDataSupplier = Suppliers.memoize(() -> JLRMethodParser.parse(getMethodString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return requestPathSupplier.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RequestMapping("+pathKey+")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullyQualifiedClassName() {
|
||||
JLRMethod m = getMethodData();
|
||||
if (m!=null) {
|
||||
return m.getFQClassName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodName() {
|
||||
JLRMethod m = getMethodData();
|
||||
if (m!=null) {
|
||||
return m.getMethodName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw string found in the requestmapping info. This is a 'toString' value
|
||||
* of java.lang.reflect.Method object.
|
||||
*/
|
||||
@Override
|
||||
public String getMethodString() {
|
||||
try {
|
||||
if (beanInfo!=null) {
|
||||
if (beanInfo.has("method")) {
|
||||
return beanInfo.getString("method");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private JLRMethod getMethodData() {
|
||||
return methodDataSupplier.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return pathKey.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
RequestMappingImpl1 other = (RequestMappingImpl1) obj;
|
||||
return Objects.equal(this.pathKey, other.pathKey)
|
||||
&& Objects.equal(this.getMethodString(), other.getMethodString());
|
||||
}
|
||||
|
||||
protected Set<String> parseRequestMethods() {
|
||||
Matcher matcher = REQUEST_METHODS_PATTERN.matcher(pathKey);
|
||||
if (matcher.matches()) {
|
||||
return Arrays.stream(matcher.group(1).split("\\s*,\\s*")).collect(Collectors.toSet());
|
||||
}
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
protected String parseRequestPath() {
|
||||
if (pathKey.startsWith("{[")) { //Case 2 (see above)
|
||||
//An almost json string. Unfortunately not really json so we can't
|
||||
//use org.json or jackson Mapper to properly parse this.
|
||||
int start = 2; //right after first '['
|
||||
int end = pathKey.indexOf(']');
|
||||
if (end>=2) {
|
||||
return pathKey.substring(start, end);
|
||||
}
|
||||
}
|
||||
//Case 1, or some unanticipated stuff.
|
||||
//Assume the key is the path, which is right for Case 1
|
||||
// and probably more useful than null for 'unanticipated stuff'.
|
||||
return pathKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getRequestMethods() {
|
||||
return requestMethodsSupplier.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSplitPath() {
|
||||
String paths = requestPathSupplier.get();
|
||||
return Arrays.stream(paths.split("\\|\\|")).map(s -> s.trim()).toArray(String[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getMethodParameters() {
|
||||
return getMethodData().getParameters();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*******************************************************************************
|
||||
* 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;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.requestmappings.RequestMappingImpl1;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
public class RequestMappingImp1Test {
|
||||
|
||||
@Test
|
||||
public void testSplitPathWithoutDuplicate() {
|
||||
RequestMappingImpl1 rm = new RequestMappingImpl1("/superpath", null);
|
||||
String[] splitPath = rm.getSplitPath();
|
||||
assertEquals(1, splitPath.length);
|
||||
assertEquals("/superpath", splitPath[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitPathSimpleCaseWithEmptyOr() {
|
||||
RequestMappingImpl1 rm = new RequestMappingImpl1("/superpath/mypath || ", null);
|
||||
String[] splitPath = rm.getSplitPath();
|
||||
assertEquals(1, splitPath.length);
|
||||
assertEquals("/superpath/mypath", splitPath[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitPathSimpleCase() {
|
||||
RequestMappingImpl1 rm = new RequestMappingImpl1("/superpath/mypath || mypath.json", null);
|
||||
String[] splitPath = rm.getSplitPath();
|
||||
assertEquals(2, splitPath.length);
|
||||
assertEquals("/superpath/mypath", splitPath[0]);
|
||||
assertEquals("/superpath/mypath.json", splitPath[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitPathMultipleCases() {
|
||||
RequestMappingImpl1 rm = new RequestMappingImpl1("/superpath/mypath || mypath.json || somethingelse.what", null);
|
||||
String[] splitPath = rm.getSplitPath();
|
||||
assertEquals(3, splitPath.length);
|
||||
assertEquals("/superpath/mypath", splitPath[0]);
|
||||
assertEquals("/superpath/mypath.json", splitPath[1]);
|
||||
assertEquals("/superpath/somethingelse.what", splitPath[2]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import static org.junit.Assert.assertTrue;
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -26,6 +27,7 @@ import org.json.JSONObject;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
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.ExternalCommand;
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
@@ -139,8 +141,8 @@ public class SpringBootAppTest {
|
||||
@Test
|
||||
public void getRequestMappings() throws Exception {
|
||||
ACondition.waitFor(TIMEOUT, () -> {
|
||||
String result = testApp.getRequestMappings();
|
||||
assertNonEmptyJsonObject(result);
|
||||
Collection<RequestMapping> result = testApp.getRequestMappings();
|
||||
assertTrue(result != null && !result.isEmpty());
|
||||
// System.out.println("requestMappings = "+result);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user