001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.rest.widget; 014 015import java.io.*; 016import java.util.*; 017 018import org.apache.juneau.rest.*; 019import org.apache.juneau.utils.*; 020 021/** 022 * Defines an interface for resolvers of <js>"$W{...}"</js> string variables. 023 * 024 * <p> 025 * Widgets must provide one of the following public constructors: 026 * <ul> 027 * <li><code><jk>public</jk> Widget();</code> 028 * <li><code><jk>public</jk> Widget(PropertyStore);</code> 029 * </ul> 030 * 031 * <p> 032 * Widgets can be defined as inner classes of REST resource classes. 033 * 034 * <h5 class='section'>See Also:</h5> 035 * <ul> 036 * <li class='link'>{@doc juneau-rest-server.HtmlDocAnnotation.Widgets} 037 * </ul> 038 */ 039public abstract class Widget { 040 041 private final ClasspathResourceManager rm = new ClasspathResourceManager(getClass(), ClasspathResourceFinderRecursive.INSTANCE, false); 042 043 /** 044 * The widget key. 045 * 046 * <p> 047 * (i.e. The variable name inside the <js>"$W{...}"</js> variable). 048 * 049 * <p> 050 * The returned value must not be <jk>null</jk>. 051 * 052 * <p> 053 * If not overridden, the default value is the class simple name. 054 * 055 * @return The widget key. 056 */ 057 public String getName() { 058 return getClass().getSimpleName(); 059 } 060 061 /** 062 * Resolves the HTML content for this widget. 063 * 064 * <p> 065 * A returned value of <jk>null</jk> will cause nothing to be added to the page. 066 * 067 * @param req The HTTP request object. 068 * @return The HTML content of this widget. 069 * @throws Exception 070 */ 071 public String getHtml(RestRequest req) throws Exception { 072 return null; 073 } 074 075 /** 076 * Resolves any Javascript that should be added to the <xt><head>/<script></xt> element. 077 * 078 * <p> 079 * A returned value of <jk>null</jk> will cause nothing to be added to the page. 080 * 081 * @param req The HTTP request object. 082 * @return The Javascript needed by this widget. 083 * @throws Exception 084 */ 085 public String getScript(RestRequest req) throws Exception { 086 return null; 087 } 088 089 /** 090 * Resolves any CSS styles that should be added to the <xt><head>/<style></xt> element. 091 * 092 * <p> 093 * A returned value of <jk>null</jk> will cause nothing to be added to the page. 094 * 095 * @param req The HTTP request object. 096 * @return The CSS styles needed by this widget. 097 * @throws Exception 098 */ 099 public String getStyle(RestRequest req) throws Exception { 100 return null; 101 } 102 103 /** 104 * Retrieves the specified classpath resource and returns the contents as a string. 105 * 106 * <p> 107 * Same as {@link Class#getResourceAsStream(String)} except if it doesn't find the resource on this class, searches 108 * up the parent hierarchy chain. 109 * 110 * <p> 111 * If the resource cannot be found in the classpath, then an attempt is made to look relative to the JVM working directory. 112 * <br>Path traversals outside the working directory are not allowed for security reasons. 113 * 114 * @param name Name of the desired resource. 115 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 116 * @throws IOException 117 */ 118 protected String getClasspathResourceAsString(String name) throws IOException { 119 return rm.getString(name); 120 } 121 122 /** 123 * Same as {@link #getClasspathResourceAsString(String)} except also looks for localized-versions of the file. 124 * 125 * <p> 126 * If the <code>locale</code> is specified, then we look for resources whose name matches that locale. 127 * <br>For example, if looking for the resource <js>"MyResource.txt"</js> for the Japanese locale, we will look for 128 * files in the following order: 129 * <ol> 130 * <li><js>"MyResource_ja_JP.txt"</js> 131 * <li><js>"MyResource_ja.txt"</js> 132 * <li><js>"MyResource.txt"</js> 133 * </ol> 134 * 135 * @param name Name of the desired resource. 136 * @param locale The locale. Can be <jk>null</jk>. 137 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 138 * @throws IOException 139 */ 140 protected String getClasspathResourceAsString(String name, Locale locale) throws IOException { 141 return rm.getString(name, locale); 142 } 143 144 /** 145 * Convenience method for calling {@link #getClasspathResourceAsString(String)} except also strips Javascript comments from 146 * the file. 147 * 148 * <p> 149 * Comments are assumed to be Java-style block comments: <js>"/*"</js>. 150 * 151 * @param name Name of the desired resource. 152 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 153 * @throws IOException 154 */ 155 protected String loadScript(String name) throws IOException { 156 String s = getClasspathResourceAsString(name); 157 if (s != null) 158 s = s.replaceAll("(?s)\\/\\*(.*?)\\*\\/\\s*", ""); 159 return s; 160 } 161 162 /** 163 * Same as {@link #loadScript(String)} but replaces request-time SVL variables. 164 * 165 * <h5 class='section'>See Also:</h5> 166 * <ul> 167 * <li class='jm'>{@link org.apache.juneau.rest.RestContext#getVarResolver()} 168 * <li class='link'>{@doc juneau-rest-server.SvlVariables} 169 * </ul> 170 * 171 * @param req The current HTTP request. 172 * @param name Name of the desired resource. 173 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 174 * @throws IOException 175 */ 176 protected String loadScriptWithVars(RestRequest req, String name) throws IOException { 177 return req.getVarResolverSession().resolve(loadScript(name)); 178 } 179 180 /** 181 * Convenience method for calling {@link #getClasspathResourceAsString(String)} except also strips CSS comments from 182 * the file. 183 * 184 * <p> 185 * Comments are assumed to be Java-style block comments: <js>"/*"</js>. 186 * 187 * @param name Name of the desired resource. 188 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 189 * @throws IOException 190 */ 191 protected String loadStyle(String name) throws IOException { 192 String s = getClasspathResourceAsString(name); 193 if (s != null) 194 s = s.replaceAll("(?s)\\/\\*(.*?)\\*\\/\\s*", ""); 195 return s; 196 } 197 198 /** 199 * Same as {@link #loadStyle(String)} but replaces request-time SVL variables. 200 * 201 * <h5 class='section'>See Also:</h5> 202 * <ul> 203 * <li class='jm'>{@link org.apache.juneau.rest.RestContext#getVarResolver()} 204 * <li class='link'>{@doc juneau-rest-server.SvlVariables} 205 * </ul> 206 * 207 * @param req The current HTTP request. 208 * @param name Name of the desired resource. 209 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 210 * @throws IOException 211 */ 212 protected String loadStyleWithVars(RestRequest req, String name) throws IOException { 213 return req.getVarResolverSession().resolve(loadStyle(name)); 214 } 215 216 /** 217 * Convenience method for calling {@link #getClasspathResourceAsString(String)} except also strips HTML comments from the 218 * file. 219 * 220 * <p> 221 * Comment are assumed to be <js>"<!-- -->"</js> code blocks. 222 * 223 * @param name Name of the desired resource. 224 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 225 * @throws IOException 226 */ 227 protected String loadHtml(String name) throws IOException { 228 String s = getClasspathResourceAsString(name); 229 if (s != null) 230 s = s.replaceAll("(?s)<!--(.*?)-->\\s*", ""); 231 return s; 232 } 233 234 /** 235 * Same as {@link #loadHtml(String)} but replaces request-time SVL variables. 236 * 237 * <h5 class='section'>See Also:</h5> 238 * <ul> 239 * <li class='jm'>{@link org.apache.juneau.rest.RestContext#getVarResolver()} 240 * <li class='link'>{@doc juneau-rest-server.SvlVariables} 241 * </ul> 242 * 243 * @param req The current HTTP request. 244 * @param name Name of the desired resource. 245 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 246 * @throws IOException 247 */ 248 protected String loadHtmlWithVars(RestRequest req, String name) throws IOException { 249 return req.getVarResolverSession().resolve(loadHtml(name)); 250 } 251}