You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2018/08/28 16:32:27 UTC
[isis] branch master updated: ISIS-1901: Swagger-UI: Replace
index.html with index.template.html
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push:
new bb7eec7 ISIS-1901: Swagger-UI: Replace index.html with index.template.html
bb7eec7 is described below
commit bb7eec7d8d0fe4850537878d2a1628e2b9af3338
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Aug 28 18:28:15 2018 +0200
ISIS-1901: Swagger-UI: Replace index.html with index.template.html
Also let the ResourceServlet handle resources that end with
'.template.html' specifically:
These templates may include placeholders ${placholder-name}.
These are replaced with actual values by the ResourceServlet as
configured.
In this particular case we make the swagger-ui aware of the actual
restful resource path configuration.
Task-Url: https://issues.apache.org/jira/browse/ISIS-1901
---
.../services/swagger/SwaggerServiceMenu.java | 2 +-
.../isis/commons/internal/base/_Strings.java | 9 +++
.../internal/base/_Strings_KeyValuePair.java | 60 ++++++++++++++
.../isis/core/commons/lang/ResourceUtil.java | 23 +++++-
.../core/webapp/content/ResourceCachingFilter.java | 63 ++-------------
.../isis/core/webapp/content/ResourceServlet.java | 91 +++++++++++++++-------
.../ResourceServlet_HtmlTemplateVariables.java | 64 +++++++++++++++
.../swagger-ui/{index.html => index.template.html} | 8 +-
core/plugins/eventbus-axon/pom.xml | 4 +
9 files changed, 231 insertions(+), 93 deletions(-)
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/swagger/SwaggerServiceMenu.java b/core/applib/src/main/java/org/apache/isis/applib/services/swagger/SwaggerServiceMenu.java
index 655a755..c840300 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/swagger/SwaggerServiceMenu.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/swagger/SwaggerServiceMenu.java
@@ -55,7 +55,7 @@ public class SwaggerServiceMenu {
)
@MemberOrder(sequence="500.600.1")
public LocalResourcePath openSwaggerUi() {
- return new LocalResourcePath("/swagger-ui/index.html");
+ return new LocalResourcePath("/swagger-ui/index.template.html");
}
public static class OpenRestApiDomainEvent extends ActionDomainEvent { private static final long serialVersionUID = 1L; }
diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings.java b/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings.java
index 273d44a..ea764f7 100644
--- a/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings.java
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings.java
@@ -24,6 +24,7 @@ import static org.apache.isis.commons.internal.base._With.mapIfPresentElse;
import static org.apache.isis.commons.internal.base._With.requires;
import java.nio.charset.Charset;
+import java.util.Map;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.UnaryOperator;
@@ -61,6 +62,14 @@ public final class _Strings {
* (a duplicate of in {@link _Constants.emptyStringArray} )
*/
public final static String[] emptyArray = new String[0];
+
+ // -- PAIR OF STRINGS
+
+ public static interface KeyValuePair extends Map.Entry<String, String> { }
+
+ public static KeyValuePair pair(final String key, final String value){
+ return _Strings_KeyValuePair.of(key, value);
+ }
// -- BASIC PREDICATES
diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings_KeyValuePair.java b/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings_KeyValuePair.java
new file mode 100644
index 0000000..7696a48
--- /dev/null
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Strings_KeyValuePair.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.isis.commons.internal.base;
+
+import static org.apache.isis.commons.internal.exceptions._Exceptions.notImplemented;
+
+import org.apache.isis.commons.internal.base._Strings.KeyValuePair;
+
+/**
+ *
+ * package private mixin for utility class {@link _Strings}
+ *
+ */
+final class _Strings_KeyValuePair implements _Strings.KeyValuePair {
+
+ static KeyValuePair of(String key, String value) {
+ return new _Strings_KeyValuePair(key, value);
+ }
+
+ private final String key;
+ private final String value;
+
+ private _Strings_KeyValuePair(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ @Override
+ public String getKey() {
+ return key;
+ }
+
+ @Override
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public String setValue(String value) {
+ throw notImplemented();
+ }
+
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ResourceUtil.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ResourceUtil.java
index c92eb89..3b31c98 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ResourceUtil.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ResourceUtil.java
@@ -19,13 +19,14 @@
package org.apache.isis.core.commons.lang;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.InputStream;
+import javax.servlet.http.HttpServletRequest;
+
import org.apache.isis.commons.internal.context._Context;
-/**
- * Adapted from Ibatis Common, now with some additional guava stuff.
- */
public class ResourceUtil {
private ResourceUtil(){}
@@ -62,5 +63,21 @@ public class ResourceUtil {
return null;
}
}
+
+ /**
+ * @param request
+ * @return real-path resource from file-system, if any
+ */
+ public static InputStream getResourceAsStream(final HttpServletRequest request) {
+ final String realPath = request.getSession().getServletContext().getRealPath(request.getServletPath());
+ if (realPath == null) {
+ return null;
+ }
+ try {
+ return new FileInputStream(realPath);
+ } catch (final FileNotFoundException e) {
+ return null;
+ }
+ }
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/webapp/content/ResourceCachingFilter.java b/core/metamodel/src/main/java/org/apache/isis/core/webapp/content/ResourceCachingFilter.java
index f95bd2a..ceb7758 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/webapp/content/ResourceCachingFilter.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/webapp/content/ResourceCachingFilter.java
@@ -33,67 +33,18 @@ import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.isis.commons.internal.exceptions._Exceptions.FluentException;
-/**
- * Adapted from {@link http
- * ://www.digitalsanctuary.com/tech-blog/java/jboss/setting
- * -cache-headers-from-jboss.html}
- *
- * <p>
- * Usage:
- *
- * <pre>
- * <filter>
- * <filter-name>ResourceCachingFilter</filter-name>
- * <filter-class>org.apache.isis.core.webapp.content.ResourceCachingFilter</filter-class>
- * <init-param>
- * <param-name>CacheTime</param-name>
- * <param-value>86400</param-value>
- * </init-param>
- * </filter>
- * ...
- * <filter-mapping>
- * <filter-name>ResourceCachingFilter</filter-name>
- * <url-pattern>*.css</url-pattern>
- * </filter-mapping>
- * <filter-mapping>
- * <filter-name>ResourceCachingFilter</filter-name>
- * <url-pattern>*.png</url-pattern>
- * </filter-mapping>
- * <filter-mapping>
- * <filter-name>ResourceCachingFilter</filter-name>
- * <url-pattern>*.jpg</url-pattern>
- * </filter-mapping>
- * <filter-mapping>
- * <filter-name>ResourceCachingFilter</filter-name>
- * <url-pattern>*.jpeg</url-pattern>
- * </filter-mapping>
- * <filter-mapping>
- * <filter-name>ResourceCachingFilter</filter-name>
- * <url-pattern>*.gif</url-pattern>
- * </filter-mapping>
- * <filter-mapping>
- * <filter-name>ResourceCachingFilter</filter-name>
- * <url-pattern>*.svg</url-pattern>
- * </filter-mapping>
- * <filter-mapping>
- * <filter-name>ResourceCachingFilter</filter-name>
- * <url-pattern>*.js</url-pattern>
- * </filter-mapping>
- * <filter-mapping>
- * <filter-name>ResourceCachingFilter</filter-name>
- * <url-pattern>*.html</url-pattern>
- * </filter-mapping>
- * <filter-mapping>
- * <filter-name>ResourceCachingFilter</filter-name>
- * <url-pattern>*.swf</url-pattern>
- * </filter-mapping>
- * </pre>
- */
+@WebFilter(
+ initParams = { @WebInitParam(name = "CacheTime", value = "86400") },
+ urlPatterns = {
+ "*.css", "*.png", "*.jpg", "*.jpeg", "*.gif", "*.svg", "*.js", "*.html", "*.swf" }
+)
public class ResourceCachingFilter implements Filter {
/**
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/webapp/content/ResourceServlet.java b/core/metamodel/src/main/java/org/apache/isis/core/webapp/content/ResourceServlet.java
index a5ef21c..69107ec 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/webapp/content/ResourceServlet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/webapp/content/ResourceServlet.java
@@ -19,12 +19,17 @@
package org.apache.isis.core.webapp.content;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
+import static org.apache.isis.commons.internal.base._Strings.pair;
+import static org.apache.isis.commons.internal.base._With.ifPresentElse;
+import static org.apache.isis.commons.internal.base._With.ifPresentElseGet;
+
import java.io.IOException;
import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -32,14 +37,34 @@ import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.isis.commons.internal.base._Bytes;
+import org.apache.isis.commons.internal.base._Strings;
+import org.apache.isis.commons.internal.resources._Resource;
import org.apache.isis.core.commons.lang.InputStreamExtensions;
import org.apache.isis.core.commons.lang.ResourceUtil;
import org.apache.isis.core.commons.lang.StringExtensions;
+/**
+ * Serves static web-resources by class-path or file-system lookup.
+ * Also handles HTML-templates, where template's placeholders get replaced by their values.
+ */
+@WebServlet(
+ urlPatterns = {
+ "*.css", "*.png", "*.jpg", "*.jpeg", "*.gif", "*.svg", "*.js", "*.html", "*.swf" }
+)
public class ResourceServlet extends HttpServlet {
private static final Logger LOG = LoggerFactory.getLogger(ResourceServlet.class);
private static final long serialVersionUID = 1L;
+ private ResourceServlet_HtmlTemplateVariables templateVariables;
+
+ @Override
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+
+ final String restfulPath = ifPresentElse(_Resource.getRestfulPathIfAny(), "restful");
+ templateVariables = new ResourceServlet_HtmlTemplateVariables(pair("restful", restfulPath));
+ }
@Override
protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
@@ -50,34 +75,53 @@ public class ResourceServlet extends HttpServlet {
protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
+
+ // -- HELPER
private void processRequest(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
final String servletPath = StringExtensions.stripLeadingSlash(request.getServletPath());
LOG.debug("request: {}", servletPath);
- // try to load from filesystem
- final InputStream is2 = getRealPath(request);
- if (is2 != null) {
- LOG.debug("request: {} loaded from filesystem", servletPath);
- writeContentType(request, response);
- InputStreamExtensions.copyTo(is2, response.getOutputStream());
- is2.close();
- return;
- }
-
- // otherwise, try to load from classpath
- final InputStream is = ResourceUtil.getResourceAsStream(servletPath);
+ final InputStream is = ifPresentElseGet(
+ ResourceUtil.getResourceAsStream(request), // try to load from file-system first
+ ()->ResourceUtil.getResourceAsStream(servletPath)); // otherwise, try to load from class-path
+
if (is != null) {
LOG.debug("request: {} loaded from classpath", servletPath );
- writeContentType(request, response);
- InputStreamExtensions.copyTo(is, response.getOutputStream());
- is.close();
- return;
+
+ try {
+ writeContentType(request, response);
+ processContent(is, request, response);
+ return;
+ } finally {
+ is.close();
+ }
}
LOG.warn("failed to load resource from classpath or file system: {}", servletPath);
}
+ private void processContent(
+ final InputStream is,
+ final HttpServletRequest request,
+ final HttpServletResponse response)
+ throws IOException {
+
+ if(request.getServletPath().endsWith(".template.html")) {
+
+ final String templateContent = _Strings.ofBytes(_Bytes.of(is), StandardCharsets.UTF_8);
+ final String htmlContent = templateVariables.applyTo(templateContent);
+
+ response.getWriter().append(htmlContent);
+
+ } else {
+
+ // direct copy
+ InputStreamExtensions.copyTo(is, response.getOutputStream());
+
+ }
+ }
+
private static void writeContentType(final HttpServletRequest request, final HttpServletResponse response) {
final String contentType = guessContentType(request.getServletPath());
if(contentType != null) {
@@ -108,15 +152,4 @@ public class ResourceServlet extends HttpServlet {
return null;
}
- private FileInputStream getRealPath(final HttpServletRequest request) {
- final String realPath = request.getSession().getServletContext().getRealPath(request.getServletPath());
- if (realPath == null) {
- return null;
- }
- try {
- return new FileInputStream(realPath);
- } catch (final FileNotFoundException e) {
- return null;
- }
- }
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/webapp/content/ResourceServlet_HtmlTemplateVariables.java b/core/metamodel/src/main/java/org/apache/isis/core/webapp/content/ResourceServlet_HtmlTemplateVariables.java
new file mode 100644
index 0000000..cc2a122
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/webapp/content/ResourceServlet_HtmlTemplateVariables.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.isis.core.webapp.content;
+
+import static org.apache.isis.commons.internal.base._NullSafe.stream;
+import static org.apache.isis.commons.internal.base._With.requires;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.isis.commons.internal.base._Strings.KeyValuePair;
+
+/**
+ * Package private mixin for ResourceServlet
+ * @since 2.0.0
+ */
+final class ResourceServlet_HtmlTemplateVariables {
+
+ final Map<String, String> placeholders = new HashMap<>();
+
+ public ResourceServlet_HtmlTemplateVariables(KeyValuePair ... kvPairs) {
+ requires(kvPairs, "placeholders");
+
+ stream(kvPairs)
+ .forEach(kvPair->placeholders.put(kvPair.getKey(), kvPair.getValue()));
+ }
+
+ /**
+ * @param template HTML template containing placeholders
+ * @return HTML post-processed template with all the placeholders replaced by their values
+ */
+ public String applyTo(final String template) {
+
+ String acc = template;
+
+ for ( Entry<String, String> entry : placeholders.entrySet()) {
+ final String placeholderLiteral = "${" + entry.getKey() + "}";
+ final String placeholderValue = entry.getValue();
+
+ acc = acc.replace(placeholderLiteral, placeholderValue);
+ }
+
+ return acc;
+ }
+
+}
diff --git a/core/metamodel/src/main/resources/swagger-ui/index.html b/core/metamodel/src/main/resources/swagger-ui/index.template.html
similarity index 96%
rename from core/metamodel/src/main/resources/swagger-ui/index.html
rename to core/metamodel/src/main/resources/swagger-ui/index.template.html
index 46247d0..38e48d2 100644
--- a/core/metamodel/src/main/resources/swagger-ui/index.html
+++ b/core/metamodel/src/main/resources/swagger-ui/index.template.html
@@ -152,15 +152,15 @@
API Select:
<select id="input_baseUrl" name="baseUrl" style="height: 26px;">
- <option id="private" label="private" value="../../restful/swagger/private">private</option>
- <option id="public" label="public" value="../../restful/swagger/public">public</option>
- <option id="prototyping" label="prototyping" value="../../restful/swagger/prototyping">prototyping</option>
+ <option id="private" label="private" value="../../${restful}/swagger/private">private</option>
+ <option id="public" label="public" value="../../${restful}/swagger/public">public</option>
+ <option id="prototyping" label="prototyping" value="../../${restful}/swagger/prototyping">prototyping</option>
</select>
</div>
<div class='input' style="display:none;"><input placeholder="api_key" id="input_apiKey" name="apiKey" type="text"/></div>
<div class='input'><a id="explore" href="#" data-sw-translate>Reload</a></div>
- <a href="../restful/" target="blank" title="You might need to login.">Direct API Link</a>
+ <a href="../${restful}/" target="blank" title="You might need to login.">Direct API Link</a>
</form>
diff --git a/core/plugins/eventbus-axon/pom.xml b/core/plugins/eventbus-axon/pom.xml
index 8c85d54..bef0454 100644
--- a/core/plugins/eventbus-axon/pom.xml
+++ b/core/plugins/eventbus-axon/pom.xml
@@ -59,6 +59,10 @@
<groupId>org.axonframework</groupId>
<artifactId>axon-core</artifactId>
<version>${axon-core.version}</version>
+ <!-- <classifier>ee-compat</classifier>
+ seems not available yet
+ see https://github.com/AxonFramework/AxonFramework/issues/534
+ -->
</dependency>
<dependency>