Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / October 2007

Tip: Looking for answers? Try searching our database.

empty interfaces via reflection

Thread view: 
Aryeh M. Friedman - 13 Oct 2007 21:40 GMT
Is it possible to force a class to implement a (empty) interface via
reflection only... the problem is I want to create a Proxy but want
the class/interface being proxied to be totally unaware of it (eg.
TestProxy does some debugging and checks on all classes
Class.newInstance() calls after it is constructor is called [from the
caller not from within itself])
Roedy Green - 13 Oct 2007 22:49 GMT
On Sat, 13 Oct 2007 20:40:50 -0000, "Aryeh M. Friedman"
<Aryeh.Friedman@gmail.com> wrote, quoted or indirectly quoted someone
who said :

>Is it possible to force a class to implement a (empty) interface via
>reflection only... the problem is I want to create a Proxy but want
>the class/interface being proxied to be totally unaware of it (eg.
>TestProxy does some debugging and checks on all classes
>Class.newInstance() calls after it is constructor is called [from the
>caller not from within itself])

I would think you would have to modify the bytes  of a the class file
to add the dummy interface and load it with your own class loader to
do that.  There may be an easier way.
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Patricia Shanahan - 13 Oct 2007 23:04 GMT
> Is it possible to force a class to implement a (empty) interface via
> reflection only... the problem is I want to create a Proxy but want
> the class/interface being proxied to be totally unaware of it (eg.
> TestProxy does some debugging and checks on all classes
> Class.newInstance() calls after it is constructor is called [from the
> caller not from within itself])

Have you considered aspect oriented programming, and AspectJ in
particular?

Patricia
Aryeh M. Friedman - 13 Oct 2007 23:17 GMT
> > Is it possible to force a class to implement a (empty) interface via
> > reflection only... the problem is I want to create a Proxy but want
[quoted text clipped - 5 lines]
> Have you considered aspect oriented programming, and AspectJ in
> particular?

For other projects yes but this is one has Java as one of it's
requirements
Patricia Shanahan - 13 Oct 2007 23:33 GMT
>>> Is it possible to force a class to implement a (empty) interface via
>>> reflection only... the problem is I want to create a Proxy but want
[quoted text clipped - 7 lines]
> For other projects yes but this is one has Java as one of it's
> requirements

AspectJ is not Java enough for the purpose? I believe the classes you
are operating on can be written in conventional Java. It is only the
code that imposes the checks and debugging that needs the AspectJ
extensions on top of Java.

Patricia
Aryeh M. Friedman - 14 Oct 2007 09:29 GMT
> >>> Is it possible to force a class to implement a (empty) interface via
> >>> reflection only... the problem is I want to create a Proxy but want
[quoted text clipped - 12 lines]
> code that imposes the checks and debugging that needs the AspectJ
> extensions on top of Java.

The reason for saying this is it needs to be 100% backwards compatible
with Java (i.e. you do not need AsepectJ to run or maintain any
component except the ones mentioned)... reason it is a commerical open-
source unit testing framework for java and part of the marketing is
all our products are 100% java.
Aryeh M. Friedman - 14 Oct 2007 09:57 GMT
> The reason for saying this is it needs to be 100% backwards compatible
> > with Java (i.e. you do not need AsepectJ to run or maintain any
> > component except the ones mentioned)... reason it is a commerical open-
> > source unit testing framework for java and part of the marketing is
> > all our products are 100% java.

In think it over I decided to post a high level summary of the
problem:

1. The framework has it's own standalone GUI see
http://www.flosoft-systems.com/thisTest_screens.php for screen shots

2. When clicking on "run tests" any recompiling done since the last
test run (either from with in the GUI or restarting the app) needs to
be honored

3. I currently solved item 2 in a very adhoc and bug prone way:
    a. Have a custom class loader (see other treads) since the system
class loader will not honor
       updated .class files
    b. A side effect of using a custom class loader is you can not
directly cast to an instance created using the system class loader.
For example:

public class Main
{
       public static void main(String[] args)
               throws Throwable
       {
               ClassLoader loader=new MyClassLoader();
               Class klass=loader.loadClass("MyClass");

               MyClass m=(MyClass) klass.newInstance();
       }
}

