You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@velocity.apache.org by Marcus Sundman <su...@iki.fi> on 2005/01/23 05:31:25 UTC

outdated links source code

After fighting velocity for several hours I finally found out that 
apparently velocity 1.4 somehow manages to ignore even public methods in 
anonymous inner classes. How such a bug is possible is a mystery to me, so 
I thought that before I waste your time I'll check out the source code 
myself and perhaps fix the bug and submit a patch. But no, apparently the 
source code is impossible to find. The location that the velocity webpages 
refer to contains only some source from <=2003-09-09 (no, I'm not joking, 
although I wish I was). Anyway, how do I get the velocity source without 
having to install SVN or somesuch?

Or even better, does someone who is familiar with the code know what the 
deal with velocity and anonymous inner classes is?


- Marcus Sundman

---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org


Re: outdated links source code

Posted by Marcus Sundman <su...@iki.fi>.
On Sunday 23 January 2005 19:50, Marcus Sundman wrote:
> The only reason it doesn't work in java without reflection is because you
> can't refer to an anonymous or private class.

No, I was wrong. It just happened to work in my test case because Test1 and 
Test2 were in the same package. I just read the JLS (2nd ed, section 
15.12.4.3 if someone is interested). The JLS says that you must have access 
to both the method and the class (so far OK, but then it gets bad:), and 
the class must either be in the same package (even a private inner class is 
visible within its package!!!), or be declared public, or be declared 
protected and a superclass of the calling class.
That's is really bad design made by morons who have no clue about security 
(*ahem*confused deputy*ahem*). Once more Gosling et al. have shown 
themselves to be idiots, but that's hardly surprising.

Anyway, sorry for wasting your time.

And thank you, Shinobu, for your help!


- Marcus Sundman

---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org


Re: outdated links source code

Posted by Shinobu Kawai Yoshida <sh...@gmail.com>.
Hi Marcus,

> The only reason it doesn't work in java without reflection is because you
> can't refer to an anonymous or private class.

Exactly.

> However, you can get the
> class instance from an instance of such a class and use it to access the
> method using relfection. In dynamically typed languages like velocity you
> don't have this problem since they always get the class from the object.
> That is, except in velocity where there are explicit checks to prevent
> overcoming this problem.
> 
> It's very handy to do something like this:
> 
> final Database db=getDatabase();
> context.put("user", new Object() {
>    // users have a name and a shoe
>    public String getName() {
>        return db.findName(USER_ID);
>    }
>    public Object getShoe() {
>        return new Object() {
>            // shoes have a size and a make
>            public int getSize() {
>                return db.findShoeSize(USER_ID);
>            }
>            public String getMake() {
>                return db.findShoeMake(USER_ID);
>            }
>        };
>    }
> });
> 
> It gets a lot less attractive if you have to make these classes named, and
> it gets really spaghetti if you had several nested anonymous classes (I
> have only 1 nested class above) and have to flatten these out.

I not quite sure of the underlying philosophy of Velocity here, but by
defining an interface, you can let Velocity recognize the methods.
eg.  In your test example,
public interface User
{
   public String getName();
   public Object getShoe();
}

context.put("user", new User() {...});

I guess it's still worksome, but it gives the developers a clearer
view of the objects.  :)

> Well, I can just remove those checks from my own copy of velocity for my own
> use.

The good thing about Velocity, is that you can customise the
introspection routine without altering the core library.  For example,
the PublicFieldUberspect exposes public fields to introspection.
cf. http://wiki.apache.org/jakarta-velocity/PublicFieldUberspect
In your case, all you have to do is override Uberspect#getMethod() and
everything goes well!

Best regards,
-- Shinobu

--
Shinobu "Kawai" Yoshida <sh...@gmail.com>

---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org


Re: outdated links source code

Posted by Marcus Sundman <su...@iki.fi>.
> > It's those cases where java can execute a method but velocity can't see
> > it that I'm worried about. Apparently velocity ignores all methods in a
> > private classes, even if the methods themselves are public.
>
> I think it is intended behaviour to only allow invocation to public
> methods of public classes.  You wouldn't be able to call other methods
> in java either (without reflection).

The only reason it doesn't work in java without reflection is because you 
can't refer to an anonymous or private class. However, you can get the 
class instance from an instance of such a class and use it to access the 
method using relfection. In dynamically typed languages like velocity you 
don't have this problem since they always get the class from the object. 
That is, except in velocity where there are explicit checks to prevent 
overcoming this problem.

It's very handy to do something like this:

final Database db=getDatabase();
context.put("user", new Object() {
    // users have a name and a shoe
    public String getName() {
        return db.findName(USER_ID);
    }
    public Object getShoe() {
        return new Object() {
            // shoes have a size and a make
            public int getSize() {
                return db.findShoeSize(USER_ID);
            }
            public String getMake() {
                return db.findShoeMake(USER_ID);
            }
        };
    }
});

