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.Time;
024
025 import java.util.ArrayList;
026 import java.util.List;
027
028
031 public abstract class BaseSearchResultPermissionFilter
032 implements SearchResultPermissionFilter {
033
034 @Override
035 public Hits search(SearchContext searchContext) throws SearchException {
036 int end = searchContext.getEnd();
037 int start = searchContext.getStart();
038
039 if ((end == QueryUtil.ALL_POS) && (start == QueryUtil.ALL_POS)) {
040 Hits hits = getHits(searchContext);
041
042 filterHits(hits, searchContext);
043
044 return hits;
045 }
046
047 if ((start < 0) || (start > end)) {
048 return new HitsImpl();
049 }
050
051 int excludedDocsSize = 0;
052 int hitsSize = 0;
053 int offset = 0;
054 long startTime = 0;
055
056 List<Document> documents = new ArrayList<Document>();
057 List<Float> scores = new ArrayList<Float>();
058
059 while (true) {
060 int count = end - documents.size();
061
062 int amplifiedCount = (int)(
063 count * _INDEX_PERMISSION_FILTER_SEARCH_AMPLIFICATION_FACTOR);
064
065 int amplifiedEnd = offset + amplifiedCount;
066
067 searchContext.setEnd(amplifiedEnd);
068 searchContext.setStart(offset);
069
070 Hits hits = getHits(searchContext);
071
072 if (startTime == 0) {
073 hitsSize = hits.getLength();
074 startTime = hits.getStart();
075 }
076
077 Document[] oldDocs = hits.getDocs();
078
079 filterHits(hits, searchContext);
080
081 Document[] newDocs = hits.getDocs();
082
083 excludedDocsSize += oldDocs.length - newDocs.length;
084
085 collectHits(hits, documents, scores, count);
086
087 if ((newDocs.length >= count) ||
088 (oldDocs.length < amplifiedCount) ||
089 (amplifiedEnd >= hitsSize)) {
090
091 updateHits(
092 hits, documents, scores, start, end,
093 hitsSize - excludedDocsSize, startTime);
094
095 return hits;
096 }
097
098 offset = amplifiedEnd;
099 }
100 }
101
102 protected void collectHits(
103 Hits hits, List<Document> documents, List<Float> scores, int count) {
104
105 Document[] docs = hits.getDocs();
106
107 if (docs.length < count) {
108 count = docs.length;
109 }
110
111 for (int i = 0; i < count; i++) {
112 documents.add(docs[i]);
113
114 scores.add(hits.score(i));
115 }
116 }
117
118 protected abstract void filterHits(Hits hits, SearchContext searchContext);
119
120 protected abstract Hits getHits(SearchContext searchContext)
121 throws SearchException;
122
123 protected void updateHits(
124 Hits hits, List<Document> documents, List<Float> scores, int start,
125 int end, int size, long startTime) {
126
127 int[] startAndEnd = SearchPaginationUtil.calculateStartAndEnd(
128 start, end, documents.size());
129
130 start = startAndEnd[0];
131 end = startAndEnd[1];
132
133 documents = documents.subList(start, end);
134 scores = scores.subList(start, end);
135
136 hits.setDocs(documents.toArray(new Document[documents.size()]));
137 hits.setScores(ArrayUtil.toFloatArray(scores));
138 hits.setLength(size);
139 hits.setSearchTime(
140 (float)(System.currentTimeMillis() - startTime) / Time.SECOND);
141 }
142
143 private static final double
144 _INDEX_PERMISSION_FILTER_SEARCH_AMPLIFICATION_FACTOR =
145 GetterUtil.getDouble(
146 PropsUtil.get(
147 PropsKeys.
148 INDEX_PERMISSION_FILTER_SEARCH_AMPLIFICATION_FACTOR));
149
150 }