Produces:
Exception in thread "main" java.lang.ClassCastException: MyClass
cannot be cast to MyClass
       at Main.main(Main.java:11)

Here is the support code:

import java.io.*;
import java.lang.reflect.*;

public class MyClassLoader extends ClassLoader
{
       public Class loadClass(String name)
       {
               try {
                       if(name.startsWith("java."))
                               return super.loadClass(name);

                       FileInputStream fis=new FileInputStream(name
+".class");
                       byte[] b=new byte[fis.available()];

                       fis.read(b);
                       fis.close();

                       return defineClass(name,b,0,b.length);
               } catch(Throwable e) {
                       e.printStackTrace();
               }

               return null;
        }
}

public class MyClass
{
       public MyClass()
       {
               ack=new Integer(0);
       }

       public Integer getAck()
       {
               return ack;
       }

       private int foo;
       private Integer ack;
}

If you want more detail and the threads proving the correctness of the
code see:

http://groups.google.com/group/comp.lang.java.programmer/browse_thread/thread/5c
d333290dc92e74/0169c9ea83253940#0169c9ea83253940


http://groups.google.com/group/comp.lang.java.programmer/browse_thread/thread/9f
84cb0f0a2ab367/f28ba3e0de4cc60f#f28ba3e0de4cc60f


One solution I have found to this problem (which I do in a adhoc and
bug baity way in the production code) is to create a second instance
of the class using the system class loader then copy the fields over
that way any getter/setter operates on stuff created by the system
class loader and not the custom class loader (this is fine because by
definition Unit tests only test the top level containing class).
Recently I have come up with the following experimental code to do
this is a more systematic way:

import java.lang.reflect.*;

public class Main
{
    public static void main(String[] args)
        throws Throwable
    {
        ClassLoader loader=new MyClassLoader();
        Class klass=loader.loadClass("MyClass");

        MyClass m=(MyClass) rebrand(MyClass.class,klass.newInstance());

        // cast to make sure rebrand works
        System.out.println((Integer) m.getAck());
    }

    public static Object rebrand(Class brand,Object obj)
        throws Throwable
    {
        ClassLoader loader=ClassLoader.getSystemClassLoader();
        Class klass=loader.loadClass(brand.getCanonicalName());
        Object real=klass.newInstance();

        for(Field f:real.getClass().getDeclaredFields()) {
            if(f.getType().isPrimitive())
                continue;

            Field oldField=obj.getClass().getDeclaredField(f.getName());
            boolean fVis=f.isAccessible();
            boolean oVis=oldField.isAccessible();

            try {
                f.setAccessible(true);
                oldField.setAccessible(true);
            } catch(Throwable e) {
                // if for some reason we can't mod the accessibility skip it
                continue;
            }

            f.set(real,oldField.get(obj));

            f.setAccessible(true);
            oldField.setAccessible(true);
        }

        return real;
    }
}

The only problem remaining is to call rebrand when ever the class
under test returns a field (see the println for an example).

This is where the proxy comes in I basically wrap Proxy.invoke(....)
around all method calls and if the return type needs to be rebranded
(made by the custom classloader) it does so.  This is safe because it
is conceptually illegal for a unit test to call any methods in the
returned value except to check it's values.
Aryeh M. Friedman - 14 Oct 2007 10:00 GMT
> This is where the proxy comes in I basically wrap Proxy.invoke(....)
> around all method calls and if the return type needs to be rebranded
> (made by the custom classloader) it does so.  This is safe because it
> is conceptually illegal for a unit test to call any methods in the
> returned value except to check it's values.

oops mentioned the one problem java.lang.reflect.Proxy requires all
acted on "classses" be interfaces not classes.  thus the desire to
make a empty interface and wrap any rebranded class in it tempurarly
so the proxy can be used.
Owen Jacobson - 14 Oct 2007 12:23 GMT
On Oct 14, 2:00 am, "Aryeh M. Friedman" <Aryeh.Fried...@gmail.com>
wrote:
> > This is where the proxy comes in I basically wrap Proxy.invoke(....)
> > around all method calls and if the return type needs to be rebranded
[quoted text clipped - 6 lines]
> make a empty interface and wrap any rebranded class in it tempurarly
> so the proxy can be used.

