You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Jon Tirsén <jo...@yahoo.com> on 2002/11/15 15:56:25 UTC

[attributes] Jakarta Commons Attributes, Nanning & XRAI

I'm CC:ing commons-dev for this. The background for
the list is:
James and Jon started commons-attributes a couple of
days ago.
Ara joined the effort today.
Commons-attributes will be a unified lightweight
runtime-API for accessing attributes. XRAI will be one
runtime-implementation and an extensive
compile-time-environment.
We're discussing how to design a good lightweight
commons-attributes-API that will not be a hindrance to
XRAIs additional features.

Ok, here's my opinions :-)

> Well, lets see how we can provide a good api, a
> forward looking one but
> one which does what it does now perfectly without
> any for-future
> sacrifices. So I propose a hierarchy of attributes:

Agreed. YAGNI. :-)

> - At the top we have the Attribute interface,
> nothing interesting there.
> 
> - Then we have SimpleAttribute derived from it, it
> has "String
> getProperty(...)" methods. They return String so
> it's the getText you're
> talking about.

I propose adding getText() to the Attribute-interface
to make things more simple. That means all Attributes
has to be able to retrieve the original textual value.
I think that's pretty reasonable. If we do this all
trivial usages will be able to access the strings.
When things needs to be more complex (support
compile-time-validation, strong typing and so on) they
can add that support in those places and still have
other trivial code left that uses strings. In that way
we can easily support a wide range of use-cases.
Seems reasonable?

> - Then we'll let user define
> EjbAttribute/custom-attribute derived from
> the new CustomAttribute class, CustomAttribute
> derived from
> SimpleAttribute. C#/jsr175 style. What it does is it
> responds to
> getProperty (overridden from SimpleAttribute) by
> doing getMethod() for
> the attribute property and fulfill that request.

Yep, but this goes into XRAI, right?

