|
27 | 27 | import org.apache.lucene.search.QueryVisitor; |
28 | 28 | import org.apache.lucene.search.ScoreMode; |
29 | 29 | import org.apache.lucene.search.Scorer; |
| 30 | +import org.apache.lucene.search.ScorerSupplier; |
30 | 31 | import org.apache.lucene.search.Weight; |
31 | 32 | import org.apache.lucene.util.BitSetIterator; |
32 | 33 | import org.apache.lucene.util.BytesRef; |
33 | 34 | import org.apache.lucene.util.FixedBitSet; |
34 | 35 | import org.jetbrains.annotations.NotNull; |
| 36 | +import org.jetbrains.annotations.Nullable; |
35 | 37 | import org.labkey.api.data.Container; |
36 | 38 | import org.labkey.api.data.ContainerManager; |
37 | 39 | import org.labkey.api.module.Module; |
@@ -96,64 +98,94 @@ public boolean isCacheable(LeafReaderContext ctx) |
96 | 98 |
|
97 | 99 | private boolean isReadable(String containerId, String categories) |
98 | 100 | { |
99 | | -// return _containerIds.containsKey(containerId); |
100 | 101 | if (StringUtils.isEmpty(categories) || !_categoryContainers.containsKey(categories)) |
101 | 102 | return _containerIds.containsKey(containerId); |
102 | 103 | else |
103 | 104 | return _categoryContainers.get(categories).contains(containerId); |
104 | 105 | } |
105 | 106 |
|
106 | 107 | @Override |
107 | | - public Scorer scorer(LeafReaderContext context) throws IOException |
| 108 | + public ScorerSupplier scorerSupplier(LeafReaderContext context) |
108 | 109 | { |
109 | | - SearchService.SEARCH_PHASE currentPhase = _iTimer.getCurrentPhase(); |
110 | | - _iTimer.setPhase(SearchService.SEARCH_PHASE.applySecurityFilter); |
111 | | - |
112 | | - LeafReader reader = context.reader(); |
113 | | - int maxDoc = reader.maxDoc(); |
114 | | - FixedBitSet bits = new FixedBitSet(maxDoc); |
| 110 | + return new ScorerSupplier() |
| 111 | + { |
| 112 | + private final LeafReader _reader; |
| 113 | + private final @Nullable BinaryDocValues _securityContextDocValues; |
115 | 114 |
|
116 | | - BinaryDocValues securityContextDocValues = reader.getBinaryDocValues(FIELD_NAME.securityContext.name()); |
| 115 | + { |
| 116 | + SearchService.SEARCH_PHASE currentPhase = _iTimer.getCurrentPhase(); |
117 | 117 |
|
118 | | - try |
119 | | - { |
120 | | - int doc; |
| 118 | + try |
| 119 | + { |
| 120 | + _iTimer.setPhase(SearchService.SEARCH_PHASE.applySecurityFilter); |
| 121 | + _reader = context.reader(); |
| 122 | + _securityContextDocValues = _reader.getBinaryDocValues(FIELD_NAME.securityContext.name()); |
| 123 | + } |
| 124 | + catch (IOException e) |
| 125 | + { |
| 126 | + throw new RuntimeException(e); |
| 127 | + } |
| 128 | + finally |
| 129 | + { |
| 130 | + _iTimer.setPhase(currentPhase); |
| 131 | + } |
| 132 | + } |
121 | 133 |
|
122 | | - // Can be null, if no documents (e.g., shortly after bootstrap or clear index) |
123 | | - if (null != securityContextDocValues) |
| 134 | + @Override |
| 135 | + public Scorer get(long leadCost) throws IOException |
124 | 136 | { |
125 | | - while (NO_MORE_DOCS != (doc = securityContextDocValues.nextDoc())) |
| 137 | + SearchService.SEARCH_PHASE currentPhase = _iTimer.getCurrentPhase(); |
| 138 | + |
| 139 | + try |
126 | 140 | { |
127 | | - BytesRef bytesRef = securityContextDocValues.binaryValue(); |
128 | | - String securityContext = StringUtils.trimToNull(bytesRef.utf8ToString()); |
129 | | - |
130 | | - final String containerId; |
131 | | - final String resourceId; |
132 | | - final String categories; |
133 | | - String[] parts = StringUtils.split(securityContext, "|"); |
134 | | - // SecurityContext is usually just a container ID and a string of categories, but in some cases it adds a resource ID. |
135 | | - containerId = parts[0]; |
136 | | - if (parts.length > 1) |
137 | | - categories = parts[1]; |
138 | | - else |
139 | | - categories = null; |
140 | | - if (parts.length > 2) |
141 | | - resourceId = parts[2]; |
142 | | - else |
143 | | - resourceId = null; |
144 | | - |
145 | | - // Must have read permission on the container (always). Must also have read permissions on resource ID, if non-null. |
146 | | - if (isReadable(containerId, categories) && (null == resourceId || canReadResource(resourceId, containerId))) |
147 | | - bits.set(doc); |
| 141 | + _iTimer.setPhase(SearchService.SEARCH_PHASE.applySecurityFilter); |
| 142 | + int maxDoc = _reader.maxDoc(); |
| 143 | + FixedBitSet bits = new FixedBitSet(maxDoc); |
| 144 | + int doc; |
| 145 | + |
| 146 | + // Can be null, if no documents (e.g., shortly after bootstrap or clear index) |
| 147 | + if (null != _securityContextDocValues) |
| 148 | + { |
| 149 | + while (NO_MORE_DOCS != (doc = _securityContextDocValues.nextDoc())) |
| 150 | + { |
| 151 | + BytesRef bytesRef = _securityContextDocValues.binaryValue(); |
| 152 | + String securityContext = StringUtils.trimToNull(bytesRef.utf8ToString()); |
| 153 | + |
| 154 | + final String containerId; |
| 155 | + final String resourceId; |
| 156 | + final String categories; |
| 157 | + String[] parts = StringUtils.split(securityContext, "|"); |
| 158 | + // SecurityContext is usually just a container ID and a string of categories, but in some cases it adds a resource ID. |
| 159 | + containerId = parts[0]; |
| 160 | + if (parts.length > 1) |
| 161 | + categories = parts[1]; |
| 162 | + else |
| 163 | + categories = null; |
| 164 | + if (parts.length > 2) |
| 165 | + resourceId = parts[2]; |
| 166 | + else |
| 167 | + resourceId = null; |
| 168 | + |
| 169 | + // Must have read permission on the container (always). Must also have read permissions on resource ID, if non-null. |
| 170 | + if (isReadable(containerId, categories) && (null == resourceId || canReadResource(resourceId, containerId))) |
| 171 | + bits.set(doc); |
| 172 | + } |
| 173 | + } |
| 174 | + |
| 175 | + return new ConstantScoreScorer(score(), scoreMode, new BitSetIterator(bits, bits.approximateCardinality())); |
| 176 | + } |
| 177 | + finally |
| 178 | + { |
| 179 | + _iTimer.setPhase(currentPhase); |
148 | 180 | } |
149 | 181 | } |
150 | 182 |
|
151 | | - return new ConstantScoreScorer(this, score(), scoreMode, new BitSetIterator(bits, bits.approximateCardinality())); |
152 | | - } |
153 | | - finally |
154 | | - { |
155 | | - _iTimer.setPhase(currentPhase); |
156 | | - } |
| 183 | + @Override |
| 184 | + public long cost() |
| 185 | + { |
| 186 | + return null == _securityContextDocValues ? 0 : _securityContextDocValues.cost(); |
| 187 | + } |
| 188 | + }; |
157 | 189 | } |
158 | 190 | }; |
159 | 191 | } |
|
0 commit comments