1 package org.apache.commons.digester3.xmlrules;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.net.MalformedURLException;
23 import java.net.URL;
24 import java.util.Set;
25
26 import org.apache.commons.digester3.Rule;
27 import org.apache.commons.digester3.binder.RulesBinder;
28 import org.apache.commons.digester3.binder.RulesModule;
29 import org.xml.sax.Attributes;
30
31
32
33
34
35
36
37
38 final class IncludeRule
39 extends Rule
40 {
41
42 private static final String CLASSPATH_URL_PREFIX = "classpath:";
43
44 private final WithMemoryRulesBinder memoryRulesBinder;
45
46 private final RulesBinder targetRulesBinder;
47
48 public IncludeRule( final WithMemoryRulesBinder memoryRulesBinder, final RulesBinder targetRulesBinder )
49 {
50 this.memoryRulesBinder = memoryRulesBinder;
51 this.targetRulesBinder = targetRulesBinder;
52 }
53
54
55
56
57 @Override
58 public void begin( String namespace, String name, Attributes attributes )
59 throws Exception
60 {
61
62 String fileName = attributes.getValue( "url" );
63 if ( fileName != null && fileName.length() > 0 )
64 {
65 final URL xmlRulesResource;
66
67 if ( fileName.startsWith( CLASSPATH_URL_PREFIX ) )
68 {
69 String path = fileName.substring( CLASSPATH_URL_PREFIX.length() );
70 if ( '/' == path.charAt( 0 ) )
71 {
72 path = path.substring( 1 );
73 }
74 xmlRulesResource = this.targetRulesBinder.getContextClassLoader().getResource( path );
75 if ( xmlRulesResource == null )
76 {
77 targetRulesBinder.addError( "Resource '%s' not found, please make sure it is in the classpath",
78 path );
79 return;
80 }
81 }
82 else
83 {
84 try
85 {
86 xmlRulesResource = new URL( fileName );
87 }
88 catch ( MalformedURLException e )
89 {
90 targetRulesBinder.addError( "An error occurred while inculing file from '%s': %s", fileName,
91 e.getMessage() );
92 return;
93 }
94 }
95
96 Set<String> includedFiles = memoryRulesBinder.getIncludedFiles();
97 String xmlRulesResourceString = xmlRulesResource.toString();
98 if ( includedFiles.add( xmlRulesResourceString ) )
99 {
100 try
101 {
102 install( new FromXmlRulesModule()
103 {
104
105 @Override
106 protected void loadRules()
107 {
108 loadXMLRules( xmlRulesResource );
109 }
110
111 } );
112 }
113 finally
114 {
115 includedFiles.remove( xmlRulesResourceString );
116 }
117 }
118 else
119 {
120 targetRulesBinder.addError( "Circular file inclusion detected for XML rules: %s", xmlRulesResource );
121 }
122 }
123
124
125
126 String className = attributes.getValue( "class" );
127 if ( className != null && className.length() > 0 )
128 {
129 try
130 {
131 Class<?> cls = Class.forName( className );
132 if ( !RulesModule.class.isAssignableFrom( cls ) )
133 {
134 targetRulesBinder.addError( "Class '%s' if not a '%s' implementation", className,
135 RulesModule.class.getName() );
136 return;
137 }
138
139 RulesModule rulesSource = (RulesModule) cls.newInstance();
140
141 install( rulesSource );
142 }
143 catch ( Exception e )
144 {
145 targetRulesBinder.addError( "Impossible to include programmatic rules from class '%s': %s", className,
146 e.getMessage() );
147 }
148 }
149 }
150
151 private void install( RulesModule rulesModule )
152 {
153
154 rulesModule.configure( new PrefixedRulesBinder( targetRulesBinder,
155 memoryRulesBinder.getPatternStack().toString() ) );
156 }
157
158 }