~mortenoh/+junk/dhis2-detailed-import-export

« back to all changes in this revision

Viewing changes to dhis-2/dhis-support/dhis-support-webwork/src/main/java/org/hisp/dhis/webwork/configuration/UrlXmlConfigurationProvider.java

  • Committer: larshelge at gmail
  • Date: 2009-03-03 16:46:36 UTC
  • Revision ID: larshelge@gmail.com-20090303164636-2sjlrquo7ib1gf7r
Initial check-in

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.hisp.dhis.webwork.configuration;
 
2
 
 
3
/*
 
4
 * This is a modified com.opensymphony.xwork.config.XmlConfigurationProvider.
 
5
 * The modification makes it possible to load xwork.xml files from inside JAR
 
6
 * files through URLs.
 
7
 * 
 
8
 * What kind of license should be put here?
 
9
 */
 
10
 
 
11
import java.io.IOException;
 
12
import java.io.InputStream;
 
13
import java.lang.reflect.Modifier;
 
14
import java.net.MalformedURLException;
 
15
import java.net.URL;
 
16
import java.util.ArrayList;
 
17
import java.util.HashMap;
 
18
import java.util.Iterator;
 
19
import java.util.LinkedHashMap;
 
20
import java.util.List;
 
21
import java.util.Map;
 
22
import java.util.Set;
 
23
import java.util.TreeSet;
 
24
 
 
25
import org.apache.commons.logging.Log;
 
26
import org.apache.commons.logging.LogFactory;
 
27
import org.w3c.dom.Document;
 
28
import org.w3c.dom.Element;
 
29
import org.w3c.dom.Node;
 
30
import org.w3c.dom.NodeList;
 
31
import org.xml.sax.InputSource;
 
32
 
 
33
import com.opensymphony.util.ClassLoaderUtil;
 
34
import com.opensymphony.util.FileManager;
 
35
import com.opensymphony.util.TextUtils;
 
36
import com.opensymphony.xwork.Action;
 
37
import com.opensymphony.xwork.ActionSupport;
 
38
import com.opensymphony.xwork.ObjectFactory;
 
39
import com.opensymphony.xwork.XworkException;
 
40
import com.opensymphony.xwork.config.Configuration;
 
41
import com.opensymphony.xwork.config.ConfigurationException;
 
42
import com.opensymphony.xwork.config.ConfigurationProvider;
 
43
import com.opensymphony.xwork.config.ConfigurationUtil;
 
44
import com.opensymphony.xwork.config.ExternalReferenceResolver;
 
45
import com.opensymphony.xwork.config.entities.ActionConfig;
 
46
import com.opensymphony.xwork.config.entities.ExceptionMappingConfig;
 
47
import com.opensymphony.xwork.config.entities.ExternalReference;
 
48
import com.opensymphony.xwork.config.entities.InterceptorConfig;
 
49
import com.opensymphony.xwork.config.entities.InterceptorStackConfig;
 
50
import com.opensymphony.xwork.config.entities.PackageConfig;
 
51
import com.opensymphony.xwork.config.entities.ResultConfig;
 
52
import com.opensymphony.xwork.config.entities.ResultTypeConfig;
 
53
import com.opensymphony.xwork.config.providers.InterceptorBuilder;
 
54
import com.opensymphony.xwork.config.providers.XmlHelper;
 
55
import com.opensymphony.xwork.util.DomHelper;
 
56
import com.opensymphony.xwork.util.location.Location;
 
57
 
 
58
/**
 
59
 * @version $Id: UrlXmlConfigurationProvider.java 6335 2008-11-20 11:11:26Z larshelg $
 
60
 */
 
61
@SuppressWarnings( { "unused", "unchecked" } )
 
62
public class UrlXmlConfigurationProvider
 
63
    implements ConfigurationProvider
 
