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 static org.apache.juneau.common.internal.ThrowableUtils.*; 016 017import java.io.*; 018 019import org.apache.juneau.rest.*; 020import org.apache.juneau.svl.*; 021import org.apache.juneau.cp.*; 022import org.apache.juneau.html.*; 023import org.apache.juneau.http.response.*; 024 025/** 026 * Defines an interface for resolvers of <js>"$W{...}"</js> string variables. 027 * 028 * <p> 029 * Widgets must provide one of the following public constructors: 030 * <ul> 031 * <li><code><jk>public</jk> Widget();</code> 032 * <li><code><jk>public</jk> Widget(ContextProperties);</code> 033 * </ul> 034 * 035 * <p> 036 * Widgets can be defined as inner classes of REST resource classes. 037 * 038 * <h5 class='section'>See Also:</h5><ul> 039 * <li class='link'><a class="doclink" href="../../../../../index.html#jrs.HtmlPredefinedWidgets">Predefined Widgets</a> 040 * <li class='link'><a class="doclink" href="../../../../../index.html#jrs.HtmlWidgets">Widgets</a> 041 * </ul> 042 */ 043public abstract class Widget implements HtmlWidget { 044 045 /** 046 * The widget key. 047 * 048 * <p> 049 * (i.e. The variable name inside the <js>"$W{...}"</js> variable). 050 * 051 * <p> 052 * The returned value must not be <jk>null</jk>. 053 * 054 * <p> 055 * If not overridden, the default value is the class simple name. 056 * 057 * @return The widget key. 058 */ 059 @Override 060 public String getName() { 061 return getClass().getSimpleName(); 062 } 063 064 private RestRequest req(VarResolverSession session) { 065 return session.getBean(RestRequest.class).orElseThrow(InternalServerError::new); 066 } 067 068 private RestResponse res(VarResolverSession session) { 069 return session.getBean(RestResponse.class).orElseThrow(InternalServerError::new); 070 } 071 072 @Override /* HtmlWidget */ 073 public String getHtml(VarResolverSession session) { 074 return getHtml(req(session), res(session)); 075 } 076 077 @Override /* HtmlWidget */ 078 public String getScript(VarResolverSession session) { 079 return getScript(req(session), res(session)); 080 } 081 082 @Override /* HtmlWidget */ 083 public String getStyle(VarResolverSession session) { 084 return getStyle(req(session), res(session)); 085 } 086 087 /** 088 * Resolves the HTML content for this widget. 089 * 090 * <p> 091 * A returned value of <jk>null</jk> will cause nothing to be added to the page. 092 * 093 * @param req The HTTP request object. 094 * @param res The current HTTP response. 095 * @return The HTML content of this widget. 096 */ 097 public String getHtml(RestRequest req, RestResponse res) { 098 return null; 099 } 100 101 /** 102 * Resolves any Javascript that should be added to the <xt><head>/<script></xt> element. 103 * 104 * <p> 105 * A returned value of <jk>null</jk> will cause nothing to be added to the page. 106 * 107 * @param req The HTTP request object. 108 * @param res The current HTTP response. 109 * @return The Javascript needed by this widget. 110 */ 111 public String getScript(RestRequest req, RestResponse res) { 112 return null; 113 } 114 115 /** 116 * Resolves any CSS styles that should be added to the <xt><head>/<style></xt> element. 117 * 118 * <p> 119 * A returned value of <jk>null</jk> will cause nothing to be added to the page. 120 * 121 * @param req The HTTP request object. 122 * @param res The current HTTP response. 123 * @return The CSS styles needed by this widget. 124 */ 125 public String getStyle(RestRequest req, RestResponse res) { 126 return null; 127 } 128 129 /** 130 * Returns the file finder to use for finding files on the file system. 131 * 132 * @param req The HTTP request object. 133 * @return The file finder to used for finding files on the file system. 134 */ 135 protected FileFinder getFileFinder(RestRequest req) { 136 return req.getStaticFiles(); 137 } 138 139 /** 140 * Loads the specified javascript file and strips any Javascript comments from the file. 141 * 142 * <p> 143 * Comments are assumed to be Java-style block comments: <js>"/*"</js>. 144 * 145 * @param req The HTTP request object. 146 * @param name Name of the desired resource. 147 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 148 */ 149 protected String loadScript(RestRequest req, String name) { 150 try { 151 String s = getFileFinder(req).getString(name, null).orElse(null); 152 if (s != null) 153 s = s.replaceAll("(?s)\\/\\*(.*?)\\*\\/\\s*", ""); 154 return s; 155 } catch (IOException e) { 156 throw new RuntimeException(e); 157 } 158 } 159 160 /** 161 * Same as {@link #loadScript(RestRequest,String)} but replaces request-time SVL variables. 162 * 163 * <h5 class='section'>See Also:</h5><ul> 164 * <li class='jm'>{@link org.apache.juneau.rest.RestContext#getVarResolver()} 165 * <li class='link'><a class="doclink" href="../../../../../index.html#jm.SvlVariables">SVL Variables</a> 166 * </ul> 167 * 168 * @param req The current HTTP request. 169 * @param res The current HTTP response. 170 * @param name Name of the desired resource. 171 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 172 * @throws IOException Thrown by underlying stream. 173 */ 174 protected String loadScriptWithVars(RestRequest req, RestResponse res, String name) throws IOException { 175 return req.getVarResolverSession().resolve(loadScript(req, name)); 176 } 177 178 /** 179 * Loads the specified CSS file and strips CSS comments from the file. 180 * 181 * <p> 182 * Comments are assumed to be Java-style block comments: <js>"/*"</js>. 183 * 184 * @param req The HTTP request object. 185 * @param name Name of the desired resource. 186 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 187 */ 188 protected String loadStyle(RestRequest req, String name) { 189 try { 190 String s = getFileFinder(req).getString(name, null).orElse(null); 191 if (s != null) 192 s = s.replaceAll("(?s)\\/\\*(.*?)\\*\\/\\s*", ""); 193 return s; 194 } catch (IOException e) { 195 throw asRuntimeException(e); 196 } 197 } 198 199 /** 200 * Same as {@link #loadStyle(RestRequest,String)} but replaces request-time SVL variables. 201 * 202 * <h5 class='section'>See Also:</h5><ul> 203 * <li class='jm'>{@link org.apache.juneau.rest.RestContext#getVarResolver()} 204 * <li class='link'><a class="doclink" href="../../../../../index.html#jm.SvlVariables">SVL Variables</a> 205 * </ul> 206 * 207 * @param req The current HTTP request. 208 * @param res The current HTTP response. 209 * @param name Name of the desired resource. 210 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 211 * @throws IOException Thrown by underlying stream. 212 */ 213 protected String loadStyleWithVars(RestRequest req, RestResponse res, String name) throws IOException { 214 return req.getVarResolverSession().resolve(loadStyle(req, name)); 215 } 216 217 /** 218 * Loads the specified HTML file and strips HTML comments from the file. 219 * 220 * <p> 221 * Comment are assumed to be <js>"<!-- -->"</js> code blocks. 222 * 223 * @param req The HTTP request object. 224 * @param name Name of the desired resource. 225 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 226 */ 227 protected String loadHtml(RestRequest req, String name) { 228 try { 229 String s = getFileFinder(req).getString(name, null).orElse(null); 230 if (s != null) 231 s = s.replaceAll("(?s)<!--(.*?)-->\\s*", ""); 232 return s; 233 } catch (IOException e) { 234 throw asRuntimeException(e); 235 } 236 } 237 238 /** 239 * Same as {@link #loadHtml(RestRequest,String)} but replaces request-time SVL variables. 240 * 241 * <h5 class='section'>See Also:</h5><ul> 242 * <li class='jm'>{@link org.apache.juneau.rest.RestContext#getVarResolver()} 243 * <li class='link'><a class="doclink" href="../../../../../index.html#jm.SvlVariables">SVL Variables</a> 244 * </ul> 245 * 246 * @param req The current HTTP request. 247 * @param res The current HTTP response. 248 * @param name Name of the desired resource. 249 * @return The resource converted to a string, or <jk>null</jk> if the resource could not be found. 250 * @throws IOException Thrown by underlying stream. 251 */ 252 protected String loadHtmlWithVars(RestRequest req, RestResponse res, String name) throws IOException { 253 return req.getVarResolverSession().resolve(loadHtml(req, name)); 254 } 255}