org.apache.juneau.rest.widget.Widget Maven / Gradle / Ivy
// ***************************************************************************************************************************
// * 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.rest.widget;
import java.io.*;
import java.util.*;
import org.apache.juneau.rest.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.utils.*;
/**
* Defines an interface for resolvers of "$W{...}" string variables.
*
*
* Widgets are associated with resources through the following
*
* - {@link HtmlDoc#widgets() @HtmlDoc.widgets}
*
- {@link RestConfig#addWidget(Class)}
*
*
*
* Widgets allow you to add arbitrary HTML, CSS, and Javascript to the page.
*
*
* The HTML content returned by the {@link #getHtml(RestRequest)} method is added where the "$W{...}" is
* referenced in the page.
* The Javascript and stylesheet content is added to the header of the page.
* They allow you to control the look and behavior of your widgets.
*
*
* The following examples shows how to associate a widget with a REST method and then have it rendered in the links
* and aside section of the page:
*
*
* @RestMethod (
* widgets={
* MyWidget.class
* }
* htmldoc=@HtmlDoc (
* navlinks={
* "$W{MyWidget}"
* },
* aside={
* "Check out this widget: $W{MyWidget}"
* }
* )
* )
*
*
*
* The following shows an example of a widget that renders an image located in the htdocs
static files
* directory in your classpath (see {@link RestResource#staticFiles()}):
*
* public class MyWidget extends Widget {
*
* @Override
* public String getHtml(RestRequest req) throws Exception {
* UriResolver r = req.getUriResolver();
* return "<img class='myimage' onclick='myalert(this)' src='" +r.resolve("servlet:/htdocs/myimage.png" )+"'>" ;
* }
*
* @Override
* public String getScript(RestRequest req) throws Exception {
* return ""
* + "\n function myalert(imageElement) {"
* + "\n alert('cool!');"
* + "\n }" ;
* }
*
* @Override
* public String getStyle(RestRequest req) throws Exception {
* return ""
* + "\n .myimage {"
* + "\n border: 10px solid red;"
* + "\n }" ;
* }
* }
*
*
*
* Note the {@link #getResourceAsString(String)} and {@link #getResourceAsString(String, Locale)} convenience methods
* provided for quickly loading javascript and css files from the classpath or file system.
* These are useful if your script or styles are complex and you want them loaded from files.
*
*
*
* public class MyWidget extends Widget {
*
* ...
*
* @Override
* public String getScript(RestRequest req) throws Exception {
* return getResourceAsString("MyWidget.js" );
* }
*
* @Override
* public String getStyle(RestRequest req) throws Exception {
* return getResourceAsString("MyWidget.css" );
* }
* }
*
*/
public abstract class Widget {
private final ResourceFinder resourceFinder = new ResourceFinder(getClass());
/**
* The widget key.
*
*
* (i.e. The variable name inside the "$W{...}" variable).
*
*
* The returned value must not be null .
*
*
* If not overridden, the default value is the class simple name.
*
* @return The widget key.
*/
public String getName() {
return getClass().getSimpleName();
}
/**
* Resolves the HTML content for this widget.
*
*
* A returned value of null will cause nothing to be added to the page.
*
* @param req The HTTP request object.
* @return The HTML content of this widget.
* @throws Exception
*/
public String getHtml(RestRequest req) throws Exception {
return null;
}
/**
* Resolves any Javascript that should be added to the <head>/<script> element.
*
*
* A returned value of null will cause nothing to be added to the page.
*
* @param req The HTTP request object.
* @return The Javascript needed by this widget.
* @throws Exception
*/
public String getScript(RestRequest req) throws Exception {
return null;
}
/**
* Resolves any CSS styles that should be added to the <head>/<style> element.
*
*
* A returned value of null will cause nothing to be added to the page.
*
* @param req The HTTP request object.
* @return The CSS styles needed by this widget.
* @throws Exception
*/
public String getStyle(RestRequest req) throws Exception {
return null;
}
/**
* Retrieves the specified classpath resource and returns the contents as a string.
*
*
* Same as {@link Class#getResourceAsStream(String)} except if it doesn't find the resource on this class, searches
* up the parent hierarchy chain.
*
*
* If the resource cannot be found in the classpath, then an attempt is made to look relative to the JVM working directory.
*
Path traversals outside the working directory are not allowed for security reasons.
*
* @param name Name of the desired resource.
* @return The resource converted to a string, or null if the resource could not be found.
* @throws IOException
*/
protected String getResourceAsString(String name) throws IOException {
return resourceFinder.getResourceAsString(name);
}
/**
* Same as {@link #getResourceAsString(String)} except also looks for localized-versions of the file.
*
*
* If the locale
is specified, then we look for resources whose name matches that locale.
*
For example, if looking for the resource "MyResource.txt" for the Japanese locale, we will look for
* files in the following order:
*
* "MyResource_ja_JP.txt"
* "MyResource_ja.txt"
* "MyResource.txt"
*
*
*
* @param name Name of the desired resource.
* @param locale The locale. Can be null .
* @return The resource converted to a string, or null if the resource could not be found.
* @throws IOException
*/
protected String getResourceAsString(String name, Locale locale) throws IOException {
return resourceFinder.getResourceAsString(name, locale);
}
/**
* Convenience method for calling {@link #getResourceAsString(String)} except also strips Javascript comments from
* the file.
*
*
* Comments are assumed to be Java-style block comments: "/*" .
*
* @param name Name of the desired resource.
* @return The resource converted to a string, or null if the resource could not be found.
* @throws IOException
*/
protected String loadScript(String name) throws IOException {
String s = getResourceAsString(name);
if (s != null)
s = s.replaceAll("(?s)\\/\\*(.*?)\\*\\/\\s*", "");
return s;
}
/**
* Convenience method for calling {@link #getResourceAsString(String)} except also strips CSS comments from
* the file.
*
*
* Comments are assumed to be Java-style block comments: "/*" .
*
* @param name Name of the desired resource.
* @return The resource converted to a string, or null if the resource could not be found.
* @throws IOException
*/
protected String loadStyle(String name) throws IOException {
String s = getResourceAsString(name);
if (s != null)
s = s.replaceAll("(?s)\\/\\*(.*?)\\*\\/\\s*", "");
return s;
}
/**
* Convenience method for calling {@link #getResourceAsString(String)} except also strips HTML comments from the
* file.
*
*
* Comment are assumed to be "" code blocks.
*
* @param name Name of the desired resource.
* @return The resource converted to a string, or null if the resource could not be found.
* @throws IOException
*/
protected String loadHtml(String name) throws IOException {
String s = getResourceAsString(name);
if (s != null)
s = s.replaceAll("(?s)\\s*", "");
return s;
}
}