001
014
015 package com.liferay.portal.kernel.search;
016
017 import com.liferay.portal.kernel.dao.orm.QueryUtil;
018 import com.liferay.portal.kernel.dao.search.SearchPaginationUtil;
019 import com.liferay.portal.kernel.util.ArrayUtil;
020 import com.liferay.portal.kernel.util.GetterUtil;
021 import com.liferay.portal.kernel.util.PropsKeys;
022 import com.liferay.portal.kernel.util.PropsUtil;
023 import com.liferay.portal.kernel.util.SetUtil;
024 import com.liferay.portal.kernel.util.Time;
025
026 import java.util.ArrayList;
027 import java.util.List;
028 import java.util.Set;
029
030
033 public abstract class BaseSearchResultPermissionFilter
034 implements SearchResultPermissionFilter {
035
036 @Override
037 public Hits search(SearchContext searchContext) throws SearchException {
038 QueryConfig queryConfig = searchContext.getQueryConfig();
039
040 if (!queryConfig.isAllFieldsSelected()) {
041 Set<String> selectedFieldNameSet = SetUtil.fromArray(
042 queryConfig.getSelectedFieldNames());
043
044 for (String selectedFieldName : _PERMISSION_SELECTED_FIELD_NAMES) {
045 selectedFieldNameSet.add(selectedFieldName);
046 }
047
048 queryConfig.setSelectedFieldNames(
049 selectedFieldNameSet.toArray(
050 new String[selectedFieldNameSet.size()]));
051 }
052
053 int end = searchContext.getEnd();
054 int start = searchContext.getStart();
055
056 if ((end == QueryUtil.ALL_POS) && (start == QueryUtil.ALL_POS)) {
057 Hits hits = getHits(searchContext);
058
059 filterHits(hits, searchContext);
060
061 return hits;
062 }
063
064 if ((start < 0) || (start > end)) {
065 return new HitsImpl();
066 }
067
068 int excludedDocsSize = 0;
069 int hitsSize = 0;
070 int offset = 0;
071 long startTime = 0;
072
073 List<Document> documents = new ArrayList<Document>();
074 List<Float> scores = new ArrayList<Float>();
075
076 while (true) {
077 int count = end - documents.size();
078
079 int amplifiedCount = (int)(
080 count * _INDEX_PERMISSION_FILTER_SEARCH_AMPLIFICATION_FACTOR);
081
082 int amplifiedEnd = offset + amplifiedCount;
083
084 searchContext.setEnd(amplifiedEnd);
085 searchContext.setStart(offset);
086
087 Hits hits = getHits(searchContext);
088
089 if (startTime == 0) {
090 hitsSize = hits.getLength();
091 startTime = hits.getStart();
092 }
093
094 Document[] oldDocs = hits.getDocs();
095
096 filterHits(hits, searchContext);
097
098 Document[] newDocs = hits.getDocs();
099
100 excludedDocsSize += oldDocs.length - newDocs.length;
101
102 collectHits(hits, documents, scores, count);
103
104 if ((newDocs.length >= count) ||
105 (oldDocs.length < amplifiedCount) ||
106 (amplifiedEnd >= hitsSize)) {
107
108 updateHits(
109 hits, documents, scores, start, end,
110 hitsSize - excludedDocsSize, startTime);
111
112 return hits;
113 }
114
115 offset = amplifiedEnd;
116 }
117 }
118
119 protected void collectHits(
120 Hits hits, List<Document> documents, List<Float> scores, int count) {
121
122 Document[] docs = hits.getDocs();
123
124 if (docs.length < count) {
125 count = docs.length;
126 }
127
128 for (int i = 0; i < count; i++) {
129 documents.add(docs[i]);
130
131 scores.add(hits.score(i));
132 }
133 }
134
135 protected abstract void filterHits(Hits hits, SearchContext searchContext);
136
137 protected abstract Hits getHits(SearchContext searchContext)
138 throws SearchException;
139
140 protected void updateHits(
141 Hits hits, List<Document> documents, List<Float> scores, int start,
142 int end, int size, long startTime) {
143
144 int[] startAndEnd = SearchPaginationUtil.calculateStartAndEnd(
145 start, end, documents.size());
146
147 start = startAndEnd[0];
148 end = startAndEnd[1];
149
150 documents = documents.subList(start, end);
151 scores = scores.subList(start, end);
152
153 hits.setDocs(documents.toArray(new Document[documents.size()]));
154 hits.setScores(ArrayUtil.toFloatArray(scores));
155 hits.setLength(size);
156 hits.setSearchTime(
157 (float)(System.currentTimeMillis() - startTime) / Time.SECOND);
158 }
159
160 private static final double
161 _INDEX_PERMISSION_FILTER_SEARCH_AMPLIFICATION_FACTOR =
162 GetterUtil.getDouble(
163 PropsUtil.get(
164 PropsKeys.
165 INDEX_PERMISSION_FILTER_SEARCH_AMPLIFICATION_FACTOR));
166
167 private static final String[] _PERMISSION_SELECTED_FIELD_NAMES =
168 {Field.ENTRY_CLASS_NAME, Field.ENTRY_CLASS_PK};
169
170 }