View Javadoc
1   /*
2    * Copyright 2012-2017 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.helper;
17  
18  import java.util.ArrayList;
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  import java.util.regex.Matcher;
23  
24  import javax.annotation.PostConstruct;
25  
26  import org.codelibs.core.lang.StringUtil;
27  import org.codelibs.fess.Constants;
28  import org.codelibs.fess.es.config.exbhv.PathMappingBhv;
29  import org.codelibs.fess.es.config.exentity.PathMapping;
30  import org.codelibs.fess.util.ComponentUtil;
31  import org.lastaflute.di.core.factory.SingletonLaContainerFactory;
32  import org.lastaflute.web.util.LaRequestUtil;
33  import org.slf4j.Logger;
34  import org.slf4j.LoggerFactory;
35  
36  public class PathMappingHelper {
37  
38      private static final Logger logger = LoggerFactory.getLogger(PathMappingHelper.class);
39  
40      private final Map<String, List<PathMapping>> pathMappingMap = new HashMap<>();
41  
42      volatile List<PathMapping> cachedPathMappingList = null;
43  
44      @PostConstruct
45      public void init() {
46          final List<String> ptList = new ArrayList<>();
47          ptList.add(Constants.PROCESS_TYPE_DISPLAYING);
48          ptList.add(Constants.PROCESS_TYPE_BOTH);
49  
50          try {
51              final PathMappingBhv pathMappingBhv = ComponentUtil.getComponent(PathMappingBhv.class);
52              cachedPathMappingList = pathMappingBhv.selectList(cb -> {
53                  cb.query().addOrderBy_SortOrder_Asc();
54                  cb.query().setProcessType_InScope(ptList);
55                  cb.fetchFirst(ComponentUtil.getFessConfig().getPagePathMappingMaxFetchSizeAsInteger());
56              });
57          } catch (final Exception e) {
58              logger.warn("Failed to load path mappings.", e);
59          }
60      }
61  
62      public void setPathMappingList(final String sessionId, final List<PathMapping> pathMappingList) {
63          if (sessionId != null) {
64              if (pathMappingList != null) {
65                  pathMappingMap.put(sessionId, pathMappingList);
66              } else {
67                  removePathMappingList(sessionId);
68              }
69          }
70      }
71  
72      public void removePathMappingList(final String sessionId) {
73          pathMappingMap.remove(sessionId);
74      }
75  
76      public List<PathMapping> getPathMappingList(final String sessionId) {
77          if (sessionId == null) {
78              return null;
79          }
80          return pathMappingMap.get(sessionId);
81      }
82  
83      public String replaceUrl(final String sessionId, final String url) {
84          final List<PathMapping> pathMappingList = getPathMappingList(sessionId);
85          if (pathMappingList == null) {
86              return url;
87          }
88          return replaceUrl(pathMappingList, url);
89      }
90  
91      public String replaceUrls(final String text) {
92          if (cachedPathMappingList == null) {
93              synchronized (this) {
94                  if (cachedPathMappingList == null) {
95                      init();
96                  }
97              }
98          }
99          String result = text;
100         for (final PathMapping pathMapping : cachedPathMappingList) {
101             if (matchUserAgent(pathMapping)) {
102                 result =
103                         result.replaceAll("(\"[^\"]*)" + pathMapping.getRegex() + "([^\"]*\")", "$1" + pathMapping.getReplacement() + "$2");
104             }
105         }
106         return result;
107     }
108 
109     public String replaceUrl(final String url) {
110         if (cachedPathMappingList == null) {
111             synchronized (this) {
112                 if (cachedPathMappingList == null) {
113                     init();
114                 }
115             }
116         }
117         return replaceUrl(cachedPathMappingList, url);
118     }
119 
120     private String replaceUrl(final List<PathMapping> pathMappingList, final String url) {
121         String newUrl = url;
122         for (final PathMapping pathMapping : pathMappingList) {
123             if (matchUserAgent(pathMapping)) {
124                 final Matcher matcher = pathMapping.getMatcher(newUrl);
125                 if (matcher.find()) {
126                     newUrl = matcher.replaceAll(pathMapping.getReplacement());
127                 }
128             }
129         }
130         return newUrl;
131     }
132 
133     private boolean matchUserAgent(final PathMapping pathMapping) {
134         if (!pathMapping.hasUAMathcer()) {
135             return true;
136         }
137 
138         if (SingletonLaContainerFactory.getExternalContext().getRequest() != null) {
139             return LaRequestUtil.getOptionalRequest().map(request -> {
140                 final String userAgent = request.getHeader("user-agent");
141                 if (StringUtil.isBlank(userAgent)) {
142                     return false;
143                 }
144 
145                 return pathMapping.getUAMatcher(userAgent).find();
146             }).orElse(false);
147         }
148         return false;
149     }
150 }