> - We'll add "SimpleAttribute
> getSimpleAttribute(...)" to ClassMetaData
> so if you want to use the simple attribute interface
> you just call it
> and no need to cast it from Attribute to
> SimpleAttribute. So a client
> which doesn't know that an EjbAttribute class exists
> or wants to deal
> with attributes with the common SimpleAttribute
> interface can use this
> method. A client who knows the @ejb.bean is actually
> the type safe
> EjbAttribute class can call "Attribute
> getAttribute(..)" method and cast
> it (C# style again).

Agreed in principal. If we add getText/getProperty to
Attribute-interface a trivial client can *always* use
the Strings. A non-trivial client can cast it to the
strongly-type (C#-style) Attribute-class.

> - We can add xdoclet xtags style attributes too,
> later. So you define an
> attributes.xml class, where you define @ejb.bean/etc
> attributes
> according to the dtd, then the serializer app looks
> at the @tags and
> according to dtd validate the @tags user put in the
> code, and finally
> serialize the XmlAttribute class.

Yup. Goes into XRAI too, right?

> Anyway I push the ClassMetaData and Attribute
> classes of xrai. It's more
> flexible than the Nanning approach. Just imagine the
> possibilities of
> this approach:
> - you can serialize them.
> - you can pass the whole metadata/attributes on the
> wire.
> - you can modify attributes at runtime, they are not
> readonly.
> - ...!

Okay, you've got a point. So let's add one more
interface: ClassMetaData/ClassAttributes (I think
ClassAttributes is better because there's a lot of
different MetaData, but we're doing Attributes here).
But we should really try hard to minimize the API
here.

Re modify attributes at runtime. I'm really having
troubles understanding the semantics of this. Does it
update the source-code? I'm opting for read-only
attributes in common-attributes and XRAI may add
modification-support.

> I would like to hear Jon's ideas too. And Aslak's
> too.
> 
> PS: I might sound a bit pushy here, bear with me.
> Trust me; it's based
> on my 2 year experience with @attributes and hearing
> all those
> complaints and struggles of xdoclet users. For
> example supporting
> validation of @tags is *very* important, ppl have
> real struggle with
> tags. The system should help them. That's why I
> don't believe in that
> String-only based approach of getting attribute
> parameters.


_____________________________________________________
Gratis e-mail resten av livet på www.yahoo.se/mail
Busenkelt!

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: [attributes] Jakarta Commons Attributes, Nanning & XRAI

Posted by Ola Berg <ol...@ports.se>.
----- Original Message ----- 
> From: "Jon Tirsén" <jo...@tirsen.com>

> Another thing: Your attribute seems to be a map of name-value-pairs. Is
> it possible to mandate this for all attributes? Isn't some attributes
> going to be more of a list of parameters, some is going to be one-value
> only, some is going to be your name-value-pairs.

>From a user POV: absolutely right. _Plus_ that the order of the properties must be preserved in someway or another.

/O


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


RE: [attributes] Jakarta Commons Attributes, Nanning & XRAI

Posted by Jon Tirsén <jo...@yahoo.com>.
 --- Ara Abrahamian <ar...@yahoo.com> skrev: > > Ok,
so maybe we just have to change our mind. What
> you are proposing
> is
> > that commons-attributes is the de facto
> runtime-implementation of
> > attributes. It could still be pluggable but we
> have a very rich
> default
> > implementation derived from the XRAI effort. Did I
> understand this
> > correctly?
> 
> Yes.

Ok, does everybody agree on this? James? Aslak?

> > My opinion on this: Sure, I could do that. One
> very important thing on
> > my agenda is timing. I think we need to focus on
> having a 1.0 with the
> > least possible functionality that is usable out
> during this year. Then
> > we would have time experimenting with the other
> cool features you've
> > been talking about. If we could agree on this I'm
> all for it.
> 
> I proposed a timeline like this:
> 
> v0.1 = abstract serialization api (like xrai) with
> default serialization
> of .ser object stream files,
> Attribute+DefaultAttribute classes with the
> simple implementation,
> ClassMetaData/DefaultClassMetaData, a smart ant
> task

Okay, I propose this to be 1.0. For several reasons.
One being that there will be a bunch of issues we need
to resolve after moving beyond this step. One of the
must difficult one being how to map attribute-names to
attribute-classes, and wheather these
attribute-classes will need to be available at
runtime. By nature this will be experimental and we
should try different approaches before we settle on
something. Another reason is that this is actually
quite useful.

This is almost what's in the CVS right now. We just
need to do the ClassMetaData-refactoring and it's
exactly what you're proposing (API-wise). Maybe some
more work on the Ant-task too.

Also we really need to discuss serialization. I think
we can do without that in all cases. Serialization is
(very, very) not recommended for long-term storage.
And for good reasons, almost every time I've tried
this it's blown up in my face. There's also major
performance issues.

The attributes are being created from strings in the
first place (all attributes are strings in the
source-code) so there's no reason we can't store these
strings and recreate the attribute at runtime. This
way we would also gracefully handle issues where
attribute-classes has been changed since the last
compile. They will be reparsed and revalidated. (For
example if you've upgraded a library in the
classpath.) Another thing is that you can edit these
strings without needing to recompile.

Serialization on the other hand is not very change
resilient. If the attribute changes after you've
serialized them it's simply gonna break. It's good for
short-term marshalling, like RMI for example. Long
term storage on the other hand, there are plenty of
other technologies that's better to use for this.

> v0.2 = Attribute metadata:
> isClassLevel/getLevel/etc, hence a simple
> form of validation of what user entered
> 
> v0.3 = CustomAttribute
> 
> v0.4 = XmlAttribute
> 
> v0.5 = BCEL attributes

I think all these can go after 1.0. I subscribe to the
release-early release-often style of process. We need
to get this out on the streets and see what the users
want, get them used to the technology. Also promoting
runtime attributes with real examples is what's
highest on my agenda, there's just so many libraries
I'm using that would be so better if they supported
runtime attriubtes. Then we'll see what kind of
technology the community needs.

> v0.1 can be out in 2 weeks, it's mostly xrai stuff
> refactored a bit.

Sure.

> > > There are other methods in Attribute too,
> metadata of the
> > > attribute: int getLevel() -> a bitset of the
> levels the
> > > attribute is applicable to,
> method/class/field/constructor/package
> > > some convenience methods like:
> isClassLevel/isMethodLevel/etc
> > >
> > > These methods help us do validation on user's
> input.
> > 
> > Ok, seems nice. Do we really need a bitset thingy?
> Doesn't just the
> > predicates do? Bitsets are ugly and seems so old
> and outdated.
> 
> I had something like Class.getModifiers() in my
> mind.

Yeah, I'm not very fond of that. Is there any other
example of using a bitset in the JDK? Any other
well-designed library? But sure if that's the easiest
way to do it, what the heck.

> > Hmm... ClassMetaData but PackageAttribute? Then
> let's name that
> > PackageMetaData too.
> 
> Typo, I meant PackageMetaData.

Ok.

> > One more thing. Don't we need to add a
> validate()-method to Attribute
> so
> > attributes can hook in and check wheather they've
> got all the
> parameters
> > they require and so on? This will be called
> runtime (when
> demarshalling
> > attributes, attribute-implementation may have
> changed since
> > compile-time) and compile-time (before marshalling
> attributes).
> 
> Yup! A validate() method to validate the attribute
> after all the
> parameters are set. An EjbAttribute will check
> whether the class is a
> subclass of EJBObject for example. So we need to
> pass in some context
> data. I'm afraid we have to pass xdoclet's XClass or
> qdox' SourceClass.
> And if we're going to validate in runtime too then
> it's trickier! Let's
> see what we come up with in v0.2.

Yeah, you're right, it needs some context. Don't you
think it's enough that we pass in the
Field/Method/Class it's bound too, and the actual text
of the attribute?
We needs some different examples and see what support
they need for validation. But it might be better to do
this later on, true.

Once again I'm gonna throw in a plug for just storing
the attribute-strings. If commons-attributes changes
to use another validation-scheme it could still use
the compiled attribute-strings and validation would at
runtime be using the new validation-scheme.

_____________________________________________________
Gratis e-mail resten av livet på www.yahoo.se/mail
Busenkelt!

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


RE: [attributes] Jakarta Commons Attributes, Nanning & XRAI

Posted by Ara Abrahamian <ar...@yahoo.com>.
> Ok, so maybe we just have to change our mind. What you are proposing
is
> that commons-attributes is the de facto runtime-implementation of
> attributes. It could still be pluggable but we have a very rich
default
> implementation derived from the XRAI effort. Did I understand this
> correctly?

Yes.

> My opinion on this: Sure, I could do that. One very important thing on
> my agenda is timing. I think we need to focus on having a 1.0 with the
> least possible functionality that is usable out during this year. Then
> we would have time experimenting with the other cool features you've
> been talking about. If we could agree on this I'm all for it.

I proposed a timeline like this:

v0.1 = abstract serialization api (like xrai) with default serialization
of .ser object stream files, Attribute+DefaultAttribute classes with the
simple implementation, ClassMetaData/DefaultClassMetaData, a smart ant
task

v0.2 = Attribute metadata: isClassLevel/getLevel/etc, hence a simple
form of validation of what user entered

v0.3 = CustomAttribute

v0.4 = XmlAttribute

v0.5 = BCEL attributes

v0.1 can be out in 2 weeks, it's mostly xrai stuff refactored a bit.

> > There are other methods in Attribute too, metadata of the
> > attribute: int getLevel() -> a bitset of the levels the
> > attribute is applicable to, method/class/field/constructor/package
> > some convenience methods like: isClassLevel/isMethodLevel/etc
> >
> > These methods help us do validation on user's input.
> 
> Ok, seems nice. Do we really need a bitset thingy? Doesn't just the
> predicates do? Bitsets are ugly and seems so old and outdated.

I had something like Class.getModifiers() in my mind.

> > > Okay, you've got a point. So let's add one more
> > > interface: ClassMetaData/ClassAttributes (I think
> > ClassAttributes is
> > > better because there's a lot of different MetaData, but we're
doing
> > > Attributes here). But we should really try hard to minimize the
API
> > > here.
> >
> > ClassMetaData is better, we'll add a PackageAttribute class
> > too. C# also has assembly/package level attribute. This is
> > quite useful, Rickard already gave us an example in his weblog.
> 
> Hmm... ClassMetaData but PackageAttribute? Then let's name that
> PackageMetaData too.

Typo, I meant PackageMetaData.

> One more thing. Don't we need to add a validate()-method to Attribute
so
> attributes can hook in and check wheather they've got all the
parameters
> they require and so on? This will be called runtime (when
demarshalling
> attributes, attribute-implementation may have changed since
> compile-time) and compile-time (before marshalling attributes).

Yup! A validate() method to validate the attribute after all the
parameters are set. An EjbAttribute will check whether the class is a
subclass of EJBObject for example. So we need to pass in some context
data. I'm afraid we have to pass xdoclet's XClass or qdox' SourceClass.
And if we're going to validate in runtime too then it's trickier! Let's
see what we come up with in v0.2.

Ara.


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


RE: [attributes] Jakarta Commons Attributes, Nanning & XRAI

Posted by Jon Tirsén <jo...@tirsen.com>.

> -----Original Message-----
> From: Ara Abrahamian [mailto:ara_e_w@yahoo.com] 
> Sent: den 15 november 2002 22:35
> To: jon@tirsen.com; 'James Strachan'; aslak.hellesoy@bekk.no
> Cc: commons-dev@jakarta.apache.org
> Subject: RE: [attributes] Jakarta Commons Attributes, Nanning & XRAI
> 
> 
> Ok, here is what I have to add to this thread.
> 
> First of all: both xrai and nanning's attribute stuff will 
> die, commons-attribute is the only runtime attribute api 
> we'll deal with.
> 

Ok, this is not according to the scope of the project that I had in my
mind. You may be correct, we just need to discuss this so we agree.

My understanding of the scope of this project was that
commons-attributes was a thin pluggable layer for a runtime API. Several
different implementations would exist. We've already seen many different
approaches: property-files, serialized objects, *BeanInfo-like class,
attributes added to the .class-file using BCEL. I imagine there will be
several thriving projects implementing attributes XRAI, attrib4j, the
JSR and so on.

Ok, so maybe we just have to change our mind. What you are proposing is
that commons-attributes is the de facto runtime-implementation of
attributes. It could still be pluggable but we have a very rich default
implementation derived from the XRAI effort. Did I understand this
correctly?

My opinion on this: Sure, I could do that. One very important thing on
my agenda is timing. I think we need to focus on having a 1.0 with the
least possible functionality that is usable out during this year. Then
we would have time experimenting with the other cool features you've
been talking about. If we could agree on this I'm all for it.

I'll still comment some of the design. But I think it's important that
everyone agrees on the basic scope of the project.

> I've changed the hierarchy a bit:
> 
> We have the Attributes class which is like the XRaiFacade 
> class. We have the ClassMetaData class which contains 
> Attributes and get/setAttribute methods. DefaultClassMetaData 
> provides the default implementation. Attribute interface is 
> the parent of all attribute types. I've moved all 
> SimpleAttribute stuff here:
> 
> String getStringProperty(String prop_name)
> void getStringProperty(String prop_name, String value)
> Object getProperty(String prop_name)
> void getProperty(String prop_name, Object value)
> 
> So we can ask for a string representation of a property from 
> any Attribute. We can ask for an Object representation too 
> which is useful when the derived Attribute class has 
> properties of other types, say int/date/etc.

Ok, we've basically agreed then. Good.

Another thing: Your attribute seems to be a map of name-value-pairs. Is
it possible to mandate this for all attributes? Isn't some attributes
going to be more of a list of parameters, some is going to be one-value
only, some is going to be your name-value-pairs.

> There are other methods in Attribute too, metadata of the 
> attribute: int getLevel() -> a bitset of the levels the 
> attribute is applicable to, method/class/field/constructor/package
> some convenience methods like: isClassLevel/isMethodLevel/etc
> 
> These methods help us do validation on user's input.

Ok, seems nice. Do we really need a bitset thingy? Doesn't just the
predicates do? Bitsets are ugly and seems so old and outdated.

> DefaultAttribute is a concrete implementation of Attribute 
> interface. It's back by a Map of name/value properties. It 
> returns all-levels for the attribute and returns true from 
> isClassLevel/etc methods.

Yup.

> Now regarding custom attributes:
> 
> A CustomAttribute interface is defined which derives from 
> Attribute interface. There's an AbstractCustomAttribute class 
> defined too. The methods from Attribute are implemented via 
> reflection on get/set property access methods 
> (getJndiName/etc) in AbstractCustomAttribute.

Ok.

> ClassMetaData has these methods:
> 
> Attribute getAttribute(String name)
> void getAttribute(String name, Attribute attr)
> DefaultAttribute getDefaultAttribute(String name)
> void getDefaultAttribute(String name, DefaultAttribute attr)
> 
> Later we'll define an XmlAttribute class too. It's derived 
> from DefaultAttribute and looks at an attribute definition file
> (attributes.xml) to validate the input. Other implementations 
> could exist too: a ValidListAttribute which has an array of 
> valid values for properties, for example.
> 
> Step by step of course....

Agreed.

> > > - Then we'll let user define
> > > EjbAttribute/custom-attribute derived from
> > > the new CustomAttribute class, CustomAttribute
> > > derived from
> > > SimpleAttribute. C#/jsr175 style. What it does is it responds to
> > > getProperty (overridden from SimpleAttribute) by
> > > doing getMethod() for
> > > the attribute property and fulfill that request.
> > 
> > Yep, but this goes into XRAI, right?
> 
> EjbBeanAttribute and basically all concrete attributes will 
> be defined in xdoclet. Commons-attribute is only the base mechanism.

Well, not all concrete attributes will be defined in Xdoclet of course.
But the concrete attributes will not be defined by commons-attributes.

> > > - We can add xdoclet xtags style attributes too,
> > > later. So you define an
> > > attributes.xml class, where you define @ejb.bean/etc attributes
> > > according to the dtd, then the serializer app looks
> > > at the @tags and
> > > according to dtd validate the @tags user put in the
> > > code, and finally
> > > serialize the XmlAttribute class.
> > 
> > Yup. Goes into XRAI too, right?
> 
> No, it will be in commons-attributes 'cause it's quite 
> general and very handy.

As I've said, we have to agree on scope here.

> > Okay, you've got a point. So let's add one more
> > interface: ClassMetaData/ClassAttributes (I think 
> ClassAttributes is 
> > better because there's a lot of different MetaData, but we're doing 
> > Attributes here). But we should really try hard to minimize the API
> > here.
> 
> ClassMetaData is better, we'll add a PackageAttribute class 
> too. C# also has assembly/package level attribute. This is 
> quite useful, Rickard already gave us an example in his weblog.

Hmm... ClassMetaData but PackageAttribute? Then let's name that
PackageMetaData too.

> > Re modify attributes at runtime. I'm really having
> > troubles understanding the semantics of this. Does it
> > update the source-code? I'm opting for read-only
> > attributes in common-attributes and XRAI may add 
> modification-support.
> 
> Yes and no:
> - in the runtime api, modifying the attributes/properties 
> only updates the in-memory object. Where's the use of it? 
> Well the best example I have is the transaction attribute. So 
> in the AOP framework you add a TransactionAspect, calculate 
> the correct transaction level (required/requires-new/etc), 
> set the attribute for the method, call the method, now the 
> method should only get the transaction level and begin/end 
> the transaction conditionally based on it.
> - in parsing time:
> 	- in AttributeSerializer it's just used for filling the 
> attributes for serialization
> 	- in xdoclet's xdocletgui app it's used for modifying 
> the attributes visually and then saving the modification to 
> source code.

Ok, that does seem reasonable. Separate processors could add and modify
attributes to classes at runtime (and compile-time). Sure, we'll
investigate that.

One more thing. Don't we need to add a validate()-method to Attribute so
attributes can hook in and check wheather they've got all the parameters
they require and so on? This will be called runtime (when demarshalling
attributes, attribute-implementation may have changed since
compile-time) and compile-time (before marshalling attributes).


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


RE: [attributes] Jakarta Commons Attributes, Nanning & XRAI

Posted by Ara Abrahamian <ar...@yahoo.com>.
Ok, here is what I have to add to this thread.

First of all: both xrai and nanning's attribute stuff will die,
commons-attribute is the only runtime attribute api we'll deal with.

I've changed the hierarchy a bit:

We have the Attributes class which is like the XRaiFacade class. We have
the ClassMetaData class which contains Attributes and get/setAttribute
methods. DefaultClassMetaData provides the default implementation.
Attribute interface is the parent of all attribute types. I've moved all
SimpleAttribute stuff here:

String getStringProperty(String prop_name)
void getStringProperty(String prop_name, String value)
Object getProperty(String prop_name)
void getProperty(String prop_name, Object value)

So we can ask for a string representation of a property from any
Attribute. We can ask for an Object representation too which is useful
when the derived Attribute class has properties of other types, say
int/date/etc.

There are other methods in Attribute too, metadata of the attribute:
int getLevel() -> a bitset of the levels the attribute is applicable to,
method/class/field/constructor/package
some convenience methods like: isClassLevel/isMethodLevel/etc

These methods help us do validation on user's input.

DefaultAttribute is a concrete implementation of Attribute interface.
It's back by a Map of name/value properties. It returns all-levels for
the attribute and returns true from isClassLevel/etc methods.

Now regarding custom attributes:

A CustomAttribute interface is defined which derives from Attribute
interface. There's an AbstractCustomAttribute class defined too. The
methods from Attribute are implemented via reflection on get/set
property access methods (getJndiName/etc) in AbstractCustomAttribute.

ClassMetaData has these methods:

Attribute getAttribute(String name)
void getAttribute(String name, Attribute attr)
DefaultAttribute getDefaultAttribute(String name)
void getDefaultAttribute(String name, DefaultAttribute attr)

Later we'll define an XmlAttribute class too. It's derived from
DefaultAttribute and looks at an attribute definition file
(attributes.xml) to validate the input. Other implementations could
exist too: a ValidListAttribute which has an array of valid values for
properties, for example.

Step by step of course....

> > - Then we'll let user define
> > EjbAttribute/custom-attribute derived from
> > the new CustomAttribute class, CustomAttribute
> > derived from
> > SimpleAttribute. C#/jsr175 style. What it does is it
> > responds to
> > getProperty (overridden from SimpleAttribute) by
> > doing getMethod() for
> > the attribute property and fulfill that request.
> 
> Yep, but this goes into XRAI, right?

EjbBeanAttribute and basically all concrete attributes will be defined
in xdoclet. Commons-attribute is only the base mechanism.

> Agreed in principal. If we add getText/getProperty to
> Attribute-interface a trivial client can *always* use
> the Strings. A non-trivial client can cast it to the
> strongly-type (C#-style) Attribute-class.

Exactly.

> > - We can add xdoclet xtags style attributes too,
> > later. So you define an
> > attributes.xml class, where you define @ejb.bean/etc
> > attributes
> > according to the dtd, then the serializer app looks
> > at the @tags and
> > according to dtd validate the @tags user put in the
> > code, and finally
> > serialize the XmlAttribute class.
> 
> Yup. Goes into XRAI too, right?

No, it will be in commons-attributes 'cause it's quite general and very
handy.

> Okay, you've got a point. So let's add one more
> interface: ClassMetaData/ClassAttributes (I think
> ClassAttributes is better because there's a lot of
> different MetaData, but we're doing Attributes here).
> But we should really try hard to minimize the API
> here.

ClassMetaData is better, we'll add a PackageAttribute class too. C# also
has assembly/package level attribute. This is quite useful, Rickard
already gave us an example in his weblog.

> Re modify attributes at runtime. I'm really having
> troubles understanding the semantics of this. Does it
> update the source-code? I'm opting for read-only
> attributes in common-attributes and XRAI may add
> modification-support.

Yes and no:
- in the runtime api, modifying the attributes/properties only updates
the in-memory object. Where's the use of it? Well the best example I
have is the transaction attribute. So in the AOP framework you add a
TransactionAspect, calculate the correct transaction level
(required/requires-new/etc), set the attribute for the method, call the
method, now the method should only get the transaction level and
begin/end the transaction conditionally based on it.
- in parsing time:
	- in AttributeSerializer it's just used for filling the
attributes for serialization
	- in xdoclet's xdocletgui app it's used for modifying the
attributes visually and then saving the modification to source code.

How does is look now?

Ara.


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>