001 package org.apache.commons.digester3.plugins.strategies; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022 import static org.apache.commons.beanutils.MethodUtils.getAccessibleMethod; 023 024 import java.lang.reflect.Method; 025 026 import org.apache.commons.digester3.Digester; 027 import org.apache.commons.digester3.plugins.PluginException; 028 import org.apache.commons.digester3.plugins.RuleLoader; 029 import org.apache.commons.logging.Log; 030 031 /** 032 * A RuleLoader which invokes a static method on a target class, leaving that method to actually instantiate and add new 033 * rules to a Digester instance. 034 * 035 * @since 1.6 036 */ 037 public class LoaderFromClass 038 extends RuleLoader 039 { 040 041 private final Class<?> rulesClass; 042 043 private final Method rulesMethod; 044 045 /** 046 * Constructor. 047 * 048 * @param rulesClass The target class 049 * @param rulesMethod The method has to be invoked 050 */ 051 public LoaderFromClass( Class<?> rulesClass, Method rulesMethod ) 052 { 053 this.rulesClass = rulesClass; 054 this.rulesMethod = rulesMethod; 055 } 056 057 /** 058 * Constructor. 059 * 060 * @param rulesClass The target class 061 * @param methodName The method name has to be invoked 062 * @throws PluginException if input method can't be located inside the given class 063 */ 064 public LoaderFromClass( Class<?> rulesClass, String methodName ) 065 throws PluginException 066 { 067 068 Method method = locateMethod( rulesClass, methodName ); 069 070 if ( method == null ) 071 { 072 throw new PluginException( "rule class " + rulesClass.getName() + " does not have method " + methodName 073 + " or that method has an invalid signature." ); 074 } 075 076 this.rulesClass = rulesClass; 077 this.rulesMethod = method; 078 } 079 080 /** 081 * {@inheritDoc} 082 */ 083 @Override 084 public void addRules( Digester d, String path ) 085 throws PluginException 086 { 087 Log log = d.getLogger(); 088 boolean debug = log.isDebugEnabled(); 089 if ( debug ) 090 { 091 log.debug( "LoaderFromClass loading rules for plugin at path [" + path + "]" ); 092 } 093 094 try 095 { 096 Object[] params = { d, path }; 097 rulesMethod.invoke( null, params ); 098 } 099 catch ( Exception e ) 100 { 101 throw new PluginException( 102 "Unable to invoke rules method " + rulesMethod + " on rules class " + rulesClass, 103 e ); 104 } 105 } 106 107 /** 108 * Find a method on the specified class whose name matches methodName, and whose signature is: 109 * <code> public static void foo(Digester d, String patternPrefix);</code>. 110 * 111 * @param rulesClass The target class 112 * @param methodName The method name has to be invoked 113 * @return The method name has to be invoked, or null if no such method exists. 114 * @throws PluginException if any error occurs while discovering the method 115 */ 116 public static Method locateMethod( Class<?> rulesClass, String methodName ) 117 throws PluginException 118 { 119 Class<?>[] paramSpec = { Digester.class, String.class }; 120 Method rulesMethod = getAccessibleMethod( rulesClass, methodName, paramSpec ); 121 122 return rulesMethod; 123 } 124 125 }