This is a cache of https://fess.codelibs.org/xref/org/codelibs/fess/taglib/FessFunctions.html. It is a snapshot of the page at 2020-10-25T01:23:32.521+0000.
FessFunctions xref
View Javadoc
1   /*
2    * Copyright 2012-2020 CodeLibs Project and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.codelibs.fess.taglib;
17  
18  import static org.codelibs.core.stream.StreamUtil.stream;
19  
20  import java.io.File;
21  import java.math.RoundingMode;
22  import java.nio.file.Files;
23  import java.nio.file.Path;
24  import java.nio.file.Paths;
25  import java.text.DecimalFormat;
26  import java.text.NumberFormat;
27  import java.text.SimpleDateFormat;
28  import java.time.LocalDateTime;
29  import java.time.ZonedDateTime;
30  import java.time.format.DateTimeFormatter;
31  import java.util.ArrayList;
32  import java.util.Base64;
33  import java.util.Calendar;
34  import java.util.Date;
35  import java.util.Enumeration;
36  import java.util.List;
37  import java.util.Locale;
38  import java.util.Map;
39  import java.util.Objects;
40  import java.util.concurrent.ExecutionException;
41  import java.util.concurrent.TimeUnit;
42  import java.util.regex.Matcher;
43  import java.util.regex.Pattern;
44  import java.util.stream.Collectors;
45  
46  import javax.servlet.http.HttpServletRequest;
47  
48  import org.apache.commons.lang3.time.DurationFormatUtils;
49  import org.apache.commons.text.StringEscapeUtils;
50  import org.apache.logging.log4j.LogManager;
51  import org.apache.logging.log4j.Logger;
52  import org.apache.pdfbox.util.DateConverter;
53  import org.codelibs.core.lang.StringUtil;
54  import org.codelibs.fess.Constants;
55  import org.codelibs.fess.app.web.base.FessAdminAction;
56  import org.codelibs.fess.app.web.base.login.FessLoginAssist;
57  import org.codelibs.fess.entity.FacetQueryView;
58  import org.codelibs.fess.helper.ViewHelper;
59  import org.codelibs.fess.util.ComponentUtil;
60  import org.elasticsearch.common.joda.Joda;
61  import org.lastaflute.di.util.LdiURLUtil;
62  import org.lastaflute.web.util.LaRequestUtil;
63  import org.lastaflute.web.util.LaResponseUtil;
64  import org.lastaflute.web.util.LaServletContextUtil;
65  
66  import com.google.common.cache.CacheBuilder;
67  import com.google.common.cache.CacheLoader;
68  import com.google.common.cache.LoadingCache;
69  
70  public class FessFunctions {
71      private static final Logger logger = LogManager.getLogger(FessFunctions.class);
72  
73      private static final String gEO_PREFIX = "geo.";
74  
75      private static final String FACET_PREFIX = "facet.";
76  
77      private static final String PDF_DATE = "pdf_date";
78  
79      private static final Pattern EMAIL_ADDRESS_PATTERN = Pattern.compile("[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}",
80              Pattern.CASE_INSENSITIVE);
81  
82      private static LoadingCache<String, Long&gt; resourceHashCache = CacheBuilder.newBuilder().maximumSize(1000)
83              .expireAfterWrite(10, TimeUnit.MINUTES).build(new CacheLoader<String, Long&gt;() {
84                  @Override
85                  public Long load(final String key) throws Exception {
86                      try {
87                          final Path path = Paths.get(LaServletContextUtil.getServletContext().getRealPath(key));
88                          if (Files.isRegularFile(path)) {
89                              return Files.getLastModifiedTime(path).toMillis();
90                          }
91                      } catch (final Exception e) {
92                          logger.debug("Failed to access {}", key, e);
93                      }
94                      return 0L;
95                  }
96              });
97  
98      protected FessFunctions() {
99          // nothing
100     }
101 
102     public static Boolean labelExists(final String value) {
103         @SuppressWarnings("unchecked")
104         final Map<String, String&gt; labelValueMap = (Map<String, String&gt;) LaRequestUtil.getRequest().getAttribute(Constants.LABEL_VALUE_MAP);
105         if (labelValueMap != null) {
106             return labelValueMap.get(value) != null;
107         }
108         return false;
109     }
110 
111     public static String label(final String value) {
112         @SuppressWarnings("unchecked")
113         final Map<String, String&gt; labelValueMap = (Map<String, String&gt;) LaRequestUtil.getRequest().getAttribute(Constants.LABEL_VALUE_MAP);
114         if (labelValueMap != null) {
115             final String name = labelValueMap.get(value);
116             if (name != null) {
117                 return name;
118             }
119         }
120         return value;
121     }
122 
123     public static Date date(final Long value) {
124         if (value == null) {
125             return null;
126         }
127         return new Date(value);
128     }
129 
130     public static Date parseDate(final String value) {
131         return parseDate(value, Constants.DATE_OPTIONAL_TIME);
132     }
133 
134     public static Date parseDate(final String value, final String format) {
135         if (value == null) {
136             return null;
137         }
138 
139         try {
140             if (PDF_DATE.equals(format)) {
141                 final Calendar cal = DateConverter.toCalendar(value);
142                 return cal != null ? cal.getTime() : null;
143             }
144 
145             final long time = Joda.forPattern(format).parseMillis(value);
146             return new Date(time);
147         } catch (final Exception e) {
148             return null;
149         }
150     }
151 
152     public static String formatDate(final Date date) {
153         if (date == null) {
154             return StringUtil.EMPTY;
155         }
156         final SimpleDateFormat sdf = new SimpleDateFormat(Constants.ISO_DATETIME_FORMAT);
157         sdf.setTimeZone(Constants.TIMEZONE_UTC);
158         return sdf.format(date);
159     }
160 
161     public static String formatDate(final LocalDateTime date) {
162         if (date == null) {
163             return StringUtil.EMPTY;
164         }
165         return date.format(DateTimeFormatter.ofPattern(Constants.ISO_DATETIME_FORMAT, Locale.ROOT));
166     }
167 
168     public static String formatDate(final ZonedDateTime date, final String format) {
169         if (date == null) {
170             return StringUtil.EMPTY;
171         }
172         return date.format(DateTimeFormatter.ofPattern(format, Locale.ROOT));
173     }
174 
175     public static String formatDuration(final long durationMillis) {
176         return DurationFormatUtils.formatDuration(durationMillis, "d 'days' HH:mm:ss.SSS").replace("0 days", StringUtil.EMPTY).trim();
177 
178     }
179 
180     public static String formatNumber(final long value, final String pattern) {
181         final DecimalFormat df = (DecimalFormat) NumberFormat.getNumberInstance(getUserLocale());
182         df.applyPattern(pattern);
183         return df.format(value);
184     }
185 
186     private static Locale getUserLocale() {
187         final Locale locale = ComponentUtil.getRequestManager().getUserLocale();
188         if (locale == null) {
189             return Locale.ROOT;
190         }
191         return locale;
192     }
193 
194     public static String formatFileSize(final long value) {
195         double target = value;
196         String unit = ""; // TODO l10n?
197         String format = "0.#";
198         if (value < 1024) {
199             format = "0";
200         } else if (value < 1024L * 1024L) {
201             target /= 1024;
202             unit = "K";
203         } else if (value < 1024L * 1024L * 1024L) {
204             target /= 1024;
205             target /= 1024;
206             unit = "M";
207         } else if (value < 1024L * 1024L * 1024L * 1024L) {
208             target /= 1024;
209             target /= 1024;
210             target /= 1024;
211             unit = "g";
212         } else {
213             target /= 1024;
214             target /= 1024;
215             target /= 1024;
216             target /= 1024;
217             unit = "T";
218         }
219         final DecimalFormat df = (DecimalFormat) NumberFormat.getNumberInstance(getUserLocale());
220         df.applyPattern(format);
221         df.setRoundingMode(RoundingMode.HALF_UP);
222         return df.format(target) + unit;
223     }
224 
225     public static String pagingQuery(final String query) {
226         final HttpServletRequest request = LaRequestUtil.getRequest();
227         @SuppressWarnings("unchecked")
228         final List<String&gt; pagingQueryList = (List<String&gt;) request.getAttribute(Constants.PAgINg_QUERY_LIST);
229         if (pagingQueryList != null) {
230             final String prefix;
231             if (query != null) {
232                 prefix = "ex_q=" + query.split(":")[0] + "%3A";
233             } else {
234                 prefix = null;
235             }
236             return pagingQueryList.stream().filter(s -&gt; prefix == null || !s.startsWith(prefix))
237                     .collect(Collectors.joining("&", "&", StringUtil.EMPTY));
238         }
239         return StringUtil.EMPTY;
240     }
241 
242     public static String facetQuery() {
243         return createQuery(Constants.FACET_QUERY, FACET_PREFIX);
244     }
245 
246     public static String geoQuery() {
247         return createQuery(Constants.gEO_QUERY, gEO_PREFIX);
248     }
249 
250     public static String facetForm() {
251         return createForm(Constants.FACET_FORM, FACET_PREFIX);
252     }
253 
254     public static String geoForm() {
255         return createForm(Constants.gEO_FORM, gEO_PREFIX);
256     }
257 
258     public static List<FacetQueryView&gt; facetQueryViewList() {
259         final ViewHelper viewHelper = ComponentUtil.getViewHelper();
260         return viewHelper.getFacetQueryViewList();
261     }
262 
263     private static String createQuery(final String key, final String prefix) {
264         final HttpServletRequest request = LaRequestUtil.getRequest();
265         String query = (String) request.getAttribute(key);
266         if (query == null) {
267             final StringBuilder buf = new StringBuilder(100);
268             final Enumeration<String&gt; names = request.getParameterNames();
269             while (names.hasMoreElements()) {
270                 final String name = names.nextElement();
271                 if (name.startsWith(prefix)) {
272                     final String[] values = request.getParameterValues(name);
273                     if (values != null) {
274                         for (final String value : values) {
275                             buf.append('&');
276                             buf.append(LdiURLUtil.encode(name, Constants.UTF_8));
277                             buf.append('=');
278                             buf.append(LdiURLUtil.encode(value, Constants.UTF_8));
279                         }
280                     }
281                 }
282             }
283             query = buf.toString();
284             request.setAttribute(key, query);
285         }
286         return query;
287     }
288 
289     private static String createForm(final String key, final String prefix) {
290         final HttpServletRequest request = LaRequestUtil.getRequest();
291         String query = (String) request.getAttribute(key);
292         if (query == null) {
293             final StringBuilder buf = new StringBuilder(100);
294             final Enumeration<String&gt; names = request.getParameterNames();
295             while (names.hasMoreElements()) {
296                 final String name = names.nextElement();
297                 if (name.startsWith(prefix)) {
298                     final String[] values = request.getParameterValues(name);
299                     if (values != null) {
300                         for (final String value : values) {
301                             buf.append("<input type=\"hidden\" name=\"");
302                             buf.append(StringEscapeUtils.escapeHtml4(name));
303                             buf.append("\" value=\"");
304                             buf.append(StringEscapeUtils.escapeHtml4(value));
305                             buf.append("\"/&gt;");
306                         }
307                     }
308                 }
309             }
310             query = buf.toString();
311             request.setAttribute(key, query);
312         }
313         return query;
314     }
315 
316     public static String base64(final String value) {
317         if (value == null) {
318             return StringUtil.EMPTY;
319         }
320         return Base64.getUrlEncoder().encodeToString(value.getBytes(Constants.CHARSET_UTF_8));
321     }
322 
323     public static boolean fileExists(final String path) {
324         final File file = new File(LaServletContextUtil.getServletContext().getRealPath(path));
325         return file.exists();
326     }
327 
328     public static String url(final String input) {
329         if (input == null) {
330             final String msg = "The argument 'input' should not be null.";
331             throw new IllegalArgumentException(msg);
332         }
333         if (!input.startsWith("/")) {
334             final String msg = "The argument 'input' should start with slash '/': " + input;
335             throw new IllegalArgumentException(msg);
336         }
337         final String contextPath = LaRequestUtil.getRequest().getContextPath();
338         final StringBuilder sb = new StringBuilder();
339         if (contextPath.length() &gt; 1) {
340             sb.append(contextPath);
341         }
342         sb.append(input);
343         if (input.indexOf('?') == -1) {
344             try {
345                 final Long value = resourceHashCache.get(input);
346                 if (value.longValue() &gt; 0) {
347                     sb.append("?t=").append(value.toString());
348                 }
349             } catch (final ExecutionException e) {
350                 logger.debug("Failed to access {}", input, e);
351             }
352         }
353         return LaResponseUtil.getResponse().encodeURL(sb.toString());
354     }
355 
356     public static String sdh(final String input) {
357         if (StringUtil.isBlank(input)) {
358             return input;
359         }
360         return ComponentUtil.getDocumentHelper().encodeSimilarDocHash(input);
361     }
362 
363     public static String join(final Object input) {
364         String[] values = null;
365         if (input instanceof String[]) {
366             values = (String[]) input;
367         } else if (input instanceof List) {
368             values = ((List<?&gt;) input).stream().filter(Objects::nonNull).map(Object::toString).toArray(n -&gt; new String[n]);
369         } else if (input instanceof String) {
370             return input.toString();
371         }
372         if (values != null) {
373             return stream(values).get(stream -&gt; stream.filter(StringUtil::isNotBlank).map(String::trim).collect(Collectors.joining(" ")));
374         }
375         return StringUtil.EMPTY;
376     }
377 
378     public static String replace(final Object input, final String regex, final String replacement) {
379         if (input == null) {
380             return StringUtil.EMPTY;
381         }
382         return input.toString().replaceAll(regex, replacement);
383     }
384 
385     public static String formatCode(final String prefix, final String style, final String mimetype, final String input) {
386         if (input == null) {
387             return StringUtil.EMPTY;
388         }
389         final Pattern pattern = Pattern.compile("^" + prefix + "([0-9]+):(.*)$");
390         final String[] values = input.split("\n");
391         final List<String&gt; list = new ArrayList<&gt;(values.length);
392         int lineNum = 0;
393         for (final String line : values) {
394             final Matcher matcher = pattern.matcher(line);
395             if (matcher.matches()) {
396                 if (lineNum == 0) {
397                     lineNum = Integer.parseInt(matcher.group(1));
398                     list.clear();
399                 }
400                 list.add(matcher.group(2));
401             } else {
402                 list.add(line);
403             }
404         }
405         if (lineNum == 0 || list.isEmpty()) {
406             return "<pre class=\"" + style + "\"&gt;" + input + "</pre&gt;";
407         }
408         int lastIndex = list.size();
409         if (list.get(list.size() - 1).endsWith("...")) {
410             lastIndex--;
411         }
412         if (lastIndex <= 0) {
413             lastIndex = 1;
414         }
415         final String content = list.subList(0, lastIndex).stream().collect(Collectors.joining("\n"));
416         if (StringUtil.isBlank(content)) {
417             return "<pre class=\"" + style + "\"&gt;" + input.replaceAll("L[0-9]+:", StringUtil.EMPTY).trim() + "</pre&gt;";
418         }
419         return "<pre class=\"" + style + " linenums:" + lineNum + "\"&gt;" + content + "</pre&gt;";
420     }
421 
422     public static String getMessage(final String key, final String defaultValue) {
423         final Locale locale = LaRequestUtil.getOptionalRequest().map(HttpServletRequest::getLocale).orElse(Locale.ROOT);
424         return ComponentUtil.getMessageManager().findMessage(locale, key).orElse(defaultValue);
425     }
426 
427     public static boolean hasActionRole(final String role) {
428         final String[] roles;
429         if (role.endsWith(FessAdminAction.VIEW)) {
430             roles = new String[] { role, role.substring(0, role.length() - FessAdminAction.VIEW.length()) };
431         } else {
432             roles = new String[] { role };
433         }
434         final FessLoginAssist loginAssist = ComponentUtil.getComponent(FessLoginAssist.class);
435         return loginAssist.getSavedUserBean()
436                 .map(user -&gt; user.hasRoles(roles) || user.hasRoles(ComponentUtil.getFessConfig().getAuthenticationAdminRolesAsArray()))
437                 .orElse(false);
438     }
439 
440     public static String maskEmail(final String value) {
441         if (value == null) {
442             return StringUtil.EMPTY;
443         }
444         return EMAIL_ADDRESS_PATTERN.matcher(value).replaceAll("******@****.***");
445     }
446 }