blob: e96053a0260f915f33b1799b63fe1ffefffdc95e [file] [log] [blame]
package org.apache.commons.digester3.binder;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import static java.lang.String.format;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.digester3.RuleSet;
/**
* The default Digester EDSL implementation.
*
* @since 3.0
*/
final class DefaultRulesBinder
implements RulesBinder
{
/**
* Errors that can occur during binding time or rules creation.
*/
private final List<ErrorMessage> errors = new ArrayList<ErrorMessage>();
/**
*
*/
private final FromBinderRuleSet fromBinderRuleSet = new FromBinderRuleSet();
/**
*
*/
private ClassLoader classLoader;
/**
*
*
* @param classLoader
*/
void initialize( ClassLoader classLoader )
{
this.classLoader = classLoader;
fromBinderRuleSet.clear();
errors.clear();
}
/**
* {@inheritDoc}
*/
public ClassLoader getContextClassLoader()
{
return this.classLoader;
}
/**
* {@inheritDoc}
*/
public void addError( String messagePattern, Object... arguments )
{
StackTraceElement[] stackTrace = new Exception().getStackTrace();
StackTraceElement element = null;
int stackIndex = stackTrace.length - 1;
while ( element == null && stackIndex > 0 ) // O(n) there's no better way
{
Class<?> moduleClass;
try
{
// check if the set ClassLoader resolves the Class in the StackTrace
moduleClass = Class.forName( stackTrace[stackIndex].getClassName(), false, this.classLoader );
}
catch ( ClassNotFoundException e )
{
try
{
// try otherwise with current ClassLoader
moduleClass =
Class.forName( stackTrace[stackIndex].getClassName(), false, this.getClass().getClassLoader() );
}
catch ( ClassNotFoundException e1 )
{
// Class in the StackTrace can't be found, don't write the file name:line number detail in the
// message
moduleClass = null;
}
}
if ( moduleClass != null && RulesModule.class.isAssignableFrom( moduleClass ) )
{
element = stackTrace[stackIndex];
}
stackIndex--;
}
if ( element != null )
{
messagePattern = format( "%s (%s:%s)", messagePattern, element.getFileName(), element.getLineNumber() );
}
addError( new ErrorMessage( messagePattern, arguments ) );
}
/**
* {@inheritDoc}
*/
public void addError( Throwable t )
{
String message = "An exception was caught and reported. Message: " + t.getMessage();
addError( new ErrorMessage( message, t ) );
}
/**
* Records an error, the full details of which will be logged, and the message of which will be presented to the
* user at a later time.
*
* @param errorMessage The error to record.
*/
private void addError( ErrorMessage errorMessage )
{
this.errors.add( errorMessage );
}
/**
* {@inheritDoc}
*/
public void install( RulesModule rulesModule )
{
rulesModule.configure( this );
}
/**
* {@inheritDoc}
*/
public LinkedRuleBuilder forPattern( String pattern )
{
final String keyPattern;
if ( pattern == null || pattern.length() == 0 )
{
addError( "Null or empty pattern is not valid" );
keyPattern = null;
}
else
{
if ( pattern.endsWith( "/" ) )
{
// to help users who accidently add '/' to the end of their patterns
keyPattern = pattern.substring( 0, pattern.length() - 1 );
}
else
{
keyPattern = pattern;
}
}
return new LinkedRuleBuilder( this, fromBinderRuleSet, classLoader, keyPattern );
}
/**
*
*
* @return
*/
boolean hasError()
{
return !errors.isEmpty();
}
/**
*
*
* @return
*/
int errorsSize()
{
return errors.size();
}
/**
*
*
* @return
*/
Iterable<ErrorMessage> getErrors()
{
return errors;
}
/**
*
*
* @return
*/
RuleSet getFromBinderRuleSet()
{
return fromBinderRuleSet;
}
}