You will discover that creating a proxy does not expose arbitrary
random method calls, nor can the proxy be (down)cast to any interface
other than the one you specified when it was created.  Java's static
type checking still applies, preventing the former, and the object the
caller invokes methods on (the proxy) doesn't have the complete
inheritance hierarchy of the proxied object.  For example, the
following won't work:

public interface Proxied {}

public class Foo implements Proxied {
 public void bar () {...}
}

...
 Foo proxyForFoo = (Foo) Proxy.newProxyInstance(
   Foo.class.getClassLoader(),
   new Class[] { Proxied.class },
   someHandler);
...

because the object returned from newProxyInstance is neither a Foo nor
a child of Foo.

In short, you can't get there from here; go back to working with class
loaders.  I think you probably want to avoid running any user code
from the System classloader at all; if possible, you want to run each
test case inside a single classloader which can be thrown away at the
end of the run and which provides canonical definitions of each class
to the tested code.

The other traditional and, more importantly, workable tool for moving
objects' states between classloaders is serialization; obviously, this
only works if the objects in question are serializable.  This is one
of the reasons EJB remote interfaces must accept only serializable
objects or primitives as arguments and only return said.
Aryeh M. Friedman - 14 Oct 2007 12:42 GMT
> On Oct 14, 2:00 am, "Aryeh M. Friedman" <Aryeh.Fried...@gmail.com>
> wrote:
[quoted text clipped - 34 lines]
> because the object returned from newProxyInstance is neither a Foo nor
> a child of Foo.

I was vaguely aware of that and was expecting something above the
proxy to unwrap before handing back the object.

> In short, you can't get there from here; go back to working with class
> loaders.  I think you probably want to avoid running any user code
> from the System classloader at all; if possible, you want to run each
> test case inside a single classloader which can be thrown away at the
> end of the run and which provides canonical definitions of each class
> to the tested code.

That was my orginial thinking but some issues came up like how to
handle result reporting when the ui code couldn't do this easily:

    Result res=test.getResult();

keep in mind the test is from MyClassLoader and the ui (which has
main()) is by definition uses SystemClassLoader

> The other traditional and, more importantly, workable tool for moving
> objects' states between classloaders is serialization; obviously, this
> only works if the objects in question are serializable.  This is one
> of the reasons EJB remote interfaces must accept only serializable
> objects or primitives as arguments and only return said.

Thats where I got stuck.... since it is a testing framework it *MUST*
work on anything including Object (in theory)
Daniel Pitts - 14 Oct 2007 18:12 GMT
>> This is where the proxy comes in I basically wrap Proxy.invoke(....)
>> around all method calls and if the return type needs to be rebranded
[quoted text clipped - 6 lines]
> make a empty interface and wrap any rebranded class in it tempurarly
> so the proxy can be used.

What you really need to do is NOT cast to an explicit object, but use
reflection to call your test hooks:

Class<?> testClass = loadTestClass();
Object testInstance = testClass.newInstance();
for (Method method: testClass.getDeclaredMethods()) {
   method.invoke(testInstance, new Object[0]);
}

Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Aryeh M. Friedman - 14 Oct 2007 18:21 GMT
On Oct 14, 5:12 pm, Daniel Pitts
<newsgroup.spamfil...@virtualinfinity.net> wrote:
> >> This is where the proxy comes in I basically wrap Proxy.invoke(....)
> >> around all method calls and if the return type needs to be rebranded
[quoted text clipped - 16 lines]
>
> }

Then how do you handle the return type?!?!?!?  Namely I can't do:

Class<?> testClass = loadTestClass();
Object testInstance = testClass.newInstance();
Result res=new Result();

for (Method method: testClass.getDeclaredMethods())
    res.merge((Result) method.invoke(testInstance, new
Object[0]));   // cast exception

reportResults(res)

...

private void reportResults(Result res)
{
....
}

