I need to know if a java class import a package

D

Daniel

Im writing a unit test class, and I want to check if a given class is
importing some package (ie: java.util.Collections) from the code, is
that posible?

With this code
Class a = myClass.getClass();
System.out.println(a.getPackage());

i can know the package of myClass, is there anything like this for
imports statements?
 
E

Eric Sosman

Daniel wrote On 04/23/07 10:20,:
Im writing a unit test class, and I want to check if a given class is
importing some package (ie: java.util.Collections) from the code, is
that posible?

With this code
Class a = myClass.getClass();
System.out.println(a.getPackage());

i can know the package of myClass, is there anything like this for
imports statements?

Probably not, since `import' is just a compile-time
convenience. You get the same byte code from

class Foo {
java.util.Set s;
}

and from

import java.util.Set;
class Foo {
Set s;
}

and from

import java.util.*;
class Foo {
Set s;
}

and from

import java.util.*;
import javax.swing.*;
class Foo {
Set s;
}

Why should your test plan care whether the source
code uses fully-qualified class names or abbreviates
them with the help of `import'?
 
D

Daniel

Its true, but is there a way to know if certain class is used inside
the tested class, despite if the developer declares them in the import
or with the fully-qualified name?
 
D

Daniel

Eric, thanks for your help
To clarify a little bit more my problem, I will try to add some
example of what I'm needing:

I need that some users fill with code in page to solve a task, this
task involves the sorting of an array of integers, this could be
easily solved with Collections.sort, but I gave them as a
precondition, they couldn't use the Collections class (because I want
to test if they can iterate an order an array by themselves).
To correct this tasks, I have a Junit class that test against the
submitted code, so I was searching for some mechanism that could help
me with this.

The webpage is an open community JavaBlackBelt.com

Note: If this could be done, I imagine that also could be applied to
test if the developers are using some classes that are not specified
by the architecture. (eg: when developing J2ee code, sometimes the
developers could use some classes from the app server that could
decrease the portability)
 
E

Eric Sosman

Daniel wrote On 04/23/07 13:53,:
Eric, thanks for your help
To clarify a little bit more my problem, I will try to add some
example of what I'm needing:

I need that some users fill with code in page to solve a task, this
task involves the sorting of an array of integers, this could be
easily solved with Collections.sort, but I gave them as a
precondition, they couldn't use the Collections class (because I want
to test if they can iterate an order an array by themselves).
To correct this tasks, I have a Junit class that test against the
submitted code, so I was searching for some mechanism that could help
me with this.

The webpage is an open community JavaBlackBelt.com

You could certainly inspect the compiled byte code for
references to "forbidden" classes. The java.lang.instrument
package might be helpful here.

However, I doubt such an approach will be all that useful
as a detector of cheating. To begin with, you need to make
a useful list of banned classes -- For example, if I were
told to sort an int[], I would use Arrays.sort() and never
touch the Collections class at all. Also, the sources for
Arrays (and Collections) are readily available; a cheater
could simply copy the source and change the package names,
and thus evade your detection.

Finally, JUnit is probably not a good framework for
this sort of thing. If I try to write an array-sorter but
make an error and introduce an infinite loop, you're going
to want some kind of timeout mechanism that prevents my
blunder (or my sabotage!) from monopolizing your page until
somebody notices the problem and restarts it. As far as
I'm aware, JUnit has no such facility; it just runs tests
until they finish or fail. If they do neither ...

Various organizations have public web pages that run
externally-submitted programs under controlled conditions,
with provision for catching runaways, guarding against hacks,
and so on. Instead of reinventing the wheel, I'd suggest
you look up a few of those sites and find out what they're
using for software; perhaps you can adapt something that
already exists as opposed to building it all from scratch.
Note: If this could be done, I imagine that also could be applied to
test if the developers are using some classes that are not specified
by the architecture. (eg: when developing J2ee code, sometimes the
developers could use some classes from the app server that could
decrease the portability)

Although this shares some aspects with the programming-
assignment problem, I think it's fundamentally a different
issue. There's no "antagonist" to worry about, and the
body of code to be inspected is more or less "known," so I
think static analysis of byte code (or source code) may be
a more appropriate tool than black-box run-time testing.
 
P

Patricia Shanahan

Eric said:
Daniel wrote On 04/23/07 13:53,:
Eric, thanks for your help
To clarify a little bit more my problem, I will try to add some
example of what I'm needing:

I need that some users fill with code in page to solve a task, this
task involves the sorting of an array of integers, this could be
easily solved with Collections.sort, but I gave them as a
precondition, they couldn't use the Collections class (because I want
to test if they can iterate an order an array by themselves).
To correct this tasks, I have a Junit class that test against the
submitted code, so I was searching for some mechanism that could help
me with this.

The webpage is an open community JavaBlackBelt.com

You could certainly inspect the compiled byte code for
references to "forbidden" classes. The java.lang.instrument
package might be helpful here.

However, I doubt such an approach will be all that useful
as a detector of cheating. To begin with, you need to make
a useful list of banned classes -- For example, if I were
told to sort an int[], I would use Arrays.sort() and never
touch the Collections class at all. Also, the sources for
Arrays (and Collections) are readily available; a cheater
could simply copy the source and change the package names,
and thus evade your detection.

For completeness, note that a cheater could use reflection and run time
string calculation to invoke Arrays.sort without any mention of it that
would be visible to static analysis of the class. However, that would be
technically more difficult than writing a sort.

The most practical cheating method would indeed be to copy any known
working sort method, not necessarily Arrays.sort, followed by a few
minutes work with e.g. the Eclipse refactoring tools - change
identifiers to protect the guilty, extract some methods...

