incubator-jspwiki-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Simon Kitching ...@ops.co.at>
Subject Re: Classmapping and final classes
Date Tue, 22 Jan 2008 12:47:53 GMT
Murray Altheim schrieb:
> Simon Kitching wrote:
>> Murray Altheim schrieb:
> [...]Using the existing feature of the ClassUtil (without
> modification), you
>>> add your class mappings to ClassUtil's classmappings.xml file:
>>>
>>>    public static final String MAPPINGS = "/ini/classmappings.xml";
>>>
>>> then let WikiEngine instantiate them using the existing code:
>>>
>>>    m_authenticationManager = (AuthenticationManager)
>>>          
>>> ClassUtil.getMappedObject(AuthenticationManager.class.getName());
>>>    m_authorizationManager  = (AuthorizationManager)
>>>            ClassUtil.getMappedObject(
>>> AuthorizationManager.class.getName());
>>>
>>> I don't see how a modification of ClassUtil is necessary here. The real
>>> grunt work is rewriting the two AA classes. But so far as I understand
>>> your requirements, the existing machinery permits this.
>>
>> As you show above, the WikiEngine class explicitly casts the returned
>> object to class AuthenticationManager. So I must *subclass*
>> AuthenticationManager or this code will throw a ClassCastException at
>> runtime. But I cannot subclass AuthenticationManager because it is
>> final, and so are many of its important methods.
>
> No, please read again either what I wrote, the ClassUtil code, or the
> contents of /etc/ini/classmappings.xml. ClassUtil receives a Class
> name, but that's *not* the class it will use if there is an
> alternative mapping set up in ClassUtil.MAPPINGS. If you modify
> classmappings.xml you can instantiate your own classes, e.g.:
>
>   <classmappings>
>     <mapping>
>      
> <requestedClass>com.ecyrd.jspwiki.auth.AuthenticationManager</requestedClass>
>
>       <mappedClass>com.acme.auth.MyAuthenticationManager</mappedClass>
>     </mapping>
>     <mapping>
>      
> <requestedClass>com.ecyrd.jspwiki.render.AuthorizationManager</requestedClass>
>
>       <mappedClass>com.acme.auth.MyAuthorizationManager</mappedClass>
>     </mapping>
>   </classmappings>
>
> There's no need to modify anything in JSPWiki's code, nor use the same
> package names as JSPWiki to obtain the behaviour you want. Just map
> to your desired, custom classes and your good to go. That's what
> ClassUtil does.
>

Thanks very much for your time Murray.

However I am still reasonably sure that the final status of the
AuthorizationManager *is* a problem (and I have been doing this Java
thing for a few years now).

Let's split up the code in WikiEngine into steps:

(1) String reqClass = AuthenticationManager.class.getName();
(2) Object mgrObj = ClassUtil.getMappedObject(reqClass);
(3) m_authenticationManager = (AuthenticationManager) mgrObj;

Steps (1) and (2) are fine. Yes, it is possible to configure the
classmappings.xml file to point to my custom implementation, and
ClassUtil will happily load the Class, create an instance and return it.
No problems here at all.

But in (3), the attempt to cast the custom object to type
com.eycrd.wiki.auth.AuthenticationManager will fail because it is not of
that type. A ClassCastException will therefore occur and the WikiEngine
will fail to initialise.

The solution is simply to make the custom class subclass
AuthenticationManager - but that is not possible because that class is
final.

Note that I've now got a solution that works for me; I have a custom jar
with a reimplementation of the problem classes (without final
qualifiers) and I have named the jar "_jspwiki_patch.jar", where the
leading underscore causes the servlet engine picks it up before the real
JSPWiki.jar (alphabetical order). But sometime it might be nice to
either fix this in the jspwiki code or rip out the
ClassUtils.getMappedObject calls and just replace them with "new"..

Regards,
Simon


Mime
View raw message