Serve frontend directly from Pulsar Manage backend process (#288)

Fixes #269 

### Motivation

Use the Tomcat Service provided by StringBoot Application to serve front-end resources.
This way in order to start a pulsar manager instance you only have to run bin/pulsar-manager
and you are able to access the UI with
https://localhost:7750/ui

### Modifications

Assume that the frontend is inside directory "ui" of pulsar manager dist package.
Deploy such static content using SpringBootMVC standard components.

### Verifying this change

- [x] Make sure that the change passes the `./gradlew build` checks.
- Run Pulsar Manager standalone and use the frontend at https://localhost:7750/ui/index.html
 


diff --git a/src/main/java/org/apache/pulsar/manager/interceptor/AdminHandlerInterceptor.java b/src/main/java/org/apache/pulsar/manager/interceptor/AdminHandlerInterceptor.java
index f59066c..433e5d0 100644
--- a/src/main/java/org/apache/pulsar/manager/interceptor/AdminHandlerInterceptor.java
+++ b/src/main/java/org/apache/pulsar/manager/interceptor/AdminHandlerInterceptor.java
@@ -63,6 +63,11 @@
 
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        // allow frontend requests, in case of front-end running on the same process of backend
+        if (request.getRequestURI().startsWith("/ui")
+                || request.getRequestURI().startsWith("/static")) {
+            return true;
+        }
         String token = request.getHeader("token");
         String saveToken = jwtService.getToken(request.getSession().getId());
         Map<String, Object> map = Maps.newHashMap();
diff --git a/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java b/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java
index c4d96b7..3f5ac4b 100644
--- a/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java
+++ b/src/main/java/org/apache/pulsar/manager/interceptor/WebAppConfigurer.java
@@ -13,15 +13,20 @@
  */
 package org.apache.pulsar.manager.interceptor;
 
+import java.io.File;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
 import javax.annotation.Resource;
 
 @Configuration
 public class WebAppConfigurer implements WebMvcConfigurer {
 
+    private static final Logger log = LoggerFactory.getLogger(WebAppConfigurer.class);
+
     @Resource
     private AdminHandlerInterceptor adminHandlerInterceptor;
 
@@ -30,6 +35,28 @@
         registry.addInterceptor(adminHandlerInterceptor).addPathPatterns("/**")
                 .excludePathPatterns("/pulsar-manager/login")
                 .excludePathPatterns("/pulsar-manager/users/superuser")
-                .excludePathPatterns("/pulsar-manager/third-party-login/**");
+                .excludePathPatterns("/pulsar-manager/third-party-login/**")
+                // static front-end resources
+                .excludePathPatterns("/ui")
+                .excludePathPatterns("/static")
+                .excludePathPatterns("/error");
+    }
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        File ui = new File("ui");
+        if (ui.isDirectory()) {
+            log.info("Found front-end at " + ui.getAbsolutePath());
+            String uipath = ui.toURI().toString();
+            String uistaticpath = new File(ui, "static").toURI().toString();
+
+            registry.addResourceHandler("/static/**")
+                    .addResourceLocations("/", uistaticpath);
+            registry.addResourceHandler("/ui/**")
+                    .addResourceLocations("/", uipath);
+        } else {
+            log.info("Front-end not found at " + ui.getAbsolutePath()
+                    + ". Maybe you are deploying the front-end as a separate process");
+        }
     }
 }