4040import java .util .concurrent .CopyOnWriteArraySet ;
4141import java .util .stream .Collectors ;
4242
43+ import static org .elasticsearch .xpack .core .security .authz .IndicesAndAliasesResolverField .NO_INDEX_PLACEHOLDER ;
44+
4345public class IndicesAndAliasesResolver {
4446
45- private static final ResolvedIndices NO_INDEX_PLACEHOLDER_RESOLVED =
46- ResolvedIndices .local (IndicesAndAliasesResolverField .NO_INDEX_PLACEHOLDER );
4747 //`*,-*` what we replace indices with if we need Elasticsearch to return empty responses without throwing exception
4848 private static final String [] NO_INDICES_ARRAY = new String [] { "*" , "-*" };
4949 static final List <String > NO_INDICES_LIST = Arrays .asList (NO_INDICES_ARRAY );
@@ -87,12 +87,14 @@ public IndicesAndAliasesResolver(Settings settings, ClusterService clusterServic
8787
8888 public ResolvedIndices resolve (TransportRequest request , MetaData metaData , AuthorizedIndices authorizedIndices ) {
8989 if (request instanceof IndicesAliasesRequest ) {
90- ResolvedIndices indices = ResolvedIndices .empty ();
90+ ResolvedIndices . Builder resolvedIndicesBuilder = new ResolvedIndices .Builder ();
9191 IndicesAliasesRequest indicesAliasesRequest = (IndicesAliasesRequest ) request ;
9292 for (IndicesRequest indicesRequest : indicesAliasesRequest .getAliasActions ()) {
93- indices = ResolvedIndices .add (indices , resolveIndicesAndAliases (indicesRequest , metaData , authorizedIndices ));
93+ final ResolvedIndices resolved = resolveIndicesAndAliases (indicesRequest , metaData , authorizedIndices );
94+ resolvedIndicesBuilder .addLocal (resolved .getLocal ());
95+ resolvedIndicesBuilder .addRemote (resolved .getRemote ());
9496 }
95- return indices ;
97+ return resolvedIndicesBuilder . build () ;
9698 }
9799
98100 // if for some reason we are missing an action... just for safety we'll reject
@@ -102,10 +104,10 @@ public ResolvedIndices resolve(TransportRequest request, MetaData metaData, Auth
102104 return resolveIndicesAndAliases ((IndicesRequest ) request , metaData , authorizedIndices );
103105 }
104106
105- ResolvedIndices resolveIndicesAndAliases (IndicesRequest indicesRequest , MetaData metaData ,
106- AuthorizedIndices authorizedIndices ) {
107+
108+ ResolvedIndices resolveIndicesAndAliases (IndicesRequest indicesRequest , MetaData metaData , AuthorizedIndices authorizedIndices ) {
109+ final ResolvedIndices .Builder resolvedIndicesBuilder = new ResolvedIndices .Builder ();
107110 boolean indicesReplacedWithNoIndices = false ;
108- final ResolvedIndices indices ;
109111 if (indicesRequest instanceof PutMappingRequest && ((PutMappingRequest ) indicesRequest ).getConcreteIndex () != null ) {
110112 /*
111113 * This is a special case since PutMappingRequests from dynamic mapping updates have a concrete index
@@ -114,7 +116,7 @@ ResolvedIndices resolveIndicesAndAliases(IndicesRequest indicesRequest, MetaData
114116 */
115117 assert indicesRequest .indices () == null || indicesRequest .indices ().length == 0
116118 : "indices are: " + Arrays .toString (indicesRequest .indices ()); // Arrays.toString() can handle null values - all good
117- return ResolvedIndices . local (((PutMappingRequest ) indicesRequest ).getConcreteIndex ().getName ());
119+ resolvedIndicesBuilder . addLocal (((PutMappingRequest ) indicesRequest ).getConcreteIndex ().getName ());
118120 } else if (indicesRequest instanceof IndicesRequest .Replaceable ) {
119121 IndicesRequest .Replaceable replaceable = (IndicesRequest .Replaceable ) indicesRequest ;
120122 final boolean replaceWildcards = indicesRequest .indicesOptions ().expandWildcardsOpen ()
@@ -127,13 +129,12 @@ ResolvedIndices resolveIndicesAndAliases(IndicesRequest indicesRequest, MetaData
127129 indicesOptions .expandWildcardsOpen (), indicesOptions .expandWildcardsClosed ());
128130 }
129131
130- ResolvedIndices result = ResolvedIndices .empty ();
131132 // check for all and return list of authorized indices
132133 if (IndexNameExpressionResolver .isAllIndices (indicesList (indicesRequest .indices ()))) {
133134 if (replaceWildcards ) {
134135 for (String authorizedIndex : authorizedIndices .get ()) {
135136 if (isIndexVisible (authorizedIndex , indicesOptions , metaData )) {
136- result = ResolvedIndices . add ( result , ResolvedIndices . local ( authorizedIndex ) );
137+ resolvedIndicesBuilder . addLocal ( authorizedIndex );
137138 }
138139 }
139140 }
@@ -144,7 +145,7 @@ ResolvedIndices resolveIndicesAndAliases(IndicesRequest indicesRequest, MetaData
144145 if (allowsRemoteIndices (indicesRequest )) {
145146 split = remoteClusterResolver .splitLocalAndRemoteIndexNames (indicesRequest .indices ());
146147 } else {
147- split = ResolvedIndices . local (indicesRequest .indices ());
148+ split = new ResolvedIndices ( Arrays . asList (indicesRequest .indices ()), Collections . emptyList ());
148149 }
149150 List <String > replaced = replaceWildcardsWithAuthorizedIndices (split .getLocal (), indicesOptions , metaData ,
150151 authorizedIndices .get (), replaceWildcards );
@@ -153,22 +154,23 @@ ResolvedIndices resolveIndicesAndAliases(IndicesRequest indicesRequest, MetaData
153154 //remove all the ones that the current user is not authorized for and ignore them
154155 replaced = replaced .stream ().filter (authorizedIndices .get ()::contains ).collect (Collectors .toList ());
155156 }
156- result = new ResolvedIndices (new ArrayList <>(replaced ), split .getRemote ());
157+ resolvedIndicesBuilder .addLocal (replaced );
158+ resolvedIndicesBuilder .addRemote (split .getRemote ());
157159 }
158- if (result .isEmpty ()) {
160+
161+ if (resolvedIndicesBuilder .isEmpty ()) {
159162 if (indicesOptions .allowNoIndices ()) {
160163 //this is how we tell es core to return an empty response, we can let the request through being sure
161164 //that the '-*' wildcard expression will be resolved to no indices. We can't let empty indices through
162165 //as that would be resolved to _all by es core.
163166 replaceable .indices (NO_INDICES_ARRAY );
164167 indicesReplacedWithNoIndices = true ;
165- indices = NO_INDEX_PLACEHOLDER_RESOLVED ;
168+ resolvedIndicesBuilder . addLocal ( NO_INDEX_PLACEHOLDER ) ;
166169 } else {
167170 throw new IndexNotFoundException (Arrays .toString (indicesRequest .indices ()));
168171 }
169172 } else {
170- replaceable .indices (result .toArray ());
171- indices = result ;
173+ replaceable .indices (resolvedIndicesBuilder .build ().toArray ());
172174 }
173175 } else {
174176 if (containsWildcards (indicesRequest )) {
@@ -182,11 +184,9 @@ ResolvedIndices resolveIndicesAndAliases(IndicesRequest indicesRequest, MetaData
182184 //That is fine though because they never contain wildcards, as they get replaced as part of the authorization of their
183185 //corresponding parent request on the coordinating node. Hence wildcards don't need to get replaced nor exploded for
184186 // shard level requests.
185- List <String > resolvedNames = new ArrayList <>();
186187 for (String name : indicesRequest .indices ()) {
187- resolvedNames . add (nameExpressionResolver .resolveDateMathExpression (name ));
188+ resolvedIndicesBuilder . addLocal (nameExpressionResolver .resolveDateMathExpression (name ));
188189 }
189- indices = new ResolvedIndices (resolvedNames , new ArrayList <>());
190190 }
191191
192192 if (indicesRequest instanceof AliasesRequest ) {
@@ -207,10 +207,10 @@ ResolvedIndices resolveIndicesAndAliases(IndicesRequest indicesRequest, MetaData
207207 //if we replaced the indices with '-*' we shouldn't be adding the aliases to the list otherwise the request will
208208 //not get authorized. Leave only '-*' and ignore the rest, result will anyway be empty.
209209 } else {
210- return ResolvedIndices . add ( indices , ResolvedIndices . local ( aliasesRequest .aliases () ));
210+ resolvedIndicesBuilder . addLocal ( aliasesRequest .aliases ());
211211 }
212212 }
213- return indices ;
213+ return resolvedIndicesBuilder . build () ;
214214 }
215215
216216 public static boolean allowsRemoteIndices (IndicesRequest request ) {
@@ -423,24 +423,8 @@ public static class ResolvedIndices {
423423 private final List <String > remote ;
424424
425425 ResolvedIndices (List <String > local , List <String > remote ) {
426- this .local = local ;
427- this .remote = remote ;
428- }
429-
430- /**
431- * Constructs a new instance of this class where both the {@link #getLocal() local} and {@link #getRemote() remote} index lists
432- * are empty.
433- */
434- private static ResolvedIndices empty () {
435- return new ResolvedIndices (Collections .emptyList (), Collections .emptyList ());
436- }
437-
438- /**
439- * Constructs a new instance of this class where both the {@link #getLocal() local} index list is populated with <code>names</code>
440- * and the {@link #getRemote() remote} index list is empty.
441- */
442- private static ResolvedIndices local (String ... names ) {
443- return new ResolvedIndices (Arrays .asList (names ), Collections .emptyList ());
426+ this .local = Collections .unmodifiableList (local );
427+ this .remote = Collections .unmodifiableList (remote );
444428 }
445429
446430 /**
@@ -449,14 +433,14 @@ private static ResolvedIndices local(String... names) {
449433 * to <code>[ "-a1", "a*" ]</code>. As a consequence, this list <em>may contain duplicates</em>.
450434 */
451435 public List <String > getLocal () {
452- return Collections . unmodifiableList ( local ) ;
436+ return local ;
453437 }
454438
455439 /**
456440 * Returns the collection of index names that have been stored as "remote" indices.
457441 */
458442 public List <String > getRemote () {
459- return Collections . unmodifiableList ( remote ) ;
443+ return remote ;
460444 }
461445
462446 /**
@@ -471,7 +455,7 @@ public boolean isEmpty() {
471455 * {@link IndicesAndAliasesResolverField#NO_INDEX_PLACEHOLDER no-index-placeholder} and nothing else.
472456 */
473457 public boolean isNoIndicesPlaceholder () {
474- return remote .isEmpty () && local .size () == 1 && local .contains (IndicesAndAliasesResolverField . NO_INDEX_PLACEHOLDER );
458+ return remote .isEmpty () && local .size () == 1 && local .contains (NO_INDEX_PLACEHOLDER );
475459 }
476460
477461 private String [] toArray () {
@@ -487,19 +471,43 @@ private String[] toArray() {
487471 }
488472
489473 /**
490- * Returns a new <code> ResolvedIndices</code> contains the {@link #getLocal() local} and {@link #getRemote() remote}
491- * index lists from <code>b</code> appended to the corresponding lists in <code>a</code>.
474+ * Builder class for ResolvedIndices that allows for the building of a list of indices
475+ * without the need to construct new objects and merging them together
492476 */
493- private static ResolvedIndices add (ResolvedIndices a , ResolvedIndices b ) {
494- List <String > local = new ArrayList <>(a .local .size () + b .local .size ());
495- local .addAll (a .local );
496- local .addAll (b .local );
497-
498- List <String > remote = new ArrayList <>(a .remote .size () + b .remote .size ());
499- remote .addAll (a .remote );
500- remote .addAll (b .remote );
501- return new ResolvedIndices (local , remote );
502- }
477+ private static class Builder {
478+
479+ private final List <String > local = new ArrayList <>();
480+ private final List <String > remote = new ArrayList <>();
503481
482+ /** add a local index name */
483+ private void addLocal (String index ) {
484+ local .add (index );
485+ }
486+
487+ /** adds the array of local index names */
488+ private void addLocal (String [] indices ) {
489+ local .addAll (Arrays .asList (indices ));
490+ }
491+
492+ /** adds the list of local index names */
493+ private void addLocal (List <String > indices ) {
494+ local .addAll (indices );
495+ }
496+
497+ /** adds the list of remote index names */
498+ private void addRemote (List <String > indices ) {
499+ remote .addAll (indices );
500+ }
501+
502+ /** @return <code>true</code> if both the local and remote index lists are empty. */
503+ private boolean isEmpty () {
504+ return local .isEmpty () && remote .isEmpty ();
505+ }
506+
507+ /** @return a immutable ResolvedIndices instance with the local and remote index lists */
508+ private ResolvedIndices build () {
509+ return new ResolvedIndices (local , remote );
510+ }
511+ }
504512 }
505513}
0 commit comments