View Javadoc
1   package org.codehaus.plexus.interpolation;
2   
3   /*
4    * Copyright 2001-2008 Codehaus Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import java.util.Collection;
20  import java.util.Collections;
21  import java.util.List;
22  import java.util.Stack;
23  
24  import org.codehaus.plexus.interpolation.util.ValueSourceUtils;
25  
26  /**
27   * {@link RecursionInterceptor} implementation that provides support for expressions
28   * with multiple synonyms, such as project.build.directory == pom.build.directory ==
29   * build.directory in Maven's POM.
30   *
31   * @author jdcasey
32   */
33  public class PrefixAwareRecursionInterceptor implements RecursionInterceptor {
34  
35      public static final String DEFAULT_START_TOKEN = "\\$\\{";
36  
37      public static final String DEFAULT_END_TOKEN = "\\}";
38  
39      private Stack<String> nakedExpressions = new Stack<String>();
40  
41      private final String[] possiblePrefixes;
42  
43      private boolean watchUnprefixedExpressions = true;
44  
45      /**
46       * Use the specified expression prefixes to detect synonyms, and specify whether
47       * unprefixed expressions can be considered synonyms.
48       *
49       * @param possiblePrefixes           The collection of expression prefixes supported
50       * @param watchUnprefixedExpressions Whether to consider unprefixed expressions as synonyms
51       */
52      public PrefixAwareRecursionInterceptor(Collection<String> possiblePrefixes, boolean watchUnprefixedExpressions) {
53          this.possiblePrefixes = possiblePrefixes.toArray(new String[possiblePrefixes.size()]);
54          this.watchUnprefixedExpressions = watchUnprefixedExpressions;
55      }
56  
57      /**
58       * Use the specified expression prefixes to detect synonyms. Consider
59       * unprefixed expressions synonyms as well.
60       *
61       * @param possiblePrefixes The collection of expression prefixes supported
62       */
63      public PrefixAwareRecursionInterceptor(Collection<String> possiblePrefixes) {
64          this.possiblePrefixes = possiblePrefixes.toArray(new String[possiblePrefixes.size()]);
65      }
66  
67      public boolean hasRecursiveExpression(String expression) {
68          String realExpr = ValueSourceUtils.trimPrefix(expression, possiblePrefixes, watchUnprefixedExpressions);
69          return realExpr != null && nakedExpressions.contains(realExpr);
70      }
71  
72      public void expressionResolutionFinished(String expression) {
73          nakedExpressions.pop();
74      }
75  
76      public void expressionResolutionStarted(String expression) {
77          String realExpr = ValueSourceUtils.trimPrefix(expression, possiblePrefixes, watchUnprefixedExpressions);
78          nakedExpressions.push(realExpr);
79      }
80  
81      /**
82       * When an expression is determined to be a recursive reference, this method
83       * returns the sublist of tracked expressions that participate in this cycle.
84       * Otherwise, if the expression isn't present in the in-process stack, return
85       * {@link Collections#EMPTY_LIST}. Also, if the expression doesn't have a matched
86       * prefix from this interceptor's list, and unprefixed expressions aren't allowed
87       * then return {@link Collections#EMPTY_LIST}.
88       */
89      public List getExpressionCycle(String expression) {
90          String expr = ValueSourceUtils.trimPrefix(expression, possiblePrefixes, watchUnprefixedExpressions);
91  
92          if (expr == null) {
93              return Collections.EMPTY_LIST;
94          }
95  
96          int idx = nakedExpressions.indexOf(expr);
97          if (idx < 0) {
98              return Collections.EMPTY_LIST;
99          } else {
100             return nakedExpressions.subList(idx, nakedExpressions.size());
101         }
102     }
103 
104     public void clear() {
105         nakedExpressions.clear();
106     }
107 }