diff options
author | Hans-Christoph Steiner <eighthave@users.sourceforge.net> | 2008-03-22 02:15:12 +0000 |
---|---|---|
committer | Hans-Christoph Steiner <eighthave@users.sourceforge.net> | 2008-03-22 02:15:12 +0000 |
commit | a764e59e1d3a8e330f0d484fdb26b35ca3f0b2e4 (patch) | |
tree | c4ecadccdecf2809b99c0da0545f255a6ad25bb5 /src/java/com/e1 |
bringing pdj-0.8.3 into the main branchsvn2git-root
svn path=/trunk/externals/loaders/pdj/; revision=9621
Diffstat (limited to 'src/java/com/e1')
-rw-r--r-- | src/java/com/e1/pdj/ConsoleStream.java | 35 | ||||
-rw-r--r-- | src/java/com/e1/pdj/ConsoleStreamWin32.java | 34 | ||||
-rw-r--r-- | src/java/com/e1/pdj/GenericCompiler.java | 71 | ||||
-rw-r--r-- | src/java/com/e1/pdj/JavacCompiler.java | 34 | ||||
-rw-r--r-- | src/java/com/e1/pdj/JikesCompiler.java | 27 | ||||
-rw-r--r-- | src/java/com/e1/pdj/PDJClassLoader.java | 206 | ||||
-rw-r--r-- | src/java/com/e1/pdj/PDJClassLoaderException.java | 17 | ||||
-rw-r--r-- | src/java/com/e1/pdj/PDJError.java | 15 | ||||
-rw-r--r-- | src/java/com/e1/pdj/PDJSystem.java | 142 | ||||
-rw-r--r-- | src/java/com/e1/pdj/PriorityQueue.java | 68 | ||||
-rw-r--r-- | src/java/com/e1/pdj/test/AtomTest.java | 92 | ||||
-rw-r--r-- | src/java/com/e1/pdj/test/CallbackTest.java | 10 | ||||
-rw-r--r-- | src/java/com/e1/pdj/test/MaxQelemTest.java | 7 |
13 files changed, 758 insertions, 0 deletions
diff --git a/src/java/com/e1/pdj/ConsoleStream.java b/src/java/com/e1/pdj/ConsoleStream.java new file mode 100644 index 0000000..cf396c7 --- /dev/null +++ b/src/java/com/e1/pdj/ConsoleStream.java @@ -0,0 +1,35 @@ +package com.e1.pdj; + +import java.io.*; + +import com.cycling74.max.MaxSystem; + +public class ConsoleStream extends OutputStream { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(4096); + + protected void send(String message) { + MaxSystem.post("pdj: " + message); + } + + public void flush() { + String msg = buffer.toString(); + if ( msg.endsWith("\n") ) { + msg = msg.substring(0, msg.length()-1); + } + if ( !msg.equals("") ) + send(buffer.toString()); + buffer.reset(); + } + + public void write(byte[] b) throws IOException { + buffer.write(b); + } + + public void write(int b) throws IOException { + buffer.write(b); + } + + public void write(byte[] b, int off, int len) throws IOException { + buffer.write(b, off, len); + } +} diff --git a/src/java/com/e1/pdj/ConsoleStreamWin32.java b/src/java/com/e1/pdj/ConsoleStreamWin32.java new file mode 100644 index 0000000..80f767e --- /dev/null +++ b/src/java/com/e1/pdj/ConsoleStreamWin32.java @@ -0,0 +1,34 @@ +package com.e1.pdj; + +import com.cycling74.max.MaxSystem; + +/** + * Win32 has a special stream since it can contains /r/n that will + * be duplicated in the console + */ +public class ConsoleStreamWin32 extends ConsoleStream { + protected void send(String message) { + StringBuffer ret = new StringBuffer(); + + for (int i=0;i<message.length();i++) { + char c = message.charAt(i); + + if ( c != '\r' ) + ret.append(c); + } + + message = ret.toString(); + if ( !message.equals("\n") ) + MaxSystem.post("pdj: " + ret.toString()); + } + + public void flush() { + String msg = buffer.toString(); + if ( msg.endsWith("\n") ) { + msg = msg.substring(0, msg.length()-1); + } + if ( !msg.equals("") ) + send(buffer.toString()); + buffer.reset(); + } +} diff --git a/src/java/com/e1/pdj/GenericCompiler.java b/src/java/com/e1/pdj/GenericCompiler.java new file mode 100644 index 0000000..31278b7 --- /dev/null +++ b/src/java/com/e1/pdj/GenericCompiler.java @@ -0,0 +1,71 @@ +package com.e1.pdj; + +import java.io.*; + +import com.cycling74.max.MaxSystem; + +abstract class GenericCompiler { + File javaFile; + String cp[]; + String compilerName; + + static String rtJar; + + GenericCompiler(String name) { + compilerName = name + ": "; + } + + String getConfigurationClassPath() { + return PDJClassLoader.getConfigurationClassPath(); + } + + File resolvJavaFile() { + int base = PDJClassLoader.fclasses.toString().length() + 1; + String className = javaFile.toString().substring(base); + return new File(className); + } + + private int doexec(String arg) throws Exception { + Process p = Runtime.getRuntime().exec(arg, null, PDJClassLoader.fclasses); + + BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream())); + BufferedReader stderr = new BufferedReader(new InputStreamReader(p.getErrorStream())); + String buff; + boolean cont = true; + while(cont) { + cont = false; + + buff = stdout.readLine(); + if ( buff != null ) { + MaxSystem.post(compilerName + buff); + cont = true; + } else { + cont = false; + } + + buff = stderr.readLine(); + if ( buff != null ) { + MaxSystem.post(compilerName + buff); + cont = true; + } else { + cont = cont & false; + } + } + + p.waitFor(); + + return p.exitValue(); + } + + int exec(String arg) throws PDJClassLoaderException { + MaxSystem.post("pdj: trying to compile class: " + resolvJavaFile().toString()); + + try { + return doexec(arg); + } catch (Exception e) { + throw new PDJClassLoaderException(e); + } + } + + abstract void compileClass() throws PDJClassLoaderException; +} diff --git a/src/java/com/e1/pdj/JavacCompiler.java b/src/java/com/e1/pdj/JavacCompiler.java new file mode 100644 index 0000000..7f2debe --- /dev/null +++ b/src/java/com/e1/pdj/JavacCompiler.java @@ -0,0 +1,34 @@ +package com.e1.pdj; + +import com.cycling74.max.MaxSystem; +import java.io.File; + +class JavacCompiler extends GenericCompiler { + + public JavacCompiler() { + super("javac"); + } + + String javacPath() { + String fullPath = System.getProperty("pdj.JAVA_HOME"); + File test = new File(new File(fullPath, "bin"), "javac"); + if ( test.exists() ) { + return test.getAbsolutePath(); + } + MaxSystem.post("unable to find 'bin/javac' from the JAVA_HOME, using PATH"); + return "javac"; + } + + void compileClass() throws PDJClassLoaderException { + String args = javacPath() + " " + resolvJavaFile() + + " -classpath " + getConfigurationClassPath() + + " -sourcepath " + PDJClassLoader.fclasses.toString(); + + int rc = exec(args); + + if ( rc != 0 ) { + throw new PDJClassLoaderException("pdj: compiler returned: "+ rc + ",args: " +args); + } + MaxSystem.post("pdj: compile successful"); + } +} diff --git a/src/java/com/e1/pdj/JikesCompiler.java b/src/java/com/e1/pdj/JikesCompiler.java new file mode 100644 index 0000000..f9337b2 --- /dev/null +++ b/src/java/com/e1/pdj/JikesCompiler.java @@ -0,0 +1,27 @@ +package com.e1.pdj; + +import java.io.*; +import com.cycling74.max.MaxSystem; + +public class JikesCompiler extends GenericCompiler { + + JikesCompiler() { + super("jikes"); + } + + void compileClass() throws PDJClassLoaderException { + if ( GenericCompiler.rtJar == null ) + throw new PDJClassLoaderException("pdj: JAVA_HOME not found"); + + String args = "jikes " + resolvJavaFile() + + " -classpath " + GenericCompiler.rtJar + getConfigurationClassPath() + + " -sourcepath " + PDJClassLoader.fclasses.toString(); + + int rc = exec(args); + + if ( rc != 0 ) { + throw new PDJClassLoaderException("pdj: compiler returned: "+ rc + ",args: " +args); + } + MaxSystem.post("pdj: compile successful"); + } +} diff --git a/src/java/com/e1/pdj/PDJClassLoader.java b/src/java/com/e1/pdj/PDJClassLoader.java new file mode 100644 index 0000000..ee54e71 --- /dev/null +++ b/src/java/com/e1/pdj/PDJClassLoader.java @@ -0,0 +1,206 @@ +package com.e1.pdj; + +import java.net.URLClassLoader; +import java.net.*; +import java.util.*; +import java.io.*; + +import com.cycling74.max.MaxSystem; + +public class PDJClassLoader extends URLClassLoader { + /** The folder where the class (and java files) are */ + static File fclasses; + + /** if this is set to true, all classloader operation will be logged */ + static boolean verboseCL = false; + + static private PDJClassLoader instance; + + static { + String prop = System.getProperty("pdj.classes-dir"); + + if ( prop == null ) { + fclasses = new File(System.getProperty("pdj.home") + "/classes"); + } else { + fclasses = new File(prop); + } + instance = new PDJClassLoader(); + + verboseCL = PDJSystem.isSystemPropertyTrue("pdj.verbose-classloader"); + } + + static public PDJClassLoader getInstance() { + return instance; + } + + public PDJClassLoader() { + super(resolvClasspath()); + } + + private static void findJars(File f, Collection v) throws MalformedURLException { + File files[] = f.listFiles(); + + for(int i = 0;i<files.length;i++) { + String filename = files[i].toString(); + if ( filename.endsWith(".jar") || filename.endsWith(".zip") ) { + v.add(new URL("jar:" + files[i].toURL().toString() + "!/")); + } + } + } + + private static URL[] resolvClasspath() { + String cp = System.getProperty("pdj.classpath"); + ArrayList list = new ArrayList(); + String pathSeparator = "" + File.pathSeparator; + + try { + if ( fclasses.isDirectory() ) + list.add(fclasses.toURL()); + + File lib = new File(System.getProperty("pdj.home") + "/lib"); + if ( lib.isDirectory() ) + findJars(lib, list); + + StringTokenizer st = new StringTokenizer(cp, pathSeparator); + while( st.hasMoreTokens() ) { + String token = st.nextToken(pathSeparator); + File f = new File(token); + if ( f.isFile() && (f.toString().endsWith(".jar") || f.toString().endsWith(".zip")) ) + list.add(new URL("jar:" + f.toURL().toString() + "!/")); + if ( f.isDirectory() ) { + findJars(f, list); + list.add(f.toURL()); + } + } + } catch ( MalformedURLException mue ) { + throw new Error("pdj: unable to add to classpath: " + mue); + } + + URL ret[] = (URL[]) list.toArray(new URL[list.size()]); + + if ( verboseCL ) { + MaxSystem.post("pdj: verbose classloader: system classpath: " + System.getProperty("java.class.path")); + MaxSystem.post("pdj: verbose classloader: dynamic classpath:"); + for(int i=0;i<ret.length;i++) { + MaxSystem.post("\t" + ret[i].toString()); + } + } + + return ret; + } + + public static String[] getCurrentClassPath() { + URL url[] = instance.getURLs(); + String ret[] = new String[url.length]; + + for(int i=0;i<url.length;i++) { + ret[i] = url[i].toString(); + } + return ret; + } + + public static String getReadableClassPath() { + PDJClassLoader cloader = getInstance(); + StringBuffer sb = new StringBuffer(); + + URL url[] = cloader.getURLs(); + for(int i=0;i<url.length;i++) { + sb.append("\t" + url[i].toString() + "\n"); + } + + return sb.toString(); + } + + /** + * Returns a readable classpath for javac + * @return the classpath for javac / jikes + */ + public static String getConfigurationClassPath() { + StringBuffer sb = new StringBuffer(); + + sb.append(System.getProperty("java.class.path") + File.pathSeparatorChar); + + URL url[] = getInstance().getURLs(); + for(int i=0;i<url.length;i++) { + String path = url[i].toString(); + + if ( path.startsWith("file:") ) { + sb.append(path.substring(6) + File.pathSeparatorChar); + continue; + } + + if ( path.startsWith("jar:") ) { + sb.append(path.substring(10, path.lastIndexOf("!")) + File.pathSeparatorChar); + continue; + } + + sb.append(path + File.pathSeparatorChar); + } + + return sb.toString(); + } + + public static void resetClassloader() { + instance = new PDJClassLoader(); + System.gc(); + } + + /** + * Dynamic resolv will try to load .java file from date with .class + * @param name classname + * @return class definition + * @throws ClassNotFoundException + */ + public static Class dynamicResolv(String name) throws PDJClassLoaderException { + if ( System.getProperty("pdj.compiler").equals("null") ) { + resetClassloader(); + try { + return instance.loadClass(name); + } catch (ClassNotFoundException e) { + throw new PDJClassLoaderException(e); + } + } + + String pathName = name.replace('.', File.pathSeparatorChar); + + File classFile = new File(fclasses, pathName + ".class"); + File javaFile = new File(fclasses, pathName + ".java"); + + if ( javaFile.exists() ) { + if ( classFile.exists() ) { + if ( javaFile.lastModified() > classFile.lastModified() ) { + compileClass(javaFile); + } else { + if ( verboseCL ) + MaxSystem.post("class: " + name + " is already compiled and younger than the source .java file"); + } + } else { + compileClass(javaFile); + } + } + + resetClassloader(); + + try { + return instance.loadClass(name); + } catch (ClassNotFoundException e) { + throw new PDJClassLoaderException(e); + } + } + + protected static void compileClass(File javaFile) throws PDJClassLoaderException { + String str_compiler = System.getProperty("pdj.compiler"); + GenericCompiler compiler = null; + + if ( str_compiler.equals("jikes") ) { + compiler = new JikesCompiler(); + } else { + if ( !str_compiler.equals("javac") ) { + System.err.println("pdj: unknown compiler:" + str_compiler + ", using javac."); + } + compiler = new JavacCompiler(); + } + compiler.javaFile = javaFile; + compiler.compileClass(); + } +} diff --git a/src/java/com/e1/pdj/PDJClassLoaderException.java b/src/java/com/e1/pdj/PDJClassLoaderException.java new file mode 100644 index 0000000..547853c --- /dev/null +++ b/src/java/com/e1/pdj/PDJClassLoaderException.java @@ -0,0 +1,17 @@ +package com.e1.pdj; + +public class PDJClassLoaderException extends Exception { + private static final long serialVersionUID = 8714491904913363787L; + + public PDJClassLoaderException(String msg) { + super(msg); + } + + public PDJClassLoaderException(String msg, Exception root) { + super(msg, root); + } + + public PDJClassLoaderException(Exception root) { + super(root); + } +} diff --git a/src/java/com/e1/pdj/PDJError.java b/src/java/com/e1/pdj/PDJError.java new file mode 100644 index 0000000..7d89f1a --- /dev/null +++ b/src/java/com/e1/pdj/PDJError.java @@ -0,0 +1,15 @@ +package com.e1.pdj; + + +public class PDJError extends Error { + private static final long serialVersionUID = 1264000707984047887L; + + public PDJError(String msg) { + super(msg); + } + public PDJError(Throwable t) { + initCause(t); + } + public PDJError() { + } +} diff --git a/src/java/com/e1/pdj/PDJSystem.java b/src/java/com/e1/pdj/PDJSystem.java new file mode 100644 index 0000000..3d30a53 --- /dev/null +++ b/src/java/com/e1/pdj/PDJSystem.java @@ -0,0 +1,142 @@ +package com.e1.pdj; + +import com.cycling74.max.MaxSystem; + +import java.awt.Component; +import java.awt.Frame; +import java.awt.Toolkit; +import java.io.*; + +/** + * Startup class for pdj. + */ +public class PDJSystem { + private static int loaded = 0; + + public static PrintStream err; + + public static PrintStream out; + + /** + * Called by the pdj external when the JVM is initializing. + */ + public static void _init_system() { + if ( loaded == 1 ) + return; + linknative(); + initIO(); + } + + static void resolvRtJar() { + char ps = File.separatorChar; + String systemCpJar = System.getProperty("pdj.JAVA_HOME"); + if ( systemCpJar == null ) { + systemCpJar = System.getProperty("JAVA_HOME"); + if ( systemCpJar == null ) { + systemCpJar = System.getenv("JAVA_HOME"); + } + } + + System.setProperty("pdj.JAVA_HOME", systemCpJar); + GenericCompiler.rtJar = systemCpJar + ps + "jre" + ps + "lib" + ps + "rt.jar" + File.pathSeparator; + } + + /** + * Link the Java native classes + */ + static void linknative() { + String pdjHome = System.getProperty("pdj.home"); + + // this is a hack to be sure that statics of MaxSystem are loaded + // before everything + Class cls = MaxSystem.class; + + String osname = System.getProperty("os.name"); + + if ( osname.indexOf("Linux") != -1 ) { + // maps PD object as a JVM native library + Runtime.getRuntime().load(pdjHome + "/pdj.pd_linux"); + loaded = 1; + resolvRtJar(); + return; + } + + if ( osname.indexOf("Windows") != -1 ) { + // maps PD object as a JVM native library + Runtime.getRuntime().load(pdjHome + "/pdj.dll"); + loaded = 1; + resolvRtJar(); + return; + } + + if ( osname.indexOf("OS X") != -1 ) { + // maps PD object as a JVM native library + try { + Runtime.getRuntime().load(pdjHome + "/pdj.pd_darwin"); + } catch (UnsatisfiedLinkError e ) { + Runtime.getRuntime().load(pdjHome + "/pdj.pd_imac"); + } + loaded = 1; + + // this will initialize the AWT component in another thread + new Thread(new Runnable() { + public void run() { + Class clz = Component.class; + } + }).start(); + + GenericCompiler.rtJar = "/System/Library/Frameworks/JavaVM.framework/Classes/classes.jar:"; + + return; + } + + System.err.println("pdj: operating system type not found, the native link has not been made"); + } + + static boolean redirectIO() { + String prop = System.getProperty("pdj.redirect-pdio"); + + if ( prop == null ) + return true; + + if ( prop.charAt(0) == '0' ) + return false; + + if ( prop.equals("false") ) + return false; + + return true; + } + + static void initIO() { + if ( redirectIO() ) { + if ( System.getProperty("os.name").indexOf("Windows") == -1 ) { + out = new PrintStream(new ConsoleStream(), true); + err = new PrintStream(new ConsoleStream(), true); + } else { + out = new PrintStream(new ConsoleStreamWin32(), true); + err = new PrintStream(new ConsoleStreamWin32(), true); + } + System.setOut(out); + System.setErr(err); + } else { + out = System.out; + err = System.err; + } + } + + public static boolean isSystemPropertyTrue(String name) { + String value = System.getProperty(name); + + if ( value == null ) + return false; + + if ( value.toLowerCase().equals("true") ) + return true; + + if ( value.equals("1") ) + return true; + + return false; + } +} diff --git a/src/java/com/e1/pdj/PriorityQueue.java b/src/java/com/e1/pdj/PriorityQueue.java new file mode 100644 index 0000000..59a69a4 --- /dev/null +++ b/src/java/com/e1/pdj/PriorityQueue.java @@ -0,0 +1,68 @@ +package com.e1.pdj; + +import java.util.*; +import com.cycling74.max.Executable; + +public class PriorityQueue implements Runnable { + List list = new ArrayList(); + private Thread thread; + boolean tostop = false; + + public PriorityQueue(int priority) { + thread = new Thread(this); + + switch( priority ) { + case Thread.MIN_PRIORITY : + thread.setName("PriorityQueue:low"); + break; + case Thread.NORM_PRIORITY : + thread.setName("PriorityQueue:norm"); + break; + case Thread.MAX_PRIORITY : + thread.setName("PriorityQueue:max"); + break; + } + thread.setPriority(priority); + thread.setDaemon(true); + thread.start(); + } + + public void shutdown() { + synchronized(this) { + tostop = true; + notify(); + } + } + + public void run() { + Executable exec; + + while(true) { + try { + synchronized(this) { + if ( list.size() == 0 ) + wait(); + + if ( tostop ) + break; + exec = (Executable) list.remove(0); + } + try { + exec.execute(); + } catch (Exception e) { + e.printStackTrace(); + } + } catch (InterruptedException e) { + break; + } + } + } + + public void defer(Executable e) { + synchronized(this) { + list.add(e); + notify(); + } + } + +} diff --git a/src/java/com/e1/pdj/test/AtomTest.java b/src/java/com/e1/pdj/test/AtomTest.java new file mode 100644 index 0000000..c900ed8 --- /dev/null +++ b/src/java/com/e1/pdj/test/AtomTest.java @@ -0,0 +1,92 @@ +package com.e1.pdj.test; + +import junit.framework.TestCase; +import com.cycling74.max.Atom; + +public class AtomTest extends TestCase { + + public void testIsIn() { + Atom[] list = new Atom[] { Atom.newAtom(1), Atom.newAtom("ok"), Atom.newAtom(5) }; + + assertEquals(Atom.isIn(Atom.newAtom("ok"), list), 1); + assertEquals(Atom.isIn(Atom.newAtom(5), list), 2); + assertEquals(Atom.isIn(Atom.newAtom(0), list), -1); + assertEquals(Atom.isIn(Atom.newAtom(1), list, 1 ,2), -1); + assertEquals(Atom.isIn(Atom.newAtom("ok"), list, 1 ,2), 1); + } + + public void testRemoveSome() { + Atom[] list = new Atom[] { Atom.newAtom(1), Atom.newAtom("ok"), Atom.newAtom(5) }; + + Atom[] test = Atom.removeSome(list, 1, 2); + assertEquals(1, test.length); + assertEquals(Atom.newAtom(1), test[0]); + } + + public void testReverse() { + Atom[] list = new Atom[] { Atom.newAtom(1), Atom.newAtom("ok"), Atom.newAtom(5) }; + + Atom[] test = Atom.reverse(list); + assertEquals(Atom.newAtom(5), test[0]); + assertEquals(Atom.newAtom("ok"), test[1]); + assertEquals(Atom.newAtom(1),test[2]); + } + + public void testRotate() { + Atom[] list = new Atom[] { Atom.newAtom(1), Atom.newAtom("ok"), Atom.newAtom(5) }; + + Atom[] test = Atom.rotate(list, 2); + assertEquals(Atom.newAtom("ok"), test[0]); + assertEquals(Atom.newAtom(5), test[1]); + assertEquals(Atom.newAtom(1), test[2]); + + test = Atom.rotate(list, 5); + assertEquals(Atom.newAtom("ok"), test[0]); + assertEquals(Atom.newAtom(5), test[1]); + assertEquals(Atom.newAtom(1), test[2]); + + test = Atom.rotate(list, 1); + assertEquals(Atom.newAtom(5), test[0]); + assertEquals(Atom.newAtom(1), test[1]); + assertEquals(Atom.newAtom("ok"), test[2]); + } + + public void testRemoveFirst() { + Atom[] list = new Atom[] { Atom.newAtom(1), Atom.newAtom("ok"), Atom.newAtom(5) }; + + Atom[] test = Atom.removeFirst(list, 2); + assertEquals(1, test.length); + assertEquals(Atom.newAtom(5), test[0]); + + test = Atom.removeFirst(list); + assertEquals(2, test.length); + assertEquals(Atom.newAtom("ok"), test[0]); + assertEquals(Atom.newAtom(5), test[1]); + } + + public void testRemoveLast() { + Atom[] list = new Atom[] { Atom.newAtom(1), Atom.newAtom("ok"), Atom.newAtom(5) }; + + Atom[] test = Atom.removeLast(list, 2); + assertEquals(1, test.length); + assertEquals(Atom.newAtom(1), test[0]); + + test = Atom.removeLast(list); + assertEquals(2, test.length); + assertEquals(Atom.newAtom(1), test[0]); + assertEquals(Atom.newAtom("ok"), test[1]); + } + + public void testUnion() { + assertTrue("union not implemented", false); + } + + public void testIntersection() { + assertTrue("intersection not implementated", false); + } + + public void testInt() { + Atom test = Atom.newAtom(0x90); + assertEquals(0x90, test.getInt()); + } +} diff --git a/src/java/com/e1/pdj/test/CallbackTest.java b/src/java/com/e1/pdj/test/CallbackTest.java new file mode 100644 index 0000000..4105479 --- /dev/null +++ b/src/java/com/e1/pdj/test/CallbackTest.java @@ -0,0 +1,10 @@ +package com.e1.pdj.test; + +import junit.framework.TestCase; + +public class CallbackTest extends TestCase { + + public void testSomething() { + + } +} diff --git a/src/java/com/e1/pdj/test/MaxQelemTest.java b/src/java/com/e1/pdj/test/MaxQelemTest.java new file mode 100644 index 0000000..a55fef9 --- /dev/null +++ b/src/java/com/e1/pdj/test/MaxQelemTest.java @@ -0,0 +1,7 @@ +package com.e1.pdj.test; + +import junit.framework.TestCase; + +public class MaxQelemTest extends TestCase { + +} |