How about picking a programming task that does not have so many correct
implementations lying around on the web?

Patricia
 
M

Mark Space

Daniel said:
Eric, thanks for your help
To clarify a little bit more my problem, I will try to add some
example of what I'm needing:

I need that some users fill with code in page to solve a task, this
task involves the sorting of an array of integers, this could be
easily solved with Collections.sort, but I gave them as a
precondition, they couldn't use the Collections class (because I want
to test if they can iterate an order an array by themselves).

I didn't read everything, but I wonder if some form of dependancy
injection would work here. You supply the object (let's call it
SortTest) to sort, rather than allow them to declare one internally.

Also, make each method call for SortTest, for a read or a write, record
what is being done. So if they are supposed to be implementing a shell
sort, you'll know if the reads and writes for the object are being done
in the correct order. This could be useful feedback for the student, to
point out common errors. If on the other hand they read each element
once, in order, then write them back once, in the sorted order, they are
probably cheating.

Rather than calling main, I think you'd have to define your own
Interface, which the user would then implement. Do the compile and run
both on your end, that way you can control which libraries are accessed.
You could also define your own classloader, to deny access to certain
classes by the user.
 
P

Philipp Taprogge

Hi!

Thus spake Patricia Shanahan on 04/23/2007 09:53 PM:
For completeness, note that a cheater could use reflection and run time
string calculation to invoke Arrays.sort without any mention of it that
would be visible to static analysis of the class.

You could certainly try and grep your way through the submitted
source code to find those fragments.
However, that would be
technically more difficult than writing a sort.

However, that would be technically more difficult than coming up
with a more challenging task ;-)
How about picking a programming task that does not have so many correct
implementations lying around on the web?

But seriously... I always hated tasks like that which forced you to
reinvent the wheel... I think I might have used exactly the approach
you mentioned above... it might have been difficult, but I think I
would have liked the idea of having circumvented a seemingly useless
condition. ;-)

Regards,

Phil
 
E

Eric Sosman

Philipp said:
Hi!

Thus spake Patricia Shanahan on 04/23/2007 09:53 PM:

You could certainly try and grep your way through the submitted
source code to find those fragments.

I'm not sure whether it would be equivalent to the Halting
Problem, but it certainly could be difficult:

StringBuffer buff =
new StringBuffer("kbwb/vujm/Bssbzt");
for (int i = 0; i < buff.length; ++i)
buff.setCharAt(i, buff.charAt(i) - 1);
Class c = Class.forName(buff.toString());
...

It's occurred to me that loading the "foreign" class with
a customized ClassLoader might be the start of a way to intercept
such dodges. It still wouldn't defend against the far simpler
cheat of copying the freely-available source code of Arrays.sort
and giving it a new name.
 
P

Patricia Shanahan

Eric said:
I'm not sure whether it would be equivalent to the Halting
Problem, but it certainly could be difficult:

StringBuffer buff =
new StringBuffer("kbwb/vujm/Bssbzt");
for (int i = 0; i < buff.length; ++i)
buff.setCharAt(i, buff.charAt(i) - 1);
Class c = Class.forName(buff.toString());
...

Or, really simple and effective, just xor "java.util.Arrays" with a
random bit pattern, and store both bit pattern and the result. The byte
code would contain two apparently random arrays of char, but their xor
would be the original string.

Patricia
 
A

Adam Maass

Daniel said:
Im writing a unit test class, and I want to check if a given class is
importing some package (ie: java.util.Collections) from the code, is
that posible?

With this code
Class a = myClass.getClass();
System.out.println(a.getPackage());

i can know the package of myClass, is there anything like this for
imports statements?

Short answer: no.

Import statements simply tell the compiler where to look for types referred
to by simple name. The imports do not exist in the .class file structure as
indepedent entities.

-- Adam Maass
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Daniel said:
I need that some users fill with code in page to solve a task, this
task involves the sorting of an array of integers, this could be
easily solved with Collections.sort, but I gave them as a
precondition, they couldn't use the Collections class (because I want
to test if they can iterate an order an array by themselves).
To correct this tasks, I have a Junit class that test against the
submitted code, so I was searching for some mechanism that could help
me with this.

You need to get the classloader used to tell you.

Here are a starting point:

import java.net.URL;
import java.net.URLClassLoader;

public class TraceClassLoader extends URLClassLoader {
public TraceClassLoader(String cp) throws Exception {
super(new URL[] { new URL(cp) });
}
protected Class<?> loadClass(String name, boolean resolve) throws
ClassNotFoundException {
System.out.println(name);
return super.loadClass(name, resolve);
}
public static void main(String[] args) throws Exception {
Class.forName(args[0], true, new
TraceClassLoader(args[1])).getMethod("main", new Class[] {
String[].class }).invoke(null, new Object[] { new String[0] });
}
}

import java.util.*;

public class Foobar {
public static void main(String[] args) throws Exception {
List lst = new ArrayList();
lst.add("CCC");
lst.add("BB");
lst.add("A");
for(int i = 0; i < lst.size(); i++) {
System.out.println(lst.get(i));
}
Collections.sort(lst);
for(int i = 0; i < lst.size(); i++) {
System.out.println(lst.get(i));
}
}
}

java TraceClassLoader Foobar file:/C:/

Foobar
java.lang.Object
java.util.List
java.lang.String
java.lang.Exception
java.util.ArrayList
java.lang.System
java.io.PrintStream
CCC
BB
A
java.util.Collections
A
BB
CCC

Arne

PS: It is important that Foobar.class is not in the classpath where
TraceClassLoader is running.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top