Repository: incubator-juneau Updated Branches: refs/heads/master b95ee52b4 -> 21a80b823
Add @HtmlDoc(head) annotation. Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/21a80b82 Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/21a80b82 Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/21a80b82 Branch: refs/heads/master Commit: 21a80b8232fd03084c629a71e6b682f77e14902d Parents: b95ee52 Author: JamesBognar <[email protected]> Authored: Sat Oct 7 17:37:18 2017 -0400 Committer: JamesBognar <[email protected]> Committed: Sat Oct 7 17:37:18 2017 -0400 ---------------------------------------------------------------------- eclipse-preferences/user-dictionary.txt | 2 + .../apache/juneau/ini/ConfigFileWrapped.java | 5 +- .../juneau/utils/StringVarResolverTest.java | 2 +- .../juneau/html/HtmlDocSerializerContext.java | 46 +++++++++++++- .../juneau/html/HtmlDocSerializerSession.java | 16 ++++- .../juneau/html/HtmlDocTemplateBasic.java | 4 ++ .../apache/juneau/svl/VarResolverSession.java | 10 +-- juneau-doc/src/main/javadoc/overview.html | 12 ++++ .../juneau/examples/rest/PetStoreResource.java | 3 + .../java/org/apache/juneau/rest/CallMethod.java | 6 +- .../org/apache/juneau/rest/RestCallHandler.java | 6 +- .../java/org/apache/juneau/rest/RestConfig.java | 64 +++++--------------- .../org/apache/juneau/rest/RestContext.java | 54 ++++++----------- .../org/apache/juneau/rest/RestRequest.java | 18 ++++++ .../org/apache/juneau/rest/RestResponse.java | 31 ++++++++++ .../apache/juneau/rest/RestServletDefault.java | 11 ++-- .../java/org/apache/juneau/rest/RestUtils.java | 17 ++++++ .../apache/juneau/rest/annotation/HtmlDoc.java | 42 +++++++++++++ .../juneau/rest/annotation/RestResource.java | 38 ------------ 19 files changed, 241 insertions(+), 146 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/eclipse-preferences/user-dictionary.txt ---------------------------------------------------------------------- diff --git a/eclipse-preferences/user-dictionary.txt b/eclipse-preferences/user-dictionary.txt index 12425c8..0c387d7 100644 --- a/eclipse-preferences/user-dictionary.txt +++ b/eclipse-preferences/user-dictionary.txt @@ -492,3 +492,5 @@ strived protobuf maven configurability +navlinks +fav http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigFileWrapped.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigFileWrapped.java b/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigFileWrapped.java index da8e83b..1454a18 100644 --- a/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigFileWrapped.java +++ b/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigFileWrapped.java @@ -241,10 +241,7 @@ public final class ConfigFileWrapped extends ConfigFile { @Override /* ConfigFile */ public String get(String sectionName, String sectionKey) { - String s = cf.get(sectionName, sectionKey); - if (s == null) - return null; - return vs.resolve(s); + return vs.resolve(cf.get(sectionName, sectionKey)); } @Override /* ConfigFile */ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringVarResolverTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringVarResolverTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringVarResolverTest.java index 364e233..baef26b 100755 --- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringVarResolverTest.java +++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringVarResolverTest.java @@ -30,7 +30,7 @@ public class StringVarResolverTest { String t; t = null; - assertEquals("", vr.resolve(t)); + assertEquals(null, vr.resolve(t)); t = ""; assertEquals("", vr.resolve(t)); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java index 55f2274..f017253 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java @@ -434,6 +434,48 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext { public static final String HTMLDOC_script_add = "HtmlDocSerializer.script.list.add"; /** + * <b>Configuration property:</b> Additional head section content. + * + * <ul> + * <li><b>Name:</b> <js>"HtmlDocSerializer.head.list"</js> + * <li><b>Data type:</b> <code>List<String></code> + * <li><b>Default:</b> empty list + * <li><b>Session-overridable:</b> <jk>true</jk> + * </ul> + * + * <p> + * Adds the specified HTML content to the head section of the page. + * + * <h5 class='section'>Example:</h5> + * <p class='bcode'> + * <ja>@RestResource</ja>( + * properties={ + * <ja>@Property</ja>(name=HtmlDocSerializerContext.<jsf>HTMLDOC_links</jsf>, + * value=<js>"['<link rel=\"icon\" href=\"htdocs/mypageicon.ico\">']"</js>) + * } + * ) + * </p> + * + * <p> + * A shortcut on <ja>@RestResource</ja> is also provided for this setting: + * <p class='bcode'> + * <ja>@RestResource</ja>( + * htmldoc=@HtmlDoc( + * head={ + * <js>"<link rel='icon' href='$U{servlet:/htdocs/mypageicon.ico}'>"</js> + * } + * ) + * ) + * </p> + */ + public static final String HTMLDOC_head = "HtmlDocSerializer.head.list"; + + /** + * <b>Configuration property:</b> Add to the {@link #HTMLDOC_head} property. + */ + public static final String HTMLDOC_links_add = "HtmlDocSerializer.head.list.add"; + + /** * <b>Configuration property:</b> HTML document template. * * <ul> @@ -462,7 +504,7 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext { public static final String HTMLDOC_template = "HtmlDocSerializer.template"; - final String[] style, stylesheet, script, navlinks; + final String[] style, stylesheet, script, navlinks, head; final String header, nav, aside, footer, noResultsMessage; final boolean nowrap; final HtmlDocTemplate template; @@ -480,6 +522,7 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext { style = ps.getProperty(HTMLDOC_style, String[].class, new String[0]); stylesheet = ps.getProperty(HTMLDOC_stylesheet, String[].class, new String[0]); script = ps.getProperty(HTMLDOC_script, String[].class, new String[0]); + head = ps.getProperty(HTMLDOC_head, String[].class, new String[0]); header = ps.getProperty(HTMLDOC_header, String.class, null); nav = ps.getProperty(HTMLDOC_nav, String.class, null); aside = ps.getProperty(HTMLDOC_aside, String.class, null); @@ -500,6 +543,7 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext { .append("aside", aside) .append("footer", footer) .append("style", style) + .append("head", head) .append("stylesheet", stylesheet) .append("nowrap", nowrap) .append("template", template) http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java index d56040d..43a2d69 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java @@ -30,7 +30,7 @@ import org.apache.juneau.serializer.*; public class HtmlDocSerializerSession extends HtmlStrippedDocSerializerSession { private final String header, nav, aside, footer, noResultsMessage; - private final String[] style, stylesheet, script, navlinks; + private final String[] style, stylesheet, script, navlinks, head; private final boolean nowrap; private final HtmlDocTemplate template; @@ -55,6 +55,7 @@ public class HtmlDocSerializerSession extends HtmlStrippedDocSerializerSession { style = ctx.style; stylesheet = ctx.stylesheet; script = ctx.script; + head = ctx.head; nowrap = ctx.nowrap; noResultsMessage = ctx.noResultsMessage; template = ClassUtils.newInstance(HtmlDocTemplate.class, ctx.template); @@ -67,6 +68,7 @@ public class HtmlDocSerializerSession extends HtmlStrippedDocSerializerSession { style = p.getStringArray(HTMLDOC_style, ctx.style); stylesheet = p.getStringArray(HTMLDOC_stylesheet, ctx.stylesheet); script = p.getStringArray(HTMLDOC_script, ctx.script); + head = p.getStringArray(HTMLDOC_head, ctx.head); nowrap = p.getBoolean(HTMLDOC_nowrap, ctx.nowrap); noResultsMessage = p.getString(HTMLDOC_noResultsMessage, ctx.noResultsMessage); template = ClassUtils.newInstance(HtmlDocTemplate.class, p.getWithDefault(HTMLDOC_template, ctx.template)); @@ -110,6 +112,18 @@ public class HtmlDocSerializerSession extends HtmlStrippedDocSerializerSession { } /** + * Returns the {@link HtmlDocSerializerContext#HTMLDOC_head} setting value in this context. + * + * @return + * The {@link HtmlDocSerializerContext#HTMLDOC_head} setting value in this context. + * An empty array if not specified. + * Never <jk>null</jk>. + */ + public final String[] getHead() { + return head; + } + + /** * Returns the {@link HtmlDocSerializerContext#HTMLDOC_nowrap} setting value in this context. * * @return The {@link HtmlDocSerializerContext#HTMLDOC_nowrap} setting value in this context. http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java index be06ac1..ffaabb5 100644 --- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java +++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java @@ -24,6 +24,10 @@ public class HtmlDocTemplateBasic implements HtmlDocTemplate { @Override /* HtmlDocTemplate */ public void head(HtmlDocSerializerSession session, HtmlWriter w, Object o) throws Exception { + + for (String h : session.getHead()) + w.appendln(2, h); + if (hasStyle(session)) { w.sTag(2, "style").nl(2); style(session, w, o); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolverSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolverSession.java b/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolverSession.java index 2e24226..f9da289 100644 --- a/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolverSession.java +++ b/juneau-core/juneau-svl/src/main/java/org/apache/juneau/svl/VarResolverSession.java @@ -71,15 +71,17 @@ public class VarResolverSession { /** * Resolve all variables in the specified string. * - * @param s The string to resolve variables in. + * @param s + * The string to resolve variables in. * @return * The new string with all variables resolved, or the same string if no variables were found. - * Null input results in a blank string. + * <br>Returns <jk>null</jk> if the input was <jk>null</jk>. */ public String resolve(String s) { - if (s == null) - return ""; + if (s == null || s.isEmpty()) + return s; + if (s.indexOf('$') == -1 && s.indexOf('\\') == -1) return s; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-doc/src/main/javadoc/overview.html ---------------------------------------------------------------------- diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html index 582a15a..351e1af 100644 --- a/juneau-doc/src/main/javadoc/overview.html +++ b/juneau-doc/src/main/javadoc/overview.html @@ -7469,6 +7469,18 @@ <ul class='spaced-list'> <li> Annotation <code><ja>@HtmlDoc</ja>(links)</code> renamed to {@link org.apache.juneau.rest.annotation.HtmlDoc#navlinks() navlinks}. + <li> + New annotation {@link org.apache.juneau.rest.annotation.HtmlDoc#head()}. + <br>Allows you to specify arbitrary HTML content in the <xt><head></xt> section of the page. + <li> + Removed annotation <code><ja>@HtmlDoc</ja>(favIcon)</code>. + <br>This was a discouraged way of defining fav-icons anyway, and with the addition of + <code><ja>@HtmlDoc</ja>(head)</code>, you can define them using: + <p class='bcode'> + head={ + <js>"<link rel='icon' href='$U{servlet:/htdocs/juneau.png}'/>"</js> + } + </p> </ul> </div> http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java ---------------------------------------------------------------------- diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java index c351b52..8f0ea69 100644 --- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java +++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java @@ -61,6 +61,9 @@ import org.apache.juneau.transforms.*; " <p>It also shows examples of HtmlRender classes and @BeanProperty(format) annotations.</p>", " <p>It also shows how the Queryable converter and query widget can be used to create searchable interfaces.</p>", "</div>" + }, + head={ + "<link rel='icon' href='$U{servlet:/htdocs/cat.png}'/>" } ) ) http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java index 192af23..7f31520 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java @@ -68,7 +68,7 @@ class CallMethod implements Comparable<CallMethod> { private final RestContext context; private final BeanContext beanContext; final String htmlHeader, htmlNav, htmlAside, htmlFooter, htmlStyle, htmlStylesheet, htmlScript, htmlNoResultsMessage; - final String[] htmlNavLinks; + final String[] htmlNavLinks, htmlHead; final boolean htmlNoWrap; final HtmlDocTemplate htmlTemplate; private final Map<String,Widget> widgets; @@ -111,6 +111,7 @@ class CallMethod implements Comparable<CallMethod> { this.htmlStyle = b.htmlStyle; this.htmlStylesheet = b.htmlStylesheet; this.htmlScript = b.htmlScript; + this.htmlHead = b.htmlHead; this.htmlNoWrap = b.htmlNoWrap; this.htmlTemplate = b.htmlTemplate; this.htmlNoResultsMessage = b.htmlNoResultsMessage; @@ -120,7 +121,7 @@ class CallMethod implements Comparable<CallMethod> { private static class Builder { private String httpMethod, defaultCharset, description, tags, summary, externalDocs, htmlNav, htmlAside, htmlFooter, htmlStyle, htmlStylesheet, htmlScript, htmlHeader, htmlNoResultsMessage; - private String[] htmlNavLinks; + private String[] htmlNavLinks, htmlHead; private boolean htmlNoWrap; private HtmlDocTemplate htmlTemplate; private UrlPathPattern pathPattern; @@ -191,6 +192,7 @@ class CallMethod implements Comparable<CallMethod> { htmlFooter = resolveNewlineSeparatedAnnotation(hd.footer(), context.getHtmlFooter()); htmlStyle = resolveNewlineSeparatedAnnotation(hd.style(), context.getHtmlStyle()); htmlScript = resolveNewlineSeparatedAnnotation(hd.script(), context.getHtmlScript()); + htmlHead = resolveContent(hd.head(), context.getHtmlHead()); htmlNavLinks = resolveLinks(hd.navlinks(), context.getHtmlNavLinks()); htmlStylesheet = hd.stylesheet().isEmpty() ? context.getHtmlStylesheet() : hd.stylesheet(); htmlNoWrap = hd.nowrap() ? hd.nowrap() : context.getHtmlNoWrap(); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallHandler.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallHandler.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallHandler.java index 4903229..5fdb378 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallHandler.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestCallHandler.java @@ -141,10 +141,10 @@ public class RestCallHandler { StreamResource r = null; if (pathInfo != null) { String p = pathInfo.substring(1); - if (p.equals("favicon.ico")) - r = context.getFavIcon(); - else if (context.isStaticFile(p)) + if (context.isStaticFile(p)) r = context.resolveStaticFile(p); + else if (p.equals("favicon.ico")) + res.setOutput(null); } if (r != null) { http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestConfig.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestConfig.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestConfig.java index ba3fff9..d08bf42 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestConfig.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestConfig.java @@ -17,7 +17,6 @@ import static org.apache.juneau.internal.ReflectionUtils.*; import static org.apache.juneau.internal.StringUtils.*; import static org.apache.juneau.rest.RestUtils.*; -import java.io.*; import java.lang.reflect.Method; import java.util.*; @@ -112,11 +111,10 @@ public class RestConfig implements ServletConfig { List<Object> responseHandlers = new ArrayList<Object>(); List<Object> childResources = new ArrayList<Object>(); List<MediaType> supportedContentTypes, supportedAcceptTypes; - Object favIcon; List<Object> staticFiles; RestContext parentContext; String path, htmlHeader, htmlNav, htmlAside, htmlFooter, htmlStyle, htmlStylesheet, htmlScript, htmlNoResultsMessage; - String[] htmlNavLinks; + String[] htmlNavLinks, htmlHead; String clientVersionHeader = "X-Client-Version"; String contextPath; @@ -224,8 +222,6 @@ public class RestConfig implements ServletConfig { serializerListener(r.serializerListener()); parserListener(r.parserListener()); contextPath(r.contextPath()); - if (! r.favicon().isEmpty()) - setFavIcon(c, r.favicon()); if (! r.staticFiles().isEmpty()) addStaticFiles(c, r.staticFiles()); if (! r.path().isEmpty()) @@ -266,6 +262,7 @@ public class RestConfig implements ServletConfig { setHtmlStyle(resolveNewlineSeparatedAnnotation(hd.style(), htmlStyle)); setHtmlScript(resolveNewlineSeparatedAnnotation(hd.script(), htmlScript)); setHtmlNavLinks(resolveLinks(hd.navlinks(), htmlNavLinks)); + setHtmlHead(resolveContent(hd.head(), htmlHead)); if (! hd.stylesheet().isEmpty()) setHtmlStylesheet(hd.stylesheet()); @@ -1017,49 +1014,6 @@ public class RestConfig implements ServletConfig { } /** - * Specifies the icon contents that make up the contents of the page <js>"/resource-path/favicon.ico"</js>. - * - * <p> - * This is the programmatic equivalent to the {@link RestResource#favicon() @RestResource.favicon()} annotation. - * - * <p> - * The object type can be any of the following: - * <ul> - * <li>{@link InputStream} - * <li>{@link File} - * <li><code><jk>byte</jk>[]</code> - * </ul> - * - * @param favIcon The contents that make up the <code>favicon.ico</code> page. - * @return This object (for method chaining). - */ - public RestConfig setFavIcon(Object favIcon) { - this.favIcon = favIcon; - return this; - } - - /** - * Specifies the icon contents that make up the contents of the page <js>"/resource-path/favicon.ico"</js>. - * - * <p> - * This is the programmatic equivalent to the {@link RestResource#favicon() @RestResource.favicon()} annotation. - * - * <p> - * Use this method to specify a resource located in the classpath. - * This call uses the {@link Class#getResourceAsStream(String)} method to retrieve the stylesheet contents. - * - * @param resourceClass The resource class used to resolve the resource stream. - * @param resourcePath - * The path passed to the {@link Class#getResourceAsStream(String)} method. - * Can also be a path starting with <js>"file://"</js> denoting a location to pull from the file system. - * @return This object (for method chaining). - */ - public RestConfig setFavIcon(Class<?> resourceClass, String resourcePath) { - this.favIcon = new Pair<Class<?>,String>(resourceClass, resourcePath); - return this; - } - - /** * Appends to the static files resource map. * * <p> @@ -1470,6 +1424,20 @@ public class RestConfig implements ServletConfig { } /** + * Adds to the HTML head section contents. + * + * <p> + * This is the programmatic equivalent to the {@link HtmlDoc#head() @HtmlDoc.head()} annotation. + * + * @param value The HTML head section content. + * @return This object (for method chaining). + */ + public RestConfig setHtmlHead(String...value) { + this.htmlHead = value; + return this; + } + + /** * Shorthand method for forcing the rendered HTML content to be no-wrap. * * <p> http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java index bd23730..d113059 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java @@ -79,7 +79,8 @@ public final class RestContext extends Context { htmlFooter, htmlNoResultsMessage; private final String[] - htmlNavLinks; + htmlNavLinks, + htmlHead; private final boolean htmlNoWrap; private final HtmlDocTemplate htmlTemplate; private final Map<String,Widget> htmlWidgets; @@ -106,7 +107,6 @@ public final class RestContext extends Context { private final RestGuard[] guards; private final ResponseHandler[] responseHandlers; private final MimetypesFileTypeMap mimetypesFileTypeMap; - private final StreamResource favIcon; private final Map<String,String> staticFilesMap; private final String[] staticFilesPrefixes; private final MessageBundle msgs; @@ -197,7 +197,6 @@ public final class RestContext extends Context { this.guards = b.guards.toArray(new RestGuard[b.guards.size()]); this.responseHandlers = toObjectArray(b.responseHandlers, ResponseHandler.class); this.mimetypesFileTypeMap = b.mimetypesFileTypeMap; - this.favIcon = b.favIcon; this.staticFilesMap = Collections.unmodifiableMap(b.staticFilesMap); this.staticFilesPrefixes = b.staticFilesPrefixes; this.msgs = b.messageBundle; @@ -214,6 +213,7 @@ public final class RestContext extends Context { this.htmlStyle = b.htmlStyle; this.htmlStylesheet = b.htmlStylesheet; this.htmlScript = b.htmlScript; + this.htmlHead = b.htmlHead; this.htmlFooter = b.htmlFooter; this.htmlNoWrap = b.htmlNoWrap; this.htmlNoResultsMessage = b.htmlNoResultsMessage; @@ -484,7 +484,7 @@ public final class RestContext extends Context { EncoderGroup encoders; String clientVersionHeader = "", defaultCharset, paramFormat, htmlHeader, htmlNav, htmlAside, htmlStyle, htmlStylesheet, htmlScript, htmlFooter, htmlNoResultsMessage; - String[] htmlNavLinks; + String[] htmlNavLinks, htmlHead; boolean htmlNoWrap; HtmlDocTemplate htmlTemplate; @@ -496,7 +496,6 @@ public final class RestContext extends Context { List<RestGuard> guards = new ArrayList<RestGuard>(); List<ResponseHandler> responseHandlers = new ArrayList<ResponseHandler>(); MimetypesFileTypeMap mimetypesFileTypeMap; - StreamResource favIcon; Map<String,String> staticFilesMap; String[] staticFilesPrefixes; MessageBundle messageBundle; @@ -589,19 +588,6 @@ public final class RestContext extends Context { VarResolver vr = sc.getVarResolverBuilder().build(); - if (sc.favIcon != null) { - Object o = sc.favIcon; - InputStream is = null; - if (o instanceof Pair) { - Pair<Class<?>,String> p = (Pair<Class<?>,String>)o; - is = ReflectionUtils.getResource(p.first(), vr.resolve(p.second())); - } else { - is = toInputStream(o); - } - if (is != null) - favIcon = new StreamResource(MediaType.forString("image/x-icon"), is); - } - staticFilesMap = new LinkedHashMap<String,String>(); if (sc.staticFiles != null) { for (Object o : sc.staticFiles) { @@ -633,6 +619,7 @@ public final class RestContext extends Context { htmlStyle = sc.htmlStyle; htmlStylesheet = sc.htmlStylesheet; htmlScript = sc.htmlScript; + htmlHead = sc.htmlHead; htmlFooter = sc.htmlFooter; htmlNoWrap = sc.htmlNoWrap; htmlNoResultsMessage = sc.htmlNoResultsMessage; @@ -998,6 +985,18 @@ public final class RestContext extends Context { } /** + * The HTML page head content. + * + * <p> + * Defined by the {@link HtmlDoc#head()} annotation or {@link RestConfig#setHtmlHead(String[])} method. + * + * @return The HTML page head content. + */ + public String[] getHtmlHead() { + return htmlHead; + } + + /** * The HTML page nowrap setting. * * <p> @@ -1753,25 +1752,6 @@ public final class RestContext extends Context { } /** - * Returns the favicon of the resource. - * - * <p> - * This is the icon served up under <js>"/favicon.ico"</jk> recognized by browsers. - * - * <p> - * The favicon is defined via one of the following: - * <ul> - * <li>{@link RestResource#favicon() @RestResource.favicon()} annotation. - * <li>{@link RestConfig#setFavIcon(Object)}/{@link RestConfig#setFavIcon(Class, String)} methods. - * </ul> - * - * @return The favicon of this resource. Can be <jk>null</jk>. - */ - protected StreamResource getFavIcon() { - return favIcon; - } - - /** * Returns <jk>true</jk> if the specified path refers to a static file. * * <p> http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java ---------------------------------------------------------------------- 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 bdb0e4a..861009f 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 @@ -325,6 +325,8 @@ public final class RestRequest extends HttpServletRequestWrapper { } else if (c2 == 'h') { if ("header".equals(name)) return cm.htmlHeader == null ? null : resolveVars(cm.htmlHeader); + if ("head.list".equals(name)) + return resolveVars(cm.htmlHead); } else if (c2 == 'n') { if ("nav".equals(name)) return cm.htmlNav == null ? null : resolveVars(cm.htmlNav); @@ -1057,6 +1059,22 @@ public final class RestRequest extends HttpServletRequestWrapper { } /** + * Shortcut for calling {@link #resolveVars(String[])} on all elements in the array. + * + * @param input The input strings to resolve variables in. + * @return A copy of the array with variables resolved. + */ + public String[] resolveVars(String[] input) { + VarResolverSession vs = getVarResolverSession(); + if (input == null || input.length == 0) + return input; + input = Arrays.copyOf(input, input.length); + for (int i = 0; i < input.length; i++) + input[i] = vs.resolve(input[i]); + return input; + } + + /** * Returns an instance of a {@link ReaderResource} that represents the contents of a resource text file from the * classpath. * http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java index 0da444f..fffd0c1 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestResponse.java @@ -728,6 +728,37 @@ public final class RestResponse extends HttpServletResponseWrapper { } /** + * Sets the HTML head section contents. + * + * <p> + * The format of this value is HTML. + * + * <p> + * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>). + * <br>See {@link RestContext#getVarResolver()} for the list of supported variables. + * + * <p> + * A value of <js>"NONE"</js> can be used to force no value. + * + * <p> + * This is the programmatic equivalent to the {@link HtmlDoc#head() @HtmlDoc.head()} annotation. + * + * @param value + * The HTML head section contents. + * <p> + * <ul class='doctree'> + * <li class='info'> + * <b>Tip:</b> Use {@link StringMessage} to generate value with delayed serialization so as not to + * waste string concatenation cycles on non-HTML views. + * </ul> + * @return This object (for method chaining). + */ + public RestResponse setHtmlHead(Object...value) { + properties.put(HtmlDocSerializerContext.HTMLDOC_head, value); + return this; + } + + /** * Shorthand method for forcing the rendered HTML content to be no-wrap. * * <p> http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServletDefault.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServletDefault.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServletDefault.java index 5751caa..1733d51 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServletDefault.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestServletDefault.java @@ -151,9 +151,6 @@ import org.apache.juneau.xml.*; * Provides a default HTML stylesheet by setting {@link HtmlDoc#stylesheet() @HtmlDoc.stylesheet()} * to <js>"styles/juneau.css"</js>. * <li> - * Provides a default favicon by setting {@link RestResource#favicon() @RestResource.favicon()} to - * <js>"juneau.ico"</js>. - * <li> * Provides a default classpath entry "htdocs" by setting * {@link RestResource#staticFiles() @RestResource.staticFiles()} to <js>"{htdocs:'htdocs'}"</js>. * This allows files inside the <code>[servletPackage].htdocs</code> package to be served up under the URL @@ -192,12 +189,12 @@ import org.apache.juneau.xml.*; "<h2>$R{methodSummary,$R{servletDescription}}</h2>", "<a href='http://juneau.apache.org'><img src='$U{servlet:/htdocs/juneau.png}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/></a>" }, - stylesheet="servlet:/styles/light.css" + stylesheet="servlet:/styles/light.css", + head={ + "<link rel='icon' href='$U{servlet:/htdocs/juneau.png}'/>" + } ), - // The location on the classpath or file system of the fav-icon. - favicon="htdocs/juneau.png", - // These are static files that are served up by the servlet under the specified sub-paths. staticFiles="{htdocs:'htdocs',styles:'styles'}" ) http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestUtils.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestUtils.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestUtils.java index 03ccbc2..aa90a63 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestUtils.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestUtils.java @@ -223,4 +223,21 @@ public final class RestUtils { } return list.toArray(new String[list.size()]); } + + static String[] resolveContent(String[] content, String[] parentContent) { + if (content.length == 0) + return parentContent; + + List<String> list = new ArrayList<String>(); + for (String l : content) { + if ("INHERIT".equals(l)) { + list.addAll(Arrays.asList(parentContent)); + } else if ("NONE".equals(l)) { + return new String[0]; + } else { + list.add(l); + } + } + return list.toArray(new String[list.size()]); + } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java index 61ab2f6..ef6d275 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java @@ -426,6 +426,48 @@ public @interface HtmlDoc { String[] script() default {}; /** + * Adds arbitrary content to the HTML <xt><head></xt> element on the page. + * + * <p> + * The format of this value is HTML. + * + * <h5 class='section'>Example:</h5> + * <p class='bcode'> + * <ja>@RestResource</ja>( + * htmldoc=<ja>@HtmlDoc</ja>( + * head={ + * <jc>// Add a shortcut link in the browser tab</jc> + * <js>"<link rel='icon' href='$U{servlet:/htdocs/mypageicon.ico}'>"</js>, + * + * <jc>// Reload the page every 5 seconds </jc> + * <js>"<meta http-equiv='refresh' content='5'>"</js> + * } + * ) + * ) + * </p> + * + * <h6 class='topic'>Other Notes</h6> + * <ul class='spaced-list'> + * <li> + * This field can contain variables (e.g. <js>"$L{my.localized.variable}"</js>). + * <br>See {@link RestContext#getVarResolver()} for the list of supported variables. + * <li> + * A value of <js>"NONE"</js> can be used to force no value. + * <li> + * The head content from the parent can be included by adding the literal <js>"INHERIT"</js> as a value. + * <li> + * The programmatic equivalent to this annotation are the + * {@link RestConfig#setHtmlHead(String[])} and {@link RestResponse#setHtmlHead(String[])} methods. + * <li> + * On methods, this value is inherited from the <ja>@HtmlDoc</ja> annotation on the servlet/resource class. + * <li> + * On servlet/resource classes, this value is inherited from the <ja>@HtmlDoc</ja> annotation on the + * parent class. + * </ul> + */ + String[] head() default {}; + + /** * Shorthand method for forcing the rendered HTML content to be no-wrap. * * <p> http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/21a80b82/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java ---------------------------------------------------------------------- diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java index 76e6123..66e9561 100644 --- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java +++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java @@ -506,44 +506,6 @@ public @interface RestResource { String config() default ""; /** - * The favicon to use for HTML views. - * - * <p> - * The name is a path to an icon file located in either the classpath or working directory. - * The resulting favicon becomes available in the servlet via the URL <js>"[servlet-path]/favicon.ico"</js>. - * - * <p> - * If the file cannot be located, the request to <js>"[servlet-path]/favicon.ico"</js> will return - * {@link HttpServletResponse#SC_NOT_FOUND}. - * - * <h5 class='section'>Example:</h5> - * <p class='bcode'> - * <jk>package</jk> com.foo.mypackage; - * - * <ja>@RestResource</ja>( - * favicon=<js>"mydocs/myicon.ico"</js> - * ) - * <jk>public class</jk> MyResource <jk>extends</jk> RestServletDefault { - * } - * </p> - * - * <p> - * In this example, the servlet will attempt to find the <code>myicon.ico</code> file in the following ordered - * locations: - * <ol> - * <li><code>com.foo.mypackage.mydocs</code> package. - * <li><code>org.apache.juneau.rest.mydocs</code> package (since <code>RestServletDefault</code> is in - * <code>org.apache.juneau.rest</code>). - * <li><code>[working-dir]/mydocs</code> directory. - * </ol> - * - * <p> - * The programmatic equivalent to this annotation are the {@link RestConfig#setFavIcon(Object)}/ - * {@link RestConfig#setFavIcon(Class, String)} methods. - */ - String favicon() default ""; - - /** * Defines paths and locations of statically served files. * * <p>
