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 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.Map;
26  import java.util.Set;
27  import java.util.regex.Pattern;
28  import java.util.stream.Collectors;
29  
30  import javax.annotation.PostConstruct;
31  import javax.annotation.Resource;
32  
33  import org.codelibs.core.lang.StringUtil;
34  import org.codelibs.fess.Constants;
35  import org.codelibs.fess.app.service.LabelTypeService;
36  import org.codelibs.fess.entity.SearchRequestParams.SearchRequestType;
37  import org.codelibs.fess.es.config.exentity.LabelType;
38  import org.codelibs.fess.util.ComponentUtil;
39  import org.slf4j.Logger;
40  import org.slf4j.LoggerFactory;
41  
42  public class LabelTypeHelper {
43      private static final Logger logger = LoggerFactory.getLogger(LabelTypeHelper.class);
44  
45      @Resource
46      protected RoleQueryHelper roleQueryHelper;
47  
48      protected volatile List<LabelTypeItem> labelTypeItemList = new ArrayList<>();
49  
50      protected volatile List<LabelTypePattern> labelTypePatternList;
51  
52      @PostConstruct
53      public void init() {
54          final List<LabelType> labelTypeList = ComponentUtil.getComponent(LabelTypeService.class).getLabelTypeList();
55          buildLabelTypeItems(labelTypeList);
56      }
57  
58      public void refresh(final List<LabelType> labelTypeList) {
59          buildLabelTypeItems(labelTypeList);
60      }
61  
62      private void buildLabelTypeItems(final List<LabelType> labelTypeList) {
63          final List<LabelTypeItem> itemList = new ArrayList<>();
64          for (final LabelType labelType : labelTypeList) {
65              final LabelTypeItem item = new LabelTypeItem();
66              item.setLabel(labelType.getName());
67              item.setValue(labelType.getValue());
68              item.setPermissions(labelType.getPermissions());
69              item.setVirtualHost(labelType.getVirtualHost());
70              itemList.add(item);
71          }
72          labelTypeItemList = itemList;
73      }
74  
75      public List<Map<String, String>> getLabelTypeItemList(final SearchRequestType searchRequestType) {
76          if (labelTypeItemList == null) {
77              init();
78          }
79  
80          final String virtualHostKey = ComponentUtil.getFessConfig().getVirtualHostKey();
81          final List<LabelTypeItem> labelList;
82          if (StringUtil.isBlank(virtualHostKey)) {
83              labelList = labelTypeItemList;
84          } else {
85              labelList =
86                      labelTypeItemList.stream().filter(item -> virtualHostKey.equals(item.getVirtualHost())).collect(Collectors.toList());
87          }
88  
89          final List<Map<String, String>> itemList = new ArrayList<>();
90          final Set<String> roleSet = roleQueryHelper.build(searchRequestType);
91          if (roleSet.isEmpty()) {
92              for (final LabelTypeItem item : labelList) {
93                  if (item.getPermissions().length == 0) {
94                      final Map<String, String> map = new HashMap<>(2);
95                      map.put(Constants.ITEM_LABEL, item.getLabel());
96                      map.put(Constants.ITEM_VALUE, item.getValue());
97                      itemList.add(map);
98                  }
99              }
100         } else {
101             for (final LabelTypeItem item : labelList) {
102                 final Set<String> permissions = stream(item.getPermissions()).get(stream -> stream.collect(Collectors.toSet()));
103                 for (final String roleValue : roleSet) {
104                     if (permissions.contains(roleValue)) {
105                         final Map<String, String> map = new HashMap<>(2);
106                         map.put(Constants.ITEM_LABEL, item.getLabel());
107                         map.put(Constants.ITEM_VALUE, item.getValue());
108                         itemList.add(map);
109                         break;
110                     }
111                 }
112             }
113         }
114 
115         return itemList;
116     }
117 
118     public Set<String> getMatchedLabelValueSet(final String path) {
119         if (labelTypePatternList == null) {
120             synchronized (this) {
121                 if (labelTypePatternList == null) {
122                     final List<LabelType> labelTypeList = ComponentUtil.getComponent(LabelTypeService.class).getLabelTypeList();
123                     final List<LabelTypePattern> list = new ArrayList<>();
124                     for (final LabelType labelType : labelTypeList) {
125                         final String includedPaths = labelType.getIncludedPaths();
126                         final String excludedPaths = labelType.getExcludedPaths();
127                         if (StringUtil.isNotBlank(includedPaths) || StringUtil.isNotBlank(excludedPaths)) {
128                             try {
129                                 list.add(new LabelTypePattern(labelType.getValue(), includedPaths, excludedPaths));
130                             } catch (final Exception e) {
131                                 logger.warn("Failed to create a matching pattern of a label: " + labelType.getValue() + ", includedPaths:"
132                                         + includedPaths + ", excludedPaths:" + excludedPaths, e);
133                             }
134                         }
135                     }
136                     labelTypePatternList = list;
137                 }
138             }
139         }
140 
141         if (labelTypePatternList.isEmpty()) {
142             return Collections.emptySet();
143         }
144 
145         final Set<String> valueSet = new HashSet<>();
146         for (final LabelTypePattern pattern : labelTypePatternList) {
147             if (pattern.match(path)) {
148                 valueSet.add(pattern.getValue());
149             }
150         }
151         return valueSet;
152     }
153 
154     protected static class LabelTypeItem {
155         private String label;
156 
157         private String value;
158 
159         private String[] permissions;
160 
161         private String virtualHost;
162 
163         public String getLabel() {
164             return label;
165         }
166 
167         public void setLabel(final String label) {
168             this.label = label;
169         }
170 
171         public String getValue() {
172             return value;
173         }
174 
175         public void setValue(final String value) {
176             this.value = value;
177         }
178 
179         public String[] getPermissions() {
180             return permissions;
181         }
182 
183         public void setPermissions(final String[] permissions) {
184             this.permissions = permissions;
185         }
186 
187         public String getVirtualHost() {
188             return virtualHost;
189         }
190 
191         public void setVirtualHost(final String virtualHost) {
192             this.virtualHost = virtualHost;
193         }
194     }
195 
196     public static class LabelTypePattern {
197 
198         private final String value;
199 
200         private Pattern includedPaths;
201 
202         private Pattern excludedPaths;
203 
204         public LabelTypePattern(final String value, final String includedPaths, final String excludedPaths) {
205             this.value = value;
206 
207             if (StringUtil.isNotBlank(includedPaths)) {
208                 final StringBuilder buf = new StringBuilder(100);
209                 char split = 0;
210                 for (final String path : includedPaths.split("\n")) {
211                     if (split == 0) {
212                         split = '|';
213                     } else {
214                         buf.append(split);
215                     }
216                     buf.append(path.trim());
217                 }
218                 this.includedPaths = Pattern.compile(buf.toString());
219             }
220 
221             if (StringUtil.isNotBlank(excludedPaths)) {
222                 final StringBuilder buf = new StringBuilder(100);
223                 char split = 0;
224                 for (final String path : excludedPaths.split("\n")) {
225                     if (split == 0) {
226                         split = '|';
227                     } else {
228                         buf.append(split);
229                     }
230                     buf.append(path.trim());
231                 }
232                 this.excludedPaths = Pattern.compile(buf.toString());
233             }
234         }
235 
236         public String getValue() {
237             return value;
238         }
239 
240         public boolean match(final String path) {
241             if (includedPaths != null) {
242                 if (includedPaths.matcher(path).matches()) {
243                     if (excludedPaths != null && excludedPaths.matcher(path).matches()) {
244                         return false;
245                     }
246                     return true;
247                 }
248                 return false;
249             } else {
250                 return !excludedPaths.matcher(path).matches();
251             }
252         }
253 
254     }
255 }