Java Forum / General / April 2007
I need to know if a java class import a package
Daniel - 23 Apr 2007 15:20 GMT 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?
Eric Sosman - 23 Apr 2007 16:09 GMT 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 [quoted text clipped - 6 lines] > 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'?
 Signature Eric.Sosman@sun.com
Daniel - 23 Apr 2007 18:39 GMT 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?
> Daniel wrote On 04/23/07 10:20,: > [quoted text clipped - 44 lines] > -- > Eric.Sos...@sun.com Daniel - 23 Apr 2007 18:53 GMT 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)
> Daniel wrote On 04/23/07 10:20,: > [quoted text clipped - 44 lines] > -- > Eric.Sos...@sun.com Eric Sosman - 23 Apr 2007 19:47 GMT 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 [quoted text clipped - 10 lines] > > 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.
 Signature Eric.Sosman@sun.com
Patricia Shanahan - 23 Apr 2007 20:53 GMT > Daniel wrote On 04/23/07 13:53,: >> Eric, thanks for your help [quoted text clipped - 24 lines] > 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
Philipp Taprogge - 23 Apr 2007 23:45 GMT Hi!
> 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
Eric Sosman - 24 Apr 2007 02:04 GMT > Hi! > [quoted text clipped - 4 lines] > 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.
 Signature Eric Sosman esosman@acm-dot-org.invalid
Patricia Shanahan - 24 Apr 2007 02:14 GMT >> Hi! >> [quoted text clipped - 14 lines] > 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
Mark Space - 23 Apr 2007 23:43 GMT > Eric, thanks for your help > To clarify a little bit more my problem, I will try to add some [quoted text clipped - 5 lines] > 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.
Arne Vajhøj - 29 Apr 2007 03:43 GMT > 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 [quoted text clipped - 4 lines] > 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.
Adam Maass - 28 Apr 2007 11:48 GMT > 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 [quoted text clipped - 6 lines] > 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
Free MagazinesGet 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 ...
|
|
|