Improved Widget API. Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/ada4053b Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/ada4053b Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/ada4053b
Branch: refs/heads/master Commit: ada4053bb8413789f8eb4ea34a939c799940b2fe Parents: f400b0c Author: JamesBognar <[email protected]> Authored: Sun Jul 2 21:17:08 2017 -0400 Committer: JamesBognar <[email protected]> Committed: Sun Jul 2 21:17:08 2017 -0400 ---------------------------------------------------------------------- .../main/java/org/apache/juneau/ObjectMap.java | 20 +- .../apache/juneau/dto/html5/HtmlElement.java | 1 - .../juneau/dto/html5/HtmlElementContainer.java | 2 +- .../juneau/dto/html5/HtmlElementMixed.java | 2 +- .../juneau/html/HtmlDocSerializerContext.java | 85 ++++-- .../juneau/html/HtmlDocSerializerSession.java | 50 +-- .../org/apache/juneau/html/HtmlDocTemplate.java | 34 ++- .../juneau/html/HtmlDocTemplateBasic.java | 44 ++- .../org/apache/juneau/internal/ArrayUtils.java | 18 ++ .../org/apache/juneau/internal/FileUtils.java | 78 ----- .../org/apache/juneau/internal/ObjectUtils.java | 164 +++++++++- .../apache/juneau/internal/ReflectionUtils.java | 30 -- .../org/apache/juneau/utils/ObjectUtils.java | 181 ----------- .../org/apache/juneau/utils/ResourceFinder.java | 304 +++++++++++++++++++ juneau-core/src/main/javadoc/overview.html | 88 ++++-- .../juneau/examples/rest/AtomFeedResource.java | 14 +- .../examples/rest/CodeFormatterResource.java | 2 +- .../juneau/examples/rest/DirectoryResource.java | 6 +- .../juneau/examples/rest/FileSpaceResource.java | 155 ---------- .../examples/rest/JsonSchemaResource.java | 11 +- .../juneau/examples/rest/PetStoreResource.java | 12 +- .../examples/rest/RequestEchoResource.java | 6 +- .../juneau/examples/rest/RootResources.java | 15 +- .../examples/rest/SampleRemoteableServlet.java | 3 +- .../examples/rest/SystemPropertiesResource.java | 17 +- .../juneau/examples/rest/TempDirResource.java | 9 +- .../rest/addressbook/AddressBookResource.java | 19 +- .../juneau/examples/rest/RootResourcesTest.java | 13 - .../.settings/org.eclipse.jdt.ui.prefs | 3 + juneau-microservice-template/microservice.cfg | 9 +- .../apache/juneau/microservice/Resource.java | 6 +- .../juneau/microservice/ResourceGroup.java | 6 +- .../juneau/microservice/ResourceJena.java | 6 +- .../juneau/microservice/ResourceJenaGroup.java | 63 ++++ .../eclipse-preferences/user-dictionary.txt | 6 + .../java/org/apache/juneau/rest/CallMethod.java | 52 +++- .../org/apache/juneau/rest/RestCallHandler.java | 2 - .../java/org/apache/juneau/rest/RestConfig.java | 131 +++----- .../org/apache/juneau/rest/RestContext.java | 122 +++----- .../org/apache/juneau/rest/RestResponse.java | 45 ++- .../apache/juneau/rest/RestServletDefault.java | 12 +- .../apache/juneau/rest/annotation/HtmlDoc.java | 37 ++- .../juneau/rest/annotation/RestResource.java | 67 +--- .../rest/jena/RestServletJenaDefault.java | 9 +- .../java/org/apache/juneau/rest/package.html | 88 +----- .../org/apache/juneau/rest/vars/WidgetVar.java | 2 +- .../widget/ContentTypeLinksColumnWidget.java | 49 --- .../rest/widget/ContentTypeLinksRowWidget.java | 49 --- .../juneau/rest/widget/ContentTypeMenuItem.java | 82 +++++ .../juneau/rest/widget/MenuItemWidget.java | 72 +++++ .../rest/widget/PoweredByApacheWidget.java | 33 +- .../rest/widget/PoweredByJuneauWidget.java | 31 +- .../juneau/rest/widget/QueryMenuItem.java | 87 ++++++ .../apache/juneau/rest/widget/QueryWidget.java | 135 -------- .../org/apache/juneau/rest/widget/Widget.java | 184 ++++++++++- .../widget/doc-files/ContentTypeMenuItem.png | Bin 0 -> 137327 bytes .../rest/widget/doc-files/PetStore_Query.png | Bin 35238 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_q1.png | Bin 18709 -> 0 bytes .../widget/doc-files/PetStore_Query_q10.png | Bin 22147 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_q2.png | Bin 20455 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_q3.png | Bin 20269 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_q4.png | Bin 21004 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_q5.png | Bin 20463 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_q6.png | Bin 19557 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_q7.png | Bin 19621 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_q8.png | Bin 21190 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_q9.png | Bin 21224 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_r1.png | Bin 32218 -> 0 bytes .../widget/doc-files/PetStore_Query_r10.png | Bin 24393 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_r2.png | Bin 15575 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_r3.png | Bin 23447 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_r4.png | Bin 15575 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_r5.png | Bin 11753 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_r6.png | Bin 32244 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_r7.png | Bin 32202 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_r8.png | Bin 15575 -> 0 bytes .../rest/widget/doc-files/PetStore_Query_r9.png | Bin 24393 -> 0 bytes .../widget/doc-files/PetStore_Query_tooltip.png | Bin 64060 -> 0 bytes .../widget/doc-files/PoweredByApacheWidget.png | Bin 0 -> 4368 bytes .../widget/doc-files/PoweredByJuneauWidget.png | Bin 0 -> 5081 bytes .../rest/widget/doc-files/QueryMenuItem_1.png | Bin 0 -> 68449 bytes .../rest/widget/doc-files/QueryMenuItem_2.png | Bin 0 -> 253370 bytes .../org/apache/juneau/rest/styles/devops.css | 30 ++ .../juneau/rest/widget/MenuItemWidget.css | 17 ++ .../apache/juneau/rest/widget/MenuItemWidget.js | 33 ++ .../apache/juneau/rest/widget/QueryMenuItem.css | 45 +++ .../juneau/rest/widget/QueryMenuItem.html | 127 ++++++++ .../apache/juneau/rest/widget/QueryWidget.html | 176 ----------- pom.xml | 2 +- 89 files changed, 1817 insertions(+), 1384 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java b/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java index 5bccde9..d9bed6b 100644 --- a/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java +++ b/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java @@ -623,6 +623,9 @@ public class ObjectMap extends LinkedHashMap<String,Object> { /** * Specialized method that calls {@link #getString(String)} and splits the results as a simple comma-delimited list. + * + * <p> + * If the value is already a collection, the individual entries are converted to strings using {@link #toString()}. * * @param key the key. * @return @@ -631,8 +634,13 @@ public class ObjectMap extends LinkedHashMap<String,Object> { * Never <jk>null</jk>. */ public String[] getStringArray(String key) { - String s = get(String.class, key); - return (s == null ? new String[0] : split(s)); + Object s = get(Object.class, key); + if (s == null) + return new String[0]; + if (s instanceof Collection) + return ArrayUtils.toStringArray((Collection<?>)s); + String[] r = split(StringUtils.toString(s)); + return r; } /** @@ -643,8 +651,12 @@ public class ObjectMap extends LinkedHashMap<String,Object> { * @return The value converted to a string array. */ public String[] getStringArray(String key, String[] def) { - String s = get(String.class, key); - String[] r = (s == null ? new String[0] : split(s)); + Object s = get(Object.class, key); + if (s == null) + return def; + if (s instanceof Collection) + return ArrayUtils.toStringArray((Collection<?>)s); + String[] r = split(StringUtils.toString(s)); return (r.length == 0 ? def : r); } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-core/src/main/java/org/apache/juneau/dto/html5/HtmlElement.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/html5/HtmlElement.java b/juneau-core/src/main/java/org/apache/juneau/dto/html5/HtmlElement.java index 926e65e..f687ee3 100644 --- a/juneau-core/src/main/java/org/apache/juneau/dto/html5/HtmlElement.java +++ b/juneau-core/src/main/java/org/apache/juneau/dto/html5/HtmlElement.java @@ -23,7 +23,6 @@ import org.apache.juneau.*; import org.apache.juneau.annotation.*; import org.apache.juneau.html.*; import org.apache.juneau.internal.*; -import org.apache.juneau.utils.ObjectUtils; import org.apache.juneau.xml.annotation.*; /** http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-core/src/main/java/org/apache/juneau/dto/html5/HtmlElementContainer.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/html5/HtmlElementContainer.java b/juneau-core/src/main/java/org/apache/juneau/dto/html5/HtmlElementContainer.java index f35f237..ef2eb89 100644 --- a/juneau-core/src/main/java/org/apache/juneau/dto/html5/HtmlElementContainer.java +++ b/juneau-core/src/main/java/org/apache/juneau/dto/html5/HtmlElementContainer.java @@ -18,7 +18,7 @@ import java.util.*; import org.apache.juneau.*; import org.apache.juneau.annotation.*; -import org.apache.juneau.utils.*; +import org.apache.juneau.internal.*; import org.apache.juneau.xml.annotation.*; /** http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-core/src/main/java/org/apache/juneau/dto/html5/HtmlElementMixed.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/html5/HtmlElementMixed.java b/juneau-core/src/main/java/org/apache/juneau/dto/html5/HtmlElementMixed.java index 5e06b73..8ca17e7 100644 --- a/juneau-core/src/main/java/org/apache/juneau/dto/html5/HtmlElementMixed.java +++ b/juneau-core/src/main/java/org/apache/juneau/dto/html5/HtmlElementMixed.java @@ -18,7 +18,7 @@ import java.util.*; import org.apache.juneau.*; import org.apache.juneau.annotation.*; -import org.apache.juneau.utils.*; +import org.apache.juneau.internal.*; import org.apache.juneau.xml.annotation.*; /** http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java index d8546c1..fa5070a 100644 --- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java +++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerContext.java @@ -450,12 +450,12 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext { public static final String HTMLDOC_nowrap = "HtmlDocSerializer.nowrap"; /** - * <b>Configuration property:</b> Stylesheet URL. + * <b>Configuration property:</b> Stylesheet import URLs. * * <ul> - * <li><b>Name:</b> <js>"HtmlDocSerializer.cssUrl"</js> - * <li><b>Data type:</b> <code>String</code> - * <li><b>Default:</b> <js>"style.css"</js> + * <li><b>Name:</b> <js>"HtmlDocSerializer.styleImport"</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> * @@ -463,19 +463,23 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext { * Adds a link to the specified stylesheet URL. * * <p> - * If not specified, defaults to the built-in stylesheet located at <js>"style.css"</js>. - * Note that this stylesheet is controlled by the <code><ja>@RestResource</ja>.stylesheet()</code> annotation. + * Note that this stylesheet is controlled by the <code><ja>@RestResource</ja>.styleImport()</code> annotation. * * <p> * A value of <js>"NONE"</js> can be used to represent no value to differentiate it from an empty string. */ - public static final String HTMLDOC_cssUrl = "HtmlDocSerializer.cssUrl"; + public static final String HTMLDOC_styleImport = "HtmlDocSerializer.styleImport"; + + /** + * <b>Configuration property:</b> Add to the {@link #HTMLDOC_styleImport} property. + */ + public static final String HTMLDOC_styleImport_add = "HtmlDocSerializer.styleImport.list.add"; /** - * <b>Configuration property:</b> CSS code. + * <b>Configuration property:</b> CSS style code. * * <ul> - * <li><b>Name:</b> <js>"HtmlDocSerializer.css.list"</js> + * <li><b>Name:</b> <js>"HtmlDocSerializer.style.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> @@ -488,7 +492,7 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext { * <p class='bcode'> * <ja>@RestResource</ja>( * properties={ - * <ja>@Property</ja>(name=HtmlDocSerializerContext.<jsf>HTMLDOC_css</jsf>, + * <ja>@Property</ja>(name=HtmlDocSerializerContext.<jsf>HTMLDOC_style</jsf>, * value=<js>"h3 { color: red; }\nh5 { font-weight: bold; }"</js>) * } * ) @@ -499,17 +503,57 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext { * <p class='bcode'> * <ja>@RestResource</ja>( * htmldoc=@HtmlDoc( - * css=<js>"h3 { color: red; }\nh5 { font-weight: bold; }"</js> + * style=<js>"h3 { color: red; }\nh5 { font-weight: bold; }"</js> + * ) + * ) + * </p> + */ + public static final String HTMLDOC_style = "HtmlDocSerializer.style.list"; + + /** + * <b>Configuration property:</b> Add to the {@link #HTMLDOC_style} property. + */ + public static final String HTMLDOC_style_add = "HtmlDocSerializer.style.list.add"; + + /** + * <b>Configuration property:</b> Javascript code. + * + * <ul> + * <li><b>Name:</b> <js>"HtmlDocSerializer.script.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 Javascript code to the HTML page. + * + * <h5 class='section'>Example:</h5> + * <p class='bcode'> + * <ja>@RestResource</ja>( + * properties={ + * <ja>@Property</ja>(name=HtmlDocSerializerContext.<jsf>HTMLDOC_script</jsf>, + * value=<js>"alert('hello!');"</js>) + * } + * ) + * </p> + * + * <p> + * A shortcut on <ja>@RestResource</ja> is also provided for this setting: + * <p class='bcode'> + * <ja>@RestResource</ja>( + * htmldoc=@HtmlDoc( + * script=<js>"alert('hello!');"</js> * ) * ) * </p> */ - public static final String HTMLDOC_css = "HtmlDocSerializer.css.list"; + public static final String HTMLDOC_script = "HtmlDocSerializer.script.list"; /** - * <b>Configuration property:</b> Add to the {@link #HTMLDOC_css} property. + * <b>Configuration property:</b> Add to the {@link #HTMLDOC_script} property. */ - public static final String HTMLDOC_css_add = "HtmlDocSerializer.css.list.add"; + public static final String HTMLDOC_script_add = "HtmlDocSerializer.script.list.add"; /** * <b>Configuration property:</b> HTML document template. @@ -540,9 +584,9 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext { public static final String HTMLDOC_template = "HtmlDocSerializer.template"; - final String[] css; + final String[] style, styleImport, script; final Map<String,Object> links; - final String title, description, branding, header, nav, aside, footer, cssUrl, noResultsMessage; + final String title, description, branding, header, nav, aside, footer, noResultsMessage; final boolean nowrap; final HtmlDocTemplate template; @@ -556,7 +600,9 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext { */ public HtmlDocSerializerContext(PropertyStore ps) { super(ps); - css = ps.getProperty(HTMLDOC_css, String[].class, new String[0]); + style = ps.getProperty(HTMLDOC_style, String[].class, new String[0]); + styleImport = ps.getProperty(HTMLDOC_styleImport, String[].class, new String[0]); + script = ps.getProperty(HTMLDOC_script, String[].class, new String[0]); title = ps.getProperty(HTMLDOC_title, String.class, null); description = ps.getProperty(HTMLDOC_description, String.class, null); branding = ps.getProperty(HTMLDOC_branding, String.class, null); @@ -564,7 +610,6 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext { nav = ps.getProperty(HTMLDOC_nav, String.class, null); aside = ps.getProperty(HTMLDOC_aside, String.class, null); footer = ps.getProperty(HTMLDOC_footer, String.class, null); - cssUrl = ps.getProperty(HTMLDOC_cssUrl, String.class, null); nowrap = ps.getProperty(HTMLDOC_nowrap, boolean.class, false); links = ps.getMap(HTMLDOC_links, String.class, Object.class, null); noResultsMessage = ps.getProperty(HTMLDOC_noResultsMessage, String.class, "<p>no results</p>"); @@ -575,7 +620,6 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext { public ObjectMap asMap() { return super.asMap() .append("HtmlDocSerializerContext", new ObjectMap() - .append("cssImports", css) .append("title", title) .append("text", description) .append("branding", branding) @@ -584,7 +628,8 @@ public final class HtmlDocSerializerContext extends HtmlSerializerContext { .append("links", links) .append("aside", aside) .append("footer", footer) - .append("cssUrl", cssUrl) + .append("style", style) + .append("styleImport", styleImport) .append("nowrap", nowrap) .append("template", template) .append("noResultsMessage", noResultsMessage) http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java index ac330a1..19a3661 100644 --- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java +++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java @@ -13,7 +13,6 @@ package org.apache.juneau.html; import static org.apache.juneau.html.HtmlDocSerializerContext.*; -import static org.apache.juneau.internal.StringUtils.*; import java.lang.reflect.*; import java.util.*; @@ -35,8 +34,8 @@ import org.apache.juneau.serializer.*; */ public final class HtmlDocSerializerSession extends HtmlSerializerSession { - private final String title, description, branding, header, nav, aside, footer, cssUrl, noResultsMessage; - private final String[] css; + private final String title, description, branding, header, nav, aside, footer, noResultsMessage; + private final String[] style, styleImport, script; private final Map<String,Object> links; private final boolean nowrap; private final HtmlDocTemplate template; @@ -78,8 +77,9 @@ public final class HtmlDocSerializerSession extends HtmlSerializerSession { aside = ctx.aside; footer = ctx.footer; links = ctx.links; - cssUrl = ctx.cssUrl; - css = ctx.css; + style = ctx.style; + styleImport = ctx.styleImport; + script = ctx.script; nowrap = ctx.nowrap; noResultsMessage = ctx.noResultsMessage; template = ClassUtils.newInstance(HtmlDocTemplate.class, ctx.template); @@ -93,8 +93,9 @@ public final class HtmlDocSerializerSession extends HtmlSerializerSession { footer = op.getString(HTMLDOC_footer, ctx.footer); Map m = op.getMap(HTMLDOC_links, ctx.links); links = ObjectUtils.isEmpty(m) ? null : new LinkedHashMap(m); - cssUrl = op.getString(HTMLDOC_cssUrl, ctx.cssUrl); - css = split(op.getString(HTMLDOC_css, null)); + style = op.getStringArray(HTMLDOC_style, ctx.style); + styleImport = op.getStringArray(HTMLDOC_styleImport, ctx.styleImport); + script = op.getStringArray(HTMLDOC_script, ctx.script); nowrap = op.getBoolean(HTMLDOC_nowrap, ctx.nowrap); noResultsMessage = op.getString(HTMLDOC_noResultsMessage, ctx.noResultsMessage); template = ClassUtils.newInstance(HtmlDocTemplate.class, op.get(HTMLDOC_template, ctx.template)); @@ -102,26 +103,39 @@ public final class HtmlDocSerializerSession extends HtmlSerializerSession { } /** - * Returns the {@link HtmlDocSerializerContext#HTMLDOC_cssUrl} setting value in this context. + * Returns the {@link HtmlDocSerializerContext#HTMLDOC_style} setting value in this context. * * @return - * The {@link HtmlDocSerializerContext#HTMLDOC_cssUrl} setting value in this context. - * <jk>null</jk> if not specified. - * Never an empty string. + * The {@link HtmlDocSerializerContext#HTMLDOC_style} setting value in this context. + * An empty array if not specified. + * Never <jk>null</jk>. */ - public final String getCssUrl() { - return cssUrl; + public final String[] getStyle() { + return style; } /** - * Returns the {@link HtmlDocSerializerContext#HTMLDOC_css} setting value in this context. + * Returns the {@link HtmlDocSerializerContext#HTMLDOC_styleImport} setting value in this context. * * @return - * The {@link HtmlDocSerializerContext#HTMLDOC_css} setting value in this context. - * <jk>null</jk> if not specified. Never an empty array. + * The {@link HtmlDocSerializerContext#HTMLDOC_styleImport} setting value in this context. + * An empty array if not specified. + * Never <jk>null</jk>. + */ + public final String[] getStyleImport() { + return styleImport; + } + + /** + * Returns the {@link HtmlDocSerializerContext#HTMLDOC_script} setting value in this context. + * + * @return + * The {@link HtmlDocSerializerContext#HTMLDOC_script} setting value in this context. + * An empty array if not specified. + * Never <jk>null</jk>. */ - public final String[] getCss() { - return css; + public final String[] getScript() { + return script; } /** http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplate.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplate.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplate.java index cc8b2b8..7cc156e 100644 --- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplate.java +++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplate.java @@ -21,9 +21,12 @@ package org.apache.juneau.html; * <p class='bcode'> * <xt><html> * <head> - * <style <xa>type</xa>=<xs>'text/css'</xs>> + * <style> * <xv>CSS styles and links to stylesheets</xv> * </style> + * <script> + * <xv>Javascript</xv> + * </script> * </head> * <body> * <header> @@ -64,8 +67,7 @@ public interface HtmlDocTemplate { public void head(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception; /** - * Renders the contents of the <code><xt><head></xt>/<xt><style</xt> - * <xa>type</xa>=<xs>"text/css"</xs><xt>></xt></code> element. + * Renders the contents of the <code><xt><head></xt>/<xt><style></xt></code> element. * * @param session The current serializer session. * @param w The writer being written to. @@ -73,7 +75,18 @@ public interface HtmlDocTemplate { * @param o The object being serialized. * @throws Exception Any exception can be thrown. */ - public void css(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception; + public void style(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception; + + /** + * Renders the contents of the <code><xt><head></xt>/<xt><script></xt></code> element. + * + * @param session The current serializer session. + * @param w The writer being written to. + * @param s The serializer calling this method. + * @param o The object being serialized. + * @throws Exception Any exception can be thrown. + */ + public void script(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception; /** * Renders the contents of the <code><xt><body></xt></code> element. @@ -142,13 +155,20 @@ public interface HtmlDocTemplate { public void footer(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception; /** - * Returns <jk>true</jk> if this page should render a <code><xt><head></xt>/<xt><style</xt> - * <xa>type</xa>=<xs>"text/css"</xs><xt>></xt></code> element. + * Returns <jk>true</jk> if this page should render a <code><xt><head></xt>/<xt><style></xt></code> element. + * + * @param session The current serializer session. + * @return A boolean flag. + */ + public boolean hasStyle(HtmlDocSerializerSession session); + + /** + * Returns <jk>true</jk> if this page should render a <code><xt><head></xt>/<xt><script></xt></code> element. * * @param session The current serializer session. * @return A boolean flag. */ - public boolean hasCss(HtmlDocSerializerSession session); + public boolean hasScript(HtmlDocSerializerSession session); /** * Returns <jk>true</jk> if this page should render a <code><xt><body></xt>/<xt><header></xt></code> http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java index 3360770..8e1441c 100644 --- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java +++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocTemplateBasic.java @@ -26,27 +26,40 @@ public class HtmlDocTemplateBasic implements HtmlDocTemplate { @Override /* HtmlDocTemplate */ public void head(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception { - if (hasCss(session)) { - w.oTag(1, "style").attr("type", "text/css").appendln(">").nl(1); - css(session, w, s, o); + if (hasStyle(session)) { + w.sTag(1, "style").nl(1); + style(session, w, s, o); w.ie(1).eTag("style").nl(1); } + if (hasScript(session)) { + w.sTag(1, "script").nl(1); + script(session, w, s, o); + w.ie(1).eTag("script").nl(1); + } } @Override /* HtmlDocTemplate */ - public void css(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception { + public void style(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception { - String cssUrl = session.getCssUrl(); - if (cssUrl == null) - cssUrl = "servlet:/style.css"; - cssUrl = session.resolveUri(cssUrl); + String[] styleImport = session.getStyleImport(); + if (! ArrayUtils.contains("NONE", styleImport)) + for (String si : styleImport) + w.append(2, "@import ").q().append(session.resolveUri(si)).q().appendln(";"); - w.append(2, "@import ").q().append(cssUrl).q().appendln(";"); if (session.isNoWrap()) w.appendln("\ndiv.data * {white-space:nowrap;}"); - if (session.getCss() != null) - for (String css : session.getCss()) - w.appendln(css); + + if (session.getStyle() != null) + for (String style : session.getStyle()) + w.appendln(style); + } + + @Override /* HtmlDocTemplate */ + public void script(HtmlDocSerializerSession session, HtmlWriter w, HtmlDocSerializer s, Object o) throws Exception { + + if (session.getScript() != null) + for (String script : session.getScript()) + w.appendln(script); } @Override /* HtmlDocTemplate */ @@ -167,7 +180,12 @@ public class HtmlDocTemplateBasic implements HtmlDocTemplate { } @Override /* HtmlDocTemplate */ - public boolean hasCss(HtmlDocSerializerSession session) { + public boolean hasStyle(HtmlDocSerializerSession session) { + return true; + } + + @Override /* HtmlDocTemplate */ + public boolean hasScript(HtmlDocSerializerSession session) { return true; } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-core/src/main/java/org/apache/juneau/internal/ArrayUtils.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/ArrayUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/ArrayUtils.java index 760353f..c088cf8 100644 --- a/juneau-core/src/main/java/org/apache/juneau/internal/ArrayUtils.java +++ b/juneau-core/src/main/java/org/apache/juneau/internal/ArrayUtils.java @@ -398,4 +398,22 @@ public final class ArrayUtils { } return null; } + + /** + * Converts the specified collection to an array of strings. + * + * <p> + * Entries are converted to strings using {@link #toString()}. + * <jk>null</jk> values remain <jk>null</jk>. + * + * @param c The collection to convert. + * @return The collection as a string array. + */ + public static String[] toStringArray(Collection<?> c) { + String[] r = new String[c.size()]; + int i = 0; + for (Object o : c) + r[i++] = StringUtils.toString(o); + return r; + } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-core/src/main/java/org/apache/juneau/internal/FileUtils.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/FileUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/FileUtils.java index f2c3000..67900e0 100644 --- a/juneau-core/src/main/java/org/apache/juneau/internal/FileUtils.java +++ b/juneau-core/src/main/java/org/apache/juneau/internal/FileUtils.java @@ -15,17 +15,12 @@ package org.apache.juneau.internal; import static org.apache.juneau.internal.ThrowableUtils.*; import java.io.*; -import java.util.*; -import java.util.ResourceBundle.*; /** * File utilities. */ public class FileUtils { - private static final ResourceBundle.Control RB_CONTROL = ResourceBundle.Control.getControl(Control.FORMAT_DEFAULT); - private static final List<Locale> ROOT_LOCALE = Arrays.asList(Locale.ROOT); - /** * Same as {@link File#mkdirs()} except throws a RuntimeExeption if directory could not be created. * @@ -172,77 +167,4 @@ public class FileUtils { return ""; return name.substring(i+1); } - - /** - * Returns the candidate file names for the specified file name in the specified locale. - * - * <p> - * For example, if looking for the <js>"MyResource.txt"</js> file in the Japanese locale, the iterator will return - * names in the following order: - * <ol> - * <li><js>"MyResource_ja_JP.txt"</js> - * <li><js>"MyResource_ja.txt"</js> - * <li><js>"MyResource.txt"</js> - * </ol> - * - * <p> - * If the locale is null, then it will only return <js>"MyResource.txt"</js>. - * - * @param fileName The name of the file to get candidate file names on. - * @param l The locale. - * @return An iterator of file names to look at. - */ - public static Iterable<String> getCandidateFileNames(final String fileName, final Locale l) { - return new Iterable<String>() { - @Override - public Iterator<String> iterator() { - return new Iterator<String>() { - final Iterator<Locale> locales = getCandidateLocales(l).iterator(); - String baseName, ext; - - @Override - public boolean hasNext() { - return locales.hasNext(); - } - - @Override - public String next() { - Locale l2 = locales.next(); - if (l2.toString().isEmpty()) - return fileName; - if (baseName == null) - baseName = getBaseName(fileName); - if (ext == null) - ext = getExtension(fileName); - return baseName + "_" + l2.toString() + (ext.isEmpty() ? "" : ('.' + ext)); - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - }; - } - - - /** - * Returns the candidate locales for the specified locale. - * - * <p> - * For example, if <code>locale</code> is <js>"ja_JP"</js>, then this method will return: - * <ol> - * <li><js>"ja_JP"</js> - * <li><js>"ja"</js> - * <li><js>""</js> - * </ol> - * - * @param locale The locale to get the list of candidate locales for. - * @return The list of candidate locales. - */ - public static List<Locale> getCandidateLocales(Locale locale) { - if (locale == null) - return ROOT_LOCALE; - return RB_CONTROL.getCandidateLocales("", locale); - } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-core/src/main/java/org/apache/juneau/internal/ObjectUtils.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/ObjectUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/ObjectUtils.java index 7aac560..aab0017 100644 --- a/juneau-core/src/main/java/org/apache/juneau/internal/ObjectUtils.java +++ b/juneau-core/src/main/java/org/apache/juneau/internal/ObjectUtils.java @@ -15,11 +15,173 @@ package org.apache.juneau.internal; import java.lang.reflect.*; import java.util.*; +import org.apache.juneau.*; +import org.apache.juneau.transform.*; + /** - * Object-related utility methods. + * Utility class for efficiently converting objects between types. + * + * <p> + * If the value isn't an instance of the specified type, then converts the value if possible. + * + * <p> + * The following conversions are valid: + * <table class='styled'> + * <tr><th>Convert to type</th><th>Valid input value types</th><th>Notes</th></tr> + * <tr> + * <td> + * A class that is the normal type of a registered {@link PojoSwap}. + * </td> + * <td> + * A value whose class matches the transformed type of that registered {@link PojoSwap}. + * </td> + * <td> </td> + * </tr> + * <tr> + * <td> + * A class that is the transformed type of a registered {@link PojoSwap}. + * </td> + * <td> + * A value whose class matches the normal type of that registered {@link PojoSwap}. + * </td> + * <td> </td> + * </tr> + * <tr> + * <td> + * {@code Number} (e.g. {@code Integer}, {@code Short}, {@code Float},...) + * <br><code>Number.<jsf>TYPE</jsf></code> (e.g. <code>Integer.<jsf>TYPE</jsf></code>, + * <code>Short.<jsf>TYPE</jsf></code>, <code>Float.<jsf>TYPE</jsf></code>,...) + * </td> + * <td> + * {@code Number}, {@code String}, <jk>null</jk> + * </td> + * <td> + * For primitive {@code TYPES}, <jk>null</jk> returns the JVM default value for that type. + * </td> + * </tr> + * <tr> + * <td> + * {@code Map} (e.g. {@code Map}, {@code HashMap}, {@code TreeMap}, {@code ObjectMap}) + * </td> + * <td> + * {@code Map} + * </td> + * <td> + * If {@code Map} is not constructible, a {@code ObjectMap} is created. + * </td> + * </tr> + * <tr> + * <td> + * {@code Collection} (e.g. {@code List}, {@code LinkedList}, {@code HashSet}, {@code ObjectList}) + * </td> + * <td> + * {@code Collection<Object>} + * <br>{@code Object[]} + * </td> + * <td> + * If {@code Collection} is not constructible, a {@code ObjectList} is created. + * </td> + * </tr> + * <tr> + * <td> + * {@code X[]} (array of any type X) + * </td> + * <td> + * {@code List<X>} + * </td> + * <td> </td> + * </tr> + * <tr> + * <td> + * {@code X[][]} (multi-dimensional arrays) + * </td> + * <td> + * {@code List<List<X>>} + * <br>{@code List<X[]>} + * <br>{@code List[]<X>} + * </td> + * <td> </td> + * </tr> + * <tr> + * <td> + * {@code Enum} + * </td> + * <td> + * {@code String} + * </td> + * <td> </td> + * </tr> + * <tr> + * <td> + * Bean + * </td> + * <td> + * {@code Map} + * </td> + * <td> </td> + * </tr> + * <tr> + * <td> + * {@code String} + * </td> + * <td> + * Anything + * </td> + * <td> + * Arrays are converted to JSON arrays + * </td> + * </tr> + * <tr> + * <td> + * Anything with one of the following methods: + * <br><code><jk>public static</jk> T fromString(String)</code> + * <br><code><jk>public static</jk> T valueOf(String)</code> + * <br><code><jk>public</jk> T(String)</code> + * </td> + * <td> + * <code>String</code> + * </td> + * <td> + * <br> + * </td> + * </tr> + * </table> */ public class ObjectUtils { + // Session objects are usually not thread safe, but we're not using any feature + // of bean sessions that would cause thread safety issues. + private static final BeanSession session = BeanContext.DEFAULT.createSession(); + + /** + * Converts the specified object to the specified type. + * + * @param <T> The class type to convert the value to. + * @param value The value to convert. + * @param type The class type to convert the value to. + * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. + * @return The converted value. + */ + public static <T> T convertToType(Object value, Class<T> type) { + return session.convertToType(value, type); + } + + /** + * Converts the specified object to the specified type. + * + * @param <T> The class type to convert the value to. + * @param outer + * If class is a member class, this is the instance of the containing class. + * Should be <jk>null</jk> if not a member class. + * @param value The value to convert. + * @param type The class type to convert the value to. + * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. + * @return The converted value. + */ + public static <T> T convertToType(Object outer, Object value, Class<T> type) { + return session.convertToType(outer, value, type); + } + /** * Returns <jk>true</jk> if the specified objects are equal. * http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-core/src/main/java/org/apache/juneau/internal/ReflectionUtils.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/ReflectionUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/ReflectionUtils.java index cc4effb..644ff3e 100644 --- a/juneau-core/src/main/java/org/apache/juneau/internal/ReflectionUtils.java +++ b/juneau-core/src/main/java/org/apache/juneau/internal/ReflectionUtils.java @@ -188,35 +188,5 @@ public final class ReflectionUtils { } return null; } - - /** - * Similar to {@link #getResource(Class, String)} except looks for localized versions of the specified resource. - * - * <p> - * For example, if looking in the Japanese locale, the order of lookup on the <js>"MyResource.txt"</js> file is: - * <ol> - * <li><js>"MyResource_ja_JP.txt"</js> - * <li><js>"MyResource_ja.txt"</js> - * <li><js>"MyResource.txt"</js> - * </ol> - * - * @param c The class to return the resource on. - * @param name The resource name. - * @param locale The locale of the resource. - * @return An input stream on the specified resource, or <jk>null</jk> if the resource could not be found. - */ - public static InputStream getLocalizedResource(Class<?> c, String name, Locale locale) { - if (locale == null || locale.toString().isEmpty()) - return getResource(c, name); - while (c != null) { - for (String n : FileUtils.getCandidateFileNames(name, locale)) { - InputStream is = c.getResourceAsStream(n); - if (is != null) - return is; - } - c = c.getSuperclass(); - } - return null; - } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-core/src/main/java/org/apache/juneau/utils/ObjectUtils.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/utils/ObjectUtils.java b/juneau-core/src/main/java/org/apache/juneau/utils/ObjectUtils.java deleted file mode 100644 index c1350a0..0000000 --- a/juneau-core/src/main/java/org/apache/juneau/utils/ObjectUtils.java +++ /dev/null @@ -1,181 +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.utils; - -import org.apache.juneau.*; -import org.apache.juneau.transform.*; - -/** - * Utility class for efficiently converting objects between types. - * - * <p> - * If the value isn't an instance of the specified type, then converts the value if possible. - * - * <p> - * The following conversions are valid: - * <table class='styled'> - * <tr><th>Convert to type</th><th>Valid input value types</th><th>Notes</th></tr> - * <tr> - * <td> - * A class that is the normal type of a registered {@link PojoSwap}. - * </td> - * <td> - * A value whose class matches the transformed type of that registered {@link PojoSwap}. - * </td> - * <td> </td> - * </tr> - * <tr> - * <td> - * A class that is the transformed type of a registered {@link PojoSwap}. - * </td> - * <td> - * A value whose class matches the normal type of that registered {@link PojoSwap}. - * </td> - * <td> </td> - * </tr> - * <tr> - * <td> - * {@code Number} (e.g. {@code Integer}, {@code Short}, {@code Float},...) - * <br><code>Number.<jsf>TYPE</jsf></code> (e.g. <code>Integer.<jsf>TYPE</jsf></code>, - * <code>Short.<jsf>TYPE</jsf></code>, <code>Float.<jsf>TYPE</jsf></code>,...) - * </td> - * <td> - * {@code Number}, {@code String}, <jk>null</jk> - * </td> - * <td> - * For primitive {@code TYPES}, <jk>null</jk> returns the JVM default value for that type. - * </td> - * </tr> - * <tr> - * <td> - * {@code Map} (e.g. {@code Map}, {@code HashMap}, {@code TreeMap}, {@code ObjectMap}) - * </td> - * <td> - * {@code Map} - * </td> - * <td> - * If {@code Map} is not constructible, a {@code ObjectMap} is created. - * </td> - * </tr> - * <tr> - * <td> - * {@code Collection} (e.g. {@code List}, {@code LinkedList}, {@code HashSet}, {@code ObjectList}) - * </td> - * <td> - * {@code Collection<Object>} - * <br>{@code Object[]} - * </td> - * <td> - * If {@code Collection} is not constructible, a {@code ObjectList} is created. - * </td> - * </tr> - * <tr> - * <td> - * {@code X[]} (array of any type X) - * </td> - * <td> - * {@code List<X>} - * </td> - * <td> </td> - * </tr> - * <tr> - * <td> - * {@code X[][]} (multi-dimensional arrays) - * </td> - * <td> - * {@code List<List<X>>} - * <br>{@code List<X[]>} - * <br>{@code List[]<X>} - * </td> - * <td> </td> - * </tr> - * <tr> - * <td> - * {@code Enum} - * </td> - * <td> - * {@code String} - * </td> - * <td> </td> - * </tr> - * <tr> - * <td> - * Bean - * </td> - * <td> - * {@code Map} - * </td> - * <td> </td> - * </tr> - * <tr> - * <td> - * {@code String} - * </td> - * <td> - * Anything - * </td> - * <td> - * Arrays are converted to JSON arrays - * </td> - * </tr> - * <tr> - * <td> - * Anything with one of the following methods: - * <br><code><jk>public static</jk> T fromString(String)</code> - * <br><code><jk>public static</jk> T valueOf(String)</code> - * <br><code><jk>public</jk> T(String)</code> - * </td> - * <td> - * <code>String</code> - * </td> - * <td> - * <br> - * </td> - * </tr> - * </table> - */ -public class ObjectUtils { - - // Session objects are usually not thread safe, but we're not using any feature - // of bean sessions that would cause thread safety issues. - private static final BeanSession session = BeanContext.DEFAULT.createSession(); - - /** - * Converts the specified object to the specified type. - * - * @param <T> The class type to convert the value to. - * @param value The value to convert. - * @param type The class type to convert the value to. - * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. - * @return The converted value. - */ - public static <T> T convertToType(Object value, Class<T> type) { - return session.convertToType(value, type); - } - - /** - * Converts the specified object to the specified type. - * - * @param <T> The class type to convert the value to. - * @param outer - * If class is a member class, this is the instance of the containing class. - * Should be <jk>null</jk> if not a member class. - * @param value The value to convert. - * @param type The class type to convert the value to. - * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. - * @return The converted value. - */ - public static <T> T convertToType(Object outer, Object value, Class<T> type) { - return session.convertToType(outer, value, type); - } -} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-core/src/main/java/org/apache/juneau/utils/ResourceFinder.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/utils/ResourceFinder.java b/juneau-core/src/main/java/org/apache/juneau/utils/ResourceFinder.java new file mode 100644 index 0000000..e2496ba --- /dev/null +++ b/juneau-core/src/main/java/org/apache/juneau/utils/ResourceFinder.java @@ -0,0 +1,304 @@ +// *************************************************************************************************************************** +// * 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.utils; + +import static org.apache.juneau.internal.FileUtils.*; + +import java.io.*; +import java.net.*; +import java.util.*; +import java.util.ResourceBundle.*; +import java.util.concurrent.*; + +import org.apache.juneau.internal.*; + +/** + * Utility class for finding resources for a class. + * + * <p> + * Same as {@link Class#getResourceAsStream(String)} except if it doesn't find the resource on this class, searches + * up the parent hierarchy chain. + * + * <p> + * If the resource cannot be found in the classpath, then an attempt is made to look in the JVM working directory. + * <br>Path traversals outside the working directory are not allowed for security reasons. + * + * <p> + * If the <code>locale</code> is specified, then we look for resources whose name matches that locale. + * For example, if looking for the resource <js>"MyResource.txt"</js> for the Japanese locale, we will look for + * files in the following order: + * <ol> + * <li><js>"MyResource_ja_JP.txt"</js> + * <li><js>"MyResource_ja.txt"</js> + * <li><js>"MyResource.txt"</js> + * </ol> + * + * <p> + * Results are cached for fast lookup. + */ +public class ResourceFinder { + + private static final ResourceBundle.Control RB_CONTROL = ResourceBundle.Control.getControl(Control.FORMAT_DEFAULT); + private static final List<Locale> ROOT_LOCALE = Arrays.asList(Locale.ROOT); + + // Maps resource names+locales to found resources. + private final ConcurrentHashMap<ResourceKey,Resource> cache = new ConcurrentHashMap<ResourceKey,Resource>(); + + // Maps resolved URLs to resources. + private final ConcurrentHashMap<URL,Resource> cacheByUrl = new ConcurrentHashMap<URL,Resource>(); + + private final Class<?> c; + + /** + * Constructor. + * + * @param forClass The class that this resource finder searches against. + */ + public ResourceFinder(Class<?> forClass) { + this.c = forClass; + } + + /** + * Finds the resource with the given name. + * + * @param name Name of the desired resource. + * @return An input stream to the object, or <jk>null</jk> if the resource could not be found. + * @throws IOException + */ + public InputStream getResourceAsStream(String name) throws IOException { + return getResourceAsStream(name, null); + } + + /** + * Finds the resource with the given name for the specified locale. + * + * @param name Name of the desired resource. + * @param locale The locale. Can be <jk>null</jk>. + * @return An input stream to the object, or <jk>null</jk> if the resource could not be found. + * @throws IOException + */ + public InputStream getResourceAsStream(String name, Locale locale) throws IOException { + return getResource(name, locale).asInputStream(); + } + + /** + * Finds the resource with the given name and converts it to a simple string. + * + * @param name Name of the desired resource. + * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. + * @throws IOException + */ + public String getResourceAsString(String name) throws IOException { + return getResourceAsString(name, null); + } + + /** + * Finds the resource with the given name and converts it to a simple string. + * + * @param name Name of the desired resource. + * @param locale The locale. Can be <jk>null</jk>. + * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. + * @throws IOException + */ + public String getResourceAsString(String name, Locale locale) throws IOException { + return getResource(name, locale).asString(); + } + + + //------------------------------------------------------------------------------------------------------------------- + // Support classes and methods. + //------------------------------------------------------------------------------------------------------------------- + + private static class ResourceKey { + private final String name; + private final Locale locale; + + ResourceKey(String name, Locale locale) { + this.name = name; + this.locale = locale; + } + + @Override + public int hashCode() { + return name.hashCode() + (locale == null ? 0 : locale.hashCode()); + } + + @Override + public boolean equals(Object o) { + if (o == null) + return false; + ResourceKey ok = (ResourceKey)o; + return ObjectUtils.equals(name, ok.name) && ObjectUtils.equals(locale, ok.locale); + } + } + + private static class Resource { + private byte[] bytes; + private String string; + + private Resource(byte[] bytes) { + this.bytes = bytes; + } + + private String asString() { + if (bytes == null) + return null; + try { + if (string == null) + string = new String(bytes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return string; + } + + private InputStream asInputStream() { + if (bytes == null) + return null; + return new ByteArrayInputStream(bytes); + } + } + + private Resource getResource(String name, Locale locale) throws IOException { + ResourceKey key = new ResourceKey(name, locale); + Resource r = cache.get(key); + if (r != null) + return r; + + r = findResource(c, key); + cache.putIfAbsent(key, r); + r = cache.get(key); + return r; + } + + private Resource findResource(Class<?> c2, ResourceKey key) throws IOException { + while (c2 != null) { + if (key.locale == null) { + URL url = c2.getResource(key.name); + if (url != null) { + Resource r = cacheByUrl.get(url); + if (r == null) { + r = new Resource(IOUtils.readBytes(c2.getResourceAsStream(key.name), 1024)); + cacheByUrl.putIfAbsent(url, r); + r = cacheByUrl.get(url); + } + return r; + } + } else { + for (String n : getCandidateFileNames(key.name, key.locale)) { + URL url = c2.getResource(n); + if (url != null) { + Resource r = cacheByUrl.get(url); + if (r == null) { + r = new Resource(IOUtils.readBytes(c2.getResourceAsStream(key.name), 1024)); + cacheByUrl.putIfAbsent(url, r); + r = cacheByUrl.get(url); + } + return r; + } + } + } + c2 = c2.getSuperclass(); + } + + if (key.name.indexOf("..") == -1) { + for (String n2 : getCandidateFileNames(key.name, key.locale)) { + File f = new File(n2); + if (f.exists() && f.canRead() && ! f.isAbsolute()) { + URL url = f.toURI().toURL(); + Resource r = cacheByUrl.get(url); + if (r == null) { + r = new Resource(IOUtils.readBytes(new FileInputStream(f), 1024)); + cacheByUrl.putIfAbsent(url, r); + r = cacheByUrl.get(url); + } + return r; + } + } + } + + return new Resource(null); + } + + /** + * Returns the candidate file names for the specified file name in the specified locale. + * + * <p> + * For example, if looking for the <js>"MyResource.txt"</js> file in the Japanese locale, the iterator will return + * names in the following order: + * <ol> + * <li><js>"MyResource_ja_JP.txt"</js> + * <li><js>"MyResource_ja.txt"</js> + * <li><js>"MyResource.txt"</js> + * </ol> + * + * <p> + * If the locale is null, then it will only return <js>"MyResource.txt"</js>. + * + * @param fileName The name of the file to get candidate file names on. + * @param l The locale. + * @return An iterator of file names to look at. + */ + private static Iterable<String> getCandidateFileNames(final String fileName, final Locale l) { + return new Iterable<String>() { + @Override + public Iterator<String> iterator() { + return new Iterator<String>() { + final Iterator<Locale> locales = getCandidateLocales(l).iterator(); + String baseName, ext; + + @Override + public boolean hasNext() { + return locales.hasNext(); + } + + @Override + public String next() { + Locale l2 = locales.next(); + if (l2.toString().isEmpty()) + return fileName; + if (baseName == null) + baseName = getBaseName(fileName); + if (ext == null) + ext = getExtension(fileName); + return baseName + "_" + l2.toString() + (ext.isEmpty() ? "" : ('.' + ext)); + } + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }; + } + + /** + * Returns the candidate locales for the specified locale. + * + * <p> + * For example, if <code>locale</code> is <js>"ja_JP"</js>, then this method will return: + * <ol> + * <li><js>"ja_JP"</js> + * <li><js>"ja"</js> + * <li><js>""</js> + * </ol> + * + * @param locale The locale to get the list of candidate locales for. + * @return The list of candidate locales. + */ + private static List<Locale> getCandidateLocales(Locale locale) { + if (locale == null) + return ROOT_LOCALE; + return RB_CONTROL.getCandidateLocales("", locale); + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-core/src/main/javadoc/overview.html ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/javadoc/overview.html b/juneau-core/src/main/javadoc/overview.html index 30be514..79d7f5c 100644 --- a/juneau-core/src/main/javadoc/overview.html +++ b/juneau-core/src/main/javadoc/overview.html @@ -2479,7 +2479,7 @@ }, <jc>// Our stylesheet for the HTML rendition.</jc> - stylesheet=<js>"styles/devops.css"</js>, + styleImport=<js>"styles/devops.css"</js>, <jc>// Support GZIP encoding on Accept-Encoding header.</jc> encoders=GzipEncoder.<jk>class</jk>, @@ -4681,7 +4681,7 @@ }, <jc>// Our stylesheet for the HTML rendition.</jc> - stylesheet=<js>"styles/devops.css"</js>, + styleImport=<js>"styles/devops.css"</js>, <jc>// Support GZIP encoding on Accept-Encoding header.</jc> encoders=GzipEncoder.<jk>class</jk>, @@ -5504,7 +5504,7 @@ <ja>@Property</ja>(name=<js>"DirectoryResource.allowDeletes"</js>, value=<js>"true"</js>), <ja>@Property</ja>(name=<js>"DirectoryResource.allowPuts"</js>, value=<js>"false"</js>) }, - stylesheet=<js>"styles/devops.css"</js> + styleImport=<js>"styles/devops.css"</js> ) <jk>public class</jk> TempDirResource <jk>extends</jk> DirectoryResource { <jk>private static final long</jk> <jsf>serialVersionUID</jsf> = 1L; @@ -6754,7 +6754,7 @@ <h5 class='toc'>What's new in each release</h5> <ul class='toc'> <li><p><a class='doclink' href='#6.3.1'>6.3.1 (TBD)</a></p> - <li><p><a class='doclink' href='#6.3.0'>6.3.0 (TBD)</a></p> + <li><p><a class='doclink' href='#6.3.0'>6.3.0 (Jun 30, 2017)</a></p> <li><p><a class='doclink' href='#6.2.0'>6.2.0 (Apr 28, 2017)</a></p> <li><p><a class='doclink' href='#6.1.0'>6.1.0 (Feb 25, 2017)</a></p> <li><p><a class='doclink' href='#6.0.1'>6.0.1 (Jan 3, 2017)</a></p> @@ -6832,19 +6832,58 @@ <ul class='spaced-list'> <li> {@link org.apache.juneau.utils.PojoQuery} improvements. - <br>Search columns containing lists and maps. - <br>Sort columns containing lists and maps. <li> New {@link org.apache.juneau.remoteable.RemoteMethod#returns()} annotation. + <br>Allows you to specify whether the remote method returns the HTTP body or status code. <li> Fixed bugs with {@link org.apache.juneau.BeanContext#BEAN_includeProperties} and {@link org.apache.juneau.BeanContext#BEAN_excludeProperties} settings. + <li> + New/modified settings in {@link org.apache.juneau.html.HtmlDocSerializerContext}: + <ul> + <li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_script HTMLDOC_script} + <li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_style HTMLDOC_style} - Was <jsf>HTMLDOC_css</jsf>. + <li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_styleImport HTMLDOC_styleImport} - Was <jsf>HTMLDOC_cssUrl</jsf>. Now an array. + </ul> + <li> + New {@link org.apache.juneau.utils.ResourceFinder} utility class. + Allows you to search for resources up the parent hierarchy chain. + Also allows you to search for localized resources. </ul> <h6 class='topic'>org.apache.juneau.rest</h6> <ul class='spaced-list'> <li> - {@link org.apache.juneau.rest.widget.QueryWidget} improvements. - <br>Fields are pre-filled with current search arguments. + Improvements made to the {@link org.apache.juneau.rest.widget.Widget} API. + <ul> + <li> + You can now add arbitrary CSS and Javascript along with your widgets through new methods: + <ul> + <li>{@link org.apache.juneau.rest.widget.Widget#getHtml(RestRequest)} + <li>{@link org.apache.juneau.rest.widget.Widget#getScript(RestRequest)} + <li>{@link org.apache.juneau.rest.widget.Widget#getStyle(RestRequest)} + </ul> + </li> + <li> + New {@link org.apache.juneau.rest.widget.MenuItemWidget} can be used to create pull-down menu items. + <li> + New {@link org.apache.juneau.rest.widget.ContentTypeMenuItem} widget that provides a pull-down menu + with hyperlinks for all supported languages for that page: + <br><img src='doc-files/ReleaseNotes_631_ContentTypeMenuItem.png'> + <li> + Improved {@link org.apache.juneau.rest.widget.QueryMenuItem} widget that provides a pull-down menu + of a search/view/order-by/page form: + <br><img src='doc-files/ReleaseNotes_631_QueryMenuItem.png'> + <br>Fields are now pre-filled with current query parameters. + </ul> + <li> + New/modified annotations on {@link org.apache.juneau.rest.annotation.HtmlDoc @HtmlDoc}: + <ul> + <li>{@link org.apache.juneau.rest.annotation.HtmlDoc#style() style()} - Renamed from <code>css()</code>. + <li>{@link org.apache.juneau.rest.annotation.HtmlDoc#styleImport() styleImport()} - Renamed from <code>cssUrl()</code>. + <br>Can now be a comma-delimited list of URLs. + <li>{@link org.apache.juneau.rest.annotation.HtmlDoc#script() script()} - Add arbitrary Javascript to page header. + </ul> + <li> Bug fix with {@link org.apache.juneau.rest.annotation.HtmlDoc#nowrap()} so that the setting only applies to the data contents, not the whole page. @@ -6863,9 +6902,20 @@ </ul> </li> <li> + Eliminated the <code>@RestResource.stylesheet()</code> annotation. + It's no longer needed now that you can easily specify styles via <ja>@Htmldoc</ja>. + <li> {@link org.apache.juneau.rest.annotation.HtmlDoc#title()} and {@link org.apache.juneau.rest.annotation.HtmlDoc#description()} can now take HTML (phrasing content only since it's still inside H3 and H5 tags). </ul> + + <h6 class='topic'>org.apache.juneau.rest.examples</h6> + <ul class='spaced-list'> + <li> + Added CONTENT-TYPE menu items to most pages. + <li> + Added improved QUERY menu items to PetStore page. + </ul> </div> <!-- ======================================================================================================== --> @@ -7013,8 +7063,8 @@ <li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_aside} <li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_footer} <li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_noResultsMessage} - <li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_cssUrl} - <li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_css} + <li><code><del>HtmlDocSerializerContext.HTMLDOC_cssUrl</del></code> + <li><code><del>HtmlDocSerializerContext.HTMLDOC_css</del></code> <li>{@link org.apache.juneau.html.HtmlDocSerializerContext#HTMLDOC_template} </ul> <li>New interface {@link org.apache.juneau.html.HtmlDocTemplate} that allows full control over rendering @@ -7195,8 +7245,8 @@ <li>{@link org.apache.juneau.rest.RestConfig#setHtmlNav(String) setHtmlNav(String)} <li>{@link org.apache.juneau.rest.RestConfig#setHtmlAside(String) setHtmlAside(String)} <li>{@link org.apache.juneau.rest.RestConfig#setHtmlFooter(String) setHtmlFooter(String)} - <li>{@link org.apache.juneau.rest.RestConfig#setHtmlCss(String) setHtmlCss(String)} - <li>{@link org.apache.juneau.rest.RestConfig#setHtmlCssUrl(String) setHtmlCssUrl(String)} + <li><code><del>setHtmlCss(String)</del></code> + <li><code><del>setHtmlCssUrl(String)</del></code> <li>{@link org.apache.juneau.rest.RestConfig#setHtmlNoWrap(boolean) setHtmlNoWrap(boolean)} <li>{@link org.apache.juneau.rest.RestConfig#setHtmlNoResultsMessage(String) setHtmlNoResultsMessage(String)} <li>{@link org.apache.juneau.rest.RestConfig#setHtmlTemplate(Class) setHtmlTemplate(Class)} @@ -7214,8 +7264,8 @@ <li>{@link org.apache.juneau.rest.RestResponse#setHtmlNav(Object) setHtmlNav(Object)} <li>{@link org.apache.juneau.rest.RestResponse#setHtmlAside(Object) setHtmlAside(Object)} <li>{@link org.apache.juneau.rest.RestResponse#setHtmlFooter(Object) setHtmlFooter(Object)} - <li>{@link org.apache.juneau.rest.RestResponse#setHtmlCss(Object) setHtmlCss(Object)} - <li>{@link org.apache.juneau.rest.RestResponse#setHtmlCssUrl(Object) setHtmlCssUrl(Object)} + <li><code><del>setHtmlCss(Object)</del></code> + <li><code><del>setHtmlCssUrl(Object)</del></code> <li>{@link org.apache.juneau.rest.RestResponse#setHtmlNoWrap(boolean) setHtmlNoWrap(boolean)} <li>{@link org.apache.juneau.rest.RestResponse#setHtmlNoResultsMessage(Object) setHtmlNoResultsMessage(Object)} <li>{@link org.apache.juneau.rest.RestResponse#setHtmlTemplate(Class) setHtmlTemplate(Class)} @@ -7228,9 +7278,9 @@ <ul> <li>{@link org.apache.juneau.rest.widget.Widget} <li>{@link org.apache.juneau.rest.widget.PoweredByJuneauWidget} - <li>{@link org.apache.juneau.rest.widget.ContentTypeLinksColumnWidget} - <li>{@link org.apache.juneau.rest.widget.ContentTypeLinksRowWidget} - <li>{@link org.apache.juneau.rest.widget.QueryWidget} + <li><code><del>ContentTypeLinksColumnWidget</del></code> + <li><code><del>ContentTypeLinksRowWidget</del></code> + <li><code><del>QueryWidget</del></code> </ul> <li> <code>devops.css</code> cleaned up. @@ -7460,7 +7510,7 @@ pageLinks=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS'}"</js> ) </p> - <li>{@link org.apache.juneau.rest.annotation.RestResource#stylesheet()} can now take in a comma-delimited list of stylesheet paths. + <li><code><del>RestResource.stylesheet()</del></code> can now take in a comma-delimited list of stylesheet paths. <li>{@link org.apache.juneau.rest.StreamResource} can now contain multiple sources from a variety of source types (e.g. <code><jk>byte</jk>[]</code> arrays, <code>InputStreams</code>, <code>Files</code>, etc...) and is now immutable. It also includes a new {@link org.apache.juneau.rest.StreamResource.Builder} class. <li>Simplified remoteable proxies using the <code><ja>@RestMethod</ja>(name=<js>"PROXY"</js>)</code> annotation on REST methods. @@ -8409,7 +8459,7 @@ <li>Removed <code>RestServletProperties.REST_htDocsFolder</code>. Replaced with {@link org.apache.juneau.rest.annotation.RestResource#staticFiles()}. <li>New annotations on {@link org.apache.juneau.rest.annotation.RestResource}. <ul> - <li>{@link org.apache.juneau.rest.annotation.RestResource#stylesheet()} + <li><code><del>RestResource.stylesheet()</del></code> <li>{@link org.apache.juneau.rest.annotation.RestResource#favicon()} <li>{@link org.apache.juneau.rest.annotation.RestResource#staticFiles()} </ul> http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java index 9da4e94..ad72535 100644 --- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/AtomFeedResource.java @@ -32,23 +32,17 @@ import org.apache.juneau.rest.widget.*; path="/atom", title="Sample ATOM feed resource", description="Sample resource that shows how to render ATOM feeds", + widgets={ + ContentTypeMenuItem.class + }, htmldoc=@HtmlDoc( - links="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/AtomFeedResource.java'}", - aside="" - + "<div style='min-width:200px' class='text'>" - + " <p>Shows how to produce ATOM feeds in a variety of languages.</p>" - + " <p>$W{contentTypeLinksRow}</p>" - + "</div>", - css="aside {display:table-caption;}" + links="{up:'request:/..',options:'servlet:/?method=OPTIONS',contentTypes:'$W{contentTypeMenuItem}',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/AtomFeedResource.java'}" ), properties={ @Property(name=SERIALIZER_quoteChar, value="'"), @Property(name=RDF_rdfxml_tab, value="5"), @Property(name=RDF_addRootProperty, value="true") }, - widgets={ - ContentTypeLinksRowWidget.class - }, encoders=GzipEncoder.class ) public class AtomFeedResource extends ResourceJena { http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/CodeFormatterResource.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/CodeFormatterResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/CodeFormatterResource.java index ed66794..a409c24 100644 --- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/CodeFormatterResource.java +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/CodeFormatterResource.java @@ -35,7 +35,7 @@ import org.apache.juneau.rest.annotation.*; + " <p>Utility for adding code syntax tags to Java and XML/HTML code.</p>" + " <p>It's by no means perfect, but provides a good starting point.</p>" + "</div>", - css="aside {display:table-caption;}" + style="aside {display:table-caption;}" ) ) @SuppressWarnings({"serial"}) http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java index 4147570..86b8101 100644 --- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/DirectoryResource.java @@ -28,6 +28,7 @@ import org.apache.juneau.rest.*; import org.apache.juneau.rest.annotation.*; import org.apache.juneau.rest.annotation.Properties; import org.apache.juneau.rest.converters.*; +import org.apache.juneau.rest.widget.*; import org.apache.juneau.utils.*; /** @@ -35,8 +36,11 @@ import org.apache.juneau.utils.*; */ @RestResource( messages="nls/DirectoryResource", + widgets={ + ContentTypeMenuItem.class + }, htmldoc=@HtmlDoc( - links="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/DirectoryResource.java'}" + links="{up:'request:/..',options:'servlet:/?method=OPTIONS',contentTypes:'$W{contentTypeMenuItem}',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/DirectoryResource.java'}" ), properties={ @Property(name=HTML_uriAnchorText, value=PROPERTY_NAME), http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/FileSpaceResource.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/FileSpaceResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/FileSpaceResource.java deleted file mode 100644 index e985f72..0000000 --- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/FileSpaceResource.java +++ /dev/null @@ -1,155 +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 org.apache.juneau.dto.html5.HtmlBuilder.*; - -import javax.servlet.http.*; - -import org.apache.juneau.*; -import org.apache.juneau.annotation.*; -import org.apache.juneau.html.*; -import org.apache.juneau.html.annotation.*; -import org.apache.juneau.microservice.*; -import org.apache.juneau.rest.*; -import org.apache.juneau.rest.annotation.*; -import org.apache.juneau.serializer.*; - -/** - * Sample REST resource that shows how to use the HtmlRender class. - */ -@RestResource( - path="/fileSpace", - title="Available file space resource", - description="Shows how to use HtmlRender class to customize HTML output.", - htmldoc=@HtmlDoc( - links="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/EnhancedHtmlResource.java'}", - aside="" - + "<div style='min-width:200px' class='text'>" - + " <p>Shows how you can use <code>HtmlRender</code> class to customize the output generated by the HTML serializer.</p>" - + "</div>" - ) -) -public class FileSpaceResource extends Resource { - private static final long serialVersionUID = 1L; - - private static final FileSpace[] fileSpaces = { - new FileSpace("C:", 1000000000, 775000000), - new FileSpace("D:", 100000000, 87500000), - new FileSpace("E:", 100000000, 97500000), - new FileSpace("F:", 100000000, 5000000) - }; - - /** - * Our bean class being serialized. - * Properties are listed to ensure order across all JVMs. - */ - @Bean(properties="drive,total,available,pctFull,status") - public static class FileSpace { - - private final String drive; - private final long total, available; - - public FileSpace(String drive, long total, long available) { - this.drive = drive; - this.total = total; - this.available = available; - } - - @Html(link="servlet:/{drive}") - public String getDrive() { - return drive; - } - - public long getTotal() { - return total; - } - - public long getAvailable() { - return available; - } - - @Html(render=FileSpacePctRender.class) - public float getPctFull() { - return ((100 * available) / total); - } - - @Html(render=FileSpaceStatusRender.class) - public FileSpaceStatus getStatus() { - float pf = getPctFull(); - if (pf < 80) - return FileSpaceStatus.OK; - if (pf < 90) - return FileSpaceStatus.WARNING; - return FileSpaceStatus.SEVERE; - } - } - - public static enum FileSpaceStatus { - OK, WARNING, SEVERE; - } - - public static class FileSpacePctRender extends HtmlRender<Float> { - - @Override - public String getStyle(SerializerSession session, Float value) { - if (value < 80) - return "background-color:lightgreen;text-align:center"; - if (value < 90) - return "background-color:yellow;text-align:center"; - return "background-color:red;text-align:center;border:;animation:color_change 0.5s infinite alternate"; - } - - @Override - public Object getContent(SerializerSession session, Float value) { - if (value >= 90) - return div( - String.format("%.0f%%", value), - style("@keyframes color_change { from { background-color: red; } to { background-color: yellow; }") - ); - return String.format("%.0f%%", value); - } - } - - public static class FileSpaceStatusRender extends HtmlRender<FileSpaceStatus> { - - @Override - public String getStyle(SerializerSession session, FileSpaceStatus value) { - return "text-align:center"; - } - - @Override - public Object getContent(SerializerSession session, FileSpaceStatus value) { - UriResolver r = session.getUriResolver(); - switch (value) { - case OK: return img().src(r.resolve("servlet:/htdocs/ok.png")); - case WARNING: return img().src(r.resolve("servlet:/htdocs/warning.png")); - default: return img().src(r.resolve("servlet:/htdocs/severe.png")); - } - } - } - - /** GET request handler */ - @RestMethod(name="GET", path="/") - public FileSpace[] getFileSpaceMetrics() { - return fileSpaces; - } - - @RestMethod(name="GET", path="{drive}") - public FileSpace getFileSpaceMetric(String drive) throws RestException { - for (FileSpace fc : fileSpaces) - if (fc.drive.equals(drive)) - return fc; - throw new RestException(HttpServletResponse.SC_NOT_FOUND, "Drive not found."); - } -} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/JsonSchemaResource.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/JsonSchemaResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/JsonSchemaResource.java index ad8d26f..62e7d5b 100644 --- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/JsonSchemaResource.java +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/JsonSchemaResource.java @@ -25,17 +25,16 @@ import org.apache.juneau.rest.widget.*; messages="nls/JsonSchemaResource", title="Sample JSON-Schema document", description="Sample resource that shows how to generate JSON-Schema documents", + widgets={ + ContentTypeMenuItem.class + }, htmldoc=@HtmlDoc( - links="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/JsonSchemaResource.java'}", + links="{up:'request:/..',options:'servlet:/?method=OPTIONS',contentTypes:'$W{contentTypeMenuItem}',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/JsonSchemaResource.java'}", aside="" + "<div style='min-width:200px' class='text'>" + " <p>Shows how to produce JSON-Schema documents in a variety of languages using the JSON-Schema DTOs.</p>" - + " <p>$W{contentTypeLinksColumn}</p>" + "</div>" - ), - widgets={ - ContentTypeLinksColumnWidget.class - } + ) ) public class JsonSchemaResource extends ResourceJena { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java index 9702326..febc781 100644 --- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/PetStoreResource.java @@ -36,10 +36,10 @@ import org.apache.juneau.transforms.*; description="An example of a typical REST resource where beans are rendered in summary and details views.", path="/petstore", widgets={ - QueryWidget.class + ContentTypeMenuItem.class }, htmldoc=@HtmlDoc( - links="{up:'request:/..',options:'servlet:/?method=OPTIONS',query:'$W{query}',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/PetStoreResource.java'}", + links="{up:'request:/..',options:'servlet:/?method=OPTIONS',contentTypes:'$W{contentTypeMenuItem}',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/PetStoreResource.java'}", aside="" + "<div style='max-width:400px' class='text'>" + " <p>This page shows a standard REST resource that renders bean summaries and details.</p>" @@ -68,6 +68,14 @@ public class PetStoreResource extends Resource { path="/", summary="The complete list of pets in the store", bpExcludes="{Pet:'breed,getsAlongWith'}", + + // Add a 'query' menu item and queryable support. + widgets={ + QueryMenuItem.class, + }, + htmldoc=@HtmlDoc( + links="{up:'request:/..',options:'servlet:/?method=OPTIONS',query:'$W{queryMenuItem}',contentTypes:'$W{contentTypeMenuItem}',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/PetStoreResource.java'}" + ), converters=Queryable.class ) public Collection<Pet> getPets() { http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java index e17458a..2df7a68 100644 --- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java @@ -22,6 +22,7 @@ import org.apache.juneau.microservice.*; import org.apache.juneau.rest.*; import org.apache.juneau.rest.annotation.*; import org.apache.juneau.rest.converters.*; +import org.apache.juneau.rest.widget.*; import org.apache.juneau.transforms.*; /** @@ -31,8 +32,11 @@ import org.apache.juneau.transforms.*; path="/echo", title="Request echo service", description="Echos the current HttpServletRequest object back to the browser.", + widgets={ + ContentTypeMenuItem.class + }, htmldoc=@HtmlDoc( - links="{up:'request:/..',options:'servlet:/?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/RequestEchoResource.java'}", + links="{up:'request:/..',options:'servlet:/?method=OPTIONS',contentTypes:'$W{contentTypeMenuItem}',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/RequestEchoResource.java'}", aside="" + "<div style='max-width:400px;min-width:200px' class='text'>" + " <p>Shows how even arbitrary POJOs such as <code>HttpServletRequest</code> can be serialized by the framework.</p>" http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java index d829209..710368b 100644 --- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java @@ -25,23 +25,23 @@ import org.apache.juneau.rest.widget.*; path="/", title="Root resources", description="Example of a router resource page.", + widgets={ + PoweredByApacheWidget.class, + ContentTypeMenuItem.class + }, htmldoc=@HtmlDoc( - links="{options:'?method=OPTIONS',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/RootResources.java'}", + links="{options:'?method=OPTIONS',contentTypes:'$W{contentTypeMenuItem}',source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/RootResources.java'}", aside="" + "<div style='max-width:400px' class='text'>" + " <p>This is an example of a 'router' page that serves as a jumping-off point to child resources.</p>" + " <p>Resources can be nested arbitrarily deep through router pages.</p>" + " <p>Note the <span class='link'>OPTIONS</span> link provided that lets you see the generated swagger doc for this page.</p>" + " <p>Also note the <span class='link'>SOURCE</span> link on these pages to view the source code for the page.</p>" - + " <p>All content on pages in the UI are serialized POJOs. In this case, it's a serialized array of beans with 2 properties.</p>" + + " <p>All content on pages in the UI are serialized POJOs. In this case, it's a serialized array of beans with 2 properties, 'name' and 'description'.</p>" + " <p>Other features (such as this aside) are added through annotations.</p>" + "</div>", footer="$W{poweredByApache}" ), - widgets={ - PoweredByJuneauWidget.class, - PoweredByApacheWidget.class - }, children={ HelloWorldResource.class, PetStoreResource.class, @@ -61,10 +61,9 @@ import org.apache.juneau.rest.widget.*; ConfigResource.class, LogsResource.class, DockerRegistryResource.class, - FileSpaceResource.class, ShutdownResource.class } ) -public class RootResources extends ResourceGroup { +public class RootResources extends ResourceJenaGroup { private static final long serialVersionUID = 1L; } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ada4053b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRemoteableServlet.java ---------------------------------------------------------------------- diff --git a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRemoteableServlet.java b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRemoteableServlet.java index 9451692..e973893 100644 --- a/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRemoteableServlet.java +++ b/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SampleRemoteableServlet.java @@ -43,8 +43,7 @@ import org.apache.juneau.rest.remoteable.*; // Allow us to use method=POST from a browser. @Property(name=REST_allowMethodParam, value="*") }, - config="$S{juneau.configFile}", // So we can resolve $C{Source/gitHub} above. - stylesheet="styles/devops.css" + config="$S{juneau.configFile}" // So we can resolve $C{Source/gitHub} above. ) public class SampleRemoteableServlet extends RemoteableServlet {