64
{
 
65
    private static final Log LOG = LogFactory.getLog( UrlXmlConfigurationProvider.class );
 
66
 
 
67
    private Configuration configuration;
 
68
 
 
69
    private Set includedFileNames = new TreeSet();
 
70
 
 
71
    private String configFileName = "xwork.xml";
 
72
 
 
73
    public UrlXmlConfigurationProvider( String filename )
 
74
    {
 
75
        this.configFileName = filename;
 
76
    }
 
77
 
 
78
    public UrlXmlConfigurationProvider( String filename, ClassLoader loader )
 
79
    {
 
80
        this.configFileName = filename;
 
81
    }
 
82
 
 
83
    public void destroy()
 
84
    {
 
85
    }
 
86
 
 
87
    public boolean equals( Object o )
 
88
    {
 
89
        if ( this == o )
 
90
        {
 
91
            return true;
 
92
        }
 
93
 
 
94
        if ( !(o instanceof UrlXmlConfigurationProvider) )
 
95
        {
 
96
            return false;
 
97
        }
 
98
 
 
99
        final UrlXmlConfigurationProvider UrlXmlConfigurationProvider = (UrlXmlConfigurationProvider) o;
 
100
 
 
101
        if ( (configFileName != null) ? (!configFileName.equals( UrlXmlConfigurationProvider.configFileName ))
 
102
            : (UrlXmlConfigurationProvider.configFileName != null) )
 
103
        {
 
104
            return false;
 
105
        }
 
106
 
 
107
        return true;
 
108
    }
 
109
 
 
110
    public int hashCode()
 
111
    {
 
112
        return ((configFileName != null) ? configFileName.hashCode() : 0);
 
113
    }
 
114
 
 
115
    public void init( Configuration configuration )
 
116
    {
 
117
        this.configuration = configuration;
 
118
        includedFileNames.clear();
 
119
 
 
120
        try
 
121
        {
 
122
            loadConfigurationFile( configFileName, null );
 
123
        }
 
124
        catch ( ConfigurationException e )
 
125
        {
 
126
            throw e;
 
127
        }
 
128
        catch ( Exception e )
 
129
        {
 
130
            LOG.fatal( "Could not load XWork configuration file, failing", e );
 
131
            throw new ConfigurationException( "Error loading configuration file " + configFileName, e );
 
132
        }
 
133
    }
 
134
 
 
135
    /**
 
136
     * Tells whether the ConfigurationProvider should reload its configuration.
 
137
     * This method should only be called if
 
138
     * ConfigurationManager.isReloadingConfigs() is true.
 
139
     * 
 
140
     * @return true if the file has been changed since the last time we read it
 
141
     */
 
142
    public boolean needsReload()
 
143
    {
 
144
        boolean needsReload = FileManager.fileNeedsReloading( configFileName );
 
145
        Iterator fileNameIterator = includedFileNames.iterator();
 
146
 
 
147
        while ( !needsReload && (fileNameIterator.hasNext()) )
 
148
        {
 
149
            String fileName = (String) fileNameIterator.next();
 
150
            needsReload = FileManager.fileNeedsReloading( fileName );
 
151
        }
 
152
 
 
153
        return needsReload;
 
154
    }
 
155
 
 
156
    protected InputStream getInputStream( String fileName )
 
157
        throws ConfigurationException
 
158
    {
 
159
        try
 
160
        {
 
161
            URL url = new URL( fileName );
 
162
            return url.openStream();
 
163
        }
 
164
        catch ( MalformedURLException e )
 
165
        {
 
166
            return FileManager.loadFile( fileName, this.getClass() );
 
167
        }
 
168
        catch ( IOException e )
 
169
        {
 
170
            throw new ConfigurationException( "The source of " + fileName + " is not accsesable.", e );
 
171
        }
 
172
    }
 
173
 
 
174
    protected void addAction( Element actionElement, PackageConfig packageContext )
 
175
        throws ConfigurationException
 
176
    {
 
177
        String name = actionElement.getAttribute( "name" );
 
178
        String className = actionElement.getAttribute( "class" );
 
179
        String methodName = actionElement.getAttribute( "method" );
 
180
        Location location = DomHelper.getLocationObject( actionElement );
 
181
 
 
182
        // methodName should be null if it's not set
 
183
        methodName = (methodName.trim().length() > 0) ? methodName.trim() : null;
 
184
 
 
185
        // if you don't specify a class on <action/>, it defaults to
 
186
        // ActionSupport
 
187
        if ( !TextUtils.stringSet( className ) )
 
188
        {
 
189
            className = ActionSupport.class.getName();
 
190
        }
 
191
 
 
192
        if ( !verifyAction( className, name, location ) )
 
193
        {
 
194
            return;
 
195
        }
 
196
 
 
197
        Map actionParams = XmlHelper.getParams( actionElement );
 
198
 
 
199
        Map results;
 
200
 
 
201
        try
 
202
        {
 
203
            results = buildResults( actionElement, packageContext );
 
204
        }
 
205
        catch ( ConfigurationException e )
 
206
        {
 
207
            throw new ConfigurationException( "Error building results for action " + name + " in namespace "
 
208
                + packageContext.getNamespace(), e, actionElement );
 
209
        }
 
210
 
 
211
        List interceptorList = buildInterceptorList( actionElement, packageContext );
 
212
 
 
213
        List externalrefs = buildExternalRefs( actionElement, packageContext );
 
214
 
 
215
        List exceptionMappings = buildExceptionMappings( actionElement, packageContext );
 
216
 
 
217
        ActionConfig actionConfig = new ActionConfig( methodName, className, actionParams, results, interceptorList,
 
218
            externalrefs, exceptionMappings, packageContext.getName() );
 
219
        actionConfig.setLocation( location );
 
220
        packageContext.addActionConfig( name, actionConfig );
 
221
 
 
222
        if ( LOG.isDebugEnabled() )
 
223
        {
 
224
            LOG.debug( "Loaded "
 
225
                + (TextUtils.stringSet( packageContext.getNamespace() ) ? (packageContext.getNamespace() + "/") : "")
 
226
                + name + " in '" + packageContext.getName() + "' package:" + actionConfig );
 
227
        }
 
228
    }
 
229
 
 
230
    protected boolean verifyAction( String className, String name, Location loc )
 
231
    {
 
232
        try
 
233
        {
 
234
            Class clazz = ObjectFactory.getObjectFactory().getClassInstance( className );
 
235
            if ( ObjectFactory.getObjectFactory().isNoArgConstructorRequired() )
 
236
            {
 
237
                if ( !Modifier.isPublic( clazz.getModifiers() ) )
 
238
                {
 
239
                    LOG.error( "Action class [" + className + "] is not public, skipping action [" + name + "]" );
 
240
                    return false;
 
241
                }
 
242
                clazz.getConstructor( new Class[] {} );
 
243
            }
 
244
            return true;
 
245
        }
 
246
        catch ( ClassNotFoundException e )
 
247
        {
 
248
            LOG.error( "Action class [" + className + "] not found, skipping action [" + name + "] at " + loc, e );
 
249
            return false;
 
250
        }
 
251
        catch ( NoSuchMethodException e )
 
252
        {
 
253
            LOG.error( "Action class [" + className + "] does not have a public no-arg constructor,"
 
254
                + " skipping action [" + name + "] at " + loc, e );
 
255
            return false;
 
256
        }
 
257
        catch ( Exception ex )
 
258
        {
 
259
            throw new ConfigurationException( ex, loc );
 
260
        }
 
261
    }
 
262
 
 
263
    /**
 
264
     * Create a PackageConfig from an XML element representing it.
 
265
     */
 
266
    protected void addPackage( Element packageElement )
 
267
        throws ConfigurationException
 
268
    {
 
269
        PackageConfig newPackage = buildPackageContext( packageElement );
 
270
 
 
271
        // Check for allready existing configurations ..
 
272
        PackageConfig check = configuration.getPackageConfig( newPackage.getName() );
 
273
        if ( check != null )
 
274
        {
 
275
            if ( LOG.isDebugEnabled() )
 
276
            {
 
277
                LOG.debug( "Package is allready loaded! " + newPackage.getName() );
 
278
            }
 
279
            return;
 
280
        }
 
281
 
 
282
        if ( LOG.isDebugEnabled() )
 
283
        {
 
284
            LOG.debug( "Loaded " + newPackage );
 
285
        }
 
286
 
 
287
        // add result types (and default result) to this package
 
288
        addResultTypes( newPackage, packageElement );
 
289
 
 
290
        // load the interceptors and interceptor stacks for this package
 
291
        loadInterceptors( newPackage, packageElement );
 
292
 
 
293
        // load the default interceptor reference for this package
 
294
        loadDefaultInterceptorRef( newPackage, packageElement );
 
295
 
 
296
        // load the global result list for this package
 
297
        loadGlobalResults( newPackage, packageElement );
 
298
 
 
299
        // load the global exception handler list for this package
 
300
        loadGobalExceptionMappings( newPackage, packageElement );
 
301
 
 
302
        // get actions
 
303
        NodeList actionList = packageElement.getElementsByTagName( "action" );
 
304
 
 
305
        for ( int i = 0; i < actionList.getLength(); i++ )
 
306
        {
 
307
            Element actionElement = (Element) actionList.item( i );
 
308
            addAction( actionElement, newPackage );
 
309
        }
 
310
 
 
311
        // load the default action reference for this package
 
312
        loadDefaultActionRef( newPackage, packageElement );
 
313
        configuration.addPackageConfig( newPackage.getName(), newPackage );
 
314
 
 
315
    }
 
316
 
 
317
    protected void addResultTypes( PackageConfig packageContext, Element element )
 
318
    {
 
319
        NodeList resultTypeList = element.getElementsByTagName( "result-type" );
 
320
 
 
321
        for ( int i = 0; i < resultTypeList.getLength(); i++ )
 
322
        {
 
323
            Element resultTypeElement = (Element) resultTypeList.item( i );
 
324
            String name = resultTypeElement.getAttribute( "name" );
 
325
            String className = resultTypeElement.getAttribute( "class" );
 
326
            String def = resultTypeElement.getAttribute( "default" );
 
327
 
 
328
            Location loc = DomHelper.getLocationObject( resultTypeElement );
 
329
 
 
330
            Class clazz = verifyResultType( className, loc );
 
331
            if ( clazz != null )
 
332
            {
 
333
                String paramName = null;
 
334
                try
 
335
                {
 
336
                    paramName = (String) clazz.getField( "DEFAULT_PARAM" ).get( null );
 
337
                }
 
338
                catch ( Throwable t )
 
339
                {
 
340
                    // if we get here, the result type doesn't have a default
 
341
                    // param defined.
 
342
                }
 
343
                ResultTypeConfig resultType = new ResultTypeConfig( name, className, paramName );
 
344
                resultType.setLocation( DomHelper.getLocationObject( resultTypeElement ) );
 
345
 
 
346
                Map params = XmlHelper.getParams( resultTypeElement );
 
347
 
 
348
                if ( !params.isEmpty() )
 
349
                {
 
350
                    resultType.setParams( params );
 
351
                }
 
352
                packageContext.addResultTypeConfig( resultType );
 
353
 
 
354
                // set the default result type
 
355
                if ( "true".equals( def ) )
 
356
                {
 
357
                    packageContext.setDefaultResultType( name );
 
358
                }
 
359
            }
 
360
        }
 
361
    }
 
362
 
 
363
    protected Class verifyResultType( String className, Location loc )
 
364
    {
 
365
        try
 
366
        {
 
367
            return ObjectFactory.getObjectFactory().getClassInstance( className );
 
368
        }
 
369
        catch ( ClassNotFoundException e )
 
370
        {
 
371
            LOG.warn( "Result class [" + className + "] doesn't exist (ClassNotFoundException) at " + loc.toString()
 
372
                + ", ignoring", e );
 
373
        }
 
374
        catch ( NoClassDefFoundError e )
 
375
        {
 
376
            LOG.warn( "Result class [" + className + "] doesn't exist (NoClassDefFoundError) at " + loc.toString()
 
377
                + ", ignoring", e );
 
378
        }
 
379
 
 
380
        return null;
 
381
    }
 
382
 
 
383
    protected List buildExternalRefs( Element element, PackageConfig context )
 
384
        throws ConfigurationException
 
385
    {
 
386
        List refs = new ArrayList();
 
387
        NodeList externalRefList = element.getElementsByTagName( "external-ref" );
 
388
 
 
389
        String refName;
 
390
        String refValue = null;
 
391
        String requiredTemp;
 
392
        boolean required;
 
393
 
 
394
        for ( int i = 0; i < externalRefList.getLength(); i++ )
 
395
        {
 
396
            Element refElement = (Element) externalRefList.item( i );
 
397
 
 
398
            if ( refElement.getParentNode().equals( element ) )
 
399
            {
 
400
                refName = refElement.getAttribute( "name" );
 
401
 
 
402
                // If the external ref is not declared explicitly, we can
 
403
                // introspect the
 
404
                // reference type using it's name and try resolving the
 
405
                // reference using it's class type
 
406
                if ( refElement.getChildNodes().getLength() > 0 )
 
407
                {
 
408
                    refValue = refElement.getChildNodes().item( 0 ).getNodeValue();
 
409
                }
 
410
 
 
411
                requiredTemp = refElement.getAttribute( "required" );
 
412
 
 
413
                if ( (requiredTemp == null) || "".equals( requiredTemp ) )
 
414
                {
 
415
                    required = true;
 
416
                }
 
417
                else
 
418
                {
 
419
                    required = Boolean.valueOf( requiredTemp ).booleanValue();
 
420
                }
 
421
 
 
422
                refs.add( new ExternalReference( refName, refValue, required ) );
 
423
            }
 
424
        }
 
425
 
 
426
        return refs;
 
427
    }
 
428
 
 
429
    protected List buildInterceptorList( Element element, PackageConfig context )
 
430
        throws ConfigurationException
 
431
    {
 
432
        List interceptorList = new ArrayList();
 
433
        NodeList interceptorRefList = element.getElementsByTagName( "interceptor-ref" );
 
434
 
 
435
        for ( int i = 0; i < interceptorRefList.getLength(); i++ )
 
436
        {
 
437
            Element interceptorRefElement = (Element) interceptorRefList.item( i );
 
438
 
 
439
            if ( interceptorRefElement.getParentNode().equals( element ) )
 
440
            {
 
441
                List interceptors = lookupInterceptorReference( context, interceptorRefElement );
 
442
                interceptorList.addAll( interceptors );
 
443
            }
 
444
        }
 
445
 
 
446
        return interceptorList;
 
447
    }
 
448
 
 
449
    /**
 
450
     * This method builds a package context by looking for the parents of this
 
451
     * new package. <p/> If no parents are found, it will return a root package.
 
452
     */
 
453
    protected PackageConfig buildPackageContext( Element packageElement )
 
454
    {
 
455
        String parent = packageElement.getAttribute( "extends" );
 
456
        String abstractVal = packageElement.getAttribute( "abstract" );
 
457
        boolean isAbstract = Boolean.valueOf( abstractVal ).booleanValue();
 
458
        String name = TextUtils.noNull( packageElement.getAttribute( "name" ) );
 
459
        String namespace = TextUtils.noNull( packageElement.getAttribute( "namespace" ) );
 
460
 
 
461
        // RM* Load the ExternalReferenceResolver if one has been set
 
462
        ExternalReferenceResolver erResolver = null;
 
463
 
 
464
        String externalReferenceResolver = TextUtils
 
465
            .noNull( packageElement.getAttribute( "externalReferenceResolver" ) );
 
466
 
 
467
        PackageConfig cfg = null;
 
468
        if ( !("".equals( externalReferenceResolver )) )
 
469
        {
 
470
            try
 
471
            {
 
472
                erResolver = (ExternalReferenceResolver) ObjectFactory.getObjectFactory().buildBean(
 
473
                    externalReferenceResolver, null );
 
474
            }
 
475
            catch ( ClassNotFoundException e )
 
476
            {
 
477
                // TODO this should be localized
 
478
                String msg = "Could not find External Reference Resolver: " + externalReferenceResolver + ". "
 
479
                    + e.getMessage();
 
480
                LOG.error( msg );
 
481
                throw new ConfigurationException( msg, e, packageElement );
 
482
            }
 
483
            catch ( Exception e )
 
484
            {
 
485
                // TODO this should be localized
 
486
                String msg = "Could not create External Reference Resolver: " + externalReferenceResolver + ". "
 
487
                    + e.getMessage();
 
488
                LOG.error( msg );
 
489
                throw new ConfigurationException( msg, e, packageElement );
 
490
            }
 
491
        }
 
492
 
 
493
        if ( !TextUtils.stringSet( TextUtils.noNull( parent ) ) )
 
494
        { // no parents
 
495
 
 
496
            cfg = new PackageConfig( name, namespace, isAbstract, erResolver );
 
497
        }
 
498
        else
 
499
        { // has parents, let's look it up
 
500
 
 
501
            List parents = ConfigurationUtil.buildParentsFromString( configuration, parent );
 
502
 
 
503
            if ( parents.size() <= 0 )
 
504
            {
 
505
                LOG.error( "Unable to find parent packages " + parent );
 
506
 
 
507
                cfg = new PackageConfig( name, namespace, isAbstract, erResolver );
 
508
            }
 
509
            else
 
510
            {
 
511
                cfg = new PackageConfig( name, namespace, isAbstract, erResolver, parents );
 
512
            }
 
513
        }
 
514
 
 
515
        if ( cfg != null )
 
516
        {
 
517
            cfg.setLocation( DomHelper.getLocationObject( packageElement ) );
 
518
        }
 
519
        return cfg;
 
520
    }
 
521
 
 
522
    /**
 
523
     * Build a map of ResultConfig objects from below a given XML element.
 
524
     */
 
525
    protected Map buildResults( Element element, PackageConfig packageContext )
 
526
    {
 
527
        NodeList resultEls = element.getElementsByTagName( "result" );
 
528
 
 
529
        Map results = new LinkedHashMap();
 
530
 
 
531
        for ( int i = 0; i < resultEls.getLength(); i++ )
 
532
        {
 
533
            Element resultElement = (Element) resultEls.item( i );
 
534
 
 
535
            if ( resultElement.getParentNode().equals( element ) )
 
536
            {
 
537
                String resultName = resultElement.getAttribute( "name" );
 
538
                String resultType = resultElement.getAttribute( "type" );
 
539
 
 
540
                // if you don't specify a name on <result/>, it defaults to
 
541
                // "success"
 
542
                if ( !TextUtils.stringSet( resultName ) )
 
543
                {
 
544
                    resultName = Action.SUCCESS;
 
545
                }
 
546
 
 
547
                // there is no result type, so let's inherit from the parent
 
548
                // package
 
549
                if ( !TextUtils.stringSet( resultType ) )
 
550
                {
 
551
                    resultType = packageContext.getFullDefaultResultType();
 
552
 
 
553
                    // now check if there is a result type now
 
554
                    if ( !TextUtils.stringSet( resultType ) )
 
555
                    {
 
556
                        // uh-oh, we have a problem
 
557
                        LOG.error( "No result type specified for result named '" + resultName
 
558
                            + "', perhaps the parent package does not specify the result type?" );
 
559
                    }
 
560
                }
 
561
 
 
562
                ResultTypeConfig config = (ResultTypeConfig) packageContext.getAllResultTypeConfigs().get( resultType );
 
563
 
 
564
                if ( config == null )
 
565
                {
 
566
                    throw new ConfigurationException( "There is no result type defined for type '" + resultType
 
567
                        + "' mapped with name '" + resultName + "'", resultElement );
 
568
                }
 
569
 
 
570
                String resultClass = config.getClazz();
 
571
 
 
572
                // invalid result type specified in result definition
 
573
                if ( resultClass == null )
 
574
                {
 
575
                    LOG.error( "Result type '" + resultType + "' is invalid. Modify your xwork.xml file." );
 
576
                }
 
577
 
 
578
                Map resultParams = XmlHelper.getParams( resultElement );
 
579
 
 
580
                if ( resultParams.size() == 0 ) // maybe we just have a body -
 
581
                // therefore a default parameter
 
582
                {
 
583
                    // if <result ...>something</result> then we add a parameter
 
584
                    // of 'something' as this is the most used result param
 
585
                    if ( (resultElement.getChildNodes().getLength() == 1)
 
586
                        && (resultElement.getChildNodes().item( 0 ).getNodeType() == Node.TEXT_NODE) )
 
587
                    {
 
588
                        resultParams = new LinkedHashMap();
 
589
 
 
590
                        String paramName = config.getDefaultResultParam();
 
591
                        if ( paramName != null )
 
592
                        {
 
593
                            String paramValue = resultElement.getChildNodes().item( 0 ).getNodeValue();
 
594
                            if ( paramValue != null )
 
595
                            {
 
596
                                paramValue = paramValue.trim();
 
597
                            }
 
598
                            resultParams.put( paramName, paramValue );
 
599
                        }
 
600
                        else
 
601
                        {
 
602
                            LOG.warn( "no default parameter defined for result of type " + config.getName() );
 
603
                        }
 
604
                    }
 
605
                }
 
606
 
 
607
                // create new param map, so that the result param can override
 
608
                // the config param
 
609
                Map params = new LinkedHashMap();
 
610
                Map configParams = config.getParams();
 
611
                if ( configParams != null )
 
612
                {
 
613
                    params.putAll( configParams );
 
614
                }
 
615
                params.putAll( resultParams );
 
616
 
 
617
                ResultConfig resultConfig = new ResultConfig( resultName, resultClass, params );
 
618
                resultConfig.setLocation( DomHelper.getLocationObject( element ) );
 
619
                results.put( resultConfig.getName(), resultConfig );
 
620
            }
 
621
        }
 
622
 
 
623
        return results;
 
624
    }
 
625
 
 
626
    /**
 
627
     * Build a map of ResultConfig objects from below a given XML element.
 
628
     */
 
629
    protected List buildExceptionMappings( Element element, PackageConfig packageContext )
 
630
    {
 
631
        NodeList exceptionMappingEls = element.getElementsByTagName( "exception-mapping" );
 
632
 
 
633
        List exceptionMappings = new ArrayList();
 
634
 
 
635
        for ( int i = 0; i < exceptionMappingEls.getLength(); i++ )
 
636
        {
 
637
            Element ehElement = (Element) exceptionMappingEls.item( i );
 
638
 
 
639
            if ( ehElement.getParentNode().equals( element ) )
 
640
            {
 
641
                String emName = ehElement.getAttribute( "name" );
 
642
                String exceptionClassName = ehElement.getAttribute( "exception" );
 
643
                String exceptionResult = ehElement.getAttribute( "result" );
 
644
 
 
645
                Map params = XmlHelper.getParams( ehElement );
 
646
 
 
647
                if ( !TextUtils.stringSet( emName ) )
 
648
                {
 
649
                    emName = exceptionResult;
 
650
                }
 
651
 
 
652
                ExceptionMappingConfig ehConfig = new ExceptionMappingConfig( emName, exceptionClassName,
 
653
                    exceptionResult, params );
 
654
                ehConfig.setLocation( DomHelper.getLocationObject( ehElement ) );
 
655
                exceptionMappings.add( ehConfig );
 
656
            }
 
657
        }
 
658
 
 
659
        return exceptionMappings;
 
660
    }
 
661
 
 
662
    protected void loadDefaultInterceptorRef( PackageConfig packageContext, Element element )
 
663
    {
 
664
        NodeList resultTypeList = element.getElementsByTagName( "default-interceptor-ref" );
 
665
 
 
666
        if ( resultTypeList.getLength() > 0 )
 
667
        {
 
668
            Element defaultRefElement = (Element) resultTypeList.item( 0 );
 
669
            packageContext.setDefaultInterceptorRef( defaultRefElement.getAttribute( "name" ) );
 
670
        }
 
671
    }
 
672
 
 
673
    protected void loadDefaultActionRef( PackageConfig packageContext, Element element )
 
674
    {
 
675
        NodeList resultTypeList = element.getElementsByTagName( "default-action-ref" );
 
676
 
 
677
        if ( resultTypeList.getLength() > 0 )
 
678
        {
 
679
            Element defaultRefElement = (Element) resultTypeList.item( 0 );
 
680
            packageContext.setDefaultActionRef( defaultRefElement.getAttribute( "name" ) );
 
681
        }
 
682
    }
 
683
 
 
684
    /**
 
685
     * Load all of the global results for this package from the XML element.
 
686
     */
 
687
    protected void loadGlobalResults( PackageConfig packageContext, Element packageElement )
 
688
    {
 
689
        NodeList globalResultList = packageElement.getElementsByTagName( "global-results" );
 
690
 
 
691
        if ( globalResultList.getLength() > 0 )
 
692
        {
 
693
            Element globalResultElement = (Element) globalResultList.item( 0 );
 
694
            Map results = buildResults( globalResultElement, packageContext );
 
695
            packageContext.addGlobalResultConfigs( results );
 
696
        }
 
697
    }
 
698
 
 
699
    /**
 
700
     * Load all of the global results for this package from the XML element.
 
701
     */
 
702
    protected void loadGobalExceptionMappings( PackageConfig packageContext, Element packageElement )
 
703
    {
 
704
        NodeList globalExceptionMappingList = packageElement.getElementsByTagName( "global-exception-mappings" );
 
705
 
 
706
        if ( globalExceptionMappingList.getLength() > 0 )
 
707
        {
 
708
            Element globalExceptionMappingElement = (Element) globalExceptionMappingList.item( 0 );
 
709
            List exceptionMappings = buildExceptionMappings( globalExceptionMappingElement, packageContext );
 
710
            packageContext.addGlobalExceptionMappingConfigs( exceptionMappings );
 
711
        }
 
712
    }
 
713
 
 
714
    // protected void loadIncludes(Element rootElement, DocumentBuilder db)
 
715
    // throws Exception {
 
716
    // NodeList includeList = rootElement.getElementsByTagName("include");
 
717
    //
 
718
    // for (int i = 0; i < includeList.getLength(); i++) {
 
719
    // Element includeElement = (Element) includeList.item(i);
 
720
    // String fileName = includeElement.getAttribute("file");
 
721
    // includedFileNames.add(fileName);
 
722
    // loadConfigurationFile(fileName, db);
 
723
    // }
 
724
    // }
 
725
    protected InterceptorStackConfig loadInterceptorStack( Element element, PackageConfig context )
 
726
        throws ConfigurationException
 
727
    {
 
728
        String name = element.getAttribute( "name" );
 
729
 
 
730
        InterceptorStackConfig config = new InterceptorStackConfig( name );
 
731
        config.setLocation( DomHelper.getLocationObject( element ) );
 
732
        NodeList interceptorRefList = element.getElementsByTagName( "interceptor-ref" );
 
733
 
 
734
        for ( int j = 0; j < interceptorRefList.getLength(); j++ )
 
735
        {
 
736
            Element interceptorRefElement = (Element) interceptorRefList.item( j );
 
737
            List interceptors = lookupInterceptorReference( context, interceptorRefElement );
 
738
            config.addInterceptors( interceptors );
 
739
        }
 
740
 
 
741
        return config;
 
742
    }
 
743
 
 
744
    protected void loadInterceptorStacks( Element element, PackageConfig context )
 
745
        throws ConfigurationException
 
746
    {
 
747
        NodeList interceptorStackList = element.getElementsByTagName( "interceptor-stack" );
 
748
 
 
749
        for ( int i = 0; i < interceptorStackList.getLength(); i++ )
 
750
        {
 
751
            Element interceptorStackElement = (Element) interceptorStackList.item( i );
 
752
 
 
753
            InterceptorStackConfig config = loadInterceptorStack( interceptorStackElement, context );
 
754
 
 
755
            context.addInterceptorStackConfig( config );
 
756
        }
 
757
    }
 
758
 
 
759
    protected void loadInterceptors( PackageConfig context, Element element )
 
760
        throws ConfigurationException
 
761
    {
 
762
        NodeList interceptorList = element.getElementsByTagName( "interceptor" );
 
763
 
 
764
        for ( int i = 0; i < interceptorList.getLength(); i++ )
 
765
        {
 
766
            Element interceptorElement = (Element) interceptorList.item( i );
 
767
            String name = interceptorElement.getAttribute( "name" );
 
768
            String className = interceptorElement.getAttribute( "class" );
 
769
 
 
770
            Map params = XmlHelper.getParams( interceptorElement );
 
771
            InterceptorConfig config = new InterceptorConfig( name, className, params );
 
772
            config.setLocation( DomHelper.getLocationObject( interceptorElement ) );
 
773
 
 
774
            context.addInterceptorConfig( config );
 
775
        }
 
776
 
 
777
        loadInterceptorStacks( element, context );
 
778
    }
 
779
 
 
780
    // protected void loadPackages(Element rootElement) throws
 
781
    // ConfigurationException {
 
782
    // NodeList packageList = rootElement.getElementsByTagName("package");
 
783
    //
 
784
    // for (int i = 0; i < packageList.getLength(); i++) {
 
785
    // Element packageElement = (Element) packageList.item(i);
 
786
    // addPackage(packageElement);
 
787
    // }
 
788
    // }
 
789
    private void loadConfigurationFile( String fileName, Element includeElement )
 
790
    {
 
791
        if ( !includedFileNames.contains( fileName ) )
 
792
        {
 
793
            if ( LOG.isDebugEnabled() )
 
794
            {
 
795
                LOG.debug( "Loading xwork configuration from: " + fileName );
 
796
            }
 
797
 
 
798
            includedFileNames.add( fileName );
 
799
 
 
800
            Document doc = null;
 
801
            InputStream is = null;
 
802
 
 
803
            try
 
804
            {
 
805
                is = getInputStream( fileName );
 
806
 
 
807
                if ( is == null )
 
808
                {
 
809
                    throw new Exception( "Could not open file " + fileName );
 
810
                }
 
811
 
 
812
                InputSource in = new InputSource( is );
 
813
 
 
814
                // FIXME: we shouldn't be doing this lookup twice
 
815
                try
 
816
                {
 
817
                    in.setSystemId( ClassLoaderUtil.getResource( fileName, getClass() ).toString() );
 
818
                }
 
819
                catch ( Exception e )
 
820
                {
 
821
                    in.setSystemId( fileName );
 
822
                }
 
823
 
 
824
                Map dtdMappings = new HashMap();
 
825
                dtdMappings.put( "-//OpenSymphony Group//XWork 1.1.1//EN", "xwork-1.1.1.dtd" );
 
826
                dtdMappings.put( "-//OpenSymphony Group//XWork 1.1//EN", "xwork-1.1.dtd" );
 
827
                dtdMappings.put( "-//OpenSymphony Group//XWork 1.0//EN", "xwork-1.0.dtd" );
 
828
 
 
829
                doc = DomHelper.parse( in, dtdMappings );
 
830
            }
 
831
            catch ( XworkException e )
 
832
            {
 
833
                // WTF!!??
 
834
                if ( includeElement != null )
 
835
                {
 
836
                    System.out.println( e );
 
837
                    throw new ConfigurationException( e, includeElement );
 
838
                }
 
839
                else
 
840
                {
 
841
                    throw new ConfigurationException( e );
 
842
                }
 
843
            }
 
844
            catch ( Exception e )
 
845
            {
 
846
                final String s = "Caught exception while loading file " + fileName;
 
847
                LOG.error( s, e );
 
848
                // throw new ConfigurationException(s, e, includeElement);
 
849
                throw new ConfigurationException( s, e );
 
850
            }
 
851
            finally
 
852
            {
 
853
                if ( is != null )
 
854
                {
 
855
                    try
 
856
                    {
 
857
                        is.close();
 
858
                    }
 
859
                    catch ( IOException e )
 
860
                    {
 
861
                        LOG.error( "Unable to close input stream", e );
 
862
                    }
 
863
                }
 
864
            }
 
865
 
 
866
            Element rootElement = doc.getDocumentElement();
 
867
            NodeList children = rootElement.getChildNodes();
 
868
            int childSize = children.getLength();
 
869
 
 
870
            for ( int i = 0; i < childSize; i++ )
 
871
            {
 
872
                Node childNode = children.item( i );
 
873
 
 
874
                if ( childNode instanceof Element )
 
875
                {
 
876
                    Element child = (Element) childNode;
 
877
 
 
878
                    final String nodeName = child.getNodeName();
 
879
 
 
880
                    if ( nodeName.equals( "package" ) )
 
881
                    {
 
882
                        addPackage( child );
 
883
                    }
 
884
                    else if ( nodeName.equals( "include" ) )
 
885
                    {
 
886
                        String includeFileName = child.getAttribute( "file" );
 
887
                        loadConfigurationFile( includeFileName, child );
 
888
                    }
 
889
                }
 
890
            }
 
891
 
 
892
            if ( LOG.isDebugEnabled() )
 
893
            {
 
894
                LOG.debug( "Loaded xwork configuration from: " + fileName );
 
895
            }
 
896
        }
 
897
    }
 
898
 
 
899
    /**
 
900
     * Looks up the Interceptor Class from the interceptor-ref name and creates
 
901
     * an instance, which is added to the provided List, or, if this is a ref to
 
902
     * a stack, it adds the Interceptor instances from the List to this stack.
 
903
     * 
 
904
     * @param interceptorRefElement Element to pull interceptor ref data from
 
905
     * @param context The PackageConfig to lookup the interceptor from
 
906
     * @return A list of Interceptor objects
 
907
     */
 
908
    private List lookupInterceptorReference( PackageConfig context, Element interceptorRefElement )
 
909
        throws ConfigurationException
 
910
    {
 
911
        String refName = interceptorRefElement.getAttribute( "name" );
 
912
        Map refParams = XmlHelper.getParams( interceptorRefElement );
 
913
 
 
914
        return InterceptorBuilder.constructInterceptorReference( context, refName, refParams );
 
915
    }
 
916
}