It gets a lot less attractive if you have to make these classes named, and 
it gets really spaghetti if you had several nested anonymous classes (I 
have only 1 nested class above) and have to flatten these out.

Well, I can just remove those checks from my own copy of velocity for my own 
use.

Thanks.

- Marcus Sundman

---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org


Re: outdated links source code

Posted by Shinobu Kawai Yoshida <sh...@gmail.com>.
Hi Marcus,

> Anyway, it seems to make some weird assumptions about accessibility. Check
> out this program and tell me if it's supposed to do this:

## snip

> It's those cases where java can execute a method but velocity can't see it
> that I'm worried about. Apparently velocity ignores all methods in a
> private classes, even if the methods themselves are public.

I think it is intended behaviour to only allow invocation to public
methods of public classes.  You wouldn't be able to call other methods
in java either (without reflection).
## But of course, Velocity is not java.  :)

Best regards,
-- Shinobu

--
Shinobu "Kawai" Yoshida <sh...@gmail.com>

---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org


Re: outdated links source code

Posted by Marcus Sundman <su...@iki.fi>.
On Sunday 23 January 2005 15:58, Shinobu Kawai Yoshida wrote:
> > I made a test for my problem and it works very well in java but not in
> > velocity. I can't even imagine how it could not work in velocity. I'll
> > check out the sources...
>
> You might want to file a new bugzilla issue while you're at it.  ;)

I first want to make sure it's not supposed to have weird behavior (which 
wouldn't be the first time.. *ahem*#set(...)*ahem*). Also, the jakarta 
bugzilla isn't among the fiftyeleven ones I have an account on. ;-)

Anyway, it seems to make some weird assumptions about accessibility. Check 
out this program and tell me if it's supposed to do this:
----8<------------------------------------------------------------------
import org.apache.velocity.util.introspection.*;
import java.lang.reflect.*;

public class Test1 {
    public static void main( String[] args ) throws Exception {
        Test2 t=new Test2();
        Object[] objs={
            t.pubStaticInner(),
            t.pubInner(),
            t.privStaticInner(),
            t.privInner(),
            t.anonymous(),
            t.privInnerPrivMethod()
        };
        for (int i=0; i<objs.length; i++) {
            Class c=objs[i].getClass();
            ClassMap map=new ClassMap(c);
            Method vm=map.findMethod("test", new Object[0]);
            Method jm=findMethod(c);
            System.out.println(c.getName()+":");
            System.out.println("- velocity finds method:   "+
                               (vm==null?"NO":"YES"));
            System.out.println("- java finds mehod:        "+
                               (jm==null?"NO":"YES"));
            System.out.println("- java can execute method: "+
                               canExec(objs[i], jm) );
        }
    }
    static Method findMethod(Class c) {
        try {
            return c.getMethod("test", new Class[0]);
        }catch (Exception ex) {
            return null;
        }
    }
    static String canExec(Object o, Method m) {
        if (m==null) return "n/a";
        try {
            m.invoke(o, new Object[0]);
            return "YES";
        }catch (Exception ex) {
            return "NO";
        }
    }
}
---->8------------------------------------------------------------------

and the helper-class:
----8<------------------------------------------------------------------
public class Test2 {
    public Object pubStaticInner() {
        return new PubStaticInner();
    }
    public Object pubInner() {
        return new PubInner();
    }
    public Object privStaticInner() {
        return new PrivStaticInner();
    }
    public Object privInner() {
        return new PrivInner();
    }
    public Object anonymous() {
        return new Object() {
            public String test() {
                return "anonymous";
            }
        };
    }
    public Object privInnerPrivMethod() {
        return new PrivInnerPrivMethod();
    }
    public static class PubStaticInner {
        public String test() {
            return "pub-static-inner";
        }
    }
    public class PubInner {
        public String test() {
            return "pub-inner";
        }
    }
    private static class PrivStaticInner {
        public String test() {
            return "priv-static-inner";
        }
    }
    private class PrivInner {
        public String test() {
            return "priv-inner";
        }
    }
    private class PrivInnerPrivMethod {
        private String test() {
            return "priv-inner-priv-method";
        }
    }
}
---->8------------------------------------------------------------------

