1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.helper;
17
18 import static org.codelibs.core.stream.StreamUtil.stream;
19
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.Locale;
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.regex.Pattern;
29 import java.util.stream.Collectors;
30
31 import javax.annotation.PostConstruct;
32
33 import org.apache.logging.log4j.LogManager;
34 import org.apache.logging.log4j.Logger;
35 import org.codelibs.core.lang.StringUtil;
36 import org.codelibs.fess.Constants;
37 import org.codelibs.fess.app.service.LabelTypeService;
38 import org.codelibs.fess.entity.SearchRequestParams.SearchRequestType;
39 import org.codelibs.fess.es.config.exentity.LabelType;
40 import org.codelibs.fess.util.ComponentUtil;
41
42 public class LabelTypeHelper extends AbstractConfigHelper {
43 private static final Logger logger = LogManager.getLogger(LabelTypeHelper.class);
44
45 protected volatile List<LabelTypeItem> labelTypeItemList;
46
47 protected volatile List<LabelTypePattern> labelTypePatternList;
48
49 @PostConstruct
50 public void init() {
51 if (logger.isDebugEnabled()) {
52 logger.debug("Initialize {}", this.getClass().getSimpleName());
53 }
54 load();
55 }
56
57 @Override
58 public int load() {
59 final List<LabelType> labelTypeList = ComponentUtil.getComponent(LabelTypeService.class).getLabelTypeList();
60 buildLabelTypeItems(labelTypeList);
61 buildLabelTypePatternList(labelTypeList);
62 return labelTypeList.size();
63 }
64
65 public void refresh(final List<LabelType> labelTypeList) {
66 buildLabelTypeItems(labelTypeList);
67 buildLabelTypePatternList(labelTypeList);
68 }
69
70 protected void buildLabelTypeItems(final List<LabelType> labelTypeList) {
71 final List<LabelTypeItem> itemList = new ArrayList<>();
72 for (final LabelType labelType : labelTypeList) {
73 final LabelTypeItem item = new LabelTypeItem();
74 item.setLabel(labelType.getName());
75 item.setValue(labelType.getValue());
76 item.setPermissions(labelType.getPermissions());
77 item.setVirtualHost(labelType.getVirtualHost());
78 item.setLocale(labelType.getLocale());
79 itemList.add(item);
80 }
81 labelTypeItemList = itemList;
82 }
83
84 public List<Map<String, String>> getLabelTypeItemList(final SearchRequestType searchRequestType) {
85 return getLabelTypeItemList(searchRequestType, Locale.ROOT);
86 }
87
88 public List<Map<String, String>> getLabelTypeItemList(final SearchRequestType searchRequestType, final Locale requestLocale) {
89 if (labelTypeItemList == null) {
90 init();
91 }
92
93 final String virtualHostKey = ComponentUtil.getVirtualHostHelper().getVirtualHostKey();
94 final List<LabelTypeItem> labelList;
95 if (StringUtil.isBlank(virtualHostKey)) {
96 labelList =
97 labelTypeItemList.stream().filter(item -> matchLocale(requestLocale, item.getLocale())).collect(Collectors.toList());
98 } else {
99 labelList = labelTypeItemList.stream()
100 .filter(item -> matchLocale(requestLocale, item.getLocale()) && virtualHostKey.equals(item.getVirtualHost()))
101 .collect(Collectors.toList());
102 }
103
104 final List<Map<String, String>> itemList = new ArrayList<>();
105 final Set<String> roleSet = ComponentUtil.getRoleQueryHelper().build(searchRequestType);
106 if (roleSet.isEmpty()) {
107 for (final LabelTypeItem item : labelList) {
108 if (item.getPermissions().length == 0) {
109 final Map<String, String> map = new HashMap<>(2);
110 map.put(Constants.ITEM_LABEL, item.getLabel());
111 map.put(Constants.ITEM_VALUE, item.getValue());
112 itemList.add(map);
113 }
114 }
115 } else {
116 for (final LabelTypeItem item : labelList) {
117 final Set<String> permissions = stream(item.getPermissions()).get(stream -> stream.collect(Collectors.toSet()));
118 for (final String roleValue : roleSet) {
119 if (permissions.contains(roleValue)) {
120 final Map<String, String> map = new HashMap<>(2);
121 map.put(Constants.ITEM_LABEL, item.getLabel());
122 map.put(Constants.ITEM_VALUE, item.getValue());
123 itemList.add(map);
124 break;
125 }
126 }
127 }
128 }
129
130 return itemList;
131 }
132
133 protected boolean matchLocale(final Locale requestLocale, final Locale targetLocale) {
134 if (targetLocale.equals(requestLocale) || targetLocale.equals(Locale.ROOT)) {
135 return true;
136 }
137 if (requestLocale == null) {
138 return false;
139 }
140 if (!requestLocale.getLanguage().equals(targetLocale.getLanguage())) {
141 return false;
142 }
143 if (targetLocale.getCountry().length() > 0 && !requestLocale.getCountry().equals(targetLocale.getCountry())) {
144 return false;
145 }
146 return true;
147 }
148
149 public Set<String> getMatchedLabelValueSet(final String path) {
150 if (labelTypePatternList == null) {
151 synchronized (this) {
152 if (labelTypePatternList == null) {
153 buildLabelTypePatternList(ComponentUtil.getComponent(LabelTypeService.class).getLabelTypeList());
154 }
155 }
156 }
157
158 if (labelTypePatternList.isEmpty()) {
159 return Collections.emptySet();
160 }
161
162 final Set<String> valueSet = new HashSet<>();
163 for (final LabelTypePattern pattern : labelTypePatternList) {
164 if (pattern.match(path)) {
165 valueSet.add(pattern.getValue());
166 }
167 }
168 return valueSet;
169 }
170
171 protected void buildLabelTypePatternList(final List<LabelType> labelTypeList) {
172 final List<LabelTypePattern> list = new ArrayList<>();
173 for (final LabelType labelType : labelTypeList) {
174 final String includedPaths = labelType.getIncludedPaths();
175 final String excludedPaths = labelType.getExcludedPaths();
176 if (StringUtil.isNotBlank(includedPaths) || StringUtil.isNotBlank(excludedPaths)) {
177 try {
178 list.add(new LabelTypePattern(labelType.getValue(), includedPaths, excludedPaths));
179 } catch (final Exception e) {
180 logger.warn("Failed to create a matching pattern of a label: {}, includedPaths:{}, excludedPaths:{}",
181 labelType.getValue(), includedPaths, excludedPaths, e);
182 }
183 }
184 }
185 labelTypePatternList = list;
186 }
187
188 protected static class LabelTypeItem {
189 private String label;
190
191 private String value;
192
193 private String[] permissions;
194
195 private String virtualHost;
196
197 private Locale locale;
198
199 public String getLabel() {
200 return label;
201 }
202
203 public void setLabel(final String label) {
204 this.label = label;
205 }
206
207 public String getValue() {
208 return value;
209 }
210
211 public void setValue(final String value) {
212 this.value = value;
213 }
214
215 public String[] getPermissions() {
216 return permissions;
217 }
218
219 public void setPermissions(final String[] permissions) {
220 this.permissions = permissions;
221 }
222
223 public String getVirtualHost() {
224 return virtualHost;
225 }
226
227 public void setVirtualHost(final String virtualHost) {
228 this.virtualHost = virtualHost;
229 }
230
231 public Locale getLocale() {
232 return locale;
233 }
234
235 public void setLocale(Locale locale) {
236 this.locale = locale;
237 }
238 }
239
240 public static class LabelTypePattern {
241
242 private final String value;
243
244 private Pattern includedPaths;
245
246 private Pattern excludedPaths;
247
248 public LabelTypePattern(final String value, final String includedPaths, final String excludedPaths) {
249 this.value = value;
250
251 final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
252 if (StringUtil.isNotBlank(includedPaths)) {
253 final StringBuilder buf = new StringBuilder(100);
254 char split = 0;
255 for (final String path : includedPaths.split("\n")) {
256 if (split == 0) {
257 split = '|';
258 } else {
259 buf.append(split);
260 }
261 final String normalizePath = systemHelper.normalizeConfigPath(path);
262 if (StringUtil.isNotBlank(normalizePath)) {
263 buf.append(normalizePath);
264 }
265 }
266 this.includedPaths = Pattern.compile(buf.toString());
267 }
268
269 if (StringUtil.isNotBlank(excludedPaths)) {
270 final StringBuilder buf = new StringBuilder(100);
271 char split = 0;
272 for (final String path : excludedPaths.split("\n")) {
273 if (split == 0) {
274 split = '|';
275 } else {
276 buf.append(split);
277 }
278 final String normalizePath = systemHelper.normalizeConfigPath(path);
279 if (StringUtil.isNotBlank(normalizePath)) {
280 buf.append(normalizePath);
281 }
282 }
283 this.excludedPaths = Pattern.compile(buf.toString());
284 }
285 }
286
287 public String getValue() {
288 return value;
289 }
290
291 public boolean match(final String path) {
292 if (includedPaths == null) {
293 if (excludedPaths != null && excludedPaths.matcher(path).matches()) {
294 if (logger.isDebugEnabled()) {
295 logger.debug("Path {} matches the exclude path expression {} on {} of label.", path, excludedPaths, value);
296 }
297 return false;
298 }
299 if (logger.isDebugEnabled()) {
300 logger.debug("Path {} does not match the exclude path expression {} on {} of label.", path, excludedPaths, value);
301 }
302 return true;
303 }
304 if (includedPaths.matcher(path).matches()) {
305 if (excludedPaths != null && excludedPaths.matcher(path).matches()) {
306 if (logger.isDebugEnabled()) {
307 logger.debug("Path {} matches the include/exclude path expression {} on {} of label.", path, excludedPaths, value);
308 }
309 return false;
310 }
311 if (logger.isDebugEnabled()) {
312 logger.debug("Path {} matches the include path expression {} on {} of label.", path, excludedPaths, value);
313 }
314 return true;
315 }
316 if (logger.isDebugEnabled()) {
317 logger.debug("Path {} does not match the include path expression {} on {} of label.", path, excludedPaths, value);
318 }
319 return false;
320 }
321
322 }
323 }