View Javadoc

1   package org.apache.commons.digester3.binder;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import static java.lang.String.format;
23  
24  import java.util.ArrayList;
25  import java.util.List;
26  
27  import org.apache.commons.digester3.RuleSet;
28  
29  /**
30   * The default Digester EDSL implementation.
31   *
32   * @since 3.0
33   */
34  final class DefaultRulesBinder
35      implements RulesBinder
36  {
37  
38      /**
39       * Errors that can occur during binding time or rules creation.
40       */
41      private final List<ErrorMessage> errors = new ArrayList<ErrorMessage>();
42  
43      /**
44       *
45       */
46      private final FromBinderRuleSet fromBinderRuleSet = new FromBinderRuleSet();
47  
48      /**
49       *
50       */
51      private ClassLoader classLoader;
52  
53      /**
54       *
55       *
56       * @param classLoader
57       */
58      void initialize( ClassLoader classLoader )
59      {
60          this.classLoader = classLoader;
61          fromBinderRuleSet.clear();
62          errors.clear();
63      }
64  
65      /**
66       * {@inheritDoc}
67       */
68      public ClassLoader getContextClassLoader()
69      {
70          return this.classLoader;
71      }
72  
73      /**
74       * {@inheritDoc}
75       */
76      public void addError( String messagePattern, Object... arguments )
77      {
78          StackTraceElement[] stackTrace = new Exception().getStackTrace();
79          StackTraceElement element = null;
80  
81          int stackIndex = stackTrace.length - 1;
82          while ( element == null && stackIndex > 0 ) // O(n) there's no better way
83          {
84              Class<?> moduleClass;
85              try
86              {
87                  // check if the set ClassLoader resolves the Class in the StackTrace
88                  moduleClass = Class.forName( stackTrace[stackIndex].getClassName(), false, this.classLoader );
89              }
90              catch ( ClassNotFoundException e )
91              {
92                  try
93                  {
94                      // try otherwise with current ClassLoader
95                      moduleClass =
96                          Class.forName( stackTrace[stackIndex].getClassName(), false, this.getClass().getClassLoader() );
97                  }
98                  catch ( ClassNotFoundException e1 )
99                  {
100                     // Class in the StackTrace can't be found, don't write the file name:line number detail in the
101                     // message
102                     moduleClass = null;
103                 }
104             }
105 
106             if ( moduleClass != null && RulesModule.class.isAssignableFrom( moduleClass ) )
107             {
108                 element = stackTrace[stackIndex];
109             }
110 
111             stackIndex--;
112         }
113 
114         if ( element != null )
115         {
116             messagePattern = format( "%s (%s:%s)", messagePattern, element.getFileName(), element.getLineNumber() );
117         }
118         addError( new ErrorMessage( messagePattern, arguments ) );
119     }
120 
121     /**
122      * {@inheritDoc}
123      */
124     public void addError( Throwable t )
125     {
126         String message = "An exception was caught and reported. Message: " + t.getMessage();
127         addError( new ErrorMessage( message, t ) );
128     }
129 
130     /**
131      * Records an error, the full details of which will be logged, and the message of which will be presented to the
132      * user at a later time.
133      *
134      * @param errorMessage The error to record.
135      */
136     private void addError( ErrorMessage errorMessage )
137     {
138         this.errors.add( errorMessage );
139     }
140 
141     /**
142      * {@inheritDoc}
143      */
144     public void install( RulesModule rulesModule )
145     {
146         rulesModule.configure( this );
147     }
148 
149     /**
150      * {@inheritDoc}
151      */
152     public LinkedRuleBuilder forPattern( String pattern )
153     {
154         final String keyPattern;
155 
156         if ( pattern == null || pattern.length() == 0 )
157         {
158             addError( "Null or empty pattern is not valid" );
159             keyPattern = null;
160         }
161         else
162         {
163             if ( pattern.endsWith( "/" ) )
164             {
165                 // to help users who accidently add '/' to the end of their patterns
166                 keyPattern = pattern.substring( 0, pattern.length() - 1 );
167             }
168             else
169             {
170                 keyPattern = pattern;
171             }
172         }
173 
174         return new LinkedRuleBuilder( this, fromBinderRuleSet, classLoader, keyPattern );
175     }
176 
177     /**
178      *
179      *
180      * @return
181      */
182     boolean hasError()
183     {
184         return !errors.isEmpty();
185     }
186 
187     /**
188      *
189      *
190      * @return
191      */
192     int errorsSize()
193     {
194         return errors.size();
195     }
196 
197     /**
198      *
199      *
200      * @return
201      */
202     Iterable<ErrorMessage> getErrors()
203     {
204         return errors;
205     }
206 
207     /**
208      *
209      *
210      * @return
211      */
212     RuleSet getFromBinderRuleSet()
213     {
214         return fromBinderRuleSet;
215     }
216 
217 }