The reason why it is not possible is any Result object created by a
test is <MyClassLoader>.Result and all the results here are
<SystemClassLoader>.Result
Steven Simpson - 14 Oct 2007 19:01 GMT
> Then how do you handle the return type?!?!?!?  Namely I can't do:
>
[quoted text clipped - 10 lines]
> <SystemClassLoader>.Result
>  

Looking back at an earlier post, your custom MyClassLoader goes like this:

> public class MyClassLoader extends ClassLoader
> {
[quoted text clipped - 4 lines]
>                                 return super.loadClass(name);
>  

A custom ClassLoader is expected to override findClass(String) rather
than loadClass(String), as the latter (indirectly) accomplishes this
behaviour:

<http://java.sun.com/javase/6/docs/api/java/lang/ClassLoader.html>

"When requested to find a class or resource, a ClassLoader instance will
delegate the search for the class or resource to its parent class loader
before attempting to find the class or resource itself."

MyClassLoader is loading Result instead of delegating to its parent
first, which should always find it first.

Signature

ss at comp dot lancs dot ac dot uk                                     |

Aryeh M. Friedman - 14 Oct 2007 20:17 GMT
> > Then how do you handle the return type?!?!?!?  Namely I can't do:
>
[quoted text clipped - 32 lines]
> MyClassLoader is loading Result instead of delegating to its parent
> first, which should always find it first.

I just tested:import java.io.*;
import java.lang.reflect.*;

public class MyClassLoader extends ClassLoader
{
       public Class findClass(String name)
       {
               try {
                       //if(name.startsWith("java."))
                       //      return super.loadClass(name);

                       FileInputStream fis=new FileInputStream(name
+".class");
                       byte[] b=new byte[fis.available()];

                       fis.read(b);
                       fis.close();

                       return defineClass(name,b,0,b.length);
               } catch(Throwable e) {
                       e.printStackTrace();
               }

               return null;
}

and now the class loader no longer honors recompiled classes:

Script started on Sun Oct 14 15:09:05 2007
jtest@monster:/home/jtest% java Main
1
^Z
Suspended
jtest@monster:/home/jtest% cat foo
import java.lang.reflect.*;

public class MyClass
{
       public MyClass()
       {
               ack=new Integer(2);
       }

       public Integer getAck()
       {
               return ack;
       }

       private int foo;
       private Integer ack;
}
jtest@monster:/home/jtest% cp foo MyClass.java
jtest@monster:/home/jtest% javac MyClass.java
jtest@monster:/home/jtest% fg
java Main

1
^C
jtest@monster:/home/jtest% exit
Script ends on Sun Oct 14 15:09:45 2007

Just for ref here is the new main():

public class Main
{
       public static void main(String[] args)
               throws Throwable
     {
               while(true) {
                       ClassLoader loader=new MyClassLoader();
                       Class klass=loader.loadClass("MyClass");

                       MyClass m=(MyClass) klass.newInstance();

                       System.out.println(m.getAck());
                       System.in.read();
               }
       }
}
Steven Simpson - 14 Oct 2007 22:31 GMT
> I just tested:import java.io.*;
> import java.lang.reflect.*;
[quoted text clipped - 11 lines]
>                         MyClass m=(MyClass) klass.newInstance();
>  

By this point at least, you'll have surely caused the system classloader
to load in MyClass itself (by referring to it in code), so later
MyClassLoaders will defer to that.

But this is just a test program right?  In your other code, you had:

Class<?> testClass = loadTestClass();
Object testInstance = testClass.newInstance();

...and you don't actually refer to MyClass.  So, as long as MyClass is
not in the program's classpath, the system classloader won't load it;
but your custom classloader will, if it looks in the right directory.

Going back to your test program to verify, you could just keep 'm' as an
Object, and invoke reflectively, also keeping MyClass out of the
classpath.  Does that help?

Signature

ss at comp dot lancs dot ac dot uk                                     |

Aryeh M. Friedman - 19 Oct 2007 16:20 GMT
> Class<?> testClass = loadTestClass();
> Object testInstance = testClass.newInstance();
>
> ...and you don't actually refer to MyClass.  So, as long as MyClass is
> not in the program's classpath, the system classloader won't load it;
> but your custom classloader will, if it looks in the right directory.

Had other things to do so sorry for not trying this sooner but the
following test code (using findClass not loadClass as the override
method) still doesn't work:

public static void main(String[] args)
               throws Throwable
       {
               while(true) {
                       ClassLoader loader=new MyClassLoader();
                       Class klass=loader.loadClass("MyClass");
                       Object o=klass.newInstance();


System.out.println(o.getClass().getDeclaredMethod("getAck").invoke(o));
                       System.in.read();
               }
       }
Steven Simpson - 19 Oct 2007 17:14 GMT
> the
> following test code (using findClass not loadClass as the override
[quoted text clipped - 5 lines]
>                 while(true) {
>                         ClassLoader loader=new MyClassLoader();

I did get the following to work.  It uses a URLClassLoader, as Daniel
Pitts suggested.  Your MyClassLoader didn't seem to be doing anything
extra, so you may as well use the existing class - though I don't see
why yours wouldn't work.

You give the directory containing the class to be tested as the first
argument, and it is turned into a URL for the class loader.  Make sure
this directory is not in your classpath.

import java.io.*;
import java.net.*;

public class Test {
 public static void main(String[] args) throws Throwable {
   File f = new File(args[0]);
   URL[] path = new URL[] { f.toURI().toURL() };

   while (true) {
     ClassLoader loader = new URLClassLoader(path);
     Class klass = loader.loadClass("SomeClass");
     Object o = klass.newInstance();

     System.out.println(o.getClass().getDeclaredMethod("getAck").
                        invoke(o));
     System.in.read();
   }
 }
}

Signature

ss at comp dot lancs dot ac dot uk                                     |

Aryeh M. Friedman - 19 Oct 2007 18:09 GMT
> > the
> > following test code (using findClass not loadClass as the override
[quoted text clipped - 14 lines]
> argument, and it is turned into a URL for the class loader.  Make sure
> this directory is not in your classpath.

There is the rub... since it is meant for a standalone commercial app
I don't feel comfortable making any assumptions about the struct of
the user's class path (matter of fact on the surface I think all
loaded classes will have to be in the class path one way or an other
[cmd line arg passing maybe but not very portable])
Daniel Pitts - 20 Oct 2007 19:01 GMT
Sorry if this a double-post. Damn google.
On Oct 19, 10:09 am, "Aryeh M. Friedman" <Aryeh.Fried...@gmail.com>
wrote:

> > > the
> > > following test code (using findClass not loadClass as the override
[quoted text clipped - 20 lines]
> loaded classes will have to be in the class path one way or an other
> [cmd line arg passing maybe but not very portable])

So, use it as an example, and work from there.
You can't do what you're trying to do without some assumptions about
the class path.  Commercial products make assumptions all the time
(like, for instance, the validity of the environment their running
on).  It is the only feasible way to do this.  Just document the fact
that your program's execution environment should be *different* than
that of the tests.  Or, figure out some other way of supporting that.
Daniel Pitts - 16 Oct 2007 01:21 GMT
On Oct 14, 12:17 pm, "Aryeh M. Friedman" <Aryeh.Fried...@gmail.com>
wrote:

> > > Then how do you handle the return type?!?!?!?  Namely I can't do:
>
[quoted text clipped - 114 lines]
>
> }

You should simply use UrlClassLoader and have the system classpath not
include your code that needs to be reloaded, and the URLClassLoader
have the path that DOES need to be reloaded (creating a new instance
of that class loader every time you need to reload the class)

That way, Result will be properly loaded by the System class loader,
and your reloadable class wont.

Hoep this helps,
Daniel.
Arne Vajhøj - 15 Oct 2007 02:37 GMT
>>>>> Is it possible to force a class to implement a (empty) interface via
>>>>> reflection only... the problem is I want to create a Proxy but want
[quoted text clipped - 16 lines]
> source unit testing framework for java and part of the marketing is
> all our products are 100% java.

I still can not really see any reason why not to use AspectJ.

Yes - you need to distribute the aspectrt.jar, but most Java apps
require some jars.

Yes - developers will need the AspectJ tools, but they also need
an editor, a Java compiler etc..

Arne
Lew - 15 Oct 2007 03:33 GMT
> I still can not really see any reason why not to use AspectJ.
>
[quoted text clipped - 3 lines]
> Yes - developers will need the AspectJ tools, but they also need
> an editor, a Java compiler etc..

Be careful which version of AspectJ you use.  Apparently some older versions
had trouble in multi-threaded, multi-processor environments.  I have heard
that these troubles were repaired in the latest release(s).

It is also true that AspectJ defines a superset language to Java, which may be
the OP's concern with it.  They do take care to maintain complete binary
compatibility with "plain" Java, though.

Still, I don't think you should minimize the differences from "plain ol' Java"
that AspectJ does introduce to the language.  Perhaps they are worthwhile, but
the OP is correct to investigate the impact of these differences.

Disclaimer: I am not anything but superficially familiar with AspectJ,
although I did review their documentation as I wrote this post.

Signature

Lew

Arne Vajhøj - 15 Oct 2007 04:07 GMT
> Be careful which version of AspectJ you use.  Apparently some older
> versions had trouble in multi-threaded, multi-processor environments.  I
[quoted text clipped - 8 lines]
> worthwhile, but the OP is correct to investigate the impact of these
> differences.

AspectJ takes a valid class file and convert it to another
valid class file based on input from a source text file. The
resulting code requires a single jar file to be in
classpath.

The concept and syntax understanding to be able to write that
source text file has a steep learning curve.

But from a runtime perspective it has less impact to use AspectJ
than to use another XML parser than the one Java comes with.

Arne
Arne Vajhøj - 15 Oct 2007 04:17 GMT
>> Be careful which version of AspectJ you use.  Apparently some older
>> versions had trouble in multi-threaded, multi-processor environments.  
[quoted text clipped - 19 lines]
> But from a runtime perspective it has less impact to use AspectJ
> than to use another XML parser than the one Java comes with.

I just refreshed:

... takes a valid java file and convert it to a valid class file
based on ...

Arne
Arne Vajhøj - 15 Oct 2007 04:20 GMT
>>> Be careful which version of AspectJ you use.  Apparently some older
>>> versions had trouble in multi-threaded, multi-processor
[quoted text clipped - 25 lines]
> ... takes a valid java file and convert it to a valid class file
> based on ...

But to quote what they write themselves in
http://www.eclipse.org/aspectj/doc/next/devguide/ajc-ref.html:

<quote>
Compatibility

AspectJ is a compatible extension to the Java programming language. The
AspectJ compiler adheres to the The Java Language Specfication, Second
Edition and to the The Java Virtual Machine Specification, Second
Edition and runs on any Java 2 compatible platform. The code it
generates runs on any Java 1.1 or later compatible platform. For more
information on compatibility with Java and with previous releases of
AspectJ, see AspectJ Version Compatibility.
</quote>

And the link points to:
  http://www.eclipse.org/aspectj/doc/next/devguide/compatibility.html
which further explains.

Arne
Aryeh M. Friedman - 19 Oct 2007 16:21 GMT
> I still can not really see any reason why not to use AspectJ.
>
[quoted text clipped - 3 lines]
> Yes - developers will need the AspectJ tools, but they also need
> an editor, a Java compiler etc..

With AspectJ can you freely change the class of an instant? (assuming
that the class your moving to implements the same methods)
Lew - 19 Oct 2007 22:54 GMT
> With AspectJ can you freely change the class of an instant? (assuming
> that the class your moving to implements the same methods)

Do you mean "change the class of an instance"?

No.  At least not as I understand the question.  AspectJ adds cross-cutting
concerns to the Java language; it doesn't change the semantics of the part
that it shares with the Java language itself.  AFAIK.

Undoubtedly there is a different strategy (!) to achieve your real, and as yet
unstated, goal (!).

What exactly do you intend to accomplish with such an idiom?

Signature

Lew

Arne Vajhøj - 25 Oct 2007 01:48 GMT
>> I still can not really see any reason why not to use AspectJ.
>>
[quoted text clipped - 6 lines]
> With AspectJ can you freely change the class of an instant? (assuming
> that the class your moving to implements the same methods)

No.

But you can add functionality to an existing class without
changing its code.

Arne


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.