From 2223ea979d1a4ad7bd0700a6b0ae92d097c632a2 Mon Sep 17 00:00:00 2001 From: yuri Date: Sun, 28 Nov 2021 21:17:13 -0500 Subject: [PATCH] eventmesh-admin-rocketmq submodule and createTopic REST API (#530) * eventmesh-admin-rocketmq submodule and createTopic draft API * add license header * change to /topicmanage * fix build error * fix some code check style issues close #435 #346 --- eventmesh-admin/README.md | 12 +- eventmesh-admin/build.gradle | 19 ++- .../eventmesh-admin-rocketmq/build.gradle | 26 +++++ .../gradle.properties | 17 +++ .../rocketmq/controller/AdminController.java | 42 +++++++ .../admin/rocketmq/handler/TopicsHandler.java | 108 +++++++++++++++++ .../rocketmq/request/TopicCreateRequest.java | 47 ++++++++ .../rocketmq/response/TopicResponse.java | 64 ++++++++++ .../admin/rocketmq/util/JsonUtils.java | 72 ++++++++++++ .../admin/rocketmq/util/NetUtils.java | 51 ++++++++ .../admin/rocketmq/util/RequestMapping.java | 60 ++++++++++ .../rocketmq/util/UrlMappingPattern.java | 109 ++++++++++++++++++ .../controller/ClientManageController.java | 25 +++- 13 files changed, 641 insertions(+), 11 deletions(-) create mode 100644 eventmesh-admin/eventmesh-admin-rocketmq/build.gradle create mode 100644 eventmesh-admin/eventmesh-admin-rocketmq/gradle.properties create mode 100644 eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/controller/AdminController.java create mode 100644 eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/handler/TopicsHandler.java create mode 100644 eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/request/TopicCreateRequest.java create mode 100644 eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/response/TopicResponse.java create mode 100644 eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/JsonUtils.java create mode 100644 eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/NetUtils.java create mode 100644 eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/RequestMapping.java create mode 100644 eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/UrlMappingPattern.java diff --git a/eventmesh-admin/README.md b/eventmesh-admin/README.md index 84f80470d8..f97d2a937d 100644 --- a/eventmesh-admin/README.md +++ b/eventmesh-admin/README.md @@ -4,10 +4,10 @@ EventMesh Administration Module for EventMesh. It manages Admin Service, Configu ## Administration Client Manager APIs -### POST /clientmanage/topics/ +### POST /topicmanage - Create a new topic if does not exist - Exposed POST endpoint to create a new topic if it does not exist. - * Url - http://localhost:8081/clientmanage/topics/ + * Url - http://localhost:8081/topicmanage * sample request payload ```json { @@ -23,12 +23,12 @@ EventMesh Administration Module for EventMesh. It manages Admin Service, Configu "created_time": "2021-09-03", } ``` -### DELETE /clientmanage/topics/(string: topic)/ +### DELETE /topicmanage/(string: topic) - Delete a specific topic. - Exposed DELETE endpoint to remove a specific topic * URL - ```url - http://localhost:8081/clientmanage/topics/mytopic1 + http://localhost:8081/topicmanage/mytopic1 ``` * Response - @@ -39,12 +39,12 @@ EventMesh Administration Module for EventMesh. It manages Admin Service, Configu } ``` -### GET /clientmanage/topics +### GET /topicmanage - Retrieve a list of topics - Exposed GET endpoint to retrieve all topics * URL - ```url - http://localhost:8081/clientmanage/topics + http://localhost:8081/topicmanage ``` * Response diff --git a/eventmesh-admin/build.gradle b/eventmesh-admin/build.gradle index 2bbbee28ff..0741bc6d52 100644 --- a/eventmesh-admin/build.gradle +++ b/eventmesh-admin/build.gradle @@ -15,5 +15,22 @@ * limitations under the License. */ -dependencies { +task copyEventMeshAdmin(dependsOn: ['jar']) { + doFirst { + new File(projectDir, '../eventmesh-admin/dist/apps').mkdir() + new File(projectDir, '../dist/admin/').mkdirs() + } + doLast { + copy { + into('../eventmesh-admin/dist/apps/') + from project.jar.getArchivePath() + exclude { + "eventmesh-admin-${version}.jar" + } + } + copy { + into '../dist/admin' + from "../eventmesh-admin/dist/apps/eventmesh-admin-rocketmq-${version}.jar" + } + } } \ No newline at end of file diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/build.gradle b/eventmesh-admin/eventmesh-admin-rocketmq/build.gradle new file mode 100644 index 0000000000..3f35730487 --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/build.gradle @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +dependencies { + compileOnly project(":eventmesh-common") + + implementation "org.apache.httpcomponents:httpclient" + implementation project(":eventmesh-connector-plugin:eventmesh-connector-api") + + testImplementation project(":eventmesh-connector-plugin:eventmesh-connector-api") +} diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/gradle.properties b/eventmesh-admin/eventmesh-admin-rocketmq/gradle.properties new file mode 100644 index 0000000000..3d49f4c756 --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/gradle.properties @@ -0,0 +1,17 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +rocketmq_version=4.7.1 \ No newline at end of file diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/controller/AdminController.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/controller/AdminController.java new file mode 100644 index 0000000000..8932afd5cb --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/controller/AdminController.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.eventmesh.admin.rocketmq.controller; + +import org.apache.eventmesh.admin.rocketmq.handler.TopicsHandler; + +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.net.httpserver.HttpServer; + +public class AdminController { + + private static final Logger logger = LoggerFactory.getLogger(AdminController.class); + + public AdminController() { + } + + public void run(HttpServer server) throws IOException { + + server.createContext("/topicmanage", new TopicsHandler()); + + logger.info("EventMesh-Admin Controller server context created successfully"); + } +} diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/handler/TopicsHandler.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/handler/TopicsHandler.java new file mode 100644 index 0000000000..345f4bca30 --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/handler/TopicsHandler.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.eventmesh.admin.rocketmq.handler; + +import org.apache.eventmesh.admin.rocketmq.request.TopicCreateRequest; +import org.apache.eventmesh.admin.rocketmq.response.TopicResponse; +import org.apache.eventmesh.admin.rocketmq.util.JsonUtils; +import org.apache.eventmesh.admin.rocketmq.util.NetUtils; +import org.apache.eventmesh.admin.rocketmq.util.RequestMapping; + +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.io.OutputStream; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; + +public class TopicsHandler implements HttpHandler { + private static final Logger logger = LoggerFactory.getLogger(TopicsHandler.class); + + @Override + public void handle(HttpExchange httpExchange) throws IOException { + + // create a new topic + if (RequestMapping.postMapping("/topicmanage", httpExchange)) { + createTopicHandler(httpExchange); + return; + } + + OutputStream out = httpExchange.getResponseBody(); + httpExchange.sendResponseHeaders(500, 0); + String result = String.format("Please check your request url"); + logger.error(result); + out.write(result.getBytes()); + return; + } + + public void createTopicHandler(HttpExchange httpExchange) throws IOException { + String result = ""; + OutputStream out = httpExchange.getResponseBody(); + try { + String params = NetUtils.parsePostBody(httpExchange); + TopicCreateRequest topicCreateRequest = + JsonUtils.toObject(params, TopicCreateRequest.class); + String topic = topicCreateRequest.getName(); + + if (StringUtils.isBlank(topic)) { + result = "Create topic failed. Parameter topic not found."; + logger.error(result); + out.write(result.getBytes()); + return; + } + + //TBD: A new rocketmq service will be implemented for creating topics + TopicResponse topicResponse = null; + if (topicResponse != null) { + logger.info("create a new topic: {}", topic); + httpExchange.getResponseHeaders().add("Content-Type", "appication/json"); + httpExchange.sendResponseHeaders(200, 0); + result = JsonUtils.toJson(topicResponse); + logger.info(result); + out.write(result.getBytes()); + return; + } else { + httpExchange.sendResponseHeaders(500, 0); + result = String.format("create topic failed! Server side error"); + logger.error(result); + out.write(result.getBytes()); + return; + } + } catch (Exception e) { + httpExchange.getResponseHeaders().add("Content-Type", "appication/json"); + httpExchange.sendResponseHeaders(500, 0); + result = String.format("create topic failed! Server side error"); + logger.error(result); + out.write(result.getBytes()); + return; + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException e) { + logger.warn("out close failed...", e); + } + } + } + } + +} diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/request/TopicCreateRequest.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/request/TopicCreateRequest.java new file mode 100644 index 0000000000..7adaa77cd2 --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/request/TopicCreateRequest.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.eventmesh.admin.rocketmq.request; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +@JsonIgnoreProperties(ignoreUnknown = true) +public class TopicCreateRequest { + + private String name; + + @JsonCreator + public TopicCreateRequest(@JsonProperty("name") String topic) { + super(); + this.name = topic; + } + + @JsonProperty("name") + public String getName() { + return this.name; + } + + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + +} diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/response/TopicResponse.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/response/TopicResponse.java new file mode 100644 index 0000000000..1dde496bcb --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/response/TopicResponse.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.eventmesh.admin.rocketmq.response; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class TopicResponse { + + private String topic; + private String createdTime; + + @JsonCreator + public TopicResponse(@JsonProperty("topic") String topic, + @JsonProperty("created_time") String createdTime) { + super(); + this.topic = topic; + this.createdTime = createdTime; + } + + @JsonProperty("topic") + public String getTopic() { + return this.topic; + } + + @JsonProperty("topic") + public void setTopic(String topic) { + this.topic = topic; + } + + @JsonProperty("created_time") + public String getCreatedTime() { + return createdTime; + } + + @JsonProperty("created_time") + public void setCreatedTime(String createdTime) { + this.createdTime = createdTime; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("TopicResponse {topic=" + this.topic + ","); + sb.append("created_time=" + this.createdTime + "}"); + return sb.toString(); + } + +} diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/JsonUtils.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/JsonUtils.java new file mode 100644 index 0000000000..69455c5db5 --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/JsonUtils.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.eventmesh.admin.rocketmq.util; + +import java.io.IOException; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + +public class JsonUtils { + + private static ObjectMapper objectMapper; + + static { + objectMapper = new ObjectMapper(); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); + } + + public static byte[] serialize(String topic, Class data) throws JsonProcessingException { + if (data == null) { + return null; + } + return objectMapper.writeValueAsBytes(data); + } + + public static String toJson(Object obj) throws JsonProcessingException { + if (obj == null) { + return null; + } + return objectMapper.writeValueAsString(obj); + } + + public static T toObject(String json, Class clazz) throws JsonProcessingException { + return objectMapper.readValue(json, clazz); + } + + public static T deserialize(Class clazz, byte[] bytes) throws IOException { + if (bytes == null || bytes.length == 0) { + return null; + } + + return objectMapper.readValue(bytes, clazz); + } + + public static T deserialize(Class clazz, String json) throws IOException { + if (json == null || json.length() == 0) { + return null; + } + + return objectMapper.readValue(json, clazz); + } +} diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/NetUtils.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/NetUtils.java new file mode 100644 index 0000000000..c6c7992d2e --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/NetUtils.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.eventmesh.admin.rocketmq.util; + +import org.apache.http.Consts; + +import java.io.IOException; +import java.io.InputStreamReader; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.net.httpserver.HttpExchange; + +public class NetUtils { + + private static final Logger logger = LoggerFactory.getLogger(NetUtils.class); + + public static String parsePostBody(HttpExchange exchange) + throws IOException { + StringBuilder body = new StringBuilder(); + if ("post".equalsIgnoreCase(exchange.getRequestMethod()) + || "put".equalsIgnoreCase(exchange.getRequestMethod())) { + try (InputStreamReader reader = + new InputStreamReader(exchange.getRequestBody(), Consts.UTF_8)) { + char[] buffer = new char[256]; + int read; + while ((read = reader.read(buffer)) != -1) { + body.append(buffer, 0, read); + } + } + } + return body.toString(); + } +} + diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/RequestMapping.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/RequestMapping.java new file mode 100644 index 0000000000..b093d3e9f3 --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/RequestMapping.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.eventmesh.admin.rocketmq.util; + +import com.sun.net.httpserver.HttpExchange; + +public class RequestMapping { + + public static boolean postMapping(String value, HttpExchange httpExchange) { + if ("post".equalsIgnoreCase(httpExchange.getRequestMethod())) { + String requestUri = httpExchange.getRequestURI().getPath(); + UrlMappingPattern matcher = new UrlMappingPattern(value); + return matcher.matches(requestUri); + } + return false; + } + + public static boolean getMapping(String value, HttpExchange httpExchange) { + if ("get".equalsIgnoreCase(httpExchange.getRequestMethod())) { + String requestUri = httpExchange.getRequestURI().getPath(); + UrlMappingPattern matcher = new UrlMappingPattern(value); + return matcher.matches(requestUri); + } + return false; + } + + public static boolean putMapping(String value, HttpExchange httpExchange) { + if ("put".equalsIgnoreCase(httpExchange.getRequestMethod())) { + String requestUri = httpExchange.getRequestURI().getPath(); + UrlMappingPattern matcher = new UrlMappingPattern(value); + return matcher.matches(requestUri); + } + return false; + } + + public static boolean deleteMapping(String value, HttpExchange httpExchange) { + if ("delete".equalsIgnoreCase(httpExchange.getRequestMethod())) { + String requestUri = httpExchange.getRequestURI().getPath(); + UrlMappingPattern matcher = new UrlMappingPattern(value); + return matcher.matches(requestUri); + } + return false; + } + +} diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/UrlMappingPattern.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/UrlMappingPattern.java new file mode 100644 index 0000000000..0e31b13ca1 --- /dev/null +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/UrlMappingPattern.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.eventmesh.admin.rocketmq.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class UrlMappingPattern { + + private static final String URL_PARAMETER_REGEX = "\\{(\\w*?)\\}"; + + private static final String URL_PARAMETER_MATCH_REGEX = + "\\([%\\\\w-.\\\\~!\\$&'\\\\(\\\\)\\\\*\\\\+,;=:\\\\[\\\\]@]+?\\)"; + + private static final Pattern URL_PARAMETER_PATTERN = Pattern.compile(URL_PARAMETER_REGEX); + + private static final String URL_FORMAT_REGEX = "(?:\\.\\{format\\})$"; + + private static final String URL_FORMAT_MATCH_REGEX = "(?:\\\\.\\([\\\\w%]+?\\))?"; + + private static final String URL_QUERY_STRING_REGEX = "(?:\\?.*?)?$"; + + private String urlMappingPattern; + + private Pattern compiledUrlMappingPattern; + + private List paramNames = new ArrayList(); + + public UrlMappingPattern(String pattern) { + super(); + setUrlMappingPattern(pattern); + compile(); + } + + public String getMappingPattern() { + return getUrlMappingPattern().replaceFirst(URL_FORMAT_REGEX, ""); + } + + private String getUrlMappingPattern() { + return urlMappingPattern; + } + + public Map extractPathParameterValues(String url) { + Matcher matcher = compiledUrlMappingPattern.matcher(url); + if (matcher.matches()) { + return extractParameters(matcher); + } + return null; + } + + public boolean matches(String url) { + return (extractPathParameterValues(url) != null); + } + + public void compile() { + acquireParamNames(); + String parsedPattern = + getUrlMappingPattern().replaceFirst(URL_FORMAT_REGEX, URL_FORMAT_MATCH_REGEX); + parsedPattern = parsedPattern.replaceAll(URL_PARAMETER_REGEX, URL_PARAMETER_MATCH_REGEX); + this.compiledUrlMappingPattern = Pattern.compile(parsedPattern + URL_QUERY_STRING_REGEX); + } + + private void acquireParamNames() { + Matcher m = URL_PARAMETER_PATTERN.matcher(getUrlMappingPattern()); + while (m.find()) { + paramNames.add(m.group(1)); + } + } + + private Map extractParameters(Matcher matcher) { + Map values = new HashMap(); + for (int i = 0; i < matcher.groupCount(); i++) { + String value = matcher.group(i + 1); + + if (value != null) { + values.put(paramNames.get(i), value); + } + } + return values; + } + + private void setUrlMappingPattern(String pattern) { + this.urlMappingPattern = pattern; + } + + public List getParamNames() { + return Collections.unmodifiableList(paramNames); + } +} diff --git a/eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/admin/controller/ClientManageController.java b/eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/admin/controller/ClientManageController.java index cd6d094db5..3fc2e8e2b8 100644 --- a/eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/admin/controller/ClientManageController.java +++ b/eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/admin/controller/ClientManageController.java @@ -17,21 +17,34 @@ package org.apache.eventmesh.runtime.admin.controller; +import org.apache.eventmesh.admin.rocketmq.controller.AdminController; +import org.apache.eventmesh.runtime.admin.handler.QueryRecommendEventMeshHandler; +import org.apache.eventmesh.runtime.admin.handler.RedirectClientByIpPortHandler; +import org.apache.eventmesh.runtime.admin.handler.RedirectClientByPathHandler; +import org.apache.eventmesh.runtime.admin.handler.RedirectClientBySubSystemHandler; +import org.apache.eventmesh.runtime.admin.handler.RejectAllClientHandler; +import org.apache.eventmesh.runtime.admin.handler.RejectClientByIpPortHandler; +import org.apache.eventmesh.runtime.admin.handler.RejectClientBySubSystemHandler; +import org.apache.eventmesh.runtime.admin.handler.ShowClientBySystemHandler; +import org.apache.eventmesh.runtime.admin.handler.ShowClientHandler; +import org.apache.eventmesh.runtime.admin.handler.ShowListenClientByTopicHandler; +import org.apache.eventmesh.runtime.boot.EventMeshTCPServer; + import java.io.IOException; import java.net.InetSocketAddress; -import com.sun.net.httpserver.HttpServer; - -import org.apache.eventmesh.runtime.admin.handler.*; -import org.apache.eventmesh.runtime.boot.EventMeshTCPServer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.sun.net.httpserver.HttpServer; + public class ClientManageController { private static final Logger logger = LoggerFactory.getLogger(ClientManageController.class); private EventMeshTCPServer eventMeshTCPServer; + + private AdminController adminController; public ClientManageController(EventMeshTCPServer eventMeshTCPServer) { this.eventMeshTCPServer = eventMeshTCPServer; @@ -50,6 +63,10 @@ public void start() throws IOException { server.createContext("/clientManage/redirectClientByIpPort", new RedirectClientByIpPortHandler(eventMeshTCPServer)); server.createContext("/clientManage/showListenClientByTopic", new ShowListenClientByTopicHandler(eventMeshTCPServer)); server.createContext("/eventMesh/recommend", new QueryRecommendEventMeshHandler(eventMeshTCPServer)); + + adminController = new AdminController(); + adminController.run(server); + server.start(); logger.info("ClientManageController start success, port:{}", port); }