commit 613bef2496fd3518bd14fc16a086d2b77dbc763f Author: Ziver Koc Date: Fri Nov 14 16:38:36 2008 +0000 lol diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..a6e589d --- /dev/null +++ b/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..fb58de7 --- /dev/null +++ b/.project @@ -0,0 +1,19 @@ + + + ZUtil + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.jdt.core.javanature + org.eclipse.jem.beaninfo.BeanInfoNature + + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..8faf322 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +#Wed Feb 06 16:42:34 CET 2008 +eclipse.preferences.version=1 +encoding/=ISO-8859-1 diff --git a/bin/zutil/History.class b/bin/zutil/History.class new file mode 100644 index 0000000..6f0f2b9 Binary files /dev/null and b/bin/zutil/History.class differ diff --git a/bin/zutil/MultiPrintStream.class b/bin/zutil/MultiPrintStream.class new file mode 100644 index 0000000..d7f7fa5 Binary files /dev/null and b/bin/zutil/MultiPrintStream.class differ diff --git a/bin/zutil/db/MySQLConnection.class b/bin/zutil/db/MySQLConnection.class new file mode 100644 index 0000000..17d96c1 Binary files /dev/null and b/bin/zutil/db/MySQLConnection.class differ diff --git a/exemple.gif b/exemple.gif new file mode 100644 index 0000000..7f8171a Binary files /dev/null and b/exemple.gif differ diff --git a/hs_err_pid1104.log b/hs_err_pid1104.log new file mode 100644 index 0000000..e43d7fc --- /dev/null +++ b/hs_err_pid1104.log @@ -0,0 +1,171 @@ +# +# An unexpected error has been detected by Java Runtime Environment: +# +# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x77cfb15f, pid=1104, tid=5336 +# +# Java VM: Java HotSpot(TM) Client VM (1.6.0_03-b05 mixed mode) +# Problematic frame: +# C [ntdll.dll+0x3b15f] +# +# If you would like to submit a bug report, please visit: +# http://java.sun.com/webapps/bugreport/crash.jsp +# + +--------------- T H R E A D --------------- + +Current thread (0x0b570400): JavaThread "Connection Thread" [_thread_in_native, id=5336] + +siginfo: ExceptionCode=0xc0000005, writing address 0x00000014 + +Registers: +EAX=0x00000000, EBX=0xfffffffc, ECX=0x00000000, EDX=0x00000004 +ESP=0x0bc3efe8, EBP=0x0bc3f038, ESI=0x0ba590bc, EDI=0x0ba590c0 +EIP=0x77cfb15f, EFLAGS=0x00010213 + +Top of Stack: (sp=0x0bc3efe8) +0x0bc3efe8: 0ba590bc 0ba590c0 00000000 001d4290 +0x0bc3eff8: 00000000 00000000 0bc3f07c 75a64c14 +0x0bc3f008: 00000424 00000420 00000002 75a63f42 +0x0bc3f018: cacfe3c5 0bc3f108 0bc3f114 00000000 +0x0bc3f028: 00000000 00000000 7ffae000 000002f0 +0x0bc3f038: 0bc3f060 77cfb071 00000000 00000000 +0x0bc3f048: 00000000 0b946e80 00000000 00000004 +0x0bc3f058: 00000000 00000001 0bc3f0f0 20b0447e + +Instructions: (pc=0x77cfb15f) +0x77cfb14f: ff 33 c0 89 45 0c 89 45 08 8b 06 83 f8 ff 74 04 +0x77cfb15f: 83 40 14 01 8b 5d f4 8b 7d f0 90 80 3d 82 03 fe + + +Stack: [0x0bbf0000,0x0bc40000), sp=0x0bc3efe8, free space=315k +Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) +C [ntdll.dll+0x3b15f] +C [ntdll.dll+0x3b071] +C [imon.dll+0x447e] + +Java frames: (J=compiled Java code, j=interpreted, Vv=VM code) +j java.net.SocketInputStream.socketRead0(Ljava/io/FileDescriptor;[BIII)I+0 +j java.net.SocketInputStream.read([BII)I+84 +j java.io.BufferedInputStream.fill()V+175 +J java.io.BufferedInputStream.read()I +j java.io.DataInputStream.readByte()B+4 +j org.eclipse.jem.internal.proxy.vm.remote.ConnectionHandler.run()Ljava/lang/Object;+54 +j org.eclipse.jem.internal.proxy.vm.remote.ConnectionThread.run()V+4 +v ~StubRoutines::call_stub + +--------------- P R O C E S S --------------- + +Java Threads: ( => current thread ) + 0x0be61000 JavaThread "AWT-Windows" daemon [_thread_in_native, id=1640] + 0x0be4ac00 JavaThread "Java2D Disposer" daemon [_thread_blocked, id=3032] +=>0x0b570400 JavaThread "Connection Thread" [_thread_in_native, id=5336] + 0x0148ec00 JavaThread "Server Thread-Project (ZUtil)-Beaninfo" [_thread_blocked, id=5880] + 0x01448800 JavaThread "Low Memory Detector" daemon [_thread_blocked, id=5052] + 0x01433c00 JavaThread "CompilerThread0" daemon [_thread_blocked, id=4504] + 0x01432800 JavaThread "Attach Listener" daemon [_thread_blocked, id=3072] + 0x01432400 JavaThread "Signal Dispatcher" daemon [_thread_blocked, id=704] + 0x01424800 JavaThread "Finalizer" daemon [_thread_blocked, id=4056] + 0x01418400 JavaThread "Reference Handler" daemon [_thread_blocked, id=4536] + 0x01388800 JavaThread "main" [_thread_blocked, id=340] + +Other Threads: + 0x01414000 VMThread [id=4904] + 0x0144a800 WatcherThread [id=2452] + +VM state:not at safepoint (normal execution) + +VM Mutex/Monitor currently owned by a thread: None + +Heap + def new generation total 960K, used 840K [0x03490000, 0x03590000, 0x03970000) + eden space 896K, 86% used [0x03490000, 0x03552328, 0x03570000) + from space 64K, 100% used [0x03570000, 0x03580000, 0x03580000) + to space 64K, 0% used [0x03580000, 0x03580000, 0x03590000) + tenured generation total 4096K, used 973K [0x03970000, 0x03d70000, 0x07490000) + the space 4096K, 23% used [0x03970000, 0x03a63430, 0x03a63600, 0x03d70000) + compacting perm gen total 12288K, used 5126K [0x07490000, 0x08090000, 0x0b490000) + the space 12288K, 41% used [0x07490000, 0x07991a68, 0x07991c00, 0x08090000) +No shared spaces configured. + +Dynamic libraries: +0x00400000 - 0x00423000 C:\Program Files\Java\jre1.6.0_03\bin\javaw.exe +0x77cc0000 - 0x77dde000 C:\Windows\system32\ntdll.dll +0x774d0000 - 0x775a8000 C:\Windows\system32\kernel32.dll +0x76890000 - 0x7694f000 C:\Windows\system32\ADVAPI32.dll +0x77630000 - 0x776f3000 C:\Windows\system32\RPCRT4.dll +0x77910000 - 0x779ae000 C:\Windows\system32\USER32.dll +0x76710000 - 0x7675b000 C:\Windows\system32\GDI32.dll +0x77e00000 - 0x77e1e000 C:\Windows\system32\IMM32.DLL +0x77bf0000 - 0x77cb7000 C:\Windows\system32\MSCTF.dll +0x77b40000 - 0x77bea000 C:\Windows\system32\msvcrt.dll +0x77e20000 - 0x77e29000 C:\Windows\system32\LPK.DLL +0x76600000 - 0x7667d000 C:\Windows\system32\USP10.dll +0x10000000 - 0x10015000 C:\Windows\system32\APSHook.dll +0x76950000 - 0x769a5000 C:\Windows\system32\SHLWAPI.dll +0x76400000 - 0x76408000 C:\Windows\system32\VERSION.dll +0x76570000 - 0x76577000 C:\Windows\system32\PSAPI.DLL +0x76000000 - 0x76194000 C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.6000.16386_none_5d07289e07e1d100\comctl32.dll +0x7c340000 - 0x7c396000 C:\Program Files\Java\jre1.6.0_03\bin\msvcr71.dll +0x6d7c0000 - 0x6da0a000 C:\Program Files\Java\jre1.6.0_03\bin\client\jvm.dll +0x75730000 - 0x75763000 C:\Windows\system32\WINMM.dll +0x777c0000 - 0x77904000 C:\Windows\system32\ole32.dll +0x76680000 - 0x7670c000 C:\Windows\system32\OLEAUT32.dll +0x756f0000 - 0x75728000 C:\Windows\system32\OLEACC.dll +0x763a0000 - 0x763cc000 C:\Windows\system32\apphelp.dll +0x6d310000 - 0x6d318000 C:\Program Files\Java\jre1.6.0_03\bin\hpi.dll +0x6d770000 - 0x6d77c000 C:\Program Files\Java\jre1.6.0_03\bin\verify.dll +0x6d3b0000 - 0x6d3cf000 C:\Program Files\Java\jre1.6.0_03\bin\java.dll +0x6d7b0000 - 0x6d7bf000 C:\Program Files\Java\jre1.6.0_03\bin\zip.dll +0x6d570000 - 0x6d583000 C:\Program Files\Java\jre1.6.0_03\bin\net.dll +0x765d0000 - 0x765fd000 C:\Windows\system32\WS2_32.dll +0x77df0000 - 0x77df6000 C:\Windows\system32\NSI.dll +0x20b00000 - 0x20b4b000 C:\Windows\system32\imon.dll +0x75ad0000 - 0x75ad7000 C:\Windows\system32\WSOCK32.dll +0x75a60000 - 0x75a9b000 C:\Windows\system32\mswsock.dll +0x75ac0000 - 0x75ac6000 C:\Windows\System32\wship6.dll +0x75690000 - 0x75696000 C:\Windows\System32\wshtcpip.dll +0x754f0000 - 0x754ff000 C:\Windows\system32\NLAapi.dll +0x75c90000 - 0x75ca9000 C:\Windows\system32\IPHLPAPI.DLL +0x75c50000 - 0x75c85000 C:\Windows\system32\dhcpcsvc.DLL +0x75ec0000 - 0x75eeb000 C:\Windows\system32\DNSAPI.dll +0x76410000 - 0x76424000 C:\Windows\system32\Secur32.dll +0x75c40000 - 0x75c47000 C:\Windows\system32\WINNSI.DLL +0x75c20000 - 0x75c40000 C:\Windows\system32\dhcpcsvc6.DLL +0x73360000 - 0x73368000 C:\Windows\System32\winrnr.dll +0x77480000 - 0x774c9000 C:\Windows\system32\WLDAP32.dll +0x73350000 - 0x7335f000 C:\Windows\system32\napinsp.dll +0x73330000 - 0x73342000 C:\Windows\system32\pnrpnsp.dll +0x73320000 - 0x7332c000 C:\Windows\system32\wshbth.dll +0x779b0000 - 0x77b39000 C:\Windows\system32\SETUPAPI.dll +0x733f0000 - 0x733f6000 C:\Windows\system32\rasadhlp.dll +0x6d000000 - 0x6d1c3000 C:\Program Files\Java\jre1.6.0_03\bin\awt.dll +0x73750000 - 0x73791000 C:\Windows\system32\WINSPOOL.DRV +0x74350000 - 0x7438f000 C:\Windows\system32\uxtheme.dll +0x01180000 - 0x01198000 c:\Program Files\Bioscrypt\VeriSoft\Bin\ItClient.dll +0x74980000 - 0x74a06000 C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.6000.16386_none_87e0cb09378714f1\Comctl32.dll +0x73010000 - 0x7301c000 C:\Windows\system32\dwmapi.dll + +VM Arguments: +jvm_args: -Dproxyvm.registryKey=11131376 -Dproxyvm.masterPort=54959 -Dproxyvm.bufsize=16000 -Dproxyvm.servername=Project (ZUtil)-Beaninfo -Xverify:none +java_command: org.eclipse.jem.internal.proxy.vm.remote.RemoteVMApplication +Launcher Type: SUN_STANDARD + +Environment Variables: +CLASSPATH=.;C:\Program Files\Java\jre1.6.0_03\lib\ext\QTJava.zip +PATH=C:\Program Files\Java\jre1.6.0_03\bin\client;C:\Program Files\Java\jre1.6.0_03\bin;C:\Windows\system32;C:\Windows;C:\Windows\system32\wbem;c:\program files\common files\roxio shared\dllshared\;c:\program files\common files\roxio shared\dllshared\;c:\program files\common files\roxio shared\9.0\dllshared\;c:\program files\bioscrypt\verisoft\bin;C:\Program Files\MATLAB\R2007a\bin;C:\Program Files\MATLAB\R2007a\bin\win32;C:\Program\Dev-Cpp\libexec\gcc\mingw32\3.4.2;C:\Program Files\Smart Projects\IsoBuster;C:\Program Files\Autodesk\Backburner\;C:\Program Files\Common Files\Autodesk Shared\;C:\Program Files\Java\jdk1.6.0_02\bin;C:\Program Files\QuickTime\QTSystem\ +USERNAME=Ziver +OS=Windows_NT +PROCESSOR_IDENTIFIER=x86 Family 6 Model 15 Stepping 10, GenuineIntel + + + +--------------- S Y S T E M --------------- + +OS: Windows Vista Build 6000 + +CPU:total 2 (2 cores per cpu, 1 threads per core) family 6 model 15 stepping 10, cmov, cx8, fxsr, mmx, sse, sse2, sse3, ssse3 + +Memory: 4k page, physical 2094912k(757952k free), swap 4194303k(1884172k free) + +vm_info: Java HotSpot(TM) Client VM (1.6.0_03-b05) for windows-x86, built on Sep 24 2007 22:24:33 by "java_re" with unknown MS VC++:1310 + diff --git a/libs/mysql-connector-java-5.0.7-bin.jar b/libs/mysql-connector-java-5.0.7-bin.jar new file mode 100644 index 0000000..412138a Binary files /dev/null and b/libs/mysql-connector-java-5.0.7-bin.jar differ diff --git a/src/zutil/Converter.java b/src/zutil/Converter.java new file mode 100644 index 0000000..c30d90a --- /dev/null +++ b/src/zutil/Converter.java @@ -0,0 +1,69 @@ +package zutil; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +public class Converter { + + /** + * Converts an object to an array of bytes. + * + * @param object the object to convert. + * @return the associated byte array. + */ + public static byte[] toBytes(Object object){ + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try{ + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(object); + oos.flush(); + oos.close(); + }catch(IOException ioe){ + System.out.println(ioe.getMessage()); + } + return baos.toByteArray(); + } + + /** + * Converts an array of bytes back to its constituent object. The + * input array is assumed to have been created from the original object. + * + * @param bytes the byte array to convert. + * @return the associated object. + */ + public static Object toObject(byte[] bytes) { + Object object = null; + try{ + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois= new ObjectInputStream(bais); + object = ois.readObject(); + ois.close(); + bais.close(); + }catch(IOException ioe){ + System.out.println(ioe.getMessage()); + }catch(ClassNotFoundException cnfe){ + System.out.println(cnfe.getMessage()); + } + return object; + } + + /** + * Checks if the given interface is implemented in the object + * @param object The object to look for the interface + * @param interf The interface to look for + * @return True if the interface is implemented else false + */ + @SuppressWarnings("unchecked") + public static boolean isInstanceOf(Object object, Class interf){ + Class[] objectInterf = object.getClass().getInterfaces(); + for(int i=0; i search(File dir){ + return search(dir, new ArrayList()); + } + + /** + * Returns a ArrayList with all the files in a folder and sub folders + * + * @param dir The directory to search in + * @param fileList The ArrayList to add the files to + * @return The ArrayList with the files + */ + public static ArrayList search(File dir, ArrayList fileList){ + String[] temp = dir.list(); + File file; + + for(int i=0; i 0) { + digest.update(buffer, 0, read); + } + byte[] md5sum = digest.digest(); + BigInteger bigInt = new BigInteger(1, md5sum); + output = bigInt.toString(16); + } + catch(IOException e) { + throw new RuntimeException("Unable to process file for MD5", e); + } + is.close(); + + MultiPrintStream.out.println("File Hash: "+output); + return output; + } + + /** + * Returns the hash of the given object + * + * @param object The object to hash + * @param hashType The hash method + * @return String containing the hash + * @throws NoSuchAlgorithmException + */ + public static String hash(Serializable object, String hashType) throws NoSuchAlgorithmException { + MessageDigest md = null; + md = MessageDigest.getInstance(hashType); //MD5 || SHA + md.update(Converter.toBytes(object)); + + byte raw[] = md.digest(); + return (new BASE64Encoder()).encode(raw); + } +} diff --git a/src/zutil/History.java b/src/zutil/History.java new file mode 100644 index 0000000..0e0b7c2 --- /dev/null +++ b/src/zutil/History.java @@ -0,0 +1,59 @@ +package zutil; + +import java.util.LinkedList; + +public class History { + public int history_length = 10; + private LinkedList history; + private int historyIndex = 0; + + public History(int histlength){ + history_length = histlength; + history = new LinkedList(); + } + + public void addToHistory(T url){ + while(historyIndex < history.size()-1){ + history.removeLast(); + } + history.addLast(url); + if(history_length < history.size()){ + history.removeFirst(); + } + + historyIndex = history.size()-1; + } + + public T getBackHistory(){ + if(historyIndex > 0){ + historyIndex -= 1; + } + else{ + historyIndex = 0; + } + return history.get(historyIndex); + } + + public T getForwHistory(){ + if(forwHistoryExist()){ + historyIndex += 1; + } + else{ + historyIndex = history.size()-1; + } + return history.get(historyIndex); + } + + public T getCurrentHistory(){ + return history.get(historyIndex); + } + + public boolean forwHistoryExist(){ + if(historyIndex < history.size()-1){ + return true; + } + else{ + return false; + } + } +} diff --git a/src/zutil/MultiPrintStream.java b/src/zutil/MultiPrintStream.java new file mode 100644 index 0000000..28f0c30 --- /dev/null +++ b/src/zutil/MultiPrintStream.java @@ -0,0 +1,309 @@ +package zutil; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.io.Reader; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; + +/** + * @author Ziver + * this class can print strings to multiple PrintStreams + */ +public class MultiPrintStream extends PrintStream { + //the print streams that will print + private ArrayList streams; + // the stream should print time stamp + private boolean timeStamp = false; + //The timestamp style + private String timeStampString = "yyyy-MM-dd HH:mm:ss:SSS# "; + //a instance of this class + public static MultiPrintStream out = new MultiPrintStream(); + + public MultiPrintStream(){ + super(new PrintStream(System.out)); + streams = new ArrayList(); + streams.add(new PrintStream(System.out)); + } + + /** + * this constructor makes a simple PrintStream that prints to the console and to a file + * @param file the file name to output to + */ + public MultiPrintStream(String file){ + super(new PrintStream(System.out)); + try { + streams = new ArrayList(); + streams.add(new PrintStream(System.out)); + streams.add(new PrintStream(new File(file))); + } catch (FileNotFoundException e) { + System.out.println("Error when declaring PrintStream!!"); + e.printStackTrace(); + } + } + + /** + * this constructor takes a array of PrintStreams to be used + * @param streams a array of the streams that will be used + */ + public MultiPrintStream(PrintStream[] streams){ + super(streams[0]); + this.streams = new ArrayList(); + for(int i=0; i- Array content + *
- Map content (HashMap etc.) + *
- List content (ArrayList, LinkedList etc.) + *
- InputStream content (Prints out until the end of the stream) + *
- Reader content (Prints out until the end of the reader) + *
- Instance variables of a Object + * + * @param o The Object to dump + * @param print If the method should print the data or just return it + * @return A String with all the printed data + */ + @SuppressWarnings("unchecked") + private String dump( Object o , boolean print) { + StringBuffer buffer = new StringBuffer(); + Class oClass = o.getClass(); + buffer.append( oClass.getName() ); + // Prints out Arrays + if ( oClass.isArray() ) { + buffer.append( "[" ); + for ( int i=0; i 0 ) + buffer.append( ", " ); + Object value = Array.get(o,i); + buffer.append( (dumbCapable(value) ? dump(value,false) : value) ); + } + buffer.append( "]" ); + } + // Prints out a list + else if(o instanceof Collection){ + Iterator it = ((Collection)o).iterator(); + buffer.append( "{" ); + while(it.hasNext()){ + Object value = it.next(); + buffer.append( (dumbCapable(value) ? dump(value,false) : value) ); + if(it.hasNext()) + buffer.append( ", " ); + } + buffer.append( "}" ); + } + // Prints out a Map + else if(o instanceof Map){ + Iterator it = ((Map)o).keySet().iterator(); + buffer.append( "{" ); + while(it.hasNext()){ + Object key = it.next(); + Object value = ((Map)o).get(key); + buffer.append( key ); + buffer.append( "=>" ); + buffer.append( (dumbCapable(value) ? dump(value,false) : value) ); + if(it.hasNext()) + buffer.append( ", " ); + } + buffer.append( "}" ); + } + // Prints out data from InputStream + else if(o instanceof InputStream){ + buffer.append( " =>{ \n" ); + try { + InputStream in = (InputStream)o; + int tmp; + while((tmp = in.read()) != -1){ + buffer.append( (char)tmp ); + } + in.close(); + } catch (IOException e) { + e.printStackTrace(this); + } + buffer.append( "\n}" ); + } + // Prints out data from InputStream + else if(o instanceof Reader){ + buffer.append( " =>{ \n" ); + try { + Reader in = (Reader)o; + int tmp; + while((tmp = in.read()) != -1){ + buffer.append( (char)tmp ); + } + in.close(); + } catch (IOException e) { + e.printStackTrace(this); + } + buffer.append( "\n}" ); + } + // Prints out Object properties + else{ + buffer.append( "{" ); + while ( oClass != null ) { + Field[] fields = oClass.getDeclaredFields(); + for ( int i=0; i 1 ) + buffer.append( ", " ); + fields[i].setAccessible( true ); + buffer.append( fields[i].getName() ); + buffer.append( "=" ); + try { + Object value = fields[i].get(o); + if (value != null) { + buffer.append( (dumbCapable(value) ? dump(value,false) : value) ); + } + } catch ( IllegalAccessException e ) {} + } + oClass = oClass.getSuperclass(); + } + buffer.append( "}" ); + } + + if(print) out.println(buffer.toString()); + return buffer.toString(); + } + + private boolean dumbCapable(Object o){ + if(o.getClass().isArray()) return true; + else if(o instanceof Collection)return true; + else if(o instanceof Map)return true; + return false; + } +} diff --git a/src/zutil/OneApp.java b/src/zutil/OneApp.java new file mode 100644 index 0000000..734ee97 --- /dev/null +++ b/src/zutil/OneApp.java @@ -0,0 +1,24 @@ +package zutil; + +/** + * This interface is used to look if another instance of the + * application is running + * + * @author Ziver + * + */ +public interface OneApp { + /** + * Checks if the application is already running + * + * @return True if the file is locked else false + */ + public boolean check(); + + /** + * Locks the application so that another one can not run + * + * @return False if there are a error else true + */ + public boolean lockApp(); +} diff --git a/src/zutil/OneAppFile.java b/src/zutil/OneAppFile.java new file mode 100644 index 0000000..310d539 --- /dev/null +++ b/src/zutil/OneAppFile.java @@ -0,0 +1,99 @@ +package zutil; + +import java.io.File; +import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.channels.OverlappingFileLockException; + +/** + * This class checks if the application is already running + * by Locking a file + * + * @author Ziver Koc + */ +public class OneAppFile implements OneApp{ + private File file; + private FileChannel channel; + private FileLock lock; + + /** + * Creates a OneApp class + * + * @param filename The name of the file to be locked + */ + public OneAppFile(String filename){ + this.file = new File(System.getProperty("user.home"), filename); + } + + /** + * Checks if the file have already bean locked + * + * @return True if the file is locked else false + */ + public boolean check() { + boolean tmp = lockApp(); + closeLock(); + return !tmp; + } + + /** + * Locks the file + * + * @return False if there are a error else true + */ + public boolean lockApp() { + try { + channel = new RandomAccessFile(file, "rw").getChannel(); + + try { + lock = channel.tryLock(); + } + catch (OverlappingFileLockException e) { + // already locked + closeLock(); + return false; + } + + if (lock == null) { + closeLock(); + return false; + } + + Runtime.getRuntime().addShutdownHook(new Thread() { + // destroy the lock when the JVM is closing + public void run() { + closeLock(); + deleteFile(); + } + }); + return true; + } + catch (Exception e) { + closeLock(); + return false; + } + } + + private void closeLock() { + try { + lock.release(); + channel.close(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + private void deleteFile() { + try { + file.delete(); + } + catch (Exception e) { + e.printStackTrace(); + } + } +} + + + diff --git a/src/zutil/OneAppNetwork.java b/src/zutil/OneAppNetwork.java new file mode 100644 index 0000000..57ce7ce --- /dev/null +++ b/src/zutil/OneAppNetwork.java @@ -0,0 +1,72 @@ +package zutil; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; + +/** + * This class checks if the app is alredy running + * by Locking a port + * + * @author Ziver Koc + */ +public class OneAppNetwork extends Thread implements OneApp{ + private int port; + + /** + * Creates a One App objekt + * + * @param port The port to lock + */ + public OneAppNetwork(int port){ + this.port = port; + } + + /** + * Starts the port lock + * + * @return Always true + */ + public boolean lockApp(){ + this.start(); + return true; + } + + /** + * he port lock thread + * should not be cald outside the class + */ + public void run() { + ServerSocket serverSocket = null; + Socket clientSocket = null; + try { + // Create the server socket + serverSocket = new ServerSocket(port, 1); + while (true) { + // Wait for a connection + clientSocket = serverSocket.accept(); + clientSocket.close(); + } + } + catch (IOException ioe) { + MultiPrintStream.out.println("Error in JustOneServer: " + ioe); + } + } + + /** + * Checks if the port is locked + * + * @return True if port is locked else false + */ + public boolean check() { + try { + Socket clientSocket = new Socket("localhost", port); + MultiPrintStream.out.println("Already running!!!"); + clientSocket.close(); + return true; + } + catch (Exception e) { + return false; + } + } +} diff --git a/src/zutil/ProgressListener.java b/src/zutil/ProgressListener.java new file mode 100644 index 0000000..d661831 --- /dev/null +++ b/src/zutil/ProgressListener.java @@ -0,0 +1,18 @@ +package zutil; + +/** + * This interface is used in some classes to handle the progress + * of some action + * + * @author Ziver + * + */ +public interface ProgressListener { + + /** + * This method is called when the progress is updated + * @param source The source object of the progress + * @param percent The progress of the object (0-100) + */ + public void progressUpdate(Object source, Object info, double percent); +} diff --git a/src/zutil/StringUtil.java b/src/zutil/StringUtil.java new file mode 100644 index 0000000..35a0a0c --- /dev/null +++ b/src/zutil/StringUtil.java @@ -0,0 +1,30 @@ +package zutil; + +/** + * This is a class whit utility methods. + * + * @author Ziver * + */ +public class StringUtil { + + /** + * Present a size (in bytes) as a human-readable value + * + * @param size size (in bytes) + * @return string + */ + public static String formatBytesToString(long bytes){ + String[] sizes = new String[]{"YB", "ZB", "EB", "PB", "TB", "GB", "MB", "kB", "B"}; + int total = sizes.length-1; + double value = bytes; + + for(; value > 1024 ;total--) { + value /= 1024; + } + + value = (double)( (int)(value*100) )/100; + return value+" "+sizes[total]; + } + + +} diff --git a/src/zutil/algo/QuickSelect.java b/src/zutil/algo/QuickSelect.java new file mode 100644 index 0000000..54edf57 --- /dev/null +++ b/src/zutil/algo/QuickSelect.java @@ -0,0 +1,68 @@ +package zutil.algo; + +import zutil.algo.sort.sortable.SortableDataList; + +/** + * This algorithm is a modified QuickSort + * to find the k smallest or biggest value + * http://en.wikipedia.org/wiki/Selection_algorithm + * + * @author Ziver + * + */ +@SuppressWarnings("unchecked") +public class QuickSelect { + + public static Object find(SortableDataList list, int k){ + return find(list, k, 0, list.size()-1); + } + + /* + function select(list, k, left, right) + select a pivot value list[pivotIndex] + pivotNewIndex := partition(list, left, right, pivotIndex) + if k = pivotNewIndex + return list[k] + else if k < pivotNewIndex + return select(list, k, left, pivotNewIndex-1) + else + return select(list, k, pivotNewIndex+1, right) + */ + public static Object find(SortableDataList list, int k, int left, int right){ + // select a pivot + int pivot = right/2; + int newPivot = partition(list, left, right, pivot); + if(k == newPivot) + return list.getIndex(k); + else if(k < newPivot) + return find(list, k, left, newPivot-1); + else + return find(list, k, newPivot+1, right); + } + + /* + function partition(list, left, right, pivotIndex) + pivotValue := list[pivotIndex] + swap list[pivotIndex] and list[right] // Move pivot to end + storeIndex := left + for i from left to right-1 + if list[i] < pivotValue + swap list[storeIndex] and list[i] + storeIndex := storeIndex + 1 + swap list[right] and list[storeIndex] // Move pivot to its final place + return storeIndex + */ + private static int partition(SortableDataList list, int left, int right, int pivot){ + Object pivotValue = list.getIndex(pivot); + list.swap(pivot, right); + int storeIndex = left; + for(int i=left; i find(PathNode start, PathNode stop){ + // TODO + /* + 1 + + 5 dist[source] := 0 // Distance from source to source + 6 Q := copy(Graph) // All nodes in the graph are unoptimized - thus are in Q + 7 while Q is not empty: // The main loop + 8 u := extract_min(Q) // Remove and return best vertex from nodes in two given nodes + // we would use a path finding algorithm on the new graph, such as depth-first search. + 9 for each neighbor v of u: // where v has not yet been considered + 10 alt = dist[u] + length(u, v) + 11 if alt < dist[v] // Relax (u,v) + 12 dist[v] := alt + 13 previous[v] := u + 14 return previous[] +*/ + + + + LinkedList path = new LinkedList(); + PathNode current = stop; + while(true){ + path.addFirst(current); + current = current.getSourceNeighbor(); + if(current.equals(start)){ + path.addFirst(start); + break; + } + } + return path; + } +} diff --git a/src/zutil/algo/path/DynamicProgramming.java b/src/zutil/algo/path/DynamicProgramming.java new file mode 100644 index 0000000..b860fed --- /dev/null +++ b/src/zutil/algo/path/DynamicProgramming.java @@ -0,0 +1,117 @@ +package zutil.algo.path; + +public class DynamicProgramming { + public static char[][] words = new char[][]{ + "bibba".toCharArray(), + "bitas".toCharArray(), + "brott".toCharArray(), + "blöja".toCharArray(), + "boson".toCharArray() + }; + + public static void main(String[] args){ + new DynamicProgramming().search(); + } + /* + +int search(words[][][]) + matrix[][][] = 0 + shortest = -1 + + for w=0->length(words) + for y=0->length(words) + for x=0->length(words) + // första raden i matrisen + if y == 0 + // finns första bokstaven i rätt position i första ordet? + if words[0][x] != words[w][0] + matrix[w][y][x] = -1 + else + matrix[w][y][x] = 0 + else + // om föregående är negativ sätt nuvarande till negativ + if matrix[w][y-1][x] < 0 + matrix[w][y-1][x] = -1 + // här så händer det riktiga i algoritmen + else + tmp = minstaForskjutning(words[y], words[w][y], x) + if tmp >= 0 + matrix[w][y][x] = matrix[w][y-1][x] + tmp + else + matrix[w][y][x] = -1 + // kolla om det är sista raden i matrisen + if y == length(matrix) + if (tmp < shortest || shortest < 0) && tmp >= 0 + shortest = tmp; + + return shortest + +int minstaForskjutning(word[], find, index){ + minsta = -1 + for i=0->length(word) + if word[i] == cfind && (abs(index-i) < minsta || minsta < 0) + minsta = abs(index-i) + + return minsta + + */ + + public int search(){ + int[][][] matrix = new int[words.length][words.length][words.length]; + int shortest = -1; + + for(int w=0; w= 0){ + matrix[w][y][x] = matrix[w][y-1][x] + tmp; + } + else{ + matrix[w][y][x] = -1; + } + } + } + if(y == words.length-1){ + int tmp = matrix[w][y][x]; + if((tmp= 0){ + shortest = tmp; + } + } + System.out.print(" "+matrix[w][y][x]); + } + } + } + + System.out.println("\n\nKortaste förflyttningen: "+shortest); + return shortest; + } + + private int minstaForskjutning(char[] word, char cfind, int index){ + int minsta = -1; + for(int i=0; i getNeighbors(); + + public int getNeighborCost(PathNode neighbor); + + public void setSourceNeighbor(PathNode neighbor); + + public PathNode getSourceNeighbor(); +} \ No newline at end of file diff --git a/src/zutil/algo/path/PathNodeDefault.java b/src/zutil/algo/path/PathNodeDefault.java new file mode 100644 index 0000000..0a88be3 --- /dev/null +++ b/src/zutil/algo/path/PathNodeDefault.java @@ -0,0 +1,38 @@ +package zutil.algo.path; + +import java.util.HashMap; + +public class PathNodeDefault implements PathNode{ + private HashMap neighbors; + private PathNode neighbor; + private boolean visited; + + public PathNodeDefault(){ + neighbors = new HashMap(); + visited = false; + } + + public void setVisited(boolean b){ + visited = b; + } + + public int getNeighborCost(PathNode neighbor) { + return neighbors.get(neighbor); + } + + public Iterable getNeighbors() { + return neighbors.keySet(); + } + + public boolean visited() { + return visited; + } + + public void setSourceNeighbor(PathNode n) { + neighbor = n; + } + + public PathNode getSourceNeighbor() { + return neighbor; + } +} diff --git a/src/zutil/algo/path/SimplePathFinder.java b/src/zutil/algo/path/SimplePathFinder.java new file mode 100644 index 0000000..592dade --- /dev/null +++ b/src/zutil/algo/path/SimplePathFinder.java @@ -0,0 +1,95 @@ +package zutil.algo.path; + +import java.util.LinkedList; +import java.util.Queue; + +/** + * A class for simple path finding algorithms + * + * @author Ziver + */ +public class SimplePathFinder { + + /** + * Returns the first path to the destination + * + * @param start Start Node + * @param stop Stop Node + * @return A list with the path + */ + public LinkedList BreadthFirstSearch(PathNode start, PathNode stop){ + Queue queue = new LinkedList(); + + queue.add(start); + start.setVisited(true); + + PathNode tmp; + while(!queue.isEmpty()){ + tmp = queue.poll(); + + for(PathNode next : tmp.getNeighbors()){ + if(!next.visited() && tmp.getNeighborCost(next) > 0){ + queue.add(next); + next.setVisited(true); + next.setSourceNeighbor(tmp); + + if(next.equals(stop)){ + LinkedList path = new LinkedList(); + for(PathNode current=stop; !current.equals(start) ;current = current.getSourceNeighbor()){ + path.addFirst(current); + } + path.addFirst(start); + return path; + } + } + } + } + + return new LinkedList(); + } + + /** + * Returns the first path to the destination + * + * @param start Start Node + * @param stop Stop Node + * @return A list with the path + */ + public LinkedList DepthFirstSearch(PathNode start, PathNode stop){ + LinkedList path = new LinkedList(); + PathNode current = DepthFirstSearchInternal(start, stop); + while(current != null){ + path.addFirst(current); + current = current.getSourceNeighbor(); + if(current.equals(start)){ + path.addFirst(start); + break; + } + } + return path; + } + + /** + * The DepthFirstSearch algorithm + * @param node The node to search from + * @return The stop PathNode if a path was found else null + */ + private PathNode DepthFirstSearchInternal(PathNode node, PathNode stop){ + node.setVisited(true); + if(node.equals(stop)){ + return node; + } + + for(PathNode next : node.getNeighbors()){ + if(!next.visited() && node.getNeighborCost(next) > 0){ + next.setSourceNeighbor(node); + PathNode tmp = DepthFirstSearchInternal(next, stop); + if(tmp != null){ + return tmp; + } + } + } + return null; + } + +} diff --git a/src/zutil/algo/sort/ExternalSort.java b/src/zutil/algo/sort/ExternalSort.java new file mode 100644 index 0000000..fba0196 --- /dev/null +++ b/src/zutil/algo/sort/ExternalSort.java @@ -0,0 +1,252 @@ +package zutil.algo.sort; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; + +/** + * Sort very big files that doesn't fit in ram + * Inspiration: + * http://www.codeodor.com/index.cfm/2007/5/14/Re-Sorting-really-BIG-files---the-Java-source-code/1208 + * + * @author Ziver + */ +public class ExternalSort { + public static int CHUNK_SIZE = 100000; + + private BufferedReader in; + private File sortedFile; + + /** + * Creates a ExternalSort object that sort a big file + * with minimal use of ram + * + * @param orgFile File to sort + * @param sortedFile The sorted file + * @throws FileNotFoundException + */ + public ExternalSort(File orgFile, File sortedFile) throws FileNotFoundException{ + in = new BufferedReader(new FileReader(orgFile)); + this.sortedFile = sortedFile; + } + + /** + * Creates a ExternalSort object that sort a big file + * with minimal use of ram + * + * @param orgFile File to sort + * @param sortedFile The sorted file + * @param chunk The chunk size + * @throws FileNotFoundException + */ + public ExternalSort(File orgFile, File sortedFile, int chunk) throws FileNotFoundException{ + in = new BufferedReader(new FileReader(orgFile)); + this.sortedFile = sortedFile; + CHUNK_SIZE = chunk; + } + + /** + * Sorts the given file + * + * @throws IOException Some kind of error + */ + public void sort() throws IOException{ + // sorting the chunks + LinkedList chunkFiles = sortChunks(); + + //merging the chunks + mergeFiles(chunkFiles); + + //removing the chunks + removeFiles(chunkFiles); + } + + /** + * Merges all the files to one + * @param files + */ + private void mergeFiles(LinkedList files){ + try { + BufferedReader[] chunkReader = new BufferedReader[files.size()]; + String[] rows = new String[files.size()]; + BufferedWriter out = new BufferedWriter(new FileWriter(sortedFile)); + + boolean someFileStillHasRows = false; + + for (int i=0; i sortChunks() throws IOException{ + LinkedList chunkFiles = new LinkedList(); + LinkedList chunk = new LinkedList(); + do{ + chunk = readChunk(in); + + //QuickSort.sort(new SortableLinkedList(chunk)); + Collections.sort(chunk); + + File file = new File("extsort"+chunkFiles.size()+".txt"); + chunkFiles.add(file); + writeChunk(chunk,file); + }while(!chunk.isEmpty()); + + return chunkFiles; + } + + /** + * Reads in a chunk of rows into a LinkedList + * + * @param list The list to populate + * @param in The BufferedReader to read from + * @return The LinkeList with the chunk + * @throws IOException Some kind of error + */ + private LinkedList readChunk(BufferedReader in) throws IOException{ + LinkedList list = new LinkedList(); + String tmp; + for(int i=0; i list, File file) throws IOException{ + BufferedWriter out = new BufferedWriter(new FileWriter(file)); + Iterator it = list.iterator(); + while(it.hasNext()){ + out.write(it.next()); + out.newLine(); + } + out.close(); + } + + private void removeFiles(LinkedList list){ + Iterator it = list.iterator(); + while(it.hasNext()){ + it.next().delete(); + } + } +} diff --git a/src/zutil/algo/sort/QuickSort.java b/src/zutil/algo/sort/QuickSort.java new file mode 100644 index 0000000..c58de5f --- /dev/null +++ b/src/zutil/algo/sort/QuickSort.java @@ -0,0 +1,106 @@ +package zutil.algo.sort; + +import zutil.algo.sort.sortable.SortableComparableArray; +import zutil.algo.sort.sortable.SortableDataList; + +/** + * This class implements QuickSort to sort a array + * + * @author Ziver + */ +public class QuickSort{ + public static final int RANDOM_PIVOT = 0; + public static final int MEDIAN_PIVOT = 1; + public static final int HALF_PIVOT = 2; + + /** + * Sort the elements in ascending order using quicksort. + * + * @param A A list to sort. + */ + @SuppressWarnings("unchecked") + public static void sort(SortableDataList list){ + sort(list, 0, list.size()-1, 2, true); + } + + /** + * Sort the elements in ascending order using quicksort. + * + * @param A A list to sort. + * @param type type of pivot + * @param insert to use insertion sort when needed + */ + @SuppressWarnings("unchecked") + public static void sort(SortableDataList list, int type, boolean insert){ + sort(list, 0, list.size()-1, type, insert); + } + + /** + * Sort the elements in ascending order using qicksort. + * after the 10 th re write and a bad mood i found this + * site that gave me much help: + * http://www.inf.fh-flensburg.de/lang/algorithmen/ + * sortieren/quick/quicken.htm + * + * @param A A list to sort. + * @param start The index to start from + * @param stop The index to stop + * @param type The type of pivot to use + */ + @SuppressWarnings("unchecked") + public static void sort(SortableDataList list, int start, int stop, int type, boolean insertionSort){ + if(stop-start <= 15 && insertionSort){ + SimpleSort.insertionSort( list, start, stop); + } + int pivotIndex = pivot(list,start,stop,type); + Object pivot = list.getIndex(pivotIndex); + int left=start, right=stop; + + do{ + while(list.compare(left, pivot) < 0){ + left++; + } + while(list.compare(right, pivot) > 0){ + right--; + } + + if(left <= right){ + list.swap(left, right); + left++; + right--; + } + }while(left <= right); + + if(start < right){ + sort(list, start, right, type, insertionSort); + } + if(left < stop){ + sort(list, left, stop, type, insertionSort); + } + + } + + + @SuppressWarnings("unchecked") + private static int pivot(SortableDataList list, int start, int stop,int type){ + switch(type){ + case 0: + return start+(int)(Math.random()*(stop-start)); + case 1: + Comparable[] i = new Comparable[]{ + (Comparable)list.getIndex(0), + (Comparable)list.getIndex(list.size()/2), + (Comparable)list.getIndex(list.size()-1)}; + SimpleSort.insertionSort(new SortableComparableArray(i),0,i.length); + if(i[i.length/2].compareTo(list.getIndex(start)) == 0) + return start; + else if(i[i.length/2].compareTo(list.getIndex(stop)) == 0) + return stop; + else + return start+(stop-start)/2; + case 2: + return (start+stop)/2; + } + return 0; + } +} \ No newline at end of file diff --git a/src/zutil/algo/sort/Randomizer.java b/src/zutil/algo/sort/Randomizer.java new file mode 100644 index 0000000..6ffb25c --- /dev/null +++ b/src/zutil/algo/sort/Randomizer.java @@ -0,0 +1,25 @@ +package zutil.algo.sort; + +import zutil.algo.sort.sortable.SortableDataList; + +/** + * This class randomizes the index of all the elements in + * the Sortable object + * + * @author Ziver + */ +public class Randomizer { + + + /** + * Randomizes the index of all the elements + * @param list The list + */ + @SuppressWarnings("unchecked") + public static void sort(SortableDataList list){ + int size = list.size(); + for(int i=0; istart ;j--){ + if(list.compare(j, j-1) < 0){ + list.swap(j, j-1); + } + } + } + return list; + } + + } \ No newline at end of file diff --git a/src/zutil/algo/sort/sortable/SortableArrayList.java b/src/zutil/algo/sort/sortable/SortableArrayList.java new file mode 100644 index 0000000..6b56207 --- /dev/null +++ b/src/zutil/algo/sort/sortable/SortableArrayList.java @@ -0,0 +1,42 @@ +package zutil.algo.sort.sortable; + +import java.util.ArrayList; + +public class SortableArrayList implements SortableDataList{ + private ArrayList list; + + public SortableArrayList(ArrayList list){ + this.list = list; + } + + public T getIndex(int i) { + return list.get(i); + } + + public int size() { + return list.size(); + } + + public void swap(int a, int b) { + T temp = list.get(a); + list.set(a, list.get(b)); + list.set(b, temp); + } + + @SuppressWarnings("unchecked") + public int compare(int a, int b) { + Comparable aa = (Comparable)list.get(a); + Comparable bb = (Comparable)list.get(b); + return aa.compareTo(bb); + } + + @SuppressWarnings("unchecked") + public int compare(int a, T b) { + Comparable aa = (Comparable)list.get(a); + Comparable bb = (Comparable)b; + return aa.compareTo(bb); + } + + + +} diff --git a/src/zutil/algo/sort/sortable/SortableComparableArray.java b/src/zutil/algo/sort/sortable/SortableComparableArray.java new file mode 100644 index 0000000..d974f96 --- /dev/null +++ b/src/zutil/algo/sort/sortable/SortableComparableArray.java @@ -0,0 +1,47 @@ +package zutil.algo.sort.sortable; + +@SuppressWarnings("unchecked") +public class SortableComparableArray implements SortableDataList{ + private Comparable[] list; + + public SortableComparableArray(Comparable[] list){ + this.list = list; + } + + public Comparable getIndex(int i) { + return list[i]; + } + + public int size() { + return list.length; + } + + public void swap(int a, int b) { + Comparable temp = list[a]; + list[a] = list[b]; + list[b] = temp; + } + + public int compare(int a, int b) { + if(list[a].compareTo(list[b]) < 0){ + return -1; + } + else if(list[a].compareTo(list[b]) > 0){ + return 1; + } + return 0; + } + + public int compare(int a, Comparable b) { + if(list[a].compareTo(b) < 0){ + return -1; + } + else if(list[a].compareTo(b) > 0){ + return 1; + } + return 0; + } + + + +} diff --git a/src/zutil/algo/sort/sortable/SortableDataList.java b/src/zutil/algo/sort/sortable/SortableDataList.java new file mode 100644 index 0000000..90ecc1a --- /dev/null +++ b/src/zutil/algo/sort/sortable/SortableDataList.java @@ -0,0 +1,50 @@ +package zutil.algo.sort.sortable; + +public interface SortableDataList{ + + /** + * Returns a specific index i the list + * @param i The index + * @return + */ + public T getIndex(int i); + + /** + * Returns the size of the list + * + * @return The size of the list + */ + public int size(); + + /** + * Swaps the given indexes + * @param a First index + * @param b Second index + */ + public void swap(int a, int b); + + /** + * Compares to indexes and returns: + * <0 if a0 if a>b , + * =0 if a=b + * + * @param a Firs index to compare + * @param b Second index to compare + * @return Look at the info + */ + public int compare(int a, int b); + + /** + * Compares to indexes and returns: + * <0 if a0 if a>b , + * =0 if a=b + * + * @param a Firs index to compare + * @param b Second Object to compare + * @return Look at the info + */ + public int compare(int a, T b); + +} diff --git a/src/zutil/algo/sort/sortable/SortableIntArray.java b/src/zutil/algo/sort/sortable/SortableIntArray.java new file mode 100644 index 0000000..b610d20 --- /dev/null +++ b/src/zutil/algo/sort/sortable/SortableIntArray.java @@ -0,0 +1,46 @@ +package zutil.algo.sort.sortable; + +public class SortableIntArray implements SortableDataList{ + private int[] list; + + public SortableIntArray(int[] list){ + this.list = list; + } + + public Integer getIndex(int i) { + return list[i]; + } + + public int size() { + return list.length; + } + + public void swap(int a, int b) { + int temp = list[a]; + list[a] = list[b]; + list[b] = temp; + } + + public int compare(int a, int b) { + if(list[a] < list[b]){ + return -1; + } + else if(list[a] > list[b]){ + return 1; + } + return 0; + } + + public int compare(int a, Integer b) { + if(list[a] < b){ + return -1; + } + else if(list[a] > b){ + return 1; + } + return 0; + } + + + +} diff --git a/src/zutil/algo/sort/sortable/SortableLinkedList.java b/src/zutil/algo/sort/sortable/SortableLinkedList.java new file mode 100644 index 0000000..30b4ab0 --- /dev/null +++ b/src/zutil/algo/sort/sortable/SortableLinkedList.java @@ -0,0 +1,42 @@ +package zutil.algo.sort.sortable; + +import java.util.LinkedList; + +public class SortableLinkedList implements SortableDataList{ + private LinkedList list; + + public SortableLinkedList(LinkedList list){ + this.list = list; + } + + public T getIndex(int i) { + return list.get(i); + } + + public int size() { + return list.size(); + } + + public void swap(int a, int b) { + T temp = list.get(a); + list.set(a, list.get(b)); + list.set(b, temp); + } + + @SuppressWarnings("unchecked") + public int compare(int a, int b) { + Comparable aa = (Comparable)list.get(a); + Comparable bb = (Comparable)list.get(b); + return aa.compareTo(bb); + } + + @SuppressWarnings("unchecked") + public int compare(int a, T b) { + Comparable aa = (Comparable)list.get(a); + Comparable bb = (Comparable)b; + return aa.compareTo(bb); + } + + + +} diff --git a/src/zutil/data/JavaConsole.png b/src/zutil/data/JavaConsole.png new file mode 100644 index 0000000..f42a4e5 Binary files /dev/null and b/src/zutil/data/JavaConsole.png differ diff --git a/src/zutil/db/MySQLConnection.java b/src/zutil/db/MySQLConnection.java new file mode 100644 index 0000000..de5ecfc --- /dev/null +++ b/src/zutil/db/MySQLConnection.java @@ -0,0 +1,76 @@ +package zutil.db; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +public class MySQLConnection { + Connection conn = null; + + /** + * Connects to a MySQL server + * @param url The URL of the MySQL server + * @param db The database to connect to + * @param user The user name + * @param password The password + * @throws SQLException + * @throws ClassNotFoundException + * @throws IllegalAccessException + * @throws InstantiationException + */ + public MySQLConnection(String url,String db,String user, String password) throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException{ + Class.forName ("com.mysql.jdbc.Driver").newInstance(); + conn = DriverManager.getConnection ("jdbc:mysql://"+url+"/"+db, user, password); + } + + /** + * Runs a query and returns the result + * NOTE: Don't forget to close the ResultSet and the Statement or it can lead to memory leak tex: rows.getStatement().close(); + * @param sql The query to execute + * @return The data that the DB returned + * @throws SQLException + */ + public synchronized ResultSet returnQuery(String sql) throws SQLException{ + Statement s = conn.createStatement (); + s.executeQuery (sql); + return s.getResultSet(); + } + + /** + * Runs a query in the MySQL server and returns effected rows + * @param sql The query to execute + * @return Number of rows effected + * @throws SQLException + */ + public synchronized int updateQuery(String sql) throws SQLException{ + Statement s = conn.createStatement (); + int ret = s.executeUpdate(sql); + s.close(); + return ret; + } + + /** + * Runs a Prepared Statement + * NOTE: Don't forget to close the PreparedStatement or it can lead to memory leak + * @param sql The SQL to run + * @return The PreparedStatement + * @throws SQLException + */ + public synchronized PreparedStatement prepareStatement(String sql) throws SQLException{ + return conn.prepareStatement(sql); + } + + /** + * Disconnects from the database + * @throws SQLException + * + */ + public synchronized void close() throws SQLException{ + if (conn != null){ + conn.close (); + } + } +} diff --git a/src/zutil/db/MySQLQueue.java b/src/zutil/db/MySQLQueue.java new file mode 100644 index 0000000..d8e45f3 --- /dev/null +++ b/src/zutil/db/MySQLQueue.java @@ -0,0 +1,181 @@ +package zutil.db; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; +import java.util.Iterator; +import java.util.Queue; + +import zutil.Converter; +import zutil.MultiPrintStream; + +/** + * This class creates a queue that stors the + * data in a mysql table. + * The table should look like this: + * CREATE TABLE `queue` ( + * `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , + * `data` BINARY NOT NULL + * ); + * @author Ziver + * + */ +public class MySQLQueue implements Queue{ + + private MySQLConnection db; + private String table; + + /** + * Initiats the queue. + * WARNING!! this will erase all rows i the table + * @param db The connection to the db + * @param table The name of the table + * @throws SQLException + */ + public MySQLQueue(MySQLConnection db, String table){ + this.db = db; + this.table = table; + } + + public boolean add(Object arg0){ + try { + PreparedStatement sql = db.prepareStatement("INSERT INTO "+table+" (data) VALUES(?)"); + sql.setObject(1, arg0); + sql.executeUpdate(); + sql.close(); + } catch (Exception e) { + e.printStackTrace(MultiPrintStream.out); + return false; + } + return true; + } + + public E element() { + return peek(); + } + + public boolean offer(Object arg0) { + // TODO Auto-generated method stub + return false; + } + + @SuppressWarnings("unchecked") + public synchronized E peek() { + try { + ResultSet rs = db.returnQuery("SELECT * FROM "+table+" LIMIT 1"); + if (rs.next()) { + return (E) Converter.toObject(rs.getBytes("data")); + } + rs.getStatement().close(); + } catch (Exception e) { + e.printStackTrace(MultiPrintStream.out); + } + return null; + } + + @SuppressWarnings("unchecked") + public synchronized E poll() { + try { + ResultSet rs = db.returnQuery("SELECT * FROM "+table+" LIMIT 1"); + if (rs.next()) { + db.updateQuery("DELETE FROM "+table+" WHERE id="+rs.getInt("id")+" LIMIT 1"); + return (E) Converter.toObject(rs.getBytes("data")); + } + rs.getStatement().close(); + } catch (Exception e) { + e.printStackTrace(MultiPrintStream.out); + } + return null; + } + + public E remove() { + return poll(); + } + + public boolean addAll(Collection arg0) { + // TODO Auto-generated method stub + return false; + } + + public void clear() { + try { + db.updateQuery("TRUNCATE TABLE `"+table+"`"); + } catch (SQLException e) { + e.printStackTrace(MultiPrintStream.out); + } + } + + public boolean contains(Object arg0) { + try { + ResultSet rs = db.returnQuery("SELECT data FROM "+table+" WHERE data='"+Converter.toBytes(arg0)+"' LIMIT 1"); + if (rs.next()) { + return true; + } + rs.getStatement().close(); + } catch (Exception e) { + e.printStackTrace(MultiPrintStream.out); + } + return false; + } + + public boolean containsAll(Collection arg0) { + // TODO Auto-generated method stub + return false; + } + + public boolean isEmpty() { + return (peek() != null); + } + + public Iterator iterator() { + // TODO Auto-generated method stub + return null; + } + + public synchronized boolean remove(Object arg0) { + try { + ResultSet rs = db.returnQuery("DELETE FROM "+table+" WHERE data='"+Converter.toBytes(arg0)+"' LIMIT 1"); + rs.getStatement().close(); + return true; + } catch (Exception e) { + e.printStackTrace(MultiPrintStream.out); + } + return false; + } + + public synchronized boolean removeAll(Collection arg0) { + // TODO Auto-generated method stub + return false; + } + + public boolean retainAll(Collection arg0) { + // TODO Auto-generated method stub + return false; + } + + public int size() { + try { + ResultSet rs = db.returnQuery("SELECT count(*) FROM "+table); + if (rs.next()) { + return rs.getInt(1); + } + rs.getStatement().close(); + } catch (Exception e) { + e.printStackTrace(MultiPrintStream.out); + } + return 0; + } + + public E[] toArray() { + // TODO Auto-generated method stub + return null; + } + + @SuppressWarnings("unchecked") + public E[] toArray(Object[] arg0) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/src/zutil/image/ImageFilterProcessor.java b/src/zutil/image/ImageFilterProcessor.java new file mode 100644 index 0000000..c1e33ae --- /dev/null +++ b/src/zutil/image/ImageFilterProcessor.java @@ -0,0 +1,210 @@ +package zutil.image; + +import java.awt.image.BufferedImage; + +import zutil.ProgressListener; + +/** + * This is a abstract class for all the effects + * + * Inspiration: + * http://www.dickbaldwin.com/tocadv.htm + * + * @author Ziver + */ +public abstract class ImageFilterProcessor { + private BufferedImage img; + private ProgressListener progress; + + public ImageFilterProcessor(BufferedImage img){ + this.img = img; + } + + /** + * Sets the listener + * @param listener The listener, null to disable the progress + */ + public void setProgressListener(ProgressListener listener){ + this.progress = listener; + } + + /** + * Sets the progress in percent + */ + protected void setProgress(double percent){ + if(progress != null) progress.progressUpdate(this, null, percent); + } + + /** + * Applies a effect to a given image + * + * @param effect The effect to use + * @param img The image to process + * @return The processed image + */ + public static ImageFilterProcessor getProcessor(String effect, BufferedImage img) throws InstantiationException, IllegalAccessException, ClassNotFoundException, InterruptedException{ + ImageFilterProcessor processor = (ImageFilterProcessor)Class.forName(effect).newInstance(); + processor.img = img; + return processor; + } + + /** + * Adds the chosen effect to the image + * + * @return The Image with the effect + * @throws InterruptedException + */ + public BufferedImage process() throws InterruptedException{ + int cols = img.getWidth(); + int rows = img.getHeight(); + + if(cols < 0 || rows < 0){ + throw new InterruptedException("Image not Loaded!!!"); + } + + // converts the img to raw data + int[][][] data = convertToArray(img, cols, rows); + //processes the image + data = process(data, cols, rows); + //converts back the image + return convertToImage(data, data[0].length, data.length); + } + + /** + * Creates a Integer array whit the pixel data of the image + * int[row][col][4] + * 0 -> Alpha data + * Red data + * Green data + * 4 -> Blue data + * + * @param img The image to convert + * @param cols Columns of the image + * @param rows Rows of the image + * @return A Integer array + * @throws InterruptedException + */ + public static int[][][] convertToArray(BufferedImage img, int cols, int rows) throws InterruptedException{ + int[][][] data = new int[rows][cols][4]; + // Reads in the image to a one dim array + int[] pixels = img.getRGB(0, 0, cols, rows, null, 0, cols); + + // Read the pixel data and put it in the data array + for(int y=0; y> 24) & 0xFF; + //Red data + data[y][x][1] = (aRow[x] >> 16) & 0xFF; + //Green data + data[y][x][2] = (aRow[x] >> 8) & 0xFF; + //Blue data + data[y][x][3] = (aRow[x])& 0xFF; + } + } + return data; + } + + + /** + * Converts a pixel data array to a java Image object + * + * @param pixels The pixel data array + * @param cols Columns of the image + * @param rows Rows of the image + * @return A Image + */ + public static BufferedImage convertToImage(int[][][] pixels, int cols, int rows){ + int[] data = new int[cols * rows * 4]; + + //Move the data into the 1D array. Note the + // use of the bitwise OR operator and the + // bitwise left-shift operators to put the + // four 8-bit bytes into each int. + int index = 0; + for(int y=0; y 255) + return 255; + else + return color; + } + + + /** + * The underlying effect is run here + * @param data The raw image to apply the effect to + * @param cols Columns of the image + * @param rows Rows of the image + */ + public abstract int[][][] process(final int[][][] data, int cols, int rows); +} diff --git a/src/zutil/image/ImageUtil.java b/src/zutil/image/ImageUtil.java new file mode 100644 index 0000000..e6e30fe --- /dev/null +++ b/src/zutil/image/ImageUtil.java @@ -0,0 +1,170 @@ +package zutil.image; + +/** + * Some util methods for image processing + * @author Ziver + * + */ +public class ImageUtil { + /** + * Returns the peek value in the image + * + * @param data The image data + * @param cols The number of columns + * @param rows The number of rows + * @return The peak value of the image + */ + public static int peakValue(int[][][] data, int cols, int rows) { + int peak = 0; + for(int y=0; y peak) peak = data[y][x][1]; + if(data[y][x][2] > peak) peak = data[y][x][2]; + if(data[y][x][3] > peak) peak = data[y][x][3]; + } + } + return peak; + } + + /** + * Normalizes the image data by the given scale + * + * @param data The image data + * @param cols The number of columns + * @param rows The number of rows + * @param scale The scale to normalize the image by + */ + public static void normalize(int[][][] data, int cols, int rows, double scale) { + for(int y=0; y 100) redScale = 100; + else if(redScale < 0) redScale = 0; + + if(greenScale > 100) greenScale = 100; + else if(greenScale < 0) greenScale = 0; + + if(blueScale > 100) blueScale = 100; + else if(blueScale < 0) blueScale = 0; + + int[][][] output = new int[rows][cols][4]; + + // Applying the color intensity to the image + for(int y=0; y Alpha data + * Red data + * Green data + * 4 -> Blue data + */ + public DitheringFilter(BufferedImage img, int[][] palette){ + super(img); + this.palette = palette; + } + + @Override + public int[][][] process(final int[][][] data, int cols, int rows) { + int error, index; + int[] currentPixel; + + int[][][] output = copyArray(data, cols, rows); + + for(int y=0; y 0) + output[y+1][x-1][i] = clip( output[y+1][x-1][i] + (error*3)/16 ); + output[y+1][x+0][i] = clip( output[y+1][x+0][i] + (error*5)/16 ); + if (x + 1 < cols) + output[y+1][x+1][i] = clip( output[y+1][x+1][i] + (error*1)/16 ); + } + } + } + } + + return output; + } + + private static int findNearestColor(int[] color, int[][] palette) { + int minDistanceSquared = 255*255 + 255*255 + 255*255 + 1; + int bestIndex = 0; + for (byte i = 0; i < palette.length; i++) { + int Rdiff = color[1] - palette[i][0]; + int Gdiff = color[2] - palette[i][1]; + int Bdiff = color[3] - palette[i][2]; + int distanceSquared = Rdiff*Rdiff + Gdiff*Gdiff + Bdiff*Bdiff; + if (distanceSquared < minDistanceSquared) { + minDistanceSquared = distanceSquared; + bestIndex = i; + } + } + return bestIndex; + } +} diff --git a/src/zutil/image/filters/FaceDetectionFilter.java b/src/zutil/image/filters/FaceDetectionFilter.java new file mode 100644 index 0000000..1f7dfcf --- /dev/null +++ b/src/zutil/image/filters/FaceDetectionFilter.java @@ -0,0 +1,171 @@ +package zutil.image.filters; + +import java.awt.Rectangle; +import java.awt.image.BufferedImage; + +import zutil.image.ImageFilterProcessor; +import zutil.math.ZMath; + +public class FaceDetectionFilter extends ImageFilterProcessor{ + + public FaceDetectionFilter(BufferedImage img) { + super(img); + } + + @Override + public int[][][] process(int[][][] data, int cols, int rows) { + int[][][] IRgBy = convertARGBToIRgBy(data, cols, rows); + + MedianFilter median = new MedianFilter(null, 4*getSCALE(cols,rows), new boolean[]{false,false,true,true}); + IRgBy = median.process(IRgBy, cols, rows); + setProgress(ZMath.percent(0, 4, 1)); + + //********* Texture Map ******** + median = new MedianFilter(null, 8*getSCALE(cols,rows), new boolean[]{false,true,false,false}); + int[][][] textureMap = median.process(IRgBy, cols, rows); + + for(int y=0; y= 120 && hue <= 160) && (saturation >= 10 && saturation <= 60)) || + (textureMap[y][x][1] < 4.5 && (hue >= 150 && hue <= 180) && (saturation >= 20 && saturation <= 80)) ){ + skinMap[y][x] = 1; + } + } + } + setProgress(ZMath.percent(0, 4, 3)); + + //************** SkinMap dilation ******************** + skinMap = dilation(skinMap , cols, rows); + + + //***************************************************** + setProgress(100); + //return convertArrayToARGBchannel(hueMap, cols, rows, -150, 150, 1); + //return convertArrayToARGBchannel(saturationMap, cols, rows, 0, 70, 1); + return convertArrayToARGBchannel(skinMap, cols, rows, 0, 1, 2); + } + + private int[][] dilation(int[][] data, int cols, int rows){ + int[][] output = new int[rows][cols]; + int radX = 8; + int radY = 8; + + for(int y=0; y= 0 && dy < rows && dx >= 0 && dx < cols) + output[dy][dx] = 1; + } + } + + } + } + } + + return output; + } + + + /** + * Converts the given data array to a color image + * + * @param data The 2d data + * @param cols The size of the image data + * @param rows The size of the image data + * @param min The minimum value in the data + * @param max The maximum value in the data + * @param channel The color channel to apply the data to + * @return A ARGB array + */ + public int[][][] convertArrayToARGBchannel(int[][] data, int cols, int rows,int min, int max, int channel){ + int[][][] output = new int[rows][cols][4]; + + for(int y=0; y= 0 && y+fy-edgeY < rows && x+fx-edgeX >= 0 && x+fx-edgeX < cols){ + //colorArray[fx][fy] := pixelvalue[x + fx - edgex][y + fy - edgey] + if(channels[0]) tmpArray[0][ getMedianIndex( data[y + fy - edgeY][x + fx - edgeX][0] ) ]++; + if(channels[1]) tmpArray[1][ getMedianIndex( data[y + fy - edgeY][x + fx - edgeX][1] ) ]++; + if(channels[2]) tmpArray[2][ getMedianIndex( data[y + fy - edgeY][x + fx - edgeX][2] ) ]++; + if(channels[3]) tmpArray[3][ getMedianIndex( data[y + fy - edgeY][x + fx - edgeX][3] ) ]++; + pixelCount++; + } + } + } + + if(channels[0])output[y][x][0] = findMedian(tmpArray[0], pixelCount/2); + else output[y][x][0] = data[y][x][0]; + if(channels[1])output[y][x][1] = findMedian(tmpArray[1], pixelCount/2); + else output[y][x][1] = data[y][x][1]; + if(channels[2])output[y][x][2] = findMedian(tmpArray[2], pixelCount/2); + else output[y][x][2] = data[y][x][2]; + if(channels[3])output[y][x][3] = findMedian(tmpArray[3], pixelCount/2); + else output[y][x][3] = data[y][x][3]; + } + } + + return output; + } + + private int getMedianIndex(int i){ + if(i < 0) return Math.abs(i); + else return i+256; + } + + private int findMedian(int[] median, int medianCount){ + int sum = 0; + int ret = 0; + for(int i=0; i= medianCount && ret == 0){ + ret = i-256; + } + } + + return ret; + } + + + class SortableARGB implements SortableDataList{ + private int[][][] data; + private int cols; + private int rows; + private int channel; + + public SortableARGB(int[][][] data, int cols, int rows, int channel){ + this.data = data; + this.cols = cols; + this.rows = rows; + this.channel = channel; + } + + public int compare(int a, int b) { + return compare(a, data[ getY(b) ][ getX(b) ][ channel ]); + } + + public int compare(int a, Integer b) { + return ((Integer)data[ getY(a) ][ getX(a) ][ channel ]).compareTo(b); + } + + public Integer getIndex(int i) { + return data[ getY(i) ][ getX(i) ][ channel ]; + } + + public int size() { + return cols * rows; + } + + public void swap(int a, int b) { + int tmp = data[ getY(a) ][ getX(a) ][ channel ]; + data[ getY(a) ][ getX(a) ][ channel ] = data[ getY(b) ][ getX(b) ][ channel ]; + data[ getY(b) ][ getX(b) ][ channel ] = tmp; + } + + + private int getX(int a){ + return a % cols; + } + + private int getY(int a){ + return a / cols; + } + + } + +} diff --git a/src/zutil/image/filters/ResizeImage.java b/src/zutil/image/filters/ResizeImage.java new file mode 100644 index 0000000..5a1b133 --- /dev/null +++ b/src/zutil/image/filters/ResizeImage.java @@ -0,0 +1,63 @@ +package zutil.image.filters; + +import java.awt.image.BufferedImage; + +import zutil.image.ImageFilterProcessor; +import zutil.math.ZMath; + +public class ResizeImage extends ImageFilterProcessor{ + private int width; + private int hight; + + + /** + * Will create a ResizeImage object and fix the hight with the aspect + * of the width + * + * @param img The image to resize + * @param w The new width + */ + public ResizeImage(BufferedImage img, int w){ + this(img, w, -1); + } + + /** + * Will create a ResizeImage object + * + * @param img The image to resize + * @param w The new width if -1 then it will be scaled whit aspect of the hight + * @param h The new hight if -1 then it will be scaled whit aspect of the width + */ + public ResizeImage(BufferedImage img, int w, int h){ + super(img); + width = w; + hight = h; + } + + @Override + public int[][][] process(final int[][][] data, int cols, int rows) { + if(width < 1){ + hight = (int)(((double)width/cols)*rows); + } + else if(hight < 1){ + width = (int)(((double)hight/rows)*cols); + } + + int[][][] tmp = new int[hight][width][4]; + double xScale = ((double)cols/width); + double yScale = ((double)rows/hight); + + for(int y=0; y radius){ + scale = 0; + } + else{ + scale = 1-(distance/radius); + } + + output[y][x][0] = data[y][x][0]; + output[y][x][1] = clip((int)(scale * data[y][x][1])); + output[y][x][2] = clip((int)(scale * data[y][x][2])); + output[y][x][3] = clip((int)(scale * data[y][x][3])); + } + } + return output; + } + +} diff --git a/src/zutil/math/Tick.java b/src/zutil/math/Tick.java new file mode 100644 index 0000000..a36182d --- /dev/null +++ b/src/zutil/math/Tick.java @@ -0,0 +1,110 @@ +package zutil.math; + +public class Tick { + + /** + * TEST + */ + public static void main(String[] args){ + String temp = "a"; + while(true){ + temp = tick(temp,3); + System.out.println(temp); + } + } + + /** + * Ticks a given string(increments the string with one) + * + * @param ts The string to tick + * @param maxChar The maximum number of characters in the string + * @return The ticked string + */ + public static String tick(String ts, int maxChar){ + StringBuffer ret = new StringBuffer(ts.trim()); + int index = ret.length()-1; + + if(ret.length() < maxChar){ + ret.append('a'); + } + else{ + while(index >= 0){ + char c = increment(ret.charAt(index)); + if(c != 0){ + if(index == 0 && ret.length() < maxChar) ret.append('a'); + if(index == 0) ret = new StringBuffer(""+c); + else ret.setCharAt(index,c); + break; + } + else{ + //ret.setCharAt(index,'a'); + ret.deleteCharAt(index); + index--; + } + } + } + + return ret.toString(); + } + + /** + * Increments the char with one after the swedish alfabet + * + * @param c The char to increment + * @return The incremented char in lowercase 0 if it reached the end + */ + public static char increment(char c){ + switch(Character.toLowerCase(c)){ + case 'z': return 'å'; + case 'å': return 'ä'; + case 'ä': return 'ö'; + } + c = (char)(Character.toLowerCase(c) + 1); + if(isAlfa(c)){ + return c; + } + return 0; + } + + /** + * Checks if the char is a valid character in + * the Swedish alfabet + * + * @param c The char to check + * @return True if the char is a valid letter + */ + public static boolean isAlfa(char c){ + switch(Character.toLowerCase(c)){ + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + case 'å': + case 'ä': + case 'ö': return true; + default: return false; + } + } +} diff --git a/src/zutil/math/ZMath.java b/src/zutil/math/ZMath.java new file mode 100644 index 0000000..d62aa31 --- /dev/null +++ b/src/zutil/math/ZMath.java @@ -0,0 +1,16 @@ +package zutil.math; + +/** + * Very Simple math functions + * + * @author Ziver + */ +public class ZMath { + + /** + * Calculates the percentige the value has + */ + public static double percent(int min, int max, int value){ + return ((double)(value-min)/(max-min))*100; + } +} diff --git a/src/zutil/math/parser/MathParser.java b/src/zutil/math/parser/MathParser.java new file mode 100644 index 0000000..fa4a8bc --- /dev/null +++ b/src/zutil/math/parser/MathParser.java @@ -0,0 +1,257 @@ +package zutil.math.parser; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * This class parses a string with math + * and solves it + * + * @author Ziver + */ +public class MathParser { + + public static MathNode parse(String functionString){ + StringBuffer functionStringBuffer = new StringBuffer(functionString+(char)0); + MathNode node = new MathNode(); + + parse(functionStringBuffer, new StringBuffer(), null, node); + + System.out.println("----------------------------------------------------------------------"); + System.out.println(node+" = "+node.exec()); + System.out.println("----------------------------------------------------------------------"); + return node; + } + + private static void parse(StringBuffer functionString, StringBuffer temp, MathOperation previus, MathNode rootNode){ + if(functionString.length() <= 0){ + return; + } + char c = functionString.charAt(0); + functionString.deleteCharAt(0); + System.out.println("char: "+c); + MathOperation current = null; + + if(!Character.isWhitespace(c)){ + if(isNumber(c)){ + temp.append(c); + } + else{ + Math container = new MathNumber(); + if(temp.length() > 0){ + System.out.println("("+Double.parseDouble(temp.toString())+")"); + ((MathNumber)container).num = Double.parseDouble(temp.toString()); + temp.delete(0, temp.length()); + } + + if(rootNode.math == null){ + System.out.println("Initializing rootNode"); + previus = getOperation(c); + System.out.println("operation: "+previus.getClass().getName()); + previus.math1 = container; + rootNode.math = previus; + } + else{ + if(c == '('){ + MathNode parantes = new MathNode(); + MathOperation previusParantes = previus; + parse(functionString, temp, previus, parantes); + previusParantes.math2 = parantes; + System.out.println(parantes); + container = parantes; + + // get the next operation + c = functionString.charAt(0); + functionString.deleteCharAt(0); + System.out.println("char: "+c); + } + + current = getOperation(c); + System.out.println("operation: "+current.getClass().getName()); + current.math1 = container; + previus.math2 = current; + + if(c == ')'){ + return; + } + } + } + } + + if(current != null) parse(functionString, temp, current, rootNode); + else parse(functionString, temp, previus, rootNode); + return; + } + + private static boolean isNumber(char c){ + if(Character.isDigit(c)){ + return true; + } + return false; + } + + private static MathOperation getOperation(char c){ + switch(c){ + case '+': return new MathAddition(); + case '-': return new MathSubtraction(); + case '*': return new MathMultiplication(); + case '/': return new MathDivision(); + case '%': return new MathModulus(); + case '^': return new MathPow(); + case ')': + case (char)0: return new EmptyMath(); + default: return null; + } + } + + public static void main(String[] args){ + try { + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + while(true){ + System.out.print(">>Math: "); + parse(in.readLine()); + } + } catch (IOException e) { + e.printStackTrace(); + } + } +} + +abstract class Math{ + public abstract double exec(); + + public abstract String toString(); +} + +class MathNode extends Math{ + Math math; + + public double exec() { + return math.exec(); + } + + public String toString() { + return "( "+math.toString()+" )"; + } +} + +class MathNumber extends Math{ + double num; + + public double exec() { + return num; + } + + public String toString() { + return ""+num; + } +} + +abstract class MathOperation extends Math{ + Math math1; + Math math2; + int priority; + + public abstract double exec(); +} + +class MathAddition extends MathOperation{ + public MathAddition(){ + priority = 1; + } + + public double exec() { + return math1.exec() + math2.exec(); + } + + public String toString() { + return math1.toString()+" + "+math2.toString(); + } +} + +class MathSubtraction extends MathOperation{ + public MathSubtraction(){ + priority = 1; + } + + public double exec() { + return math1.exec() - math2.exec(); + } + + public String toString() { + return math1.toString()+" - "+math2.toString(); + } +} + +class MathMultiplication extends MathOperation{ + public MathMultiplication(){ + priority = 2; + } + + public double exec() { + return math1.exec() * math2.exec(); + } + + public String toString() { + return math1.toString()+" * "+math2.toString(); + } +} + +class MathDivision extends MathOperation{ + public MathDivision(){ + priority = 2; + } + + public double exec() { + return math1.exec() / math2.exec(); + } + + public String toString() { + return math1.toString()+" / "+math2.toString(); + } +} + +class MathModulus extends MathOperation{ + public MathModulus(){ + priority = 2; + } + + public double exec() { + return math1.exec() % math2.exec(); + } + + public String toString() { + return math1.toString()+" % "+math2.toString(); + } +} + +class MathPow extends MathOperation{ + public MathPow(){ + priority = 3; + } + + public double exec() { + double ret = 1; + double tmp1 = math1.exec(); + double tmp2 = math2.exec(); + for(int i=0; i getFileList(String path) throws IOException{ + LinkedList list = new LinkedList(); + + BufferedReader data_in = getDataInputStream(); + sendCommand("NLST "+path, true); + + String tmp = ""; + while((tmp = data_in.readLine()) != null){ + list.add(tmp); + } + + data_in.close(); + readCommand(true); + return list; + } + + /** + * Returns information about the file or directory + * (This is system specific information) + * + * TODO: + * @deprecated DOSENT WORK!!!! + * @param path The path and filename of a file or a directory + * @return A String with information + * @throws IOException + */ + public String getFileInfo(String path) throws IOException{ + StringBuffer info = new StringBuffer(""); + + BufferedReader data_in = getDataInputStream(); + sendCommand("LIST "+path, true); + + String tmp = ""; + while((tmp = data_in.readLine()) != null){ + info.append(tmp); + } + + data_in.close(); + readCommand(true); + return info.toString(); + } + + /** + * Creates a file at the server with the given data + * + * @param path The path and filename + * @param data The data to put in the file + * @throws IOException + */ + public void sendFile(String path, String data) throws IOException{ + PrintStream data_out = getDataOutputStream(); + sendCommand("STOR "+path, true); + data_out.println(data); + data_out.close(); + readCommand(true); + } + + /** + * Creates a directory at the server + * + * @param path The path to the directory + * @throws IOException + */ + public boolean createDir(String path) throws IOException{ + if(sendCommand("MKD "+path) == FTPC_PATH_CREATED) + return true; + return false; + } + + /** + * Returns a BufferedReader with the file data + * WARNING: you must run readCommand(true); after you close the stream + * + * @param path The path and filename + * @return Stream with the file + * @throws IOException + */ + private BufferedReader getFile(String path) throws IOException{ + BufferedReader ret = getDataInputStream(); + sendCommand("RETR "+path, true); + return ret; + } + + /** + * Downloads a file from the FTP server to a local file + * + * @param source The source file on the server + * @param destination The local file to save to + * @throws IOException + */ + public void getFile(String source, String destination) throws IOException{ + BufferedReader file_in = getFile(source); + PrintStream file_out = new PrintStream(new File(destination)); + + String tmp = ""; + while((tmp = file_in.readLine()) != null){ + file_out.println(tmp); + } + readCommand(true); + } + + /** + * Removes a file from the FTP server + * + * @param path The path and filename of the file to be deleted + * @return True if the command was successful or false otherwise + * @throws IOException + */ + public boolean removeFile(String path) throws IOException{ + if(sendCommand("DELE "+path) == FTPC_FILE_ACTION_OK) + return true; + return false; + } + + /** + * Removes a directory from the FTP server + * + * @param path The path of the directory to be deleted + * @return True if the command was successful or false otherwise + * @throws IOException + */ + public boolean removeDir(String path) throws IOException{ + if(sendCommand("RMD "+path) == FTPC_FILE_ACTION_OK) + return true; + return false; + } + +//************************************************************************************** +//************************************************************************************** +//******************************** Data Connection ************************************* + + /** + * Starts a connection to the server. It automatically handles + * passive or active mode + * + * @return The PrintStream for the channel + * @throws IOException + */ + public synchronized PrintStream getDataOutputStream() throws IOException{ + int port = getDataConnectionPortType(); + if(port < 0){ // Active Mode + port *= -1; + return getActiveDataOutputStream(port); + } + else{ + System.out.println("port: "+port); + return getPassiveDataOutputStream(port); + } + } + + /** + * Starts a connection to the server. It automatically handles + * passive or active mode + * + * @return The BufferedReader for the channel + * @throws IOException + */ + public synchronized BufferedReader getDataInputStream() throws IOException{ + int port = getDataConnectionPortType(); + if(port < 0){ // Active Mode + port *= -1; + return getActiveDataInputStream(port); + } + else{ + return getPassiveDataInputStream(port); + } + } + + /** + * This method chooses the appropriate data connection type + * to the server (Passive or Active) and returns the port number + * + * @return A port number. If port > 0 = Passive AND port < 0 Active + * @throws IOException + */ + private int getDataConnectionPortType() throws IOException{ + return setPassiveMode(); + } + + /** + * Connects to the data port on the server and returns the InputStream + * + * @param port The port to connect to + * @return The InputStream for the data channel + * @throws IOException + */ + private BufferedReader getPassiveDataInputStream(int port) throws IOException{ + Socket data_socket = new Socket(socket.getInetAddress().getHostAddress(), port); + BufferedReader data_in = new BufferedReader(new InputStreamReader(data_socket.getInputStream())); + + return data_in; + } + + /** + * Connects to the data port on the server and returns the OutputStream + * + * @param port The port to connect to + * @return The OutputStream for the data channel + * @throws IOException + */ + private PrintStream getPassiveDataOutputStream(int port) throws IOException{ + Socket data_socket = new Socket(socket.getInetAddress().getHostAddress(), port); + PrintStream data_out = new PrintStream(data_socket.getOutputStream()); + + return data_out; + } + + /** + * Listens on a local port for a connection from the server + * and returns with the InputStream of the connection from the server + * + * @param port The port to listen to + * @return The InputStream for the data channel + * @throws IOException + */ + private BufferedReader getActiveDataInputStream(int port) throws IOException{ + // TODO: + return null; + } + + /** + * Listens on a local port for a connection from the server + * and returns with the OutputStream of the connection from the server + * + * @param port The port to listen to + * @return The OutputStream for the data channel + * @throws IOException + */ + private PrintStream getActiveDataOutputStream(int port) throws IOException{ + // TODO: + return null; + } + + /** + * Sets Passive mode at the server and returns the port number + * for the data channel + * + * @return Port number for data channel + * @throws IOException + */ + private int setPassiveMode() throws IOException{ + String tmp = sendCommand("PASV", true); + if(parseReturnCode(tmp) != FTPC_ENTERING_PASSIVE){ + throw new IOException(tmp); + } + tmp = tmp.substring(tmp.indexOf('(')+1, tmp.indexOf(')')); + String[] tmpArray = tmp.split("[,]"); + + if(tmpArray.length <= 1) + return Integer.parseInt(tmpArray[0]); + else + return Integer.parseInt(tmpArray[4])*256 + Integer.parseInt(tmpArray[5]); + } + +//************************************************************************************** +//************************************************************************************** + + /** + * To keep the connection alive + */ + public void run(){ + try { + while(true){ + if(last_sent > System.currentTimeMillis() + FTP_NOOP_INT*1000){ + sendCommand("NOOP"); + } + try{ Thread.sleep(5000); }catch(Exception e){} + } + } catch (IOException e1) { + e1.printStackTrace(); + } + } + + /** + * Close the FTP connection + * + * @throws IOException + */ + @SuppressWarnings("deprecation") + public void close() throws IOException{ + sendCommand("QUIT", true); + in.close(); + out.close(); + socket.close(); + this.stop(); + } +} diff --git a/src/zutil/network/ServerFind.java b/src/zutil/network/ServerFind.java new file mode 100644 index 0000000..2003b4f --- /dev/null +++ b/src/zutil/network/ServerFind.java @@ -0,0 +1,73 @@ +package zutil.network; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.MulticastSocket; + +import zutil.MultiPrintStream; + +/** + * This class broadcast its address in the LAN so that + * the ServerFindClient can get the server IP + * + * @author Ziver + * + */ +public class ServerFind extends Thread { + public String broadcastAddress = "230.0.0.1"; + + private InetAddress group; + private MulticastSocket Msocket; + + private boolean avsluta; + private int port; + + /** + * Creates a ServerFind Thread an the specified port + * + * @param port The port to run the ServerFind Server on + * @throws IOException + */ + public ServerFind (int port) throws IOException { + this.port = port; + avsluta = false; + group = InetAddress.getByName(broadcastAddress); + Msocket = new MulticastSocket(port); + Msocket.joinGroup(group); + + start(); + } + + public void run (){ + byte[] buf = new byte[256]; + DatagramPacket packet; + DatagramSocket lan_socket = null; + + while (!avsluta){ + try { + packet = new DatagramPacket(buf, buf.length); + Msocket.receive(packet); + + lan_socket = new DatagramSocket(port , packet.getAddress()); + packet = new DatagramPacket(buf, buf.length, group, port); + lan_socket.send(packet); + lan_socket.close(); + } catch (Exception e) { + MultiPrintStream.out.println("Error Establishing ServerFind Connection!!!\n" + e); + e.printStackTrace(); + } + } + + close(); + } + + /** + * Closes the broadcast socket + */ + public void close(){ + avsluta = true; + Msocket.close(); + } +} \ No newline at end of file diff --git a/src/zutil/network/ServerFindClient.java b/src/zutil/network/ServerFindClient.java new file mode 100644 index 0000000..78bdb5b --- /dev/null +++ b/src/zutil/network/ServerFindClient.java @@ -0,0 +1,50 @@ +package zutil.network; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.MulticastSocket; + +/** + * This class is the client for ServerFind that receives the server IP + * + * @author Ziver + * + */ +public class ServerFindClient{ + public String broadcastAddress = "230.0.0.1"; + + private int port; + + /** + * Creates a ServerFind Client + * + * @param port The port to contact the server on + */ + public ServerFindClient(int port){ + this.port = port; + } + + /** + * Requests IP from server + * + * @return The address of the server + * @throws IOException + */ + public InetAddress find() throws IOException{ + InetAddress group = InetAddress.getByName(broadcastAddress); + DatagramSocket lan_socket = new DatagramSocket(); + MulticastSocket Msocket = new MulticastSocket(port); + Msocket.joinGroup(group); + + byte[] buf = new byte[256]; + DatagramPacket packet = new DatagramPacket(buf, buf.length, group, port); + lan_socket.send(packet); + + packet = new DatagramPacket(buf, buf.length); + Msocket.receive(packet); + + return packet.getAddress(); + } +} \ No newline at end of file diff --git a/src/zutil/network/UpdateClient.java b/src/zutil/network/UpdateClient.java new file mode 100644 index 0000000..89fb1c4 --- /dev/null +++ b/src/zutil/network/UpdateClient.java @@ -0,0 +1,134 @@ +package zutil.network; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.Socket; +import java.util.ArrayList; + +import zutil.FileFinder; +import zutil.MultiPrintStream; +import zutil.ProgressListener; + +/** + * This class connects to a update server and updates a path + * with the servers + * + * @author Ziver + * + */ +public class UpdateClient{ + private ArrayList clientFileList; + private Socket socket; + private String path; + private ProgressListener progress; + private int speed; + private long totalReceived; + + /** + * Creates a UpdateClient + * + * @param address Address to the UpdateServer + * @param port The port on the server + * @param path Path to the files to update + * @throws Exception + */ + public UpdateClient(String address, int port, String path) throws Exception{ + clientFileList = UpdateServer.getFileList(path); + socket = new Socket(address, port); + this.path = path; + } + + public void setProgressListener(ProgressListener p){ + progress = p; + } + + /** + * Updates the files + * + * @throws Exception + */ + public void update() throws Exception{ + ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); + ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); + + // send client file list + out.writeObject(clientFileList); + out.flush(); + + // receive file updates + FileHash fileInfo = (FileHash)in.readObject(); + File tmpPath = FileFinder.find(path); + while(!fileInfo.path.isEmpty()){ + MultiPrintStream.out.println("Updating: "+path+fileInfo.path); + // reading new file data + File file = new File(tmpPath.getAbsolutePath()+fileInfo.path); + File tmpFile = File.createTempFile(file.getName(), ".tmp", tmpPath); + tmpFile.getParentFile().mkdirs(); + tmpFile.deleteOnExit(); + + FileOutputStream fileOut = new FileOutputStream(tmpFile); + byte[] buffer = new byte[socket.getReceiveBufferSize()]; + + int bytesReceived = 0; + totalReceived = 0; + long time = System.currentTimeMillis(); + long timeTotalRecived = 0; + + while((bytesReceived = in.read(buffer)) > 0) { + fileOut.write(buffer, 0, bytesReceived); + + if(time+1000 < System.currentTimeMillis()){ + time = System.currentTimeMillis(); + speed = (int)(totalReceived - timeTotalRecived); + timeTotalRecived = totalReceived; + } + + totalReceived += bytesReceived; + if(progress != null) progress.progressUpdate(this, fileInfo, (double)totalReceived/fileInfo.size*100); + } + fileOut.close(); + speed = 0; + + // delete old file and replace whit new + file.delete(); + if(!tmpFile.renameTo(file)){ + throw new Exception("Cannot update file: "+file.getAbsolutePath()); + } + // read new message + fileInfo = (FileHash)in.readObject(); + } + + MultiPrintStream.out.println("Update Done!!"); + } + + /** + * Returns the speed of the transfer + * + * @return The speed in bytes/s + */ + public int speed(){ + return speed; + } + + /** + * Returns the total amount of data received for the + * current file + * + * @return The speed in bytes/s + */ + public long totalReceived(){ + return totalReceived; + } + + /** + * Closes the connection + * + * @throws IOException + */ + public void close() throws IOException{ + socket.close(); + } +} diff --git a/src/zutil/network/UpdateServer.java b/src/zutil/network/UpdateServer.java new file mode 100644 index 0000000..1d47116 --- /dev/null +++ b/src/zutil/network/UpdateServer.java @@ -0,0 +1,165 @@ +package zutil.network; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URISyntaxException; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; + +import zutil.FileFinder; +import zutil.Hasher; +import zutil.MultiPrintStream; + +public class UpdateServer extends Thread{ + private ArrayList fileList; + private ServerSocket server; + private boolean close; + private String path; + + /** + * Creates a UpdateServer Thread + * + * @param path The path to sync the clients with + * @throws IOException + * @throws URISyntaxException + * @throws NoSuchAlgorithmException + */ + public UpdateServer(int port, String path) throws Exception{ + fileList = getFileList(path); + server = new ServerSocket(port); + close = false; + this.path = path; + + this.start(); + MultiPrintStream.out.println("Update Server Online!!!"); + } + + public void run(){ + while (!close){ + try { + new UpdateServerThread(server.accept()).start(); + MultiPrintStream.out.println("Update Server: Client Connected!!!"); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * Handles all the connecting clients + * + * @author Ziver + */ + class UpdateServerThread extends Thread{ + private ObjectOutputStream out; + private ObjectInputStream in; + private Socket client; + + /** + * Creates a UpdateServerThread + * @param client The socket to the client + * @throws IOException + */ + public UpdateServerThread(Socket c) throws IOException { + client = c; + out = new ObjectOutputStream(client.getOutputStream()); + in = new ObjectInputStream(client.getInputStream()); + } + + @SuppressWarnings("unchecked") + public void run(){ + try { + // receive the clients filelist + ArrayList clientFileList = (ArrayList)in.readObject(); + File tmpPath = FileFinder.find(path); + + for(FileHash file : fileList){ + if(!clientFileList.contains(file)){ + // send new file to client + out.writeObject(file); + out.flush(); + + // send file data + FileInputStream input = new FileInputStream(tmpPath.getAbsolutePath()+file.path); + byte[] nextBytes = new byte[client.getSendBufferSize()]; + int bytesRead = 0; + while((bytesRead = input.read(nextBytes)) > 0){ + out.write(nextBytes,0,bytesRead); + } + } + } + + // send update done message + out.writeObject(new FileHash("","",0)); + out.flush(); + + out.close(); + in.close(); + client.close(); + } catch (Exception e) { + MultiPrintStream.out.println("Update Server: Client Error!!! "+e.getMessage()); + } finally { + MultiPrintStream.out.println("Update Server: Client Update Done!!!"); + } + } + } + + /** + * Returns a ArrayList with all the files in the specified folder and there + * MD5 hashes + * + * @param path The path to search + * @return A ArrayList with all the files in the path + * @throws URISyntaxException + * @throws NoSuchAlgorithmException + * @throws IOException + */ + public static ArrayList getFileList(String path) throws Exception{ + ArrayList fileHash = new ArrayList(); + + ArrayList files = FileFinder.search(FileFinder.find(path)); + for(File file : files){ + fileHash.add(new FileHash( + FileFinder.relativePath(file, path), + Hasher.hash(file, "MD5"), + file.length())); + } + + return fileHash; + } +} + +/** + * This class is used to store the files + * and there hashes + * + * @author Ziver + */ +class FileHash implements Serializable{ + private static final long serialVersionUID = 1L; + + public String path; + public String hash; + public long size; + + public FileHash(String p, String h, long s){ + path = p; + hash = h; + size = s; + } + + public boolean equals(Object comp){ + FileHash tmp = (FileHash)comp; + return path.equals(tmp.path) && hash.equals(tmp.hash); + } + + public String toString(){ + return path; + } +} diff --git a/src/zutil/network/Zupdater.java b/src/zutil/network/Zupdater.java new file mode 100644 index 0000000..497a6ef --- /dev/null +++ b/src/zutil/network/Zupdater.java @@ -0,0 +1,232 @@ +/* + * Zupdater.java + * + * Created on den 27 juli 2008, 23:32 + */ + +package zutil.network; + +import java.awt.Dimension; + +import zutil.ProgressListener; +import zutil.StringUtil; + +/** + * + * @author Ziver + */ +public class Zupdater extends javax.swing.JFrame implements ProgressListener{ + private static final long serialVersionUID = 1L; + + /** Creates new form Zupdater */ + public Zupdater() { + super("Zupdater"); + initComponents(); + centerScreen(); + setVisible(true); + } + + public void centerScreen(){ + Dimension screen = getToolkit().getScreenSize(); + this.setBounds( + (screen.width-getWidth())/2, + (screen.height-getHeight())/2, + getWidth(), + getHeight() ); + } + + public void progressUpdate(Object source, Object info, double percent) { + if(info instanceof FileHash){ + FileHash fileHash = (FileHash) info; + fileLabel.setText(fileHash.toString()); + fileProgressBar.setValue((int)percent); + percentLabel.setText((int)percent+"%"); + + speedLabel.setText(StringUtil.formatBytesToString(((UpdateClient)source).speed())+"/s"); + transferedLabel.setText(StringUtil.formatBytesToString(((UpdateClient)source).totalReceived())+ + " / "+StringUtil.formatBytesToString(fileHash.size)); + } + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // + private void initComponents() { + + jSeparator1 = new javax.swing.JSeparator(); + cancelButton = new javax.swing.JButton(); + jPanel1 = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + totalProgressBar = new javax.swing.JProgressBar(); + jLabel2 = new javax.swing.JLabel(); + fileProgressBar = new javax.swing.JProgressBar(); + fileLabel = new javax.swing.JLabel(); + totalProgressLabel = new javax.swing.JLabel(); + speedLabel = new javax.swing.JLabel(); + percentLabel = new javax.swing.JLabel(); + transferedLabel = new javax.swing.JLabel(); + etaLabel = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + + setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + + cancelButton.setText("Cancel"); + cancelButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cancel(); + } + }); + + jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Update")); + + jLabel1.setFont(new java.awt.Font("Tahoma", 1, 11)); + jLabel1.setText("Total Progress:"); + + totalProgressBar.setIndeterminate(true); + + jLabel2.setFont(new java.awt.Font("Tahoma", 1, 11)); + jLabel2.setText("File: "); + + fileLabel.setFont(new java.awt.Font("Tahoma", 0, 11)); + fileLabel.setText("file"); + + totalProgressLabel.setFont(new java.awt.Font("Tahoma", 0, 11)); + totalProgressLabel.setText("totalProgress"); + + speedLabel.setFont(new java.awt.Font("Tahoma", 1, 11)); + speedLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); + speedLabel.setText("speed"); + + percentLabel.setFont(new java.awt.Font("Tahoma", 1, 11)); + percentLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + percentLabel.setText("0%"); + + transferedLabel.setFont(new java.awt.Font("Tahoma", 2, 11)); + transferedLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); + transferedLabel.setText("transfer"); + + etaLabel.setFont(new java.awt.Font("Tahoma", 0, 11)); + etaLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); + etaLabel.setText("eta"); + + jLabel3.setFont(new java.awt.Font("Tahoma", 1, 11)); + jLabel3.setText("ETA:"); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(totalProgressLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 464, Short.MAX_VALUE)) + .addComponent(totalProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, 555, Short.MAX_VALUE) + .addComponent(fileProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, 555, Short.MAX_VALUE) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel2) + .addComponent(jLabel3)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(etaLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(percentLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 130, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(transferedLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 207, Short.MAX_VALUE)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(fileLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 399, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(speedLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 119, Short.MAX_VALUE))))) + .addContainerGap()) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(totalProgressLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(totalProgressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel2) + .addComponent(fileLabel) + .addComponent(speedLabel)) + .addGap(6, 6, 6) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel3) + .addComponent(etaLabel) + .addComponent(transferedLabel) + .addComponent(percentLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(fileProgressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jSeparator1, javax.swing.GroupLayout.DEFAULT_SIZE, 587, Short.MAX_VALUE) + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(cancelButton, javax.swing.GroupLayout.Alignment.TRAILING)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cancelButton) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + pack(); + }// + + public void cancel(){ + System.exit(0); + } + + /** + * @param args the command line arguments + */ + public static void main(String args[]) { + java.awt.EventQueue.invokeLater(new Runnable() { + public void run() { + new Zupdater().setVisible(true); + } + }); + } + + // Variables declaration - do not modify + private javax.swing.JButton cancelButton; + private javax.swing.JLabel etaLabel; + private javax.swing.JLabel fileLabel; + private javax.swing.JProgressBar fileProgressBar; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JPanel jPanel1; + private javax.swing.JSeparator jSeparator1; + private javax.swing.JLabel percentLabel; + private javax.swing.JLabel speedLabel; + private javax.swing.JProgressBar totalProgressBar; + private javax.swing.JLabel totalProgressLabel; + private javax.swing.JLabel transferedLabel; + // End of variables declaration + +} diff --git a/src/zutil/network/http/HttpPage.java b/src/zutil/network/http/HttpPage.java new file mode 100644 index 0000000..b109266 --- /dev/null +++ b/src/zutil/network/http/HttpPage.java @@ -0,0 +1,28 @@ +package zutil.network.http; + +import java.util.HashMap; + +/** + * This is a interface for a ordinary page for the HttpServer + * + * @author Ziver + * + */ +public interface HttpPage{ + /** + * This method has to be implemented for every page. + * This method is called when a client wants a response + * from this specific page. + * + * @param out The PrintStream to the client + * @param client_info Information about the client + * @param session Session values for the client + * @param cookie Cookie information from the client + * @param request POST and GET requests from the client + */ + public abstract void respond(HttpPrintStream out, + HashMap client_info, + HashMap session, + HashMap cookie, + HashMap request); +} \ No newline at end of file diff --git a/src/zutil/network/http/HttpPrintStream.java b/src/zutil/network/http/HttpPrintStream.java new file mode 100644 index 0000000..e7d0888 --- /dev/null +++ b/src/zutil/network/http/HttpPrintStream.java @@ -0,0 +1,135 @@ +package zutil.network.http; + +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.HashMap; + +/** + * This PrintStream is written for HTTP use + * It has buffer capabilities and cookie management. + * + * @author Ziver + * + */ +public class HttpPrintStream extends PrintStream{ + private HashMap cookie; + private StringBuffer buffer; + private boolean buffer_enabled; + + public HttpPrintStream(OutputStream out) { + super(out); + + cookie = new HashMap(); + buffer = new StringBuffer(); + buffer_enabled = false; + } + + /** + * Enable the buffering capability of the PrintStream. + * Nothing will be sent to the client when buffering + * is enabled until you close or flush the stream. + * + * @param b + */ + public void enableBuffering(boolean b){ + buffer_enabled = b; + } + + /** + * Adds a cookie that will be sent to the client + * + * @param key The name of the cookie + * @param value The value of the cookie + * @throws Exception Throws exception if the header has already been sent + */ + public void setCookie(String key, String value) throws Exception{ + if(cookie == null) + throw new Exception("Header already sent!!!"); + cookie.put(key, value); + } + + /** + * Sends the given header directly to the client. + * No buffering involved. + * + * @param header The header to send + * @throws Exception Throws exception if the header has already been sent + */ + public void sendHeader(String header) throws Exception{ + if(cookie == null) + throw new Exception("Header already sent!!!"); + super.println(header); + } + + /** + * prints whit a new line + */ + public void println(String s){ + printOrBuffer(s+"\n"); + } + + /** + * NOT TO BE USED!!!! + * use printOrBuffer(String s) instead + */ + @Deprecated + public void print(String s){ + super.print(s); + } + + /** + * prints to all + */ + public void printOrBuffer(String s){ + if(buffer_enabled){ + buffer.append(s); + } + else{ + if(cookie != null){ + for(String key : cookie.keySet()){ + super.println("Set-Cookie: "+key+"="+cookie.get(key)+"; "); + } + super.println(" \n"); + cookie = null; + } + super.print(s); + } + } + + /** + * Sends out all the buffer and clears it + */ + public void flush(){ + if(buffer_enabled){ + buffer_enabled = false; + printOrBuffer(buffer.toString()); + buffer.delete(0, buffer.length()); + buffer_enabled = true; + } + super.flush(); + } + + public void close(){ + flush(); + super.close(); + } + + public void println(){ println("");} + public void println(boolean x){ println(""+x);} + public void println(char x){ println(""+x);} + public void println(char[] x){ println(new String(x));} + public void println(double x){ println(""+x);} + public void println(float x){ println(""+x);} + public void println(int x){ println(""+x);} + public void println(long x){ println(""+x);} + public void println(Object x){ println(""+x);} + + public void print(boolean x){ printOrBuffer(""+x);} + public void print(char x){ printOrBuffer(""+x);} + public void print(char[] x){ printOrBuffer(new String(x));} + public void print(double x){ printOrBuffer(""+x);} + public void print(float x){ printOrBuffer(""+x);} + public void print(int x){ printOrBuffer(""+x);} + public void print(long x){ printOrBuffer(""+x);} + public void print(Object x){ printOrBuffer(""+x);} +} diff --git a/src/zutil/network/http/HttpServer.java b/src/zutil/network/http/HttpServer.java new file mode 100644 index 0000000..28196cf --- /dev/null +++ b/src/zutil/network/http/HttpServer.java @@ -0,0 +1,282 @@ +package zutil.network.http; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.HashMap; + +import zutil.MultiPrintStream; + +/** + * A simple web server that handles both cookies and + * sessions for all the clients + * + * @author Ziver + * TODO: File upload + */ +public class HttpServer extends Thread{ + public static final boolean DEBUG = false; + public static final String SERVER_VERSION = "Evil HttpServer 1.0"; + public static final int COOKIE_TTL = 200; + public static final int SESSION_TTL = 200; + + public final String server_url; + public final int server_port; + + private HashMap pages; + private HttpPage defaultPage; + private HashMap> sessions; + private int nextSessionId; + + /** + * Creates a new instance of the sever + * + * @param url The address to the server + * @param port The port that the server should listen to + */ + public HttpServer(String url, int port){ + this.server_url = url; + this.server_port = port; + + pages = new HashMap(); + sessions = new HashMap>(); + nextSessionId = 0; + } + + /** + * Add a HttpPage to a specific URL + * + * @param name The URL or name of the page + * @param page The page itself + */ + public void setPage(String name, HttpPage page){ + pages.put(name, page); + } + + /** + * This is a default page that will be shown + * if there is no other matching page, + * + * @param page The HttpPage that will be shown + */ + public void setDefaultPage(HttpPage page){ + defaultPage = page; + } + + public void run(){ + try{ + ServerSocket ss = new ServerSocket(server_port); + MultiPrintStream.out.println("Http Server Running!!!"); + + while(true){ + new HttpServerThread(ss.accept()); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Internal class that handles all the requests + * + * @author Ziver + * + */ + class HttpServerThread extends Thread{ + private HttpPrintStream out; + private BufferedReader in; + private Socket socket; + + public HttpServerThread(Socket socket) throws IOException{ + out = new HttpPrintStream(socket.getOutputStream()); + in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + this.socket = socket; + start(); + if(DEBUG)MultiPrintStream.out.println("New Connection!!! "+socket.getInetAddress().getHostName()); + } + + public void run(){ + String tmp = null; + int tmpi; + + String page_url = ""; + HashMap client_info = new HashMap(); + HashMap cookie = new HashMap(); + HashMap request = new HashMap(); + + //**************************** REQUEST ********************************* + try { + if(DEBUG)MultiPrintStream.out.println("Reciving Http Request!!!"); + while(!(tmp=in.readLine()).isEmpty()){ + //System.err.println(tmp); + //*********** Handling Get variables + if(tmp.startsWith("GET")){ + // Gets the file URL and get values + tmp = (tmp.substring(5, tmp.indexOf("HTTP/"))).trim(); + page_url = parseHttpHeader(tmp, request); + } + //********* Handling Post variable data + else if(tmp.startsWith("POST")){ + // Gets the file URL and get values + tmp = (tmp.substring(6, tmp.indexOf("HTTP/"))).trim(); + page_url = parseHttpHeader(tmp, request); + } + //********* Handling Cookies + else if(tmp.startsWith("Cookie")){ + tmp = tmp.substring(tmp.indexOf(':')+1, tmp.length()); + while(!tmp.isEmpty()){ + tmpi = ( (tmpi = tmp.indexOf(';')) == -1 ? tmp.length() : tmpi); + cookie.put( + (tmp.substring(0, tmp.indexOf('=')).trim() ), // Key + (tmp.substring(tmp.indexOf('=')+1, tmpi)).trim() ); //Value + if(tmp.indexOf(';') > 0) + tmp = tmp.substring(tmp.indexOf(';')+1, tmp.length()); + else + break; + } + } + //********* Handling Client info + else{ + if(tmp.indexOf(':') > -1){ + client_info.put( + (tmp.substring(0, tmp.indexOf(':')).trim() ), // Key + (tmp.substring(tmp.indexOf(':')+1, tmp.length())).trim() ); //Value + } + else{ + MultiPrintStream.out.println("Faild to parsse header: "+tmp); + } + } + } + + //******* Read in the post data if available + if(client_info.containsKey("Content-Length")){ + // Reads the post data size + tmp = client_info.get("Content-Length"); + int post_data_length = Integer.parseInt( + tmp.substring(tmp.indexOf(':')+1, tmp.length()).trim() ); + + if(client_info.get("Content-Type").equals("application/x-www-form-urlencoded")){ + StringBuffer tmpb = new StringBuffer(); + // read the data + for(int i=0; i client_session; + if(cookie.containsKey("session_id") && sessions.containsKey(cookie.get("session_id"))){ + client_session = sessions.get(cookie.get("session_id")); + } + else{ + client_session = new HashMap(); + client_session.put("session_id", ""+nextSessionId); + sessions.put(""+nextSessionId, client_session); + nextSessionId++; + } + // Debug + if(DEBUG){ + MultiPrintStream.out.println("# page_url: "+page_url); + MultiPrintStream.out.println("# cookie: "+cookie); + MultiPrintStream.out.println("# client_session: "+client_session); + MultiPrintStream.out.println("# client_info: "+client_info); + MultiPrintStream.out.println("# request: "+request); + } + //**************************** RESPONSE ************************************ + if(DEBUG)MultiPrintStream.out.println("Sending Http Response!!!"); + out.sendHeader("HTTP/1.0 200 OK"); + out.sendHeader("Server: "+SERVER_VERSION); + out.sendHeader("Content-Type: text/html"); + out.setCookie("session_id", client_session.get("session_id")); + + + if(!page_url.isEmpty() && pages.containsKey(page_url)){ + pages.get(page_url).respond(out, client_info, client_session, cookie, request); + } + else if(defaultPage != null){ + defaultPage.respond(out, client_info, client_session, cookie, request); + } + else{ + out.println("404 ERROR"); + } + + //******************************************************************************** + } catch (Exception e) { + e.printStackTrace(); + out.println("500 Internal Error: "+e.getMessage()); + } + + try{ + if(DEBUG)MultiPrintStream.out.println("Conection Closed!!!"); + out.close(); + in.close(); + socket.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** + * Parses the first header line and ads the values to + * the map and returns the file name and path + * + * @param header The header String + * @param map The HashMap to put the variables to + * @return The path and file name as a String + */ + private String parseHttpHeader(String header, HashMap map){ + String page_url = ""; + // cut out the page name + if(header.indexOf('?') > -1){ + page_url = header.substring(0, header.indexOf('?')); + header = header.substring(header.indexOf('?')+1, header.length()); + parseVariables(header, map); + } + else{ + page_url = header; + } + + return page_url; + } + + /** + * Parses a String with variables from a get or post + * from a client and puts the data into a HashMap + * + * @param header A String with all the variables + * @param map The HashMap to put all the variables into + */ + private void parseVariables(String header, HashMap map){ + int tmpi; + // get the variables + while(!header.isEmpty()){ + tmpi = ( (tmpi = header.indexOf('&')) == -1 ? header.length() : tmpi); + map.put( + (header.substring(0, header.indexOf('=')).trim() ), // Key + (header.substring(header.indexOf('=')+1, tmpi )).trim() ); //Value + if(header.indexOf('&') > 0) + header = header.substring(header.indexOf('&')+1, header.length()); + else + break; + } + } +} \ No newline at end of file diff --git a/src/zutil/network/nio/NioClient.java b/src/zutil/network/nio/NioClient.java new file mode 100644 index 0000000..41e985d --- /dev/null +++ b/src/zutil/network/nio/NioClient.java @@ -0,0 +1,57 @@ +package zutil.network.nio; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.channels.Selector; +import java.nio.channels.SocketChannel; +import java.nio.channels.spi.SelectorProvider; + +import zutil.network.nio.message.Message; +import zutil.network.nio.message.type.ResponseRequestMessage; +import zutil.network.nio.response.ResponseEvent; + + +public class NioClient extends NioNetwork{ + private SocketChannel serverSocket; + + /** + * Creates a NioClient that connects to a server + * + * @param hostAddress The server address + * @param port The port to listen on + */ + public NioClient(InetAddress serverAddress, int port) throws IOException { + super(InetAddress.getLocalHost(), port, NetworkType.CLIENT); + serverSocket = initiateConnection(new InetSocketAddress(serverAddress, port)); + Thread thread = new Thread(this); + thread.setDaemon(false); + thread.start(); + } + + protected Selector initSelector() throws IOException { + // Create a new selector + return SelectorProvider.provider().openSelector(); + } + + /** + * Sends a Message to the default server + * + * @param data The data to be sent + * @throws IOException Something got wrong + */ + public void send(Message data) throws IOException { + send(serverSocket, data); + } + + /** + * This method is for the Client to send a message to the server + * + * @param handler The response handler + * @param data The data to send + * @throws IOException + */ + public void send(ResponseEvent handler, ResponseRequestMessage data) throws IOException { + send(serverSocket, handler, data); + } +} diff --git a/src/zutil/network/nio/NioNetwork.java b/src/zutil/network/nio/NioNetwork.java new file mode 100644 index 0000000..9e3140e --- /dev/null +++ b/src/zutil/network/nio/NioNetwork.java @@ -0,0 +1,433 @@ +package zutil.network.nio; + +import java.io.IOException; +import java.net.ConnectException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import zutil.Converter; +import zutil.Encrypter; +import zutil.MultiPrintStream; +import zutil.network.nio.message.type.ResponseRequestMessage; +import zutil.network.nio.message.type.SystemMessage; +import zutil.network.nio.response.ResponseEvent; +import zutil.network.nio.server.ChangeRequest; +import zutil.network.nio.server.ClientData; +import zutil.network.nio.worker.SystemWorker; +import zutil.network.nio.worker.Worker; + + +public abstract class NioNetwork implements Runnable { + /** + * Debug level + * 0 = nothing + * 1 = connection debug + * 2 = message debug + * 3 = selector debug + */ + public static final int DEBUG = 1; + public static enum NetworkType {SERVER, CLIENT}; + + private NetworkType type; + + // The host:port combination to listen on + protected InetAddress address; + protected int port; + + // The channel on which we'll accept connections + protected ServerSocketChannel serverChannel; + // The selector we'll be monitoring + private Selector selector; + // The buffer into which we'll read data when it's available + private ByteBuffer readBuffer = ByteBuffer.allocate(8192); + protected Worker worker; + protected SystemWorker systemWorker; + + // This map contains all the clients that are conncted + protected Map clients = new HashMap(); + + // A list of PendingChange instances + private List pendingChanges = new LinkedList(); + // Maps a SocketChannel to a list of ByteBuffer instances + private Map> pendingData = new HashMap>(); + // The encrypter + private Encrypter encrypter; + + /** + * Create a nio network class + * + * @param hostAddress The host address + * @param port The port + * @param type The type of network host + * @throws IOException + */ + public NioNetwork(InetAddress address, int port, NetworkType type) throws IOException { + this.port = port; + this.address = address; + this.type = type; + this.selector = initSelector(); + this.systemWorker = new SystemWorker(this); + } + + protected abstract Selector initSelector() throws IOException; + + /** + * Sets the Worker for the network messages + * + * @param worker The worker that handles the incoming messages + */ + public void setDefaultWorker(Worker worker){ + this.worker = worker; + } + + /** + * Sets the encrypter to use in the network + * + * @param enc The encrypter to use or null fo no encryption + */ + public void setEncrypter(Encrypter enc){ + encrypter = enc; + MultiPrintStream.out.println("Network Encryption "+ + (encrypter != null ? "Enabled("+encrypter.getAlgorithm()+")" : "Disabled")+"!!"); + } + + public void send(SocketChannel socket, Object data) { + send(socket, Converter.toBytes(data)); + } + + public void send(InetSocketAddress address, Object data){ + send(address, Converter.toBytes(data)); + } + + public void send(InetSocketAddress address, byte[] data){ + send(getSocketChannel(address), data); + } + + public void send(SocketChannel socket, ResponseEvent handler, ResponseRequestMessage data) throws IOException { + // Register the response handler + systemWorker.addResponseHandler(handler, data); + + queueSend(socket,Converter.toBytes(data)); + } + + /** + * This method sends data true the given socket + * + * @param socket The socket + * @param data The data to send + */ + public void send(SocketChannel socket, byte[] data) { + queueSend(socket,data); + } + + /** + * Queues the message to be sent and wakeups the selector + * + * @param socket The socet to send the message thrue + * @param data The data to send + */ + protected void queueSend(SocketChannel socket, byte[] data){ + if(DEBUG>=3)MultiPrintStream.out.println("Sending Queue..."); + // And queue the data we want written + synchronized (pendingData) { + List queue = pendingData.get(socket); + if (queue == null) { + queue = new ArrayList(); + pendingData.put(socket, queue); + } + //encrypts + if(encrypter != null) + queue.add(ByteBuffer.wrap(encrypter.encrypt(data))); + else queue.add(ByteBuffer.wrap(data)); + } + // Changing the key state to write + synchronized (pendingChanges) { + // Indicate we want the interest ops set changed + pendingChanges.add(new ChangeRequest(socket, ChangeRequest.CHANGEOPS, SelectionKey.OP_WRITE)); + } + if(DEBUG>=3)MultiPrintStream.out.println("selector.wakeup();"); + // Finally, wake up our selecting thread so it can make the required changes + selector.wakeup(); + } + + public void run() { + if(DEBUG>=1)MultiPrintStream.out.println("NioNetwork Started!!!"); + while (true) { + try { + // Process any pending changes + synchronized (pendingChanges) { + Iterator changes = pendingChanges.iterator(); + while (changes.hasNext()) { + ChangeRequest change = changes.next(); + switch (change.type) { + case ChangeRequest.CHANGEOPS: + SelectionKey key = change.socket.keyFor(selector); + key.interestOps(change.ops); + if(DEBUG>=3)MultiPrintStream.out.println("change.ops "+change.ops); + break; + case ChangeRequest.REGISTER: + change.socket.register(selector, change.ops); + if(DEBUG>=3)MultiPrintStream.out.println("register socket "); + break; + } + } + pendingChanges.clear(); + } + + // Wait for an event one of the registered channels + selector.select(); + if(DEBUG>=3)MultiPrintStream.out.println("selector is awake"); + + // Iterate over the set of keys for which events are available + Iterator selectedKeys = selector.selectedKeys().iterator(); + while (selectedKeys.hasNext()) { + SelectionKey key = (SelectionKey) selectedKeys.next(); + selectedKeys.remove(); + if(DEBUG>=3)MultiPrintStream.out.println("KeyOP: "+key.interestOps()+" isAcceptable: "+SelectionKey.OP_ACCEPT+" isConnectable: "+SelectionKey.OP_CONNECT+" isWritable: "+SelectionKey.OP_WRITE+" isReadable: "+SelectionKey.OP_READ); + + if (key.isValid()) { + // Check what event is available and deal with it + if (key.isAcceptable()) { + if(DEBUG>=3)MultiPrintStream.out.println("Accepting Connection!!"); + accept(key); + } + else if (key.isConnectable()) { + if(DEBUG>=3)MultiPrintStream.out.println("Finnishing Connection!!"); + finishConnection(key); + } + else if (key.isWritable()) { + if(DEBUG>=3)MultiPrintStream.out.println("Writing"); + write(key); + } + else if (key.isReadable()) { + if(DEBUG>=3)MultiPrintStream.out.println("Reading"); + read(key); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** + * Server + */ + private void accept(SelectionKey key) throws IOException { + // For an accept to be pending the channel must be a server socket channel. + ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel(); + + // Accept the connection and make it non-blocking + SocketChannel socketChannel = serverSocketChannel.accept(); + socketChannel.socket().setReuseAddress(true); + socketChannel.configureBlocking(false); + + // Register the new SocketChannel with our Selector, indicating + // we'd like to be notified when there's data waiting to be read + socketChannel.register(selector, SelectionKey.OP_READ); + + // adds the client to the clients list + InetSocketAddress remoteAdr = (InetSocketAddress) socketChannel.socket().getRemoteSocketAddress(); + if(!clients.containsValue(remoteAdr)){ + clients.put(remoteAdr, new ClientData(socketChannel)); + if(DEBUG>=1)MultiPrintStream.out.println("New Connection("+remoteAdr+")!!! Count: "+clients.size()); + } + } + + /** + * Client and Server + */ + private void read(SelectionKey key) throws IOException { + SocketChannel socketChannel = (SocketChannel) key.channel(); + InetSocketAddress remoteAdr = (InetSocketAddress) socketChannel.socket().getRemoteSocketAddress(); + + // Clear out our read buffer so it's ready for new data + readBuffer.clear(); + + // Attempt to read off the channel + int numRead; + try { + numRead = socketChannel.read(readBuffer); + } catch (IOException e) { + // The remote forcibly closed the connection, cancel + // the selection key and close the channel. + key.cancel(); + socketChannel.close(); + clients.remove(remoteAdr); + if(DEBUG>=1)MultiPrintStream.out.println("Connection Forced Close("+remoteAdr+")!!! Connection Count: "+clients.size()); + if(type == NetworkType.CLIENT) throw new ConnectException("Server Closed The Connection!!!"); + return; + } + + if (numRead == -1) { + // Remote entity shut the socket down cleanly. Do the + // same from our end and cancel the channel. + key.channel().close(); + key.cancel(); + clients.remove(remoteAdr); + if(DEBUG>=1)MultiPrintStream.out.println("Connection Close("+remoteAdr+")!!! Connection Count: "+clients.size()); + if(type == NetworkType.CLIENT) throw new ConnectException("Server Closed The Connection!!!"); + return; + } + + // Make a correctly sized copy of the data before handing it + // to the client + byte[] rspByteData = new byte[numRead]; + System.arraycopy(readBuffer.array(), 0, rspByteData, 0, numRead); + + handleRecivedMessage(socketChannel, rspByteData); + } + + /** + * Client and Server + */ + private void write(SelectionKey key) throws IOException { + SocketChannel socketChannel = (SocketChannel) key.channel(); + + synchronized (pendingData) { + List queue = pendingData.get(socketChannel); + if(queue == null){ + queue = new ArrayList(); + } + + // Write until there's not more data ... + while (!queue.isEmpty()) { + ByteBuffer buf = queue.get(0); + socketChannel.write(buf); + if (buf.remaining() > 0) { + // ... or the socket's buffer fills up + break; + } + queue.remove(0); + } + + if (queue.isEmpty()) { + // We wrote away all data, so we're no longer interested + // in writing on this socket. Switch back to waiting for + // data. + if(DEBUG>=3)MultiPrintStream.out.println("No more Data to write!!"); + key.interestOps(SelectionKey.OP_READ); + } + } + } + + private void handleRecivedMessage(SocketChannel socketChannel, byte[] rspByteData){ + //Encryption + Object rspData; + if(encrypter != null) + rspData = Converter.toObject(encrypter.decrypt(rspByteData)); + else rspData = Converter.toObject(rspByteData); + if(DEBUG>=2)MultiPrintStream.out.println("Handling incomming message..."); + + if(rspData instanceof SystemMessage){ + if(systemWorker != null){ + if(DEBUG>=3)MultiPrintStream.out.println("System Message!!!"); + systemWorker.processData(this, socketChannel, rspData); + } + else{ + if(DEBUG>=2)MultiPrintStream.out.println("Unhandled System Message!!!"); + } + } + else{ + // Hand the data off to our worker thread + if(worker != null){ + if(DEBUG>=3)MultiPrintStream.out.println("Worker Message!!!"); + worker.processData(this, socketChannel, rspData); + } + else{ + if(DEBUG>=1)MultiPrintStream.out.println("Unhandled Message!!!"); + } + } + } + + /** + * Initializes a socket to the server + */ + protected SocketChannel initiateConnection(InetSocketAddress address) throws IOException { + // Create a non-blocking socket channel + SocketChannel socketChannel = SocketChannel.open(); + socketChannel.socket().setReuseAddress(true); + socketChannel.configureBlocking(false); + if(DEBUG>=1)MultiPrintStream.out.println("Connecting to: "+address); + + // Kick off connection establishment + socketChannel.connect(address); + + // Queue a channel registration since the caller is not the + // selecting thread. As part of the registration we'll register + // an interest in connection events. These are raised when a channel + // is ready to complete connection establishment. + synchronized(this.pendingChanges) { + pendingChanges.add(new ChangeRequest(socketChannel, ChangeRequest.REGISTER, SelectionKey.OP_CONNECT)); + } + + return socketChannel; + } + + protected SocketChannel getSocketChannel(InetSocketAddress address){ + return clients.get(address).getSocketChannel(); + } + + /** + * Client + */ + private void finishConnection(SelectionKey key){ + SocketChannel socketChannel = (SocketChannel) key.channel(); + + // Finish the connection. If the connection operation failed + // this will raise an IOException. + try { + socketChannel.finishConnect(); + } catch (IOException e) { + // Cancel the channel's registration with our selector + e.printStackTrace(); + key.cancel(); + return; + } + + // Register an interest in writing on this channel + key.interestOps(SelectionKey.OP_WRITE); + } + + /** + * Client + * @throws IOException + */ + protected void closeConnection(SocketChannel socketChannel) throws IOException{ + socketChannel.close(); + socketChannel.keyFor(selector).cancel(); + } + + /** + * Client + * @throws IOException + */ + protected void closeConnection(InetSocketAddress address) throws IOException{ + closeConnection(getSocketChannel(address)); + } + + /* + public void close() throws IOException{ + if(serverChannel != null){ + serverChannel.close(); + serverChannel.keyFor(selector).cancel(); + } + selector.close(); + }*/ + + public NetworkType getType(){ + return type; + } +} diff --git a/src/zutil/network/nio/NioServer.java b/src/zutil/network/nio/NioServer.java new file mode 100644 index 0000000..a5c4ff7 --- /dev/null +++ b/src/zutil/network/nio/NioServer.java @@ -0,0 +1,68 @@ +package zutil.network.nio; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.spi.SelectorProvider; +import java.util.Iterator; + +public class NioServer extends NioNetwork{ + + /** + * Creates a NioServer object which listens on localhost + * + * @param port The port to listen to + */ + public NioServer(int port) throws IOException { + this(null, port); + } + + /** + * Creates a NioServer object which listens to a specific address + * + * @param address The address to listen to + * @param port The port to listen to + */ + public NioServer(InetAddress address, int port) throws IOException { + super(address, port, NetworkType.SERVER); + new Thread(this).start(); + } + + protected Selector initSelector() throws IOException { + // Create a new selector + Selector socketSelector = SelectorProvider.provider().openSelector(); + + // Create a new non-blocking server socket channel + serverChannel = ServerSocketChannel.open(); + serverChannel.socket().setReuseAddress(true); + serverChannel.configureBlocking(false); + + // Bind the server socket to the specified address and port + InetSocketAddress isa = new InetSocketAddress(address, port); + serverChannel.socket().bind(isa); + + // Register the server socket channel, indicating an interest in + // accepting new connections + serverChannel.register(socketSelector, SelectionKey.OP_ACCEPT); + + return socketSelector; + } + + /** + * Broadcasts the message to all the connected clients + * + * @param data The data to broadcast + */ + public void broadcast(byte[] data){ + synchronized(clients){ + Iterator it = clients.keySet().iterator(); + while(it.hasNext()){ + send(it.next(), data); + } + } + } + +} diff --git a/src/zutil/network/nio/message/ChatMessage.java b/src/zutil/network/nio/message/ChatMessage.java new file mode 100644 index 0000000..353b07b --- /dev/null +++ b/src/zutil/network/nio/message/ChatMessage.java @@ -0,0 +1,45 @@ +package zutil.network.nio.message; + +public class ChatMessage extends Message{ + private static final long serialVersionUID = 1L; + + public static enum ChatMessageType {REGISTER, UNREGISTER, MESSAGE}; + + public ChatMessageType type; + public String msg; + public String room; + + /** + * Registers the user to the main chat + * + * @param name Name of user + */ + public ChatMessage(){ + this("", "", ChatMessageType.REGISTER); + } + + /** + * Registers the user to the given room + * + * @param room The room to register to + */ + public ChatMessage(String room){ + this("", room, ChatMessageType.REGISTER); + } + + /** + * Sends a message to the given room + * + * @param msg The message + * @param room The room + */ + public ChatMessage(String msg, String room){ + this(msg, room, ChatMessageType.MESSAGE); + } + + public ChatMessage(String msg, String room, ChatMessageType type){ + this.msg = msg; + this.room = room; + this.type = type; + } +} diff --git a/src/zutil/network/nio/message/GraphicsSyncMessage.java b/src/zutil/network/nio/message/GraphicsSyncMessage.java new file mode 100644 index 0000000..49a8ce8 --- /dev/null +++ b/src/zutil/network/nio/message/GraphicsSyncMessage.java @@ -0,0 +1,31 @@ +package zutil.network.nio.message; + + +public class GraphicsSyncMessage extends SyncMessage{ + private static final long serialVersionUID = 1L; + + public float locX; + public float locY; + public float locZ; + + public float rotX; + public float rotY; + public float rotZ; + public float rotW; + + public GraphicsSyncMessage(String id){ + this.type = MessageType.SYNC; + this.id = id; + } + + public boolean equals(Object obj){ + if(obj instanceof GraphicsSyncMessage){ + GraphicsSyncMessage tmp = (GraphicsSyncMessage)obj; + return (tmp.locX == locX && tmp.locY == locY && + tmp.locZ == locZ && tmp.rotX == rotX && + tmp.rotY == rotY && tmp.rotZ == rotZ && + tmp.rotW == rotW); + } + return false; + } +} diff --git a/src/zutil/network/nio/message/KeepAliveMessage.java b/src/zutil/network/nio/message/KeepAliveMessage.java new file mode 100644 index 0000000..5f57898 --- /dev/null +++ b/src/zutil/network/nio/message/KeepAliveMessage.java @@ -0,0 +1,16 @@ +package zutil.network.nio.message; + +import zutil.network.nio.message.type.SystemMessage; + +/** + * Tells the destination that the + * source is still online + * + * @author Ziver + * + */ +public class KeepAliveMessage extends Message implements SystemMessage{ + + private static final long serialVersionUID = 1L; + +} diff --git a/src/zutil/network/nio/message/Message.java b/src/zutil/network/nio/message/Message.java new file mode 100644 index 0000000..8792f14 --- /dev/null +++ b/src/zutil/network/nio/message/Message.java @@ -0,0 +1,9 @@ +package zutil.network.nio.message; + +import java.io.Serializable; + +public class Message implements Serializable{ + private static final long serialVersionUID = 1L; + + +} diff --git a/src/zutil/network/nio/message/StringMessage.java b/src/zutil/network/nio/message/StringMessage.java new file mode 100644 index 0000000..ff9376a --- /dev/null +++ b/src/zutil/network/nio/message/StringMessage.java @@ -0,0 +1,34 @@ +package zutil.network.nio.message; + +import zutil.network.nio.message.type.EchoMessage; +import zutil.network.nio.message.type.ResponseRequestMessage; + + + +public class StringMessage extends EchoMessage implements ResponseRequestMessage{ + private static final long serialVersionUID = 1L; + private double responseId; + + private String msg; + + public StringMessage(String msg){ + this.msg = msg; + responseId = Math.random(); + } + + public String getString(){ + return msg; + } + + public void setString(String msg){ + this.msg = msg; + } + + public String toString(){ + return getString(); + } + + public double getResponseId() { + return responseId; + } +} diff --git a/src/zutil/network/nio/message/SyncMessage.java b/src/zutil/network/nio/message/SyncMessage.java new file mode 100644 index 0000000..d595071 --- /dev/null +++ b/src/zutil/network/nio/message/SyncMessage.java @@ -0,0 +1,13 @@ +package zutil.network.nio.message; + +import zutil.network.nio.message.type.SystemMessage; + +public class SyncMessage extends Message implements SystemMessage{ + private static final long serialVersionUID = 1L; + public static enum MessageType { REQUEST_ID, NEW, REMOVE, SYNC }; + + // type of message + public MessageType type; + // id of the Object + public String id; +} diff --git a/src/zutil/network/nio/message/type/EchoMessage.java b/src/zutil/network/nio/message/type/EchoMessage.java new file mode 100644 index 0000000..bb40f79 --- /dev/null +++ b/src/zutil/network/nio/message/type/EchoMessage.java @@ -0,0 +1,34 @@ +package zutil.network.nio.message.type; + +import zutil.network.nio.message.Message; + +/** + * The reciver will echo out this message to the sender + * + * @author Ziver + */ +public abstract class EchoMessage extends Message implements SystemMessage{ + private static final long serialVersionUID = 1L; + + private boolean echo; + + public EchoMessage(){ + echo = true; + } + + /** + * This method returns if the message should be echoed + * @return If the message should be echoed + */ + public boolean echo() { + return echo; + } + + /** + * Called by the reciver to disable looping of the message + * + */ + public void recived() { + echo = false; + } +} diff --git a/src/zutil/network/nio/message/type/ResponseRequestMessage.java b/src/zutil/network/nio/message/type/ResponseRequestMessage.java new file mode 100644 index 0000000..6ee1823 --- /dev/null +++ b/src/zutil/network/nio/message/type/ResponseRequestMessage.java @@ -0,0 +1,18 @@ +package zutil.network.nio.message.type; + +/** + * This interface means that the sender + * wants a reply from the destination + * + * @author Ziver + * + */ +public interface ResponseRequestMessage { + + /** + * The id of the response to identify the response event + * @return Response id + */ + public double getResponseId(); + +} diff --git a/src/zutil/network/nio/message/type/SystemMessage.java b/src/zutil/network/nio/message/type/SystemMessage.java new file mode 100644 index 0000000..f2f07dd --- /dev/null +++ b/src/zutil/network/nio/message/type/SystemMessage.java @@ -0,0 +1,12 @@ +package zutil.network.nio.message.type; + +/** + * A message that implements this will be + * handeld internaly by the network engine + * + * @author Ziver + * + */ +public interface SystemMessage { + +} diff --git a/src/zutil/network/nio/response/PrintRsp.java b/src/zutil/network/nio/response/PrintRsp.java new file mode 100644 index 0000000..394f0a9 --- /dev/null +++ b/src/zutil/network/nio/response/PrintRsp.java @@ -0,0 +1,12 @@ +package zutil.network.nio.response; + +import zutil.MultiPrintStream; + +public class PrintRsp extends ResponseEvent{ + + @Override + protected void responseEvent(Object rsp) { + MultiPrintStream.out.println(rsp); + } + +} diff --git a/src/zutil/network/nio/response/ResponseEvent.java b/src/zutil/network/nio/response/ResponseEvent.java new file mode 100644 index 0000000..3e0a444 --- /dev/null +++ b/src/zutil/network/nio/response/ResponseEvent.java @@ -0,0 +1,43 @@ +package zutil.network.nio.response; + + +public abstract class ResponseEvent { + private Object rsp = null; + + public synchronized boolean handleResponse(Object rsp) { + this.rsp = rsp; + notify(); + return true; + } + + /** + * Blocks the Thread until there is a response + */ + public synchronized void waitForResponse() { + while(!gotResponse()) { + try { + this.wait(); + } catch (InterruptedException e) {} + } + + responseEvent(rsp); + } + + /** + * Handles the response + */ + public void handleResponse(){ + if(gotResponse()){ + responseEvent(rsp); + } + } + + /** + * @return If there is an response + */ + public boolean gotResponse(){ + return (rsp != null); + } + + protected abstract void responseEvent(Object rsp); +} diff --git a/src/zutil/network/nio/response/ResponseHandler.java b/src/zutil/network/nio/response/ResponseHandler.java new file mode 100644 index 0000000..9c28ac9 --- /dev/null +++ b/src/zutil/network/nio/response/ResponseHandler.java @@ -0,0 +1,41 @@ +package zutil.network.nio.response; + +import java.util.LinkedList; +import java.util.List; + + +public abstract class ResponseHandler implements Runnable{ + private List queue = new LinkedList(); + + public ResponseHandler(){ + + } + + public synchronized void addResponseEvent(ResponseEvent re){ + queue.add(re); + notify(); + } + + public synchronized void removeResponseEvent(ResponseEvent re){ + queue.remove(re); + } + + public void run() { + while(true) { + try { + this.wait(); + } catch (InterruptedException e) {} + + update(); + } + } + + public synchronized void update(){ + while(!queue.isEmpty()){ + queue.get(0).handleResponse(); + if(queue.get(0).gotResponse()){ + queue.remove(0); + } + } + } +} diff --git a/src/zutil/network/nio/server/ChangeRequest.java b/src/zutil/network/nio/server/ChangeRequest.java new file mode 100644 index 0000000..366d33b --- /dev/null +++ b/src/zutil/network/nio/server/ChangeRequest.java @@ -0,0 +1,18 @@ +package zutil.network.nio.server; + +import java.nio.channels.SocketChannel; + +public class ChangeRequest { + public static final int REGISTER = 1; + public static final int CHANGEOPS = 2; + + public SocketChannel socket; + public int type; + public int ops; + + public ChangeRequest(SocketChannel socket, int type, int ops) { + this.socket = socket; + this.type = type; + this.ops = ops; + } +} diff --git a/src/zutil/network/nio/server/ClientData.java b/src/zutil/network/nio/server/ClientData.java new file mode 100644 index 0000000..aeca8ec --- /dev/null +++ b/src/zutil/network/nio/server/ClientData.java @@ -0,0 +1,29 @@ +package zutil.network.nio.server; + +import java.net.InetSocketAddress; +import java.nio.channels.SocketChannel; + +public class ClientData { + private SocketChannel socketChannel; + private long lastMessageReceived; + + public ClientData(SocketChannel socketChannel){ + this.socketChannel = socketChannel; + } + + public SocketChannel getSocketChannel(){ + return socketChannel; + } + + public InetSocketAddress getAddress(){ + return (InetSocketAddress) socketChannel.socket().getRemoteSocketAddress(); + } + + public void setLastMessageReceived(long time){ + lastMessageReceived = time; + } + + public long getLastMessageReceived(){ + return lastMessageReceived; + } +} diff --git a/src/zutil/network/nio/service/ChatListener.java b/src/zutil/network/nio/service/ChatListener.java new file mode 100644 index 0000000..e7ca05b --- /dev/null +++ b/src/zutil/network/nio/service/ChatListener.java @@ -0,0 +1,10 @@ +package zutil.network.nio.service; + +/** + * Tis is a listener class for new chat messages + * @author Ziver + * + */ +public interface ChatListener { + public void messageAction(String msg, String room); +} diff --git a/src/zutil/network/nio/service/ChatService.java b/src/zutil/network/nio/service/ChatService.java new file mode 100644 index 0000000..a4fbdae --- /dev/null +++ b/src/zutil/network/nio/service/ChatService.java @@ -0,0 +1,121 @@ +package zutil.network.nio.service; + +import java.nio.channels.SocketChannel; +import java.util.HashMap; +import java.util.LinkedList; + +import zutil.MultiPrintStream; +import zutil.network.nio.NioNetwork; +import zutil.network.nio.message.ChatMessage; +import zutil.network.nio.message.Message; + +public class ChatService extends NetworkService{ + private HashMap> rooms; + private ChatListener listener; + + public ChatService(NioNetwork nio){ + super(nio); + rooms = new HashMap>(); + } + + @Override + public void handleMessage(Message message, SocketChannel socket) { + // New message + if(message instanceof ChatMessage){ + ChatMessage chatmessage = (ChatMessage)message; + //is this a new message + if(chatmessage.type == ChatMessage.ChatMessageType.MESSAGE){ + // Is this the server + if(nio.getType() == NioNetwork.NetworkType.SERVER){ + if(rooms.containsKey(chatmessage.room)){ + LinkedList tmpList = rooms.get(chatmessage.room); + + // Broadcast the message + for(SocketChannel s : tmpList){ + if(s.isConnected()){ + nio.send(s, chatmessage); + } + else{ + unRegisterUser(chatmessage.room, s); + } + } + } + } + if(NioNetwork.DEBUG>=2)MultiPrintStream.out.println("New Chat Message: "+chatmessage.msg); + listener.messageAction(chatmessage.msg, chatmessage.room); + } + // register to a room + else if(chatmessage.type == ChatMessage.ChatMessageType.REGISTER){ + registerUser(chatmessage.room, socket); + } + // unregister to a room + else if(chatmessage.type == ChatMessage.ChatMessageType.UNREGISTER){ + unRegisterUser(chatmessage.room, socket); + } + } + + } + + /** + * Registers a user to the main room + * + * @param socket The socket to the user + */ + public void registerUser(SocketChannel socket){ + registerUser("", socket); + } + + /** + * Registers the given user to a specific room + * + * @param room The room + * @param socket The socket to the user + */ + public void registerUser(String room, SocketChannel socket){ + addRoom(room); + if(NioNetwork.DEBUG>=1)MultiPrintStream.out.println("New Chat User: "+socket); + rooms.get(room).add(socket); + } + + /** + * Unregisters a user from a room and removes the room if its empty + * + * @param room The room + * @param socket The socket to the user + */ + public void unRegisterUser(String room, SocketChannel socket){ + if(rooms.containsKey(room)){ + if(NioNetwork.DEBUG>=1)MultiPrintStream.out.println("Remove Chat User: "+socket); + rooms.get(room).remove(socket); + removeRoom(room); + } + } + + /** + * Adds a room into the list + * + * @param room The name of the room + */ + public void addRoom(String room){ + if(!rooms.containsKey(room)){ + if(NioNetwork.DEBUG>=1)MultiPrintStream.out.println("New Chat Room: "+room); + rooms.put(room, new LinkedList()); + } + } + + /** + * Removes the given room if its empty + * + * @param room The room + */ + public void removeRoom(String room){ + if(rooms.get(room).isEmpty()){ + if(NioNetwork.DEBUG>=1)MultiPrintStream.out.println("Remove Chat Room: "+room); + rooms.remove(room); + } + } + + public static ChatService getInstance(){ + return (ChatService)instance; + } +} diff --git a/src/zutil/network/nio/service/NetworkService.java b/src/zutil/network/nio/service/NetworkService.java new file mode 100644 index 0000000..f0a00ef --- /dev/null +++ b/src/zutil/network/nio/service/NetworkService.java @@ -0,0 +1,25 @@ +package zutil.network.nio.service; + +import java.nio.channels.SocketChannel; + +import zutil.network.nio.NioNetwork; +import zutil.network.nio.message.Message; + +public abstract class NetworkService { + protected static NetworkService instance; + protected NioNetwork nio; + + public NetworkService(NioNetwork nio){ + instance = this; + this.nio = nio; + } + + public abstract void handleMessage(Message message, SocketChannel socket); + + /** + * @return A instance of this class + */ + public static NetworkService getInstance(){ + return instance; + } +} diff --git a/src/zutil/network/nio/service/sync/ObjectSync.java b/src/zutil/network/nio/service/sync/ObjectSync.java new file mode 100644 index 0000000..71eb24a --- /dev/null +++ b/src/zutil/network/nio/service/sync/ObjectSync.java @@ -0,0 +1,28 @@ +package zutil.network.nio.service.sync; + +import zutil.network.nio.message.SyncMessage; + +public abstract class ObjectSync { + public String id; + + public ObjectSync(String id){ + this.id = id; + } + + /** + * Sends sync message if the object has bean changed + */ + public abstract void sendSync(); + + /** + * Applies the SyncMessage to the object + * @param message + * @param object + */ + public abstract void syncObject(SyncMessage message); + + /** + * Called when the object is removed from the sync list + */ + public abstract void remove(); +} diff --git a/src/zutil/network/nio/service/sync/SyncService.java b/src/zutil/network/nio/service/sync/SyncService.java new file mode 100644 index 0000000..ad93fe0 --- /dev/null +++ b/src/zutil/network/nio/service/sync/SyncService.java @@ -0,0 +1,58 @@ +package zutil.network.nio.service.sync; + +import java.nio.channels.SocketChannel; +import java.util.HashMap; + +import zutil.MultiPrintStream; +import zutil.network.nio.NioNetwork; +import zutil.network.nio.message.Message; +import zutil.network.nio.message.SyncMessage; +import zutil.network.nio.service.NetworkService; + +public class SyncService extends NetworkService{ + // list of objects to sync + private HashMap sync; + + public SyncService(NioNetwork nio){ + super(nio); + sync = new HashMap(); + } + + /** + * Adds a SyncObject to the sync list + * @param os The object to sync + */ + public void addSyncObject(ObjectSync os){ + sync.put(os.id, os); + if(NioNetwork.DEBUG>=1)MultiPrintStream.out.println("New Sync object: "+os); + } + + public void handleMessage(Message message, SocketChannel socket){ + if(message instanceof SyncMessage){ + SyncMessage syncMessage = (SyncMessage)message; + if(syncMessage.type == SyncMessage.MessageType.SYNC){ + ObjectSync obj = sync.get(syncMessage.id); + if(obj != null){ + if(NioNetwork.DEBUG>=2)MultiPrintStream.out.println("Syncing Message..."); + obj.syncObject(syncMessage); + } + } + else if(syncMessage.type == SyncMessage.MessageType.REMOVE){ + sync.remove(syncMessage.id).remove(); + } + } + } + + /** + * Syncs all the objects whit the server + */ + public void sync(){ + for(String id : sync.keySet()){ + sync.get(id).sendSync(); + } + } + + public static SyncService getInstance(){ + return (SyncService)instance; + } +} diff --git a/src/zutil/network/nio/worker/EchoWorker.java b/src/zutil/network/nio/worker/EchoWorker.java new file mode 100644 index 0000000..2156eb3 --- /dev/null +++ b/src/zutil/network/nio/worker/EchoWorker.java @@ -0,0 +1,16 @@ +package zutil.network.nio.worker; + +import zutil.MultiPrintStream; + +public class EchoWorker extends ThreadedEventWorker { + + @Override + public void messageEvent(WorkerDataEvent dataEvent) { + // Return to sender + MultiPrintStream.out.println("Recived Msg: "+dataEvent.data); + dataEvent.network.send(dataEvent.socket, dataEvent.data); + + } + + +} diff --git a/src/zutil/network/nio/worker/SystemWorker.java b/src/zutil/network/nio/worker/SystemWorker.java new file mode 100644 index 0000000..51ef1e6 --- /dev/null +++ b/src/zutil/network/nio/worker/SystemWorker.java @@ -0,0 +1,126 @@ +package zutil.network.nio.worker; + +import java.util.HashMap; +import java.util.Map; + +import zutil.MultiPrintStream; +import zutil.network.nio.NioNetwork; +import zutil.network.nio.message.ChatMessage; +import zutil.network.nio.message.Message; +import zutil.network.nio.message.SyncMessage; +import zutil.network.nio.message.type.EchoMessage; +import zutil.network.nio.message.type.ResponseRequestMessage; +import zutil.network.nio.response.ResponseEvent; +import zutil.network.nio.service.ChatService; +import zutil.network.nio.service.NetworkService; +import zutil.network.nio.service.sync.SyncService; + + +public class SystemWorker extends ThreadedEventWorker { + private NioNetwork nio; + // Maps a SocketChannel to a RspHandler + private Map rspEvents = new HashMap(); + // Difren services listening on specific messages + @SuppressWarnings("unchecked") + private Map services = new HashMap(); + /** + * Creates a new SystemWorker + * @param nio The Network + */ + public SystemWorker(NioNetwork nio){ + this.nio = nio; + } + + @Override + public void messageEvent(WorkerDataEvent event) { + if(NioNetwork.DEBUG>=2)MultiPrintStream.out.println("System Message: "+event.data.getClass().getName()); + if(event.data instanceof Message){ + if(event.data instanceof EchoMessage && ((EchoMessage)event.data).echo()){ + // Echos back the recived message + ((EchoMessage)event.data).recived(); + if(NioNetwork.DEBUG>=3)MultiPrintStream.out.println("Echoing Message: "+event.data); + nio.send(event.socket, event.data); + } + else if(event.data instanceof ResponseRequestMessage && + rspEvents.get(((ResponseRequestMessage)event.data).getResponseId()) != null){ + // Handle the response + handleResponse(((ResponseRequestMessage)event.data).getResponseId(), event.data); + if(NioNetwork.DEBUG>=3)MultiPrintStream.out.println("Response Request Message: "+event.data); + } + else{ + //Services + if(services.containsKey(event.data.getClass()) || + !services.containsKey(event.data.getClass()) && defaultServices(event.data)){ + services.get(event.data.getClass()).handleMessage((Message)event.data, event.socket); + } + } + } + } + + /** + * Registers a Service to a specific message + * + * @param c The Message class + * @param ns The service + */ + @SuppressWarnings("unchecked") + public void registerService(Class c, NetworkService ns){ + services.put(c, ns); + } + + /** + * Unregisters a service + * + * @param c The class + */ + @SuppressWarnings("unchecked") + public void unregisterService(Class c){ + services.remove(c); + } + + /** + * Connects a ResponseHandler to a specific message + * @param handler The Handler + * @param data The Message + */ + public void addResponseHandler(ResponseEvent handler, ResponseRequestMessage data){ + rspEvents.put(data.getResponseId(), handler); + } + + /** + * Client And Server ResponseEvent + */ + private void handleResponse(double responseId, Object rspData){ + // Look up the handler for this channel + ResponseEvent handler = rspEvents.get(responseId); + // And pass the response to it + handler.handleResponse(rspData); + + rspEvents.remove(responseId); + } + + /** + * Registers the default services in the engin e + * if the message needs one of them + * + * @param o The message + */ + private boolean defaultServices(Object o){ + if(o instanceof SyncMessage){ + if(SyncService.getInstance() == null) + registerService(o.getClass(), new SyncService(nio)); + else + registerService(o.getClass(), SyncService.getInstance()); + return true; + } + else if(o instanceof ChatMessage){ + if(ChatService.getInstance() == null) + registerService(o.getClass(), new ChatService(nio)); + else + registerService(o.getClass(), ChatService.getInstance()); + return true; + } + return false; + } + +} diff --git a/src/zutil/network/nio/worker/ThreadedEventWorker.java b/src/zutil/network/nio/worker/ThreadedEventWorker.java new file mode 100644 index 0000000..cf7eb3c --- /dev/null +++ b/src/zutil/network/nio/worker/ThreadedEventWorker.java @@ -0,0 +1,34 @@ +package zutil.network.nio.worker; + +public abstract class ThreadedEventWorker extends Worker{ + private Thread thread; + + public ThreadedEventWorker(){ + thread = new Thread(this); + thread.start(); + } + + public void update() { + WorkerDataEvent dataEvent; + + while(true) { + try{ + // Wait for data to become available + synchronized(getEventQueue()) { + while(getEventQueue().isEmpty()) { + try { + getEventQueue().wait(); + } catch (InterruptedException e) {} + } + dataEvent = (WorkerDataEvent) getEventQueue().remove(0); + } + messageEvent(dataEvent); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public abstract void messageEvent(WorkerDataEvent e); + +} diff --git a/src/zutil/network/nio/worker/Worker.java b/src/zutil/network/nio/worker/Worker.java new file mode 100644 index 0000000..b19cfb1 --- /dev/null +++ b/src/zutil/network/nio/worker/Worker.java @@ -0,0 +1,52 @@ +package zutil.network.nio.worker; + +import java.nio.channels.SocketChannel; +import java.util.LinkedList; +import java.util.List; + +import zutil.network.nio.NioNetwork; + + +public abstract class Worker implements Runnable { + private LinkedList queue = new LinkedList(); + + public void processData(NioNetwork server, SocketChannel socket, Object data) { + synchronized(queue) { + queue.add(new WorkerDataEvent(server, socket, data)); + queue.notify(); + } + } + + /** + * @return The event queue + */ + protected List getEventQueue(){ + return queue; + } + + /** + * @return If there is a event in the queue + */ + protected boolean hasEvent(){ + return !queue.isEmpty(); + } + + /** + * Polls a event from the list or waits until there is a event + * @return The next event + */ + protected WorkerDataEvent pollEvent(){ + while(queue.isEmpty()) { + try { + this.wait(); + } catch (InterruptedException e) {} + } + return queue.poll(); + } + + public void run(){ + update(); + } + + public abstract void update(); +} diff --git a/src/zutil/network/nio/worker/WorkerDataEvent.java b/src/zutil/network/nio/worker/WorkerDataEvent.java new file mode 100644 index 0000000..1b7733d --- /dev/null +++ b/src/zutil/network/nio/worker/WorkerDataEvent.java @@ -0,0 +1,18 @@ +package zutil.network.nio.worker; + +import java.nio.channels.SocketChannel; + +import zutil.network.nio.NioNetwork; + + +public class WorkerDataEvent { + public NioNetwork network; + public SocketChannel socket; + public Object data; + + public WorkerDataEvent(NioNetwork server, SocketChannel socket, Object data) { + this.network = server; + this.socket = socket; + this.data = data; + } +} \ No newline at end of file diff --git a/src/zutil/test/ConsoleTest.java b/src/zutil/test/ConsoleTest.java new file mode 100644 index 0000000..24d03bf --- /dev/null +++ b/src/zutil/test/ConsoleTest.java @@ -0,0 +1,25 @@ +package zutil.test; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import zutil.ui.Console; + +public class ConsoleTest { + public static void main(String[] args) throws IOException{ + new Console("Console Test", true); + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + + while(true){ + System.out.println("hello= "+in.readLine()); + for(int i=0; i<20 ;i++){ + System.out.println(i+"Hello World!!!sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"); + System.err.println(i+"Hello World!!!sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"); + try { + Thread.sleep(100); + } catch (InterruptedException e) {} + } + } + } +} diff --git a/src/zutil/test/EncryptionTest.java b/src/zutil/test/EncryptionTest.java new file mode 100644 index 0000000..1750c77 --- /dev/null +++ b/src/zutil/test/EncryptionTest.java @@ -0,0 +1,38 @@ +package zutil.test; + +import zutil.Encrypter; + +public class EncryptionTest { + public static String data = "Hello there wats yor name my is a secret 123456789"; + public static Encrypter enc; + public static Encrypter enc2; + + public static void main(String[] args) throws Exception { + System.out.println("input text : " + data); + + //**************************************************************************************** + System.out.println("Test1 passphrase"); + Encrypter.randomizeSalt(); + enc = new Encrypter("Hello World!!", Encrypter.PASSPHRASE_DES_ALGO); + enc2 = new Encrypter("Hello World!!", Encrypter.PASSPHRASE_DES_ALGO); + + byte[] encrypted = enc.encrypt(data.getBytes()); + System.out.println("cipher text: " + new String(encrypted) + " bytes: " + encrypted.length); + + byte[] decrypted = enc2.decrypt(encrypted); + System.out.println("plain text : " + new String(decrypted) + " bytes: " + decrypted.length); + + //**************************************************************************************** + System.out.println("Test2 randome"); + Encrypter.randomizeSalt(); + enc = new Encrypter(Encrypter.BLOWFISH_ALGO); + Encrypter.randomizeSalt(); + enc2 = new Encrypter(enc.getKey()); + + encrypted = enc.encrypt(data.getBytes()); + System.out.println("cipher text: " + new String(encrypted) + " bytes: " + encrypted.length); + + decrypted = enc2.decrypt(encrypted); + System.out.println("plain text : " + new String(decrypted) + " bytes: " + decrypted.length); + } +} diff --git a/src/zutil/test/ExternalSortTest.java b/src/zutil/test/ExternalSortTest.java new file mode 100644 index 0000000..17bff41 --- /dev/null +++ b/src/zutil/test/ExternalSortTest.java @@ -0,0 +1,20 @@ +package zutil.test; + +import java.io.File; + +import zutil.algo.sort.ExternalSort; + + +public class ExternalSortTest { + public static void main(String[] args){ + try { + File file = new File("C:\\Users\\Ziver\\Desktop\\IndexFile.txt"); + File sortedFile = new File("C:\\Users\\Ziver\\Desktop\\SortedIndexFile.txt"); + + ExternalSort sort = new ExternalSort(file, sortedFile); + sort.sort(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/zutil/test/FileChangedTest.java b/src/zutil/test/FileChangedTest.java new file mode 100644 index 0000000..6177199 --- /dev/null +++ b/src/zutil/test/FileChangedTest.java @@ -0,0 +1,29 @@ +package zutil.test; + +import java.io.File; +import java.io.FileNotFoundException; +import java.net.URISyntaxException; + +import zutil.FileChangeListener; +import zutil.FileFinder; +import zutil.FileWatcher; + +public class FileChangedTest implements FileChangeListener{ + public static void main(String[] args) throws URISyntaxException, FileNotFoundException{ + FileWatcher watcher = new FileWatcher(FileFinder.find("test.txt")); + watcher.setListener(new FileChangedTest()); + + while(true){ + try { + Thread.sleep(10); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + public void fileChangedEvent(File file) { + System.out.println(file); + } +} diff --git a/src/zutil/test/FileFinderHasherTest.java b/src/zutil/test/FileFinderHasherTest.java new file mode 100644 index 0000000..bd79c0e --- /dev/null +++ b/src/zutil/test/FileFinderHasherTest.java @@ -0,0 +1,26 @@ +package zutil.test; + +import java.io.File; +import java.net.URISyntaxException; +import java.util.ArrayList; + +import zutil.FileFinder; +import zutil.Hasher; + +public class FileFinderHasherTest { + public static void main(String[] args) throws URISyntaxException{ + String relativePath = "zutil/test"; + + File path = FileFinder.find(relativePath); + ArrayList files = FileFinder.search(path); + for(int i=0; i client_info, + HashMap session, HashMap cookie, + HashMap request) { + + out.enableBuffering(true); + out.println(""); + out.println("

Welcome To The Number Guess Game!

"); + + if(session.containsKey("random_nummber") && request.containsKey("guess")){ + int guess = Integer.parseInt(request.get("guess")); + int nummber = Integer.parseInt(session.get("random_nummber")); + try { + if(guess == nummber){ + session.remove("random_nummber"); + out.println("You Guessed Right! Congrats!"); + out.println(""); + return; + } + else if(guess > nummber){ + out.println("To High
"); + if(Integer.parseInt(cookie.get("high")) > guess){ + out.setCookie("high", ""+guess); + cookie.put("high", ""+guess); + } + } + else{ + out.println("To Low
"); + if(Integer.parseInt(cookie.get("low")) < guess){ + out.setCookie("low", ""+guess); + cookie.put("low", ""+guess); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + else{ + session.put("random_nummber", ""+(int)(Math.random()*99+1)); + try { + out.setCookie("low", "0"); + out.setCookie("high", "100"); + cookie.put("low", "0"); + cookie.put("high", "100"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + out.println("
"); + out.println(cookie.get("low")+" < X < "+cookie.get("high")+"
"); + out.println("Guess a number between 0 and 100:
"); + out.println(""); + out.println(""); + out.println(""); + out.println("
"); + out.println(""); + //out.println("DEBUG: nummber="+session.get("random_nummber")+"
"); + out.println(""); + } + +} diff --git a/src/zutil/test/ImageProcessorTest.java b/src/zutil/test/ImageProcessorTest.java new file mode 100644 index 0000000..e8e0fab --- /dev/null +++ b/src/zutil/test/ImageProcessorTest.java @@ -0,0 +1,116 @@ +package zutil.test; + +import javax.imageio.ImageIO; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JProgressBar; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.image.BufferedImage; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.swing.JLabel; + +import zutil.ProgressListener; +import zutil.image.ImageFilterProcessor; +import zutil.image.filters.BlurFilter; +import zutil.image.filters.ColorIntensityFilter; +import zutil.image.filters.ContrastBrightnessFilter; +import zutil.image.filters.DitheringFilter; +import zutil.image.filters.FaceDetectionFilter; +import zutil.image.filters.MedianFilter; +import zutil.image.filters.ResizeImage; +import zutil.image.filters.SpotLightFilter; + +@SuppressWarnings("unused") +public class ImageProcessorTest implements ProgressListener{ + private static String imgPath = "Image6.gif"; + + private JLabel processedLabel; + private JLabel orginalLabel; + private JProgressBar progress; + + public static void main(String[] args){ + new ImageProcessorTest(); + } + + public ImageProcessorTest(){ + JFrame frame = getJFrame(); + BufferedImage img = null; + + try { + // Read from an input stream + InputStream is = new BufferedInputStream(new FileInputStream(imgPath)); + img = ImageIO.read(is); + } catch (IOException e) { + e.printStackTrace(); + System.exit(1); + } + + ImageIcon orginalIcon = new ImageIcon(img); + orginalLabel.setIcon(orginalIcon); + frame.setVisible(true); + frame.pack(); + + BufferedImage procImg = null; + try { + //ImageFilterProcessor processor = new SpotLightFilter(img,100,100,100); + //ImageFilterProcessor processor = new ContrastBrightnessFilter(img); + //ImageFilterProcessor processor = new ColorIntensityFilter(img, true); + //ImageFilterProcessor processor = new BlurFilter(img); + //ImageFilterProcessor processor = new DitheringFilter(img); + //ImageFilterProcessor processor = new ResizeImage(img,100,100); + //ImageFilterProcessor processor = new MedianFilter(img); + ImageFilterProcessor processor = new FaceDetectionFilter(img); + + processor.setProgressListener(this); + procImg = processor.process(); + } catch (Exception e) { + e.printStackTrace(); + } + ImageIcon processedIcon = new ImageIcon(procImg); + processedLabel.setIcon(processedIcon); + + + frame.pack(); + } + + private JFrame getJFrame() { + processedLabel = new JLabel("Processed"); + orginalLabel = new JLabel("Orginal"); + + progress = new JProgressBar(); + progress.setMaximum(100); + progress.setValue(0); + progress.setIndeterminate(false); + progress.setStringPainted(true); + + JPanel jPanel = new JPanel(); + jPanel.setLayout(new BorderLayout()); + jPanel.add(orginalLabel, BorderLayout.NORTH); + jPanel.add(processedLabel, BorderLayout.CENTER); + jPanel.add(progress, BorderLayout.SOUTH); + + JFrame jFrame = new JFrame("ImageProcessorTest"); + jFrame.setSize(new Dimension(715, 361)); + jFrame.setContentPane(jPanel); + jFrame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + return jFrame; + } + + public void progressUpdate(Object source, Object info, double percent) { + progress.setValue((int)percent); + } +} diff --git a/src/zutil/test/NetworkClientTest.java b/src/zutil/test/NetworkClientTest.java new file mode 100644 index 0000000..7bda364 --- /dev/null +++ b/src/zutil/test/NetworkClientTest.java @@ -0,0 +1,37 @@ +package zutil.test; + +import java.io.IOException; +import java.net.InetAddress; +import java.security.NoSuchAlgorithmException; + +import zutil.Encrypter; +import zutil.network.nio.NioClient; +import zutil.network.nio.message.StringMessage; +import zutil.network.nio.response.PrintRsp; + + +@SuppressWarnings("unused") +public class NetworkClientTest { + public static void main(String[] args) throws NoSuchAlgorithmException { + try { + int count = 0; + long time = System.currentTimeMillis()+1000*60; + NioClient client = new NioClient(InetAddress.getByName("localhost"), 6056); + //client.setEncrypter(new Encrypter("lol", Encrypter.PASSPHRASE_DES_ALGO)); + while(time > System.currentTimeMillis()){ + PrintRsp handler = new PrintRsp(); + client.send(handler, new StringMessage("StringMessage: "+count)); + handler.waitForResponse(); + //try {Thread.sleep(100);} catch (InterruptedException e) {} + //System.out.println("sending.."); + count++; + } + + System.out.println("Message Count 1m: "+count); + System.out.println("Message Count 1s: "+count/60); + System.exit(0); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/zutil/test/NetworkServerTest.java b/src/zutil/test/NetworkServerTest.java new file mode 100644 index 0000000..9b627e9 --- /dev/null +++ b/src/zutil/test/NetworkServerTest.java @@ -0,0 +1,20 @@ +package zutil.test; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; + +import zutil.Encrypter; +import zutil.network.nio.NioServer; + + +@SuppressWarnings("unused") +public class NetworkServerTest { + public static void main(String[] args) throws NoSuchAlgorithmException { + try { + NioServer server = new NioServer(6056); + //server.setEncrypter(new Encrypter("lol", Encrypter.PASSPHRASE_DES_ALGO)); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/zutil/test/QuickSelectTest.java b/src/zutil/test/QuickSelectTest.java new file mode 100644 index 0000000..db41927 --- /dev/null +++ b/src/zutil/test/QuickSelectTest.java @@ -0,0 +1,26 @@ +package zutil.test; + +import java.util.Arrays; + +import zutil.algo.QuickSelect; +import zutil.algo.sort.sortable.SortableIntArray; + +public class QuickSelectTest { + public static void main(String[] args){ + int[] array = {1,3,4,6,3,2,98,5,7,8,543,2,4,5,8,9,5,2,3,5,7,5,3,2,6,8,5,324,8,6}; + //int[] array = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,17,18,19,20}; + + long time = System.currentTimeMillis(); + int median = (Integer)QuickSelect.find(new SortableIntArray(array), array.length/2); + System.out.println("QuickSelection("+(System.currentTimeMillis()-time)+"ms): "+median); + + time = System.currentTimeMillis(); + Arrays.sort(array); + System.out.println("RightAnswer("+(System.currentTimeMillis()-time)+"ms): "+array[array.length/2]); + + System.out.println("Sorted Array("+array.length+"): "); + for(int i=0; i array[i]){ + fail("Array not sorted!! ("+array[i-1]+" > "+array[i]+")"); + } + } + } +} \ No newline at end of file diff --git a/src/zutil/test/QuickSortTestSimple.java b/src/zutil/test/QuickSortTestSimple.java new file mode 100644 index 0000000..c922b0f --- /dev/null +++ b/src/zutil/test/QuickSortTestSimple.java @@ -0,0 +1,63 @@ +package zutil.test; +import zutil.algo.sort.QuickSort; +import zutil.algo.sort.sortable.SortableIntArray; +import junit.framework.*; + +public class QuickSortTestSimple extends TestCase { + + public static void main(String[] args){ + int[] array = new int[1000]; + + for(int i=0; i array[i]){ + System.out.println("Array not sorted!! ("+array[i-1]+" > "+array[i]+")"); + } + } + } + + static void quicksort (int[] a, int lo, int hi) { + // lo is the lower index, hi is the upper index + // of the region of array a that is to be sorted + int i=lo, j=hi, h; + int x=a[(lo+hi)/2]; + + // partition + do + { + while (a[i]x){ + j--; + } + if (i<=j) + { + h=a[i]; a[i]=a[j]; a[j]=h; + i++; j--; + } + } while (i<=j); + + // recursion + if (lo bufferSize){ + doc.remove(0, doc.getLength() - bufferSize); + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + /** + * Enables the tray icon and sets the icon + * @param img The image to use as the icon + */ + public void setTrayIcon(Image img){ + enableTray(true); + trayIcon.setImage(img); + } + + /** + * Sets the icon for the Frame + * + * @param img The image to use as a icon + */ + public void setFrameIcon(Image img){ + frame.setIconImage(img); + } + + /** + * Enables the tray + * + * @param enable True to enable tray + * @param img The Tray image + */ + public void enableTray(boolean enable){ + if(enable && SystemTray.isSupported()){ + frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); + SystemTray tray = SystemTray.getSystemTray(); + + if(trayIcon == null){ + // Menu + PopupMenu menu = new PopupMenu(); + MenuItem item = new MenuItem("Open"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + frame.setVisible(true); + } + }); + menu.add(item); + menu.addSeparator(); + item = new MenuItem("Exit"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + System.exit(0); + } + }); + menu.add(item); + + // Icon + trayIcon = new TrayIcon( + Toolkit.getDefaultToolkit().getImage(defaultIcon), + "Console", menu); + trayIcon.setImageAutoSize(true); + trayIcon.addMouseListener(new MouseListener(){ + public void mouseClicked(MouseEvent e) { + if(e.getClickCount() == 2) + frame.setVisible(true); + } + public void mouseEntered(MouseEvent e) {} + public void mouseExited(MouseEvent e) {} + public void mousePressed(MouseEvent e) {} + public void mouseReleased(MouseEvent e) {} + }); + } + + try { + tray.add(trayIcon); + } catch (AWTException e) { + System.err.println("TrayIcon could not be added."); + } + } + else{ + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + SystemTray.getSystemTray().remove(trayIcon); + } + } + + + /** + * The Stream to replace System.out + * + * @author Ziver + * + * TrayIcon.MessageType.ERROR An error message + * TrayIcon.MessageType.INFO An information message + * TrayIcon.MessageType.NONE A simple message + * TrayIcon.MessageType.WARNING A warning message + */ + private class ConsolePrintStream extends PrintStream{ + private Style style; + private MessageType trayMessageType; + + public ConsolePrintStream(OutputStream out, Color c) { + this(out, c, null); + } + + public ConsolePrintStream(OutputStream out, Color c, MessageType type) { + super(out); + style = console.addStyle("PrintStream", null); + StyleConstants.setForeground(style, c); + trayMessageType = type; + } + + public void print(String s){ + appendConsole(s, style); + console.setCaretPosition(console.getDocument().getLength()); + if(trayMessageType != null){ + trayIcon.displayMessage( + s.substring(0, (s.length() > 25 ? 25 : s.length()))+"...", + s, trayMessageType); + + } + } + + public void println(String s){ + print(s+"\n"); + } + + public void println(){ println("");} + public void println(boolean x){ println(""+x);} + public void println(char x){ println(""+x);} + public void println(char[] x){ println(new String(x));} + public void println(double x){ println(""+x);} + public void println(float x){ println(""+x);} + public void println(int x){ println(""+x);} + public void println(long x){ println(""+x);} + public void println(Object x){ println(""+x);} + + public void print(boolean x){ print(""+x);} + public void print(char x){ print(""+x);} + public void print(char[] x){ print(new String(x));} + public void print(double x){ print(""+x);} + public void print(float x){ print(""+x);} + public void print(int x){ print(""+x);} + public void print(long x){ print(""+x);} + public void print(Object x){ print(""+x);} + } + + private class ConsoleInputStream extends InputStream implements KeyListener{ + private boolean read = false; + private int input; + + @Override + public int read() throws IOException { + if(input < 0) { + input = 0; + return -1; + } + read = true; + input = 0; + while(input == 0){ + try {Thread.sleep(10);} catch (InterruptedException e) {} + } + read = false; + System.out.print((char)input); + if(input == KeyEvent.VK_ENTER){ + input = -1; + return '\n'; + } + return input; + } + /* + @Override + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + System.out.println(off+"-"+len); + int i; + for(i=-1; i= buf_end) { + if(fillBuffer() < 0) + return -1; + } + if(buf_end == 0) { + return -1; + } else { + buf_pos++; + return buffer[buf_pos-1]; + } + } + + /** + * Reads in data from the file to the buffer + * + * @return The buffer + * @throws IOException + */ + private int fillBuffer() throws IOException { + int n = super.read(buffer, 0, BUF_SIZE ); + if(n >= 0) { + real_pos +=n; + buf_end = n; + buf_pos = 0; + } + return n; + } + + /** + * Resets the buffer + * + * @throws IOException + */ + private void invalidate() throws IOException { + buf_end = 0; + buf_pos = 0; + real_pos = super.getFilePointer(); + } + + /** + * This class while read in b.length from the file + */ + public int read(byte b[]) throws IOException { + return read(b, 0, b.length); + } + + /** + * Reads a given length of bytes from the buffer + * + */ + public int read(byte b[], int off, int len) throws IOException { + int leftover = buf_end - buf_pos; + if(len <= leftover) { + System.arraycopy(buffer, buf_pos, b, off, len); + buf_pos += len; + return len; + } + for(int i = 0; i < len; i++) { + int c = this.read(); + if(c != -1) + b[off+i] = (byte)c; + else { + return i; + } + } + return len; + } + + /** + * Returns the file pointer in the file + */ + public long getFilePointer() throws IOException{ + long l = real_pos; + return (l - buf_end + buf_pos) ; + } + + /** + * Changes the file pointer to another position + * + * @param pos The position to move the pointer to + */ + public void seek(long pos) throws IOException { + int n = (int)(real_pos - pos); + if(n >= 0 && n <= buf_end) { + buf_pos = buf_end - n; + } else { + super.seek(pos); + invalidate(); + } + } + + /** + * Returns the next line in the file + * This method is a replacement for readLine() + */ + public final String readNextLine() throws IOException { + String str = null; + if(buf_end-buf_pos <= 0) { + if(fillBuffer() < 0) { + throw new IOException("Error filling buffer!"); + } + } + int lineend = -1; + for(int i = buf_pos; i < buf_end; i++) { + if(buffer[i] == '\n') { + lineend = i; + break; + } + } + if(lineend < 0) { + StringBuffer input = new StringBuffer(256); + int c; + while (((c = read()) != -1) && (c != '\n')) { + input.append((char)c); + } + if ((c == -1) && (input.length() == 0)) { + return null; + } + return input.toString(); + } + + if(lineend > 0 && buffer[lineend-1] == '\r'){ + str = new String(buffer, buf_pos, lineend - buf_pos -1); + } + else { + str = new String(buffer, buf_pos, lineend - buf_pos); + } + buf_pos = lineend +1; + return str; + } + +} diff --git a/src/zutil/wrapper/SerializableBufferedImage.java b/src/zutil/wrapper/SerializableBufferedImage.java new file mode 100644 index 0000000..3ec3acb --- /dev/null +++ b/src/zutil/wrapper/SerializableBufferedImage.java @@ -0,0 +1,35 @@ +package zutil.wrapper; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +import javax.imageio.ImageIO; + +public class SerializableBufferedImage implements Serializable{ + private static final long serialVersionUID = 1L; + + private BufferedImage image; + + public SerializableBufferedImage(BufferedImage image){ + this.image = image; + } + + public BufferedImage getImage(){ + return image; + } + + public void setImage(BufferedImage image){ + this.image=image; + } + + private void writeObject(ObjectOutputStream out)throws IOException{ + ImageIO.write(image,"jpeg",ImageIO.createImageOutputStream(out)); + } + + private void readObject(ObjectInputStream in)throws IOException, ClassNotFoundException{ + image = ImageIO.read(ImageIO.createImageInputStream(in)); + } +} \ No newline at end of file