This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new 6aa81ab Swagger UI improvements.
6aa81ab is described below
commit 6aa81abfc100bd624921267ba9e7bb54ce0472a8
Author: JamesBognar <[email protected]>
AuthorDate: Fri Apr 13 19:19:50 2018 -0400
Swagger UI improvements.
---
.../java/org/apache/juneau/html/BasicHtmlTest.java | 2 +-
.../org/apache/juneau/utils/StringUtilsTest.java | 12 +
.../java/org/apache/juneau/dto/LinkString.java | 43 +--
.../apache/juneau/dto/swagger/OperationMap.java | 31 +-
.../org/apache/juneau/html/HtmlParserSession.java | 2 +-
.../apache/juneau/html/HtmlSerializerSession.java | 2 +-
.../apache/juneau/html/annotation/HtmlLink.java | 4 +-
.../org/apache/juneau/internal/StringUtils.java | 17 ++
juneau-doc/src/main/javadoc/overview.html | 23 +-
juneau-examples/juneau-examples-rest/examples.cfg | 2 +-
.../juneau/examples/rest/DirectoryResource.java | 305 -------------------
.../examples/rest/PredefinedLabelsResource.java | 19 +-
.../examples/rest/SystemPropertiesResource.java | 16 +-
.../juneau/examples/rest/TempDirResource.java | 13 +-
.../examples/rest/TestMultiPartFormPostsTest.java | 2 +-
.../microservice/resources/DirectoryResource.java | 327 ++++++++-------------
.../my-microservice.cfg | 2 +-
.../org/apache/juneau/rest/BasicRestConfig.java | 2 +-
.../java/org/apache/juneau/rest/RestRequest.java | 9 +
...ServletRoot.java => RedirectToServletRoot.java} | 6 +-
.../apache/juneau/rest/vars/RequestPathVar.java | 2 +
21 files changed, 257 insertions(+), 584 deletions(-)
diff --git
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/html/BasicHtmlTest.java
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/html/BasicHtmlTest.java
index 10b9c5f..61d7f0d 100644
---
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/html/BasicHtmlTest.java
+++
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/html/BasicHtmlTest.java
@@ -2832,7 +2832,7 @@ public class BasicHtmlTest {
}
}
- @HtmlLink(nameProperty="a",hrefProperty="b")
+ @HtmlLink(nameProperty="a",uriProperty="b")
public static class LinkBean {
public String a;
public String b;
diff --git
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
index 1b9f080..44eaa14 100755
---
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
+++
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
@@ -875,4 +875,16 @@ public class StringUtilsTest {
assertEquals("1: foo\n", getNumberedLines("foo"));
assertEquals("1: foo\n2: bar\n", getNumberedLines("foo\nbar"));
}
+
+
//====================================================================================================
+ // compare(String,String)
+
//====================================================================================================
+ @Test
+ public void testCompare() throws Exception {
+ assertTrue(compare("a","b") < 0);
+ assertTrue(compare("b","a") > 0);
+ assertTrue(compare(null,"b") < 0);
+ assertTrue(compare("b",null) > 0);
+ assertTrue(compare(null,null) == 0);
+ }
}
diff --git
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/LinkString.java
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/LinkString.java
index 0bb04d6..a91d85a 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/LinkString.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/LinkString.java
@@ -16,6 +16,7 @@ import static org.apache.juneau.internal.StringUtils.*;
import java.text.*;
+import org.apache.juneau.annotation.*;
import org.apache.juneau.html.*;
import org.apache.juneau.html.annotation.*;
import org.apache.juneau.httppart.*;
@@ -34,9 +35,11 @@ import org.apache.juneau.utils.*;
* When encountered by the {@link HtmlSerializer} class, this object gets
converted to a hyperlink.
* All other serializers simply convert it to a simple bean.
*/
-@HtmlLink(nameProperty = "name", hrefProperty = "href")
+@HtmlLink
+@Bean(fluentSetters=true)
public class LinkString implements Comparable<LinkString> {
- private String name, href;
+ private String name;
+ private java.net.URI uri;
/** No-arg constructor. */
public LinkString() {}
@@ -45,12 +48,12 @@ public class LinkString implements Comparable<LinkString> {
* Constructor.
*
* @param name Corresponds to the text inside of the <xt><A></xt>
element.
- * @param href Corresponds to the value of the <xa>href</xa> attribute
of the <xt><A></xt> element.
- * @param hrefArgs Optional arguments for {@link MessageFormat} style
arguments in the href.
+ * @param uri Corresponds to the value of the <xa>href</xa> attribute
of the <xt><A></xt> element.
+ * @param uriArgs Optional arguments for {@link MessageFormat} style
arguments in the href.
*/
- public LinkString(String name, String href, Object...hrefArgs) {
- setName(name);
- setHref(href, hrefArgs);
+ public LinkString(String name, String uri, Object...uriArgs) {
+ name(name);
+ uri(uri, uriArgs);
}
@@ -76,48 +79,48 @@ public class LinkString implements Comparable<LinkString> {
* @param name The new value for the <property>name</property> property
on this bean.
* @return This object (for method chaining).
*/
- public LinkString setName(String name) {
+ public LinkString name(String name) {
this.name = name;
return this;
}
/**
- * Bean property getter: <property>href</property>.
+ * Bean property getter: <property>uri</property>.
*
* <p>
* Corresponds to the value of the <xa>href</xa> attribute of the
<xt><A></xt> element.
*
* @return The value of the <property>href</property> property on this
bean, or <jk>null</jk> if it is not set.
*/
- public String getHref() {
- return href;
+ public java.net.URI getUri() {
+ return uri;
}
/**
- * Bean property setter: <property>href</property>.
+ * Bean property setter: <property>uri</property>.
*
- * @param href The new value for the <property>href</property> property
on this bean.
+ * @param uri The new value for the <property>href</property> property
on this bean.
* @return This object (for method chaining).
*/
- public LinkString setHref(String href) {
- setHref(href, new Object[0]);
+ public LinkString uri(String uri) {
+ uri(uri, new Object[0]);
return this;
}
/**
- * Bean property setter: <property>href</property>.
+ * Bean property setter: <property>uri</property>.
*
* <p>
- * Same as {@link #setHref(String)} except allows for {@link
MessageFormat} style arguments.
+ * Same as {@link #uri(String)} except allows for {@link MessageFormat}
style arguments.
*
- * @param href The new href.
+ * @param uri The new href.
* @param args Optional {@link MessageFormat}-style arguments.
* @return This object (for method chaining).
*/
- public LinkString setHref(String href, Object...args) {
+ public LinkString uri(String uri, Object...args) {
for (int i = 0; i < args.length; i++)
args[i] =
SimpleUonPartSerializer.DEFAULT.serialize(HttpPartType.PATH, args[i]);
- this.href = format(href, args);
+ this.uri = java.net.URI.create(format(uri, args));
return this;
}
diff --git
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/OperationMap.java
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/OperationMap.java
index 8221758..017d0c1 100644
---
a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/OperationMap.java
+++
b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/OperationMap.java
@@ -16,6 +16,7 @@ import static org.apache.juneau.internal.StringUtils.*;
import java.util.*;
+import org.apache.juneau.internal.*;
import org.apache.juneau.utils.*;
/**
@@ -38,24 +39,24 @@ public class OperationMap extends TreeMap<String,Operation>
{
private static final long serialVersionUID = 1L;
private static final Comparator<String> OP_SORTER = new
Comparator<String>() {
- private final Map<String,Integer> methods = new
AMap<String,Integer>()
- .append("get",7)
- .append("put",6)
- .append("post",5)
- .append("delete",4)
- .append("options",3)
- .append("head",2)
- .append("patch",1);
+ private final Map<String,String> methods = new
AMap<String,String>()
+ .append("get","0")
+ .append("put","1")
+ .append("post","2")
+ .append("delete","3")
+ .append("options","4")
+ .append("head","5")
+ .append("patch","6");
@Override
public int compare(String o1, String o2) {
- Integer i1 = methods.get(o1);
- Integer i2 = methods.get(o2);
- if (i1 == null)
- i1 = 0;
- if (i2 == null)
- i2 = 0;
- return i2.compareTo(i1);
+ String s1 = methods.get(o1);
+ String s2 = methods.get(o2);
+ if (s1 == null)
+ s1 = o1;
+ if (s2 == null)
+ s2 = o2;
+ return StringUtils.compare(s1, s2);
}
};
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java
index 993b603..72b3be3 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java
@@ -315,7 +315,7 @@ public final class HtmlParserSession extends
XmlParserSession {
if (beanClass.isAnnotationPresent(HtmlLink.class)) {
HtmlLink h = beanClass.getAnnotation(HtmlLink.class);
BeanMap<T> m = newBeanMap(beanClass);
- m.put(h.hrefProperty(), href);
+ m.put(h.uriProperty(), href);
m.put(h.nameProperty(), name);
return m.getBean();
}
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
index 5bb1124..94871d3 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
@@ -378,7 +378,7 @@ public class HtmlSerializerSession extends
XmlSerializerSession {
Class<?> c = o.getClass();
if (c.isAnnotationPresent(HtmlLink.class)) {
HtmlLink h =
o.getClass().getAnnotation(HtmlLink.class);
- Object urlProp =
m.get(h.hrefProperty());
+ Object urlProp = m.get(h.uriProperty());
Object nameProp =
m.get(h.nameProperty());
out.oTag("a").attrUri("href",
urlProp).append('>').text(nameProp).eTag("a");
cr = CR_MIXED;
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlLink.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlLink.java
index 735e970..7a4873c 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlLink.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/annotation/HtmlLink.java
@@ -44,10 +44,10 @@ public @interface HtmlLink {
/**
* The bean property whose value becomes the name in the hyperlink.
*/
- String nameProperty() default "";
+ String nameProperty() default "name";
/**
* The bean property whose value becomes the url in the hyperlink.
*/
- String hrefProperty() default "";
+ String uriProperty() default "uri";
}
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
index 58af833..694a01b 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
@@ -2149,4 +2149,21 @@ public final class StringUtils {
sb.append(String.format("%0"+digits+"d",
start++)).append(": ").append(l).append("\n");
return sb.toString();
}
+
+ /**
+ * Compares two strings, but gracefully handles <jk>nulls</jk>.
+ *
+ * @param s1 The first string.
+ * @param s2 The second string.
+ * @return The same as {@link String#compareTo(String)}.
+ */
+ public static int compare(String s1, String s2) {
+ if (s1 == null && s2 == null)
+ return 0;
+ if (s1 == null)
+ return Integer.MIN_VALUE;
+ if (s2 == null)
+ return Integer.MAX_VALUE;
+ return s1.compareTo(s2);
+ }
}
diff --git a/juneau-doc/src/main/javadoc/overview.html
b/juneau-doc/src/main/javadoc/overview.html
index e0f54db..7f3922d 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -15443,14 +15443,23 @@
}
</p>
<p>
- This example renders the following consisting of a list
of hyperlinks:
+ The {@link org.apache.juneau.dto.LinkString Action}
bean is a predefined <ja>@HtmlLink</ja> bean provided
+ to simplify specifying actions.
+ <br>The following is equivalent to above.
+ </p>
+ <p class='bcode w800'>
+ <ja>@RestMethod</ja>(name=<jsf>GET</jsf>, path=<js>"/htmlLinks"</js>)
+ <jk>public</jk> Action[] htmlLinks() {
+ <jk>return new</jk> Action[] {
+ <jk>new</jk> Action(<js>"apache"</js>,
<js>"http://apache.org"</js>),
+ <jk>new</jk> Action(<js>"juneau"</js>,
<js>"http://juneau.apache.org"</js>)
+ };
+ }
+ </p>
+ <p>
+ Both examples render the following consisting of a list
of hyperlinks:
</p>
<img class='bordered'
src='doc-files/juneau-rest-server.PredefinedLabelBeans.3.png'
style='width:92px'/>
-
- <h5 class='section'>See Also:</h5>
- <ul>
- <li class='jc'>{@link org.apache.juneau.dto.LinkString}
- </ul>
</div>
<!--
========================================================================================================
-->
@@ -21392,7 +21401,7 @@
<li class='jc'>{@link
org.apache.juneau.rest.helper.ReaderResource}
<li class='jc'>{@link
org.apache.juneau.rest.helper.ReaderResourceBuilder}
<li class='jc'>{@link
org.apache.juneau.rest.helper.Redirect}
- <li class='jc'>{@link
org.apache.juneau.rest.helper.RedirectServletRoot}
+ <li class='jc'>{@link
org.apache.juneau.rest.helper.RedirectToServletRoot}
<li class='jc'>{@link
org.apache.juneau.rest.helper.ResourceDescription}
<li class='jc'>{@link
org.apache.juneau.rest.helper.StreamResource}
<li class='jc'>{@link
org.apache.juneau.rest.helper.StreamResourceBuilder}
diff --git a/juneau-examples/juneau-examples-rest/examples.cfg
b/juneau-examples/juneau-examples-rest/examples.cfg
index 5336293..e869a35 100755
--- a/juneau-examples/juneau-examples-rest/examples.cfg
+++ b/juneau-examples/juneau-examples-rest/examples.cfg
@@ -55,7 +55,7 @@ headerLink = http://juneau.apache.org
footerIcon = servlet:/htdocs/images/asf.png
footerLink = http://www.apache.org
-icon = $C{REST/headerIcon}
+favicon = $C{REST/headerIcon}
header = <a href='$U{$C{REST/headerLink}}'><img src='$U{$C{REST/headerIcon}}'
style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/></a>
footer = <a href='$U{$C{REST/footerLink}}'><img
style='float:right;padding-right:20px;height:32px'
src='$U{$C{REST/footerIcon}}'>
diff --git
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java
b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java
deleted file mode 100644
index 069da14..0000000
---
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java
+++ /dev/null
@@ -1,305 +0,0 @@
-//
***************************************************************************************************************************
-// * 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.juneau.examples.rest;
-
-import static java.util.logging.Level.*;
-import static org.apache.juneau.html.HtmlSerializer.*;
-import static org.apache.juneau.http.HttpMethodName.*;
-import static org.apache.juneau.rest.annotation.HookEvent.*;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.logging.*;
-
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.converters.*;
-import org.apache.juneau.rest.exception.*;
-import org.apache.juneau.rest.helper.*;
-import org.apache.juneau.rest.widget.*;
-import org.apache.juneau.utils.*;
-
-/**
- * Sample REST resource for exploring local file systems.
- */
-@RestResource(
- messages="nls/DirectoryResource",
- htmldoc=@HtmlDoc(
- widgets={
- ContentTypeMenuItem.class,
- ThemeMenuItem.class
- },
- navlinks={
- "up: request:/..",
- "options: servlet:/?method=OPTIONS",
- "$W{ContentTypeMenuItem}",
- "$W{ThemeMenuItem}",
- "source:
$C{Source/gitHub}/org/apache/juneau/examples/rest/$R{servletClassSimple}.java"
- }
- ),
- allowedMethodParams="*",
- properties={
- @Property(name=HTML_uriAnchorText, value="PROPERTY_NAME"),
- @Property(name="rootDir", value="$S{java.io.tmpdir}"),
- @Property(name="allowViews", value="false"),
- @Property(name="allowDeletes", value="false"),
- @Property(name="allowPuts", value="false")
- },
- swagger={
- "info: {",
- "contact:{name:'Juneau
Developer',email:'[email protected]'},",
- "license:{name:'Apache
2.0',url:'http://www.apache.org/licenses/LICENSE-2.0.html'},",
- "version:'2.0',",
- "termsOfService:'You are on your own.'",
- "},",
- "externalDocs:{description:'Apache
Juneau',url:'http://juneau.apache.org'}"
- }
-)
-public class DirectoryResource extends BasicRestServlet {
- private static final long serialVersionUID = 1L;
-
- private File rootDir; // The root directory
-
- // Settings enabled through servlet init parameters
- boolean allowDeletes, allowPuts, allowViews;
-
- private static Logger logger =
Logger.getLogger(DirectoryResource.class.getName());
-
- @RestHook(INIT)
- public void init(RestContextBuilder builder) throws Exception {
- RestContextProperties p = builder.getProperties();
- rootDir = new File(p.getString("rootDir"));
- allowViews = p.getBoolean("allowViews", false);
- allowDeletes = p.getBoolean("allowDeletes", false);
- allowPuts = p.getBoolean("allowPuts", false);
- }
-
- /** Returns the root directory defined by the 'rootDir' init parameter
*/
- protected File getRootDir() {
- if (rootDir == null) {
- rootDir = new
File(getProperties().getString("rootDir"));
- if (! rootDir.exists())
- if (! rootDir.mkdirs())
- throw new RuntimeException("Could not
create root dir");
- }
- return rootDir;
- }
-
- @RestMethod(
- name=GET,
- path="/*",
- summary="Get file or directory information",
- description="Returns information about a file or directory.",
- converters={Queryable.class},
- swagger={
- "parameters:[",
- Queryable.SWAGGER_PARAMS,
- "]"
- }
- )
- public Object doGet(RestRequest req, RequestProperties properties)
throws NotFound, InternalServerError {
-
- String pathInfo = req.getPathInfo();
- File f = pathInfo == null ? rootDir : new
File(rootDir.getAbsolutePath() + pathInfo);
-
- if (!f.exists())
- throw new NotFound("File not found");
-
- properties.put("path", f.getAbsolutePath());
-
- try {
- if (f.isDirectory()) {
- List<FileResource> l = new LinkedList<>();
- File[] lfc = f.listFiles();
- if (lfc != null) {
- for (File fc : lfc) {
- URL fUrl = new
URL(req.getRequestURL().append("/").append(fc.getName()).toString());
- l.add(new FileResource(fc,
fUrl));
- }
- }
- return l;
- }
-
- return new FileResource(f, new
URL(req.getRequestURL().toString()));
-
- } catch (MalformedURLException e) {
- throw new InternalServerError(e);
- }
- }
-
- @RestMethod(
- name=DELETE,
- path="/*",
- summary="Delete file",
- description="Delete a file on the file system.",
- guards=AdminGuard.class
- )
- public Object doDelete(RestRequest req) throws MethodNotAllowed,
Forbidden {
-
- if (! allowDeletes)
- throw new MethodNotAllowed("DELETE not enabled");
-
- File f = new File(rootDir.getAbsolutePath() +
req.getPathInfo());
- deleteFile(f);
-
- if (req.getHeader("Accept").contains("text/html"))
- return new Redirect();
-
- return "File deleted";
- }
-
- @RestMethod(
- name=PUT,
- path="/*",
- summary="Upload file",
- description="Uploads a file to the file system.",
- guards=AdminGuard.class
- )
- public Object doPut(RestRequest req) throws MethodNotAllowed,
InternalServerError, Forbidden {
-
- if (! allowPuts)
- throw new MethodNotAllowed("PUT not enabled");
-
- File f = new File(rootDir.getAbsolutePath() +
req.getPathInfo());
- String parentSubPath =
f.getParentFile().getAbsolutePath().substring(rootDir.getAbsolutePath().length());
-
- try (InputStream is = req.getInputStream(); OutputStream os =
new BufferedOutputStream(new FileOutputStream(f))) {
- IOPipe.create(is, os).run();
- } catch (IOException e) {
- throw new InternalServerError(e);
- }
-
- if (req.getContentType().contains("html"))
- return new Redirect(parentSubPath);
-
- return "File added";
- }
-
- /** VIEW request handler (overloaded GET for viewing file contents) */
- @SuppressWarnings("resource")
- @RestMethod(
- name="VIEW",
- path="/*",
- summary="View file",
- description="Views the contents of a file as plain text."
- )
- public void doView(RestRequest req, RestResponse res) throws
MethodNotAllowed, NotFound {
-
- if (! allowViews)
- throw new MethodNotAllowed("VIEW not enabled");
-
- File f = new File(rootDir.getAbsolutePath() +
req.getPathInfo());
-
- if (f.isDirectory())
- throw new MethodNotAllowed("VIEW not available on
directories");
-
- try {
- res.setOutput(new
FileReader(f)).setContentType("text/plain");
- } catch (FileNotFoundException e) {
- throw new NotFound("File not found");
- }
- }
-
- /** DOWNLOAD request handler (overloaded GET for downloading file
contents) */
- @SuppressWarnings("resource")
- @RestMethod(
- name="DOWNLOAD",
- path="/*",
- summary="Download file",
- description="Download the contents of a file as an octet
stream."
- )
- public void doDownload(RestRequest req, RestResponse res) throws
MethodNotAllowed, NotFound {
-
- if (! allowViews)
- throw new MethodNotAllowed("DOWNLOAD not enabled");
-
- File f = new File(rootDir.getAbsolutePath() +
req.getPathInfo());
-
- if (f.isDirectory())
- throw new MethodNotAllowed("DOWNLOAD not available on
directories");
-
- try {
- res.setOutput(new
FileReader(f)).setContentType("application");
- } catch (FileNotFoundException e) {
- throw new NotFound("File not found");
- }
- }
-
- /** File POJO */
- public class FileResource {
- private File f;
- private URL url;
-
- /** Constructor */
- public FileResource(File f, URL url) {
- this.f = f;
- this.url = url;
- }
-
- // Bean property getters
-
- public URL getUrl() {
- return url;
- }
-
- public String getType() {
- return (f.isDirectory() ? "dir" : "file");
- }
-
- public String getName() {
- return f.getName();
- }
-
- public long getSize() {
- return f.length();
- }
-
- public Date getLastModified() {
- return new Date(f.lastModified());
- }
-
- public URL getView() throws Exception {
- if (allowViews && f.canRead() && ! f.isDirectory())
- return new URL(url + "?method=VIEW");
- return null;
- }
-
- public URL getDownload() throws Exception {
- if (allowViews && f.canRead() && ! f.isDirectory())
- return new URL(url + "?method=DOWNLOAD");
- return null;
- }
-
- public URL getDelete() throws Exception {
- if (allowDeletes && f.canWrite())
- return new URL(url + "?method=DELETE");
- return null;
- }
- }
-
- /** Utility method */
- private void deleteFile(File f) {
- try {
- if (f.isDirectory()) {
- File[] lfc = f.listFiles();
- if (lfc != null)
- for (File fc : lfc)
- deleteFile(fc);
- }
- f.delete();
- } catch (Exception e) {
- logger.log(WARNING, "Cannot delete file '" +
f.getAbsolutePath() + "'", e);
- }
- }
-}
diff --git
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PredefinedLabelsResource.java
b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PredefinedLabelsResource.java
index af80312..da0befb 100644
---
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PredefinedLabelsResource.java
+++
b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PredefinedLabelsResource.java
@@ -14,8 +14,8 @@ package org.apache.juneau.examples.rest;
import static org.apache.juneau.http.HttpMethodName.*;
+import org.apache.juneau.dto.*;
import org.apache.juneau.examples.addressbook.*;
-import org.apache.juneau.html.annotation.*;
import org.apache.juneau.rest.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.helper.*;
@@ -68,19 +68,10 @@ public class PredefinedLabelsResource extends
BasicRestServlet {
}
@RestMethod(name=GET, path="/htmlLinks")
- public ALink[] htmlLinks() throws Exception {
- return new ALink[] {
- new ALink("apache", "http://apache.org"),
- new ALink("juneau", "http://juneau.apache.org")
+ public LinkString[] htmlLinks() throws Exception {
+ return new LinkString[] {
+ new LinkString("apache", "http://apache.org"),
+ new LinkString("juneau", "http://juneau.apache.org")
};
}
-
- @HtmlLink(nameProperty="n", hrefProperty="l")
- public static class ALink {
- public String n, l;
- public ALink(String n, String l) {
- this.n = n;
- this.l = l;
- }
- }
}
diff --git
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
index f381e63..591d042 100644
---
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
+++
b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
@@ -134,13 +134,13 @@ public class SystemPropertiesResource extends
BasicRestServlet {
description="Sets a new value for the specified system
property.",
guards=AdminGuard.class
)
- public RedirectServletRoot setSystemProperty(
+ public RedirectToServletRoot setSystemProperty(
@Path(description="The system property name") String
propertyName,
@Body(description="The new system property value")
String value
) throws UserNotAdminException, NotAcceptable,
UnsupportedMediaType {
System.setProperty(propertyName, value);
- return RedirectServletRoot.INSTANCE;
+ return RedirectToServletRoot.INSTANCE;
}
@RestMethod(
@@ -149,12 +149,12 @@ public class SystemPropertiesResource extends
BasicRestServlet {
description="Takes in a map of key/value pairs and creates a
set of new system properties.",
guards=AdminGuard.class
)
- public RedirectServletRoot setSystemProperties(
+ public RedirectToServletRoot setSystemProperties(
@Body(description="The new system property values",
example="{key1:'val1',key2:123}") java.util.Properties newProperties
) throws UserNotAdminException, NotAcceptable,
UnsupportedMediaType {
System.setProperties(newProperties);
- return RedirectServletRoot.INSTANCE;
+ return RedirectToServletRoot.INSTANCE;
}
@RestMethod(
@@ -163,12 +163,12 @@ public class SystemPropertiesResource extends
BasicRestServlet {
description="Deletes the specified system property.",
guards=AdminGuard.class
)
- public RedirectServletRoot deleteSystemProperty(
+ public RedirectToServletRoot deleteSystemProperty(
@Path(description="The system property name",
example="PATH") String propertyName
) throws UserNotAdminException, NotAcceptable {
System.clearProperty(propertyName);
- return RedirectServletRoot.INSTANCE;
+ return RedirectToServletRoot.INSTANCE;
}
@RestMethod(
@@ -207,13 +207,13 @@ public class SystemPropertiesResource extends
BasicRestServlet {
description="Accepts a simple form post of a system property
name/value pair.",
guards=AdminGuard.class
)
- public RedirectServletRoot formPagePost(
+ public RedirectToServletRoot formPagePost(
@FormData("name") String name,
@FormData("value") String value
) throws UserNotAdminException, NotAcceptable,
UnsupportedMediaType {
System.setProperty(name, value);
- return RedirectServletRoot.INSTANCE;
+ return RedirectToServletRoot.INSTANCE;
}
diff --git
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java
b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java
index a3a3bf7..79d3fb3 100644
---
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java
+++
b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/TempDirResource.java
@@ -22,6 +22,7 @@ import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.servlet.*;
import org.apache.commons.io.*;
import org.apache.juneau.dto.html5.*;
+import org.apache.juneau.microservice.resources.*;
import org.apache.juneau.rest.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.helper.*;
@@ -56,10 +57,10 @@ import org.apache.juneau.utils.*;
}
),
properties={
- @Property(name="rootDir",
value="$C{TempDirResource/dir,$S{java.io.tmpdir}}"),
- @Property(name="allowViews", value="true"),
- @Property(name="allowDeletes", value="true"),
- @Property(name="allowPuts", value="false")
+ @Property(name="DirectoryResource.rootDir",
value="$C{TempDirResource/dir,$S{java.io.tmpdir}}"),
+ @Property(name="DirectoryResource.allowViews", value="true"),
+ @Property(name="DirectoryResource.allowDeletes", value="true"),
+ @Property(name="DirectoryResource.allowPuts", value="false")
},
swagger={
"info: {",
@@ -115,7 +116,7 @@ public class TempDirResource extends DirectoryResource {
},
matchers=TempDirResource.MultipartFormDataMatcher.class
)
- public Redirect uploadFile(RestRequest req) throws Exception {
+ public RedirectToServletRoot uploadFile(RestRequest req) throws
Exception {
ServletFileUpload upload = new ServletFileUpload();
FileItemIterator iter = upload.getItemIterator(req);
while (iter.hasNext()) {
@@ -127,7 +128,7 @@ public class TempDirResource extends DirectoryResource {
}
}
}
- return new Redirect(); // Redirect to the servlet root.
+ return RedirectToServletRoot.INSTANCE;
}
/** Causes a 404 if POST isn't multipart/form-data */
diff --git
a/juneau-examples/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/TestMultiPartFormPostsTest.java
b/juneau-examples/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/TestMultiPartFormPostsTest.java
index 55dc99b..7f43edd 100644
---
a/juneau-examples/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/TestMultiPartFormPostsTest.java
+++
b/juneau-examples/juneau-examples-rest/src/test/java/org/apache/juneau/examples/rest/TestMultiPartFormPostsTest.java
@@ -41,7 +41,7 @@ public class TestMultiPartFormPostsTest extends RestTestcase {
HttpEntity entity =
MultipartEntityBuilder.create().addBinaryBody(f.getName(), f).build();
client.doPost(URL + "/upload", entity);
- String downloaded = client.doGet(URL + '/' + f.getName() +
"?method=VIEW").getResponseAsString();
+ String downloaded = client.doGet(URL + "/file/" + f.getName() +
"?method=VIEW").getResponseAsString();
assertEquals("test!", downloaded);
}
}
\ No newline at end of file
diff --git
a/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
b/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
index 679b50d..e5be768 100755
---
a/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
+++
b/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
@@ -15,15 +15,16 @@ package org.apache.juneau.microservice.resources;
import static java.util.logging.Level.*;
import static org.apache.juneau.html.HtmlDocSerializer.*;
import static org.apache.juneau.http.HttpMethodName.*;
+import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.rest.annotation.HookEvent.*;
import java.io.*;
-import java.net.*;
+import java.net.URI;
import java.util.*;
import java.util.logging.*;
-import javax.servlet.*;
-
import org.apache.juneau.annotation.*;
+import org.apache.juneau.dto.*;
import org.apache.juneau.rest.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.converters.*;
@@ -60,7 +61,6 @@ import org.apache.juneau.utils.*;
*/
@RestResource(
title="File System Explorer",
- description="Contents of $RA{path}",
messages="nls/DirectoryResource",
htmldoc=@HtmlDoc(
navlinks={
@@ -74,6 +74,7 @@ import org.apache.juneau.utils.*;
@Property(name="DirectoryResource.rootDir", value="")
}
)
+@SuppressWarnings("javadoc")
public class DirectoryResource extends BasicRestServlet {
private static final long serialVersionUID = 1L;
@@ -84,9 +85,9 @@ public class DirectoryResource extends BasicRestServlet {
private static Logger logger =
Logger.getLogger(DirectoryResource.class.getName());
- @Override /* Servlet */
- public void init() throws ServletException {
- RestContextProperties p = getProperties();
+ @RestHook(INIT)
+ public void init(RestContextBuilder b) throws Exception {
+ RestContextProperties p = b.getProperties();
rootDir = new File(p.getString("DirectoryResource.rootDir"));
allowViews = p.getBoolean("DirectoryResource.allowViews",
false);
allowDeletes = p.getBoolean("DirectoryResource.allowDeletes",
false);
@@ -111,257 +112,189 @@ public class DirectoryResource extends BasicRestServlet
{
return rootDir;
}
- /**
- * [GET /*] - On directories, returns a directory listing. On files,
returns information about the file.
- *
- * @param req The HTTP request.
- * @return Either a FileResource or list of FileResources depending on
whether it's a
- * file or directory.
- * @throws NotFound If file was not found.
- * @throws MalformedURLException
- */
- @RestMethod(name=GET, path="/*",
- description="On directories, returns a directory listing.\nOn
files, returns information about the file.",
+ @RestMethod(
+ name=GET,
+ path="/*",
+ summary="View files on directory",
+ description="Returns a listing of all files in the specified
directory.",
converters={Queryable.class}
)
- public Object doGet(RestRequest req) throws NotFound,
MalformedURLException {
- checkAccess(req);
-
- String pathInfo = req.getPathInfo();
- File f = pathInfo == null ? rootDir : new
File(rootDir.getAbsolutePath() + pathInfo);
-
- if (!f.exists())
- throw new NotFound("File not found");
-
- req.setAttribute("path", f.getAbsolutePath());
-
- if (f.isDirectory()) {
- List<FileResource> l = new LinkedList<>();
- File[] files = f.listFiles();
- if (files != null) {
- for (File fc : files) {
- URL fUrl = new
URL(req.getRequestURL().append("/").append(fc.getName()).toString());
- l.add(new FileResource(fc, fUrl));
- }
- }
- return l;
- }
-
- return new FileResource(f, new
URL(req.getRequestURL().toString()));
+ public FileListing listFiles(@PathRemainder String path) throws
NotFound, Exception {
+ FileListing l = new FileListing();
+ for (File fc : getDir(path).listFiles())
+ l.add(new FileResource(fc, (path != null ? (path + '/')
: "") + urlEncode(fc.getName())));
+ return l;
+ }
+
+ @RestMethod(
+ name=GET,
+ path="/file/*",
+ summary="View information about file",
+ description="Returns detailed information about the specified
file."
+ )
+ public FileResource getFileInfo(@PathRemainder String path) throws
NotFound, Exception {
+ return new FileResource(getFile(path), path);
}
- /**
- * [DELETE /*] - Delete a file on the file system.
- *
- * @param req The HTTP request.
- * @return The message <js>"File deleted"</js> if successful.
- * @throws Exception If file could not be read or access was not
granted.
- */
- @RestMethod(name=DELETE, path="/*",
+ @RestMethod(
+ name=DELETE,
+ path="/file/*",
+ summary="Delete file",
description="Delete a file on the file system."
)
- public Object doDelete(RestRequest req) throws Exception {
- checkAccess(req);
-
- File f = new File(rootDir.getAbsolutePath() +
req.getPathInfo());
- deleteFile(f);
-
- if (req.getHeader("Accept").contains("text/html"))
- return new Redirect();
- return "File deleted";
+ public RedirectToRoot deleteFile(@PathRemainder String path) throws
MethodNotAllowed {
+ if (! allowDeletes)
+ throw new MethodNotAllowed("DELETE not enabled");
+ deleteFile(getFile(path));
+ return new RedirectToRoot();
}
- /**
- * [PUT /*] - Add or overwrite a file on the file system.
- *
- * @param req The HTTP request.
- * @return The message <js>"File added"</js> if successful.
- * @throws InternalServerError If file could not be read or access was
not granted.
- */
- @RestMethod(name=PUT, path="/*",
+ @RestMethod(
+ name=PUT,
+ path="/file/*",
+ summary="Add or replace file",
description="Add or overwrite a file on the file system."
)
- public Object doPut(RestRequest req) throws InternalServerError {
- checkAccess(req);
+ public RedirectToRoot updateFile(
+ @Body(schema="{type:'string',format:'binary'}") InputStream is,
+ @PathRemainder String path
+ ) throws InternalServerError {
+
+ if (! allowPuts)
+ throw new MethodNotAllowed("PUT not enabled");
- File f = new File(rootDir.getAbsolutePath() +
req.getPathInfo());
- String parentSubPath =
f.getParentFile().getAbsolutePath().substring(rootDir.getAbsolutePath().length());
- try (InputStream is = req.getInputStream(); OutputStream os =
new BufferedOutputStream(new FileOutputStream(f))) {
+ File f = getFile(path);
+
+ try (OutputStream os = new BufferedOutputStream(new
FileOutputStream(f))) {
IOPipe.create(is, os).run();
} catch (IOException e) {
throw new InternalServerError(e);
}
- if (req.getContentType().contains("html"))
- return new Redirect(parentSubPath);
- return "File added";
+
+ return new RedirectToRoot();
}
- /**
- * [VIEW /*] - View the contents of a file.
- *
- * <p>
- * Applies to files only.
- *
- * @param req The HTTP request.
- * @param res The HTTP response.
- * @return A Reader containing the contents of the file.
- * @throws NotFound File not found.
- * @throws MethodNotAllowed Method not allowed on directories.
- */
- @RestMethod(name="VIEW", path="/*",
- description="View the contents of a file.\nApplies to files
only."
+ @RestMethod(
+ name="VIEW",
+ path="/file/*",
+ summary="View contents of file",
+ description="View the contents of a file."
)
- public Reader doView(RestRequest req, RestResponse res) throws
NotFound, MethodNotAllowed {
- checkAccess(req);
-
- File f = new File(rootDir.getAbsolutePath() +
req.getPathInfo());
-
- if (f.isDirectory())
- throw new MethodNotAllowed("VIEW not available on
directories");
+ public FileContents doView(RestResponse res, @PathRemainder String
path) throws NotFound, MethodNotAllowed {
+ if (! allowViews)
+ throw new MethodNotAllowed("VIEW not enabled");
res.setContentType("text/plain");
try {
- return new FileReader(f);
+ return new FileContents(getFile(path));
} catch (FileNotFoundException e) {
throw new NotFound("File not found");
}
}
-
- /**
- * [DOWNLOAD /*] - Download the contents of a file.
- *
- * <p>
- * Applies to files only.
- *
- * @param req The HTTP request.
- * @param res The HTTP response.
- * @return A Reader containing the contents of the file.
- * @throws NotFound Found could not be found.
- * @throws MethodNotAllowed Cannot call on a directory.
- */
- @RestMethod(name="DOWNLOAD", path="/*",
- description="Download the contents of a file.\nApplies to files
only."
+
+ @RestMethod(
+ name="DOWNLOAD",
+ path="/file/*",
+ summary="Download file",
+ description="Download the contents of a file"
)
- public Reader doDownload(RestRequest req, RestResponse res) throws
NotFound, MethodNotAllowed {
- checkAccess(req);
-
- File f = new File(rootDir.getAbsolutePath() +
req.getPathInfo());
-
- if (f.isDirectory())
- throw new MethodNotAllowed("DOWNLOAD not available on
directories");
+ public FileContents doDownload(RestResponse res, @PathRemainder String
path) throws NotFound, MethodNotAllowed {
+ if (! allowViews)
+ throw new MethodNotAllowed("DOWNLOAD not enabled");
- res.setContentType("application");
+ res.setContentType("application/octet-stream");
try {
- return new FileReader(f);
+ return new FileContents(getFile(path));
} catch (FileNotFoundException e) {
throw new NotFound("File not found");
}
}
- /**
- * Verify that the specified request is allowed.
- *
- * <p>
- * Subclasses can override this method to provide customized behavior.
- * Method should throw a {@link RestException} if the request should be
disallowed.
- *
- * @param req The HTTP request.
- * @throws MethodNotAllowed Thrown if specified method is not allowed.
- */
- protected void checkAccess(RestRequest req) throws MethodNotAllowed {
- String method = req.getMethod();
- if (method.equals("VIEW") && ! allowViews)
- throw new MethodNotAllowed("VIEW not enabled");
- if (method.equals("PUT") && ! allowPuts)
- throw new MethodNotAllowed("PUT not enabled");
- if (method.equals("DELETE") && ! allowDeletes)
- throw new MethodNotAllowed("DELETE not enabled");
- if (method.equals("DOWNLOAD") && ! allowViews)
- throw new MethodNotAllowed("DOWNLOAD not enabled");
+ private File getFile(String path) throws NotFound {
+ File f = new File(rootDir.getAbsolutePath() + '/' + path);
+ if (f.exists() && f.isFile())
+ return f;
+ throw new NotFound("File not found.");
+ }
+
+ private File getDir(String path) throws NotFound {
+ if (path == null)
+ return rootDir;
+ File f = new File(rootDir.getAbsolutePath() + '/' + path);
+ if (f.exists() && f.isDirectory())
+ return f;
+ throw new NotFound("Directory not found.");
+ }
+
+
//-----------------------------------------------------------------------------------------------------------------
+ // Helper beans
+
//-----------------------------------------------------------------------------------------------------------------
+
+ @SuppressWarnings("serial")
+ @ResponseInfo(description="Directory listing")
+ static class FileListing extends ArrayList<FileResource> {}
+
+ @ResponseInfo(schema="{schema:{type:'string',format:'binary'}}",
description="Contents of file")
+ static class FileContents extends FileReader {
+ public FileContents(File file) throws FileNotFoundException {
+ super(file);
+ }
+ }
+
+ @ResponseInfo(description="Redirect to root page on success")
+ static class RedirectToRoot extends RedirectToServletRoot {}
+
+ @ResponseInfo(description="File action")
+ public static class Action extends LinkString {
+ public Action(String name, String uri, Object...uriArgs) {
+ super(name, uri, uriArgs);
+ }
}
- /** File POJO */
+ @ResponseInfo(description="File or directory details")
public class FileResource {
private File f;
- private URL url;
+ private String path;
- /**
- * Constructor.
- *
- * @param f The file.
- * @param url The URL of the file resource.
- */
- public FileResource(File f, URL url) {
+ public FileResource(File f, String path) {
this.f = f;
- this.url = url;
+ this.path = path;
}
// Bean property getters
- /**
- * @return The URL of the file resource.
- */
- public URL getUrl() {
- return url;
+ public URI getUri() {
+ if (f.isDirectory())
+ return URI.create("servlet:/"+path);
+ return URI.create("servlet:/file/"+path);
}
- /**
- * @return The file type.
- */
public String getType() {
return (f.isDirectory() ? "dir" : "file");
}
- /**
- * @return The file name.
- */
public String getName() {
return f.getName();
}
- /**
- * @return The file size.
- */
public long getSize() {
- return f.length();
+ return f.isDirectory() ? f.listFiles().length :
f.length();
}
- /**
- * @return The file last modified timestamp.
- */
@Swap(DateSwap.ISO8601DTP.class)
public Date getLastModified() {
return new Date(f.lastModified());
}
- /**
- * @return A hyperlink to view the contents of the file.
- * @throws Exception If access is not allowed.
- */
- public URL getView() throws Exception {
- if (allowViews && f.canRead() && ! f.isDirectory())
- return new URL(url + "?method=VIEW");
- return null;
- }
-
- /**
- * @return A hyperlink to download the contents of the file.
- * @throws Exception If access is not allowed.
- */
- public URL getDownload() throws Exception {
- if (allowViews && f.canRead() && ! f.isDirectory())
- return new URL(url + "?method=DOWNLOAD");
- return null;
- }
-
- /**
- * @return A hyperlink to delete the file.
- * @throws Exception If access is not allowed.
- */
- public URL getDelete() throws Exception {
- if (allowDeletes && f.canWrite())
- return new URL(url + "?method=DELETE");
- return null;
+ public List<Action> getActions() throws Exception {
+ List<Action> l = new ArrayList<>();
+ if (allowViews && f.canRead() && ! f.isDirectory()) {
+ l.add(new Action("view", getUri().toString() +
"?method=VIEW"));
+ l.add(new Action("download",
getUri().toString() + "?method=DOWNLOAD"));
+ }
+ if (allowDeletes && f.canWrite() && ! f.isDirectory())
+ l.add(new Action("delete", getUri().toString()
+ "?method=DELETE"));
+ return l;
}
}
diff --git
a/juneau-microservice/juneau-microservice-template/my-microservice.cfg
b/juneau-microservice/juneau-microservice-template/my-microservice.cfg
index 3c8aea5..10c9306 100755
--- a/juneau-microservice/juneau-microservice-template/my-microservice.cfg
+++ b/juneau-microservice/juneau-microservice-template/my-microservice.cfg
@@ -55,7 +55,7 @@ headerLink = http://juneau.apache.org
footerIcon = servlet:/htdocs/images/asf.png
footerLink = http://www.apache.org
-icon = $C{REST/headerIcon}
+favicon = $C{REST/headerIcon}
header = <a href='$U{$C{REST/headerLink}}'><img src='$U{$C{REST/headerIcon}}'
style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/></a>
footer = <a href='$U{$C{REST/footerLink}}'><img
style='float:right;padding-right:20px;height:32px'
src='$U{$C{REST/footerIcon}}'>
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestConfig.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestConfig.java
index fdfce10..0828de5 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestConfig.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestConfig.java
@@ -75,7 +75,7 @@ import org.apache.juneau.xmlschema.*;
},
stylesheet="$C{REST/theme,servlet:/htdocs/themes/devops.css}",
head={
- "<link rel='icon' href='$U{$C{REST/icon}}'/>"
+ "<link rel='icon' href='$U{$C{REST/favicon}}'/>"
},
footer="$C{REST/footer}"
),
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
index f992917..ca8e06b 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
@@ -650,6 +650,15 @@ public final class RestRequest extends
HttpServletRequestWrapper {
return getPathMatch().get(name);
}
+ /**
+ * Shortcut for calling <code>getPathMatch().getRemainder()</code>.
+ *
+ * @return The path remainder value, or <jk>null</jk> if not found.
+ */
+ public String getPathRemainder() {
+ return getPathMatch().getRemainder();
+ }
+
//--------------------------------------------------------------------------------
// Body methods
//--------------------------------------------------------------------------------
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/RedirectServletRoot.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/RedirectToServletRoot.java
similarity index 91%
rename from
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/RedirectServletRoot.java
rename to
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/RedirectToServletRoot.java
index 71f6f2a..b1acdeb 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/RedirectServletRoot.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/helper/RedirectToServletRoot.java
@@ -18,17 +18,17 @@ import org.apache.juneau.rest.annotation.*;
* Convenience subclass of {@link Redirect} for redirecting a response to the
servlet root.
*/
@ResponseInfo(description="Redirect to servlet root")
-public class RedirectServletRoot extends Redirect {
+public class RedirectToServletRoot extends Redirect {
/**
* Reusable instance.
*/
- public static final RedirectServletRoot INSTANCE = new
RedirectServletRoot();
+ public static final RedirectToServletRoot INSTANCE = new
RedirectToServletRoot();
/**
* Constructor.
*/
- public RedirectServletRoot() {
+ public RedirectToServletRoot() {
super("servlet:/");
}
}
\ No newline at end of file
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/RequestPathVar.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/RequestPathVar.java
index 508ef22..7c6cb4b 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/RequestPathVar.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/vars/RequestPathVar.java
@@ -77,6 +77,8 @@ public class RequestPathVar extends MultipartResolvingVar {
@Override /* Parameter */
public String resolve(VarResolverSession session, String key) {
RestRequest req = session.getSessionObject(RestRequest.class,
SESSION_req);
+ if ("REMAINDER".equals(key))
+ return req.getPathRemainder();
return req.getPath(key);
}
}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
[email protected].