I get the following output:
----8<------------------------------------------------------------------
Test2$PubStaticInner:
- velocity finds method:   YES
- java finds mehod:        YES
- java can execute method: YES
Test2$PubInner:
- velocity finds method:   YES
- java finds mehod:        YES
- java can execute method: YES
Test2$PrivStaticInner:
- velocity finds method:   NO
- java finds mehod:        YES
- java can execute method: YES
Test2$PrivInner:
- velocity finds method:   NO
- java finds mehod:        YES
- java can execute method: YES
Test2$1:
- velocity finds method:   NO
- java finds mehod:        YES
- java can execute method: YES
Test2$PrivInnerPrivMethod:
- velocity finds method:   NO
- java finds mehod:        NO
- java can execute method: n/a
---->8------------------------------------------------------------------

It's those cases where java can execute a method but velocity can't see it 
that I'm worried about. Apparently velocity ignores all methods in a 
private classes, even if the methods themselves are public.


- Marcus Sundman

---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org


Re: outdated links source code

Posted by Shinobu Kawai Yoshida <sh...@gmail.com>.
Hi Marcus,

> Thanks! At other places "binary release" means that it's binary only, but
> apparently not at jakarta. Still, I should have checked it out anyway when
> I couldn't find the source where it was supposed to be.

Well, actually it might be a Velocity thing.  Velocity is shipped with
binaries and sources all together.  Other ASF products are shipped
separately.

> I made a test for my problem and it works very well in java but not in
> velocity. I can't even imagine how it could not work in velocity. I'll
> check out the sources...

You might want to file a new bugzilla issue while you're at it.  ;)

Best regards,
-- Shinobu

--
Shinobu "Kawai" Yoshida <sh...@gmail.com>

---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org


Re: outdated links source code

Posted by Marcus Sundman <su...@iki.fi>.
On Sunday 23 January 2005 13:54, Shinobu Kawai Yoshida wrote:
> > I thought that before I waste your time I'll check out the source code
> > myself and perhaps fix the bug and submit a patch. But no, apparently
> > the source code is impossible to find. The location that the velocity
> > webpages refer to contains only some source from <=2003-09-09 (no, I'm
> > not joking, although I wish I was). Anyway, how do I get the velocity
> > source without having to install SVN or somesuch?
>
> Without SVN, you'll only get the source of Velocity 1.4.  I don't know
> what links lead you to the "obsolete" source code, but the following
> links will let you get the 1.4 source code.
> Velocity top page:
>     http://jakarta.apache.org/velocity/
> The "Download" link:
>     http://jakarta.apache.org/site/binindex.cgi
> At Velocity:
>     http://jakarta.apache.org/site/binindex.cgi#velocity
> Either "1.4 zip" or "1.4 tar.gz":
>     The Velocity 1.4 archive!

Thanks! At other places "binary release" means that it's binary only, but 
apparently not at jakarta. Still, I should have checked it out anyway when 
I couldn't find the source where it was supposed to be.

> > Or even better, does someone who is familiar with the code know what
> > the deal with velocity and anonymous inner classes is?
>
> The stuff is handled somewhere in the
> org.apache.velocity.util.introspection package.  Look especially at
> the ClassMap class.  ;)

Thanks!

> There's also a known bug about method findings due to another bug in
> reflection in JDK.  :(
>     http://issues.apache.org/bugzilla/show_bug.cgi?id=8651

OK. This is not related to that bug, though.

I made a test for my problem and it works very well in java but not in 
velocity. I can't even imagine how it could not work in velocity. I'll 
check out the sources...


- Marcus Sundman

---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org


Re: outdated links source code

Posted by Shinobu Kawai Yoshida <sh...@gmail.com>.
Hi Marcus,

> I thought that before I waste your time I'll check out the source code
> myself and perhaps fix the bug and submit a patch. But no, apparently the
> source code is impossible to find. The location that the velocity webpages
> refer to contains only some source from <=2003-09-09 (no, I'm not joking,
> although I wish I was). Anyway, how do I get the velocity source without
> having to install SVN or somesuch?

Without SVN, you'll only get the source of Velocity 1.4.  I don't know
what links lead you to the "obsolete" source code, but the following
links will let you get the 1.4 source code.
Velocity top page:
    http://jakarta.apache.org/velocity/
The "Download" link:
    http://jakarta.apache.org/site/binindex.cgi
At Velocity:
    http://jakarta.apache.org/site/binindex.cgi#velocity
Either "1.4 zip" or "1.4 tar.gz":
    The Velocity 1.4 archive!

> Or even better, does someone who is familiar with the code know what the
> deal with velocity and anonymous inner classes is?

The stuff is handled somewhere in the
org.apache.velocity.util.introspection package.  Look especially at
the ClassMap class.  ;)

There's also a known bug about method findings due to another bug in
reflection in JDK.  :(
    http://issues.apache.org/bugzilla/show_bug.cgi?id=8651

Best regards,
-- Shinobu

--
Shinobu "Kawai" Yoshida <sh...@gmail.com>

---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org