lol
This commit is contained in:
commit
613bef2496
108 changed files with 8397 additions and 0 deletions
8
.classpath
Normal file
8
.classpath
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="lib" path="libs/mysql-connector-java-5.0.7-bin.jar"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
19
.project
Normal file
19
.project
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>ZUtil</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.jem.beaninfo.BeanInfoNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
3
.settings/org.eclipse.core.resources.prefs
Normal file
3
.settings/org.eclipse.core.resources.prefs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#Wed Feb 06 16:42:34 CET 2008
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=ISO-8859-1
|
||||
BIN
bin/zutil/History.class
Normal file
BIN
bin/zutil/History.class
Normal file
Binary file not shown.
BIN
bin/zutil/MultiPrintStream.class
Normal file
BIN
bin/zutil/MultiPrintStream.class
Normal file
Binary file not shown.
BIN
bin/zutil/db/MySQLConnection.class
Normal file
BIN
bin/zutil/db/MySQLConnection.class
Normal file
Binary file not shown.
BIN
exemple.gif
Normal file
BIN
exemple.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 77 KiB |
171
hs_err_pid1104.log
Normal file
171
hs_err_pid1104.log
Normal file
|
|
@ -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
|
||||
|
||||
BIN
libs/mysql-connector-java-5.0.7-bin.jar
Normal file
BIN
libs/mysql-connector-java-5.0.7-bin.jar
Normal file
Binary file not shown.
69
src/zutil/Converter.java
Normal file
69
src/zutil/Converter.java
Normal file
|
|
@ -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<objectInterf.length ;i++){
|
||||
if(objectInterf[i] == interf){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
184
src/zutil/Encrypter.java
Normal file
184
src/zutil/Encrypter.java
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
package zutil;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.security.spec.KeySpec;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.CipherInputStream;
|
||||
import javax.crypto.CipherOutputStream;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.crypto.spec.PBEParameterSpec;
|
||||
|
||||
|
||||
/**
|
||||
* Basic symmetric encryption example
|
||||
*/
|
||||
public class Encrypter {
|
||||
public static final String BLOWFISH_ALGO = "Blowfish";
|
||||
public static final String DES_ALGO = "DES";
|
||||
public static final String DESEDE_ALGO = "DESede";
|
||||
public static final String TRIPLEDES_ALGO = "TripleDES";
|
||||
public static final String PASSPHRASE_TOWFISH_ALGO = "PBEWithSHAAndTwofish-CBC";
|
||||
public static final String PASSPHRASE_TRIPLEDES_ALGO = "PBEWithMD5AndTripleDES";
|
||||
public static final String PASSPHRASE_DES_ALGO = "PBEWithMD5AndDES";
|
||||
|
||||
// 8-byte Salt
|
||||
public static byte[] salt = {
|
||||
(byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32,
|
||||
(byte)0x56, (byte)0x35, (byte)0xE3, (byte)0x03
|
||||
};
|
||||
// Iteration count
|
||||
public static int iterationCount = 19;
|
||||
|
||||
private Cipher encipher;
|
||||
private Cipher decipher;
|
||||
private Key key;
|
||||
private AlgorithmParameterSpec paramSpec;
|
||||
|
||||
/**
|
||||
* Generates a random key
|
||||
* @param algorithm The algorithm to use
|
||||
*/
|
||||
public Encrypter(String algorithm) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException{
|
||||
KeyGenerator keygenerator = KeyGenerator.getInstance(algorithm);
|
||||
|
||||
key = keygenerator.generateKey();
|
||||
encipher = Cipher.getInstance(key.getAlgorithm());
|
||||
decipher = Cipher.getInstance(key.getAlgorithm());
|
||||
encipher.init(Cipher.ENCRYPT_MODE, key);
|
||||
decipher.init(Cipher.DECRYPT_MODE, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the given key for encryption
|
||||
* @param key The key to use
|
||||
*/
|
||||
public Encrypter(Key key) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException{
|
||||
this.key = key;
|
||||
encipher = Cipher.getInstance(key.getAlgorithm());
|
||||
decipher = Cipher.getInstance(key.getAlgorithm());
|
||||
encipher.init(Cipher.ENCRYPT_MODE, key);
|
||||
decipher.init(Cipher.DECRYPT_MODE, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a encrypter with a passphrase
|
||||
*
|
||||
* @param stringKey The pass
|
||||
* @param algorithm The algoritm to use
|
||||
*/
|
||||
public Encrypter(String stringKey, String algorithm) throws NoSuchAlgorithmException{
|
||||
try {
|
||||
// Install SunJCE provider
|
||||
Provider sunJce = new com.sun.crypto.provider.SunJCE();
|
||||
Security.addProvider(sunJce);
|
||||
|
||||
// Generate the secret key specs.
|
||||
KeySpec keySpec = new PBEKeySpec(stringKey.toCharArray());
|
||||
|
||||
key = SecretKeyFactory.getInstance(algorithm).generateSecret(keySpec);
|
||||
paramSpec = new PBEParameterSpec(salt, iterationCount);
|
||||
|
||||
encipher = Cipher.getInstance(key.getAlgorithm());
|
||||
decipher = Cipher.getInstance(key.getAlgorithm());
|
||||
encipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
|
||||
decipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the given data
|
||||
*
|
||||
* @param data Data to encrypt
|
||||
* @return The encrypted data
|
||||
*/
|
||||
public byte[] encrypt(byte[] data){
|
||||
try {
|
||||
byte[] encryption = new byte[encipher.getOutputSize(data.length)];
|
||||
int ctLength = encipher.update(data, 0, data.length, encryption, 0);
|
||||
|
||||
ctLength += encipher.doFinal(encryption, ctLength);
|
||||
return encryption;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds encryption to the OutputStream
|
||||
* @param out The OutputStream to enable encryption on
|
||||
* @return A new encrypted OutputStream
|
||||
*/
|
||||
public OutputStream encrypt(OutputStream out) {
|
||||
// Bytes written to out will be encrypted
|
||||
return new CipherOutputStream(out, encipher);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts encrypted data
|
||||
* @param encrypted The encrypted data
|
||||
* @return The decrypted data
|
||||
*/
|
||||
public byte[] decrypt(byte[] encrypted){
|
||||
try {
|
||||
byte[] dataTmp = new byte[encrypted.length];
|
||||
int ptLength = decipher.update(encrypted, 0, encrypted.length, dataTmp, 0);
|
||||
ptLength += decipher.doFinal(dataTmp, ptLength);
|
||||
|
||||
byte[] data = new byte[ptLength];
|
||||
System.arraycopy(dataTmp, 0, data, 0, ptLength);
|
||||
return data;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds decryption to the InputStream
|
||||
* @param in The InputStream to enable decryption on
|
||||
* @return A new decrypted InputStream
|
||||
*/
|
||||
public InputStream decrypt(InputStream in) {
|
||||
// Bytes read from in will be decrypted
|
||||
return new CipherInputStream(in, decipher);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The key for this encrypter
|
||||
*/
|
||||
public Key getKey(){
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The algorithm used by this encrypter
|
||||
*/
|
||||
public String getAlgorithm(){
|
||||
return key.getAlgorithm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Randomizes the salt for the key
|
||||
*/
|
||||
public static void randomizeSalt(){
|
||||
Random random = new Random();
|
||||
random.nextBytes(salt);
|
||||
}
|
||||
}
|
||||
19
src/zutil/FileChangeListener.java
Normal file
19
src/zutil/FileChangeListener.java
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
package zutil;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Interface for the FileWatcher class
|
||||
*
|
||||
* @author Ziver
|
||||
*/
|
||||
public interface FileChangeListener{
|
||||
|
||||
/**
|
||||
* This method is called when there is a change in
|
||||
* a file
|
||||
*
|
||||
* @param file The file that has changed
|
||||
*/
|
||||
public void fileChangedEvent(File file);
|
||||
}
|
||||
121
src/zutil/FileFinder.java
Normal file
121
src/zutil/FileFinder.java
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
package zutil;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
/**
|
||||
* File path utilities
|
||||
*
|
||||
* @author Ziver
|
||||
*/
|
||||
public class FileFinder {
|
||||
|
||||
/**
|
||||
* Returns a String with a relative path from the given path
|
||||
*
|
||||
* @param file The file to get a relative path from
|
||||
* @param path The path
|
||||
* @return A String with a relative path
|
||||
*/
|
||||
public static String relativePath(File file, String path){
|
||||
String absolute = file.getAbsolutePath();
|
||||
String tmpPath = path.replaceAll(
|
||||
"[/\\\\]",
|
||||
Matcher.quoteReplacement(File.separator));
|
||||
|
||||
String relative = absolute.substring(
|
||||
absolute.indexOf(tmpPath)+path.length(),
|
||||
absolute.length());
|
||||
return relative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the File object for the given file
|
||||
*
|
||||
* @param path The path to the file (no / if not absolute path)
|
||||
* @return A File object for the file
|
||||
* @throws URISyntaxException
|
||||
*/
|
||||
public static File find(String path){
|
||||
try {
|
||||
File file = new File(path);
|
||||
if(file!=null && file.exists()){
|
||||
return file;
|
||||
}
|
||||
return new File(findURL(path).toURI());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL to the given file
|
||||
*
|
||||
* @param path The path to the file (no / if not absolute path)
|
||||
* @return A URL object for the file
|
||||
* @throws URISyntaxException
|
||||
*/
|
||||
public static URL findURL(String path){
|
||||
return FileFinder.class.getClassLoader().getResource(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a ArrayList with all the files in a folder and sub folders
|
||||
*
|
||||
* @param dir The directory to search in
|
||||
* @return The ArrayList with the files
|
||||
*/
|
||||
public static ArrayList<File> search(File dir){
|
||||
return search(dir, new ArrayList<File>());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<File> search(File dir, ArrayList<File> fileList){
|
||||
String[] temp = dir.list();
|
||||
File file;
|
||||
|
||||
for(int i=0; i<temp.length ;i++){
|
||||
file = new File(dir.getPath()+File.separator+temp[i]);
|
||||
if(file.isDirectory()){
|
||||
search(new File(dir.getPath()+File.separator+temp[i]+File.separator),fileList);
|
||||
}
|
||||
else if(file.isFile()){
|
||||
MultiPrintStream.out.println("File Found: "+file);
|
||||
fileList.add(file);
|
||||
}
|
||||
}
|
||||
|
||||
return fileList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the extension of the file
|
||||
* @param file The file
|
||||
* @return The extension
|
||||
*/
|
||||
public static String fileExtension(File file){
|
||||
return fileExtension(file.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the extension of the file
|
||||
* @param file The file
|
||||
* @return The extension
|
||||
*/
|
||||
public static String fileExtension(String file){
|
||||
if(file.lastIndexOf(".")==-1)
|
||||
return "";
|
||||
return file.substring(file.lastIndexOf(".")+1,file.length());
|
||||
}
|
||||
|
||||
}
|
||||
63
src/zutil/FileWatcher.java
Normal file
63
src/zutil/FileWatcher.java
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
package zutil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* This class calls a given listener
|
||||
* when a file is changed
|
||||
* @author Ziver
|
||||
*
|
||||
*/
|
||||
public class FileWatcher extends TimerTask{
|
||||
private FileChangeListener listener;
|
||||
private long lastChanged;
|
||||
private File file;
|
||||
|
||||
/**
|
||||
* Creates a watcher for the given file whit the check
|
||||
* interval of 1 second
|
||||
*
|
||||
* @param file The file to check
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
public FileWatcher(File file) throws FileNotFoundException{
|
||||
this(file, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a watcher for the given file whit the given
|
||||
* check interval
|
||||
*
|
||||
* @param file The file
|
||||
* @param intervall The interval
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
public FileWatcher(File file, int intervall) throws FileNotFoundException{
|
||||
if(file==null || !file.exists()) throw new FileNotFoundException("File not found: "+file);
|
||||
this.file = file;
|
||||
lastChanged = file.lastModified();
|
||||
|
||||
Timer t = new Timer(true);
|
||||
t.schedule(this, 0, intervall);
|
||||
}
|
||||
|
||||
public void setListener(FileChangeListener listener){
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (lastChanged != file.lastModified()) {
|
||||
lastChanged = file.lastModified();
|
||||
if(listener != null){
|
||||
listener.fileChangedEvent(file);
|
||||
}
|
||||
else{
|
||||
MultiPrintStream.out.println("File Changed: "+file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
64
src/zutil/Hasher.java
Normal file
64
src/zutil/Hasher.java
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
package zutil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import sun.misc.BASE64Encoder;
|
||||
|
||||
public class Hasher {
|
||||
|
||||
/**
|
||||
* Returns a hash of a file
|
||||
*
|
||||
* @param file The path to the file
|
||||
* @param hashType The hash type
|
||||
* @return A String with the hash
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static String hash(File file, String hashType) throws NoSuchAlgorithmException, IOException {
|
||||
MessageDigest digest = MessageDigest.getInstance(hashType);//"MD5"
|
||||
InputStream is = new FileInputStream(file);
|
||||
String output = "";
|
||||
byte[] buffer = new byte[8192];
|
||||
int read = 0;
|
||||
try {
|
||||
while( (read = is.read(buffer)) > 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);
|
||||
}
|
||||
}
|
||||
59
src/zutil/History.java
Normal file
59
src/zutil/History.java
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
package zutil;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class History<T> {
|
||||
public int history_length = 10;
|
||||
private LinkedList<T> history;
|
||||
private int historyIndex = 0;
|
||||
|
||||
public History(int histlength){
|
||||
history_length = histlength;
|
||||
history = new LinkedList<T>();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
309
src/zutil/MultiPrintStream.java
Normal file
309
src/zutil/MultiPrintStream.java
Normal file
|
|
@ -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<PrintStream> 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<PrintStream>();
|
||||
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<PrintStream>();
|
||||
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<PrintStream>();
|
||||
for(int i=0; i<streams.length ;i++){
|
||||
this.streams.add(streams[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* this constructor takes a array of PrintStreams to be used
|
||||
* @param streams a array of the streams that will be used
|
||||
*/
|
||||
public static void makeInstance(MultiPrintStream instanceStream){
|
||||
out = instanceStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a printstream to the list pf streams
|
||||
* @param p The Printstream to add
|
||||
*/
|
||||
public void addPrintStream(PrintStream p){
|
||||
streams.add(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a printstream from the list
|
||||
* @param p The PrintStream to remove
|
||||
*/
|
||||
public void removePrintStream(PrintStream p){
|
||||
streams.remove(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a printstream from the list
|
||||
* @param p The index of the PrintStream to remove
|
||||
*/
|
||||
public void removePrintStream(int p){
|
||||
streams.remove(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* prints whit a new line to all the PrintStreams
|
||||
*/
|
||||
public void println(String s){
|
||||
if(!s.equals(""))s = getTime() + s;
|
||||
for(int i=0; i<streams.size() ;i++)
|
||||
streams.get(i).println(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* prints to all the PrintStreams
|
||||
*/
|
||||
public void print(String s){
|
||||
for(int i=0; i<streams.size() ;i++)
|
||||
streams.get(i).print(s);
|
||||
}
|
||||
|
||||
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);}
|
||||
|
||||
|
||||
/**
|
||||
* If the streams should print timestamp in front
|
||||
* of the msgs
|
||||
* @param enable True to activate
|
||||
*/
|
||||
public void printTimeStamp(boolean enable){
|
||||
timeStamp = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* The DateFormat to print in the time stamp
|
||||
* @param ts String to send to SimpleDateFormat
|
||||
*/
|
||||
public void setTimeStamp(String ts){
|
||||
timeStampString = ts;
|
||||
}
|
||||
|
||||
private String getTime(){
|
||||
if(timeStamp)
|
||||
return "" + (new SimpleDateFormat(timeStampString)).format(new java.util.Date());
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
public boolean checkError(){
|
||||
for(int i=0; i<streams.size() ;i++)
|
||||
if(streams.get(i).checkError())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* closes all the PrintStreams
|
||||
*/
|
||||
public void close(){
|
||||
for(int i=0; i<streams.size() ;i++)
|
||||
streams.get(i).close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the content of:
|
||||
* - 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
|
||||
* @return A String with all the printed data
|
||||
*/
|
||||
public String dump( Object o ){
|
||||
return dump( o , true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the content of:
|
||||
* <br>- Array content
|
||||
* <br>- Map content (HashMap etc.)
|
||||
* <br>- List content (ArrayList, LinkedList etc.)
|
||||
* <br>- InputStream content (Prints out until the end of the stream)
|
||||
* <br>- Reader content (Prints out until the end of the reader)
|
||||
* <br>- 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<Array.getLength(o) ;i++ ) {
|
||||
if ( 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<fields.length; i++ ) {
|
||||
if ( buffer.length() > 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;
|
||||
}
|
||||
}
|
||||
24
src/zutil/OneApp.java
Normal file
24
src/zutil/OneApp.java
Normal file
|
|
@ -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();
|
||||
}
|
||||
99
src/zutil/OneAppFile.java
Normal file
99
src/zutil/OneAppFile.java
Normal file
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
72
src/zutil/OneAppNetwork.java
Normal file
72
src/zutil/OneAppNetwork.java
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/zutil/ProgressListener.java
Normal file
18
src/zutil/ProgressListener.java
Normal file
|
|
@ -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);
|
||||
}
|
||||
30
src/zutil/StringUtil.java
Normal file
30
src/zutil/StringUtil.java
Normal file
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
68
src/zutil/algo/QuickSelect.java
Normal file
68
src/zutil/algo/QuickSelect.java
Normal file
|
|
@ -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<right ;i++){
|
||||
if(list.compare(i, pivotValue) < 0){
|
||||
list.swap(storeIndex, i);
|
||||
storeIndex = storeIndex+1;
|
||||
}
|
||||
}
|
||||
list.swap(right, storeIndex);
|
||||
return storeIndex;
|
||||
}
|
||||
}
|
||||
39
src/zutil/algo/path/DijkstraPathFinder.java
Normal file
39
src/zutil/algo/path/DijkstraPathFinder.java
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package zutil.algo.path;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class DijkstraPathFinder {
|
||||
|
||||
public static LinkedList<PathNode> 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<PathNode> path = new LinkedList<PathNode>();
|
||||
PathNode current = stop;
|
||||
while(true){
|
||||
path.addFirst(current);
|
||||
current = current.getSourceNeighbor();
|
||||
if(current.equals(start)){
|
||||
path.addFirst(start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
}
|
||||
117
src/zutil/algo/path/DynamicProgramming.java
Normal file
117
src/zutil/algo/path/DynamicProgramming.java
Normal file
|
|
@ -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<words.length ;w++){ //lodräta ordet
|
||||
System.out.print("\n\n"+new String(words[w])+"\n ");
|
||||
for(int y=0; y<words.length ;y++){ // vågräta ordet
|
||||
System.out.print("\n"+ new String(words[y])+": ");
|
||||
for(int x=0; x<words.length ;x++){ // psition i y
|
||||
// första vågräta ordet
|
||||
if(y == 0){
|
||||
if(words[0][x] != words[w][0]){
|
||||
matrix[w][y][x] = -1;
|
||||
}
|
||||
else{
|
||||
matrix[w][y][x] = 0;
|
||||
}
|
||||
}
|
||||
//resten av de vågräta orden
|
||||
else{
|
||||
if(matrix[w][y-1][x] < 0){
|
||||
matrix[w][y][x] = -1;
|
||||
}
|
||||
else{
|
||||
int 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(y == words.length-1){
|
||||
int tmp = matrix[w][y][x];
|
||||
if((tmp<shortest || shortest<0)
|
||||
&& 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<word.length ;i++){
|
||||
if(word[i] == cfind && (Math.abs(index-i)<minsta || minsta<0)){
|
||||
minsta = Math.abs(index-i);
|
||||
}
|
||||
}
|
||||
return minsta;
|
||||
}
|
||||
}
|
||||
17
src/zutil/algo/path/PathNode.java
Normal file
17
src/zutil/algo/path/PathNode.java
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package zutil.algo.path;
|
||||
|
||||
|
||||
public interface PathNode {
|
||||
|
||||
public void setVisited(boolean b);
|
||||
|
||||
public boolean visited();
|
||||
|
||||
public Iterable<PathNode> getNeighbors();
|
||||
|
||||
public int getNeighborCost(PathNode neighbor);
|
||||
|
||||
public void setSourceNeighbor(PathNode neighbor);
|
||||
|
||||
public PathNode getSourceNeighbor();
|
||||
}
|
||||
38
src/zutil/algo/path/PathNodeDefault.java
Normal file
38
src/zutil/algo/path/PathNodeDefault.java
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package zutil.algo.path;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class PathNodeDefault implements PathNode{
|
||||
private HashMap<PathNode,Integer> neighbors;
|
||||
private PathNode neighbor;
|
||||
private boolean visited;
|
||||
|
||||
public PathNodeDefault(){
|
||||
neighbors = new HashMap<PathNode,Integer>();
|
||||
visited = false;
|
||||
}
|
||||
|
||||
public void setVisited(boolean b){
|
||||
visited = b;
|
||||
}
|
||||
|
||||
public int getNeighborCost(PathNode neighbor) {
|
||||
return neighbors.get(neighbor);
|
||||
}
|
||||
|
||||
public Iterable<PathNode> getNeighbors() {
|
||||
return neighbors.keySet();
|
||||
}
|
||||
|
||||
public boolean visited() {
|
||||
return visited;
|
||||
}
|
||||
|
||||
public void setSourceNeighbor(PathNode n) {
|
||||
neighbor = n;
|
||||
}
|
||||
|
||||
public PathNode getSourceNeighbor() {
|
||||
return neighbor;
|
||||
}
|
||||
}
|
||||
95
src/zutil/algo/path/SimplePathFinder.java
Normal file
95
src/zutil/algo/path/SimplePathFinder.java
Normal file
|
|
@ -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<PathNode> BreadthFirstSearch(PathNode start, PathNode stop){
|
||||
Queue<PathNode> queue = new LinkedList<PathNode>();
|
||||
|
||||
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<PathNode> path = new LinkedList<PathNode>();
|
||||
for(PathNode current=stop; !current.equals(start) ;current = current.getSourceNeighbor()){
|
||||
path.addFirst(current);
|
||||
}
|
||||
path.addFirst(start);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new LinkedList<PathNode>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first path to the destination
|
||||
*
|
||||
* @param start Start Node
|
||||
* @param stop Stop Node
|
||||
* @return A list with the path
|
||||
*/
|
||||
public LinkedList<PathNode> DepthFirstSearch(PathNode start, PathNode stop){
|
||||
LinkedList<PathNode> path = new LinkedList<PathNode>();
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
252
src/zutil/algo/sort/ExternalSort.java
Normal file
252
src/zutil/algo/sort/ExternalSort.java
Normal file
|
|
@ -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<File> chunkFiles = sortChunks();
|
||||
|
||||
//merging the chunks
|
||||
mergeFiles(chunkFiles);
|
||||
|
||||
//removing the chunks
|
||||
removeFiles(chunkFiles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges all the files to one
|
||||
* @param files
|
||||
*/
|
||||
private void mergeFiles(LinkedList<File> 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<files.size(); i++){
|
||||
chunkReader[i] = new BufferedReader(new FileReader(files.get(i)));
|
||||
|
||||
// get the first row
|
||||
String line = chunkReader[i].readLine();
|
||||
if (line != null){
|
||||
rows[i] = line;
|
||||
someFileStillHasRows = true;
|
||||
}
|
||||
else{
|
||||
rows[i] = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
String row;
|
||||
while (someFileStillHasRows){
|
||||
String min;
|
||||
int minIndex = 0;
|
||||
|
||||
row = rows[0];
|
||||
if (row!=null) {
|
||||
min = row;
|
||||
minIndex = 0;
|
||||
}
|
||||
else {
|
||||
min = null;
|
||||
minIndex = -1;
|
||||
}
|
||||
|
||||
// check which one is minimum
|
||||
for(int i=1; i<rows.length ;i++){
|
||||
row = rows[i];
|
||||
if (min!=null) {
|
||||
|
||||
if(row!=null && row.compareTo(min) < 0){
|
||||
minIndex = i;
|
||||
min = row;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(row!=null){
|
||||
min = row;
|
||||
minIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (minIndex < 0) {
|
||||
someFileStillHasRows = false;
|
||||
}
|
||||
else{
|
||||
// write to the sorted file
|
||||
out.append(rows[minIndex]);
|
||||
out.newLine();
|
||||
|
||||
// get another row from the file that had the min
|
||||
String line = chunkReader[minIndex].readLine();
|
||||
if (line != null){
|
||||
rows[minIndex] = line;
|
||||
}
|
||||
else{
|
||||
rows[minIndex] = null;
|
||||
}
|
||||
}
|
||||
|
||||
// check if one still has rows
|
||||
someFileStillHasRows = false;
|
||||
for(int i=0; i<rows.length ; i++){
|
||||
if(rows[i] != null){
|
||||
if (minIndex < 0){
|
||||
throw(new IOException("Error sorting!!!"));
|
||||
}
|
||||
someFileStillHasRows = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check the actual files one more time
|
||||
if (!someFileStillHasRows){
|
||||
//write the last one not covered above
|
||||
for(int i=0; i<rows.length ; i++){
|
||||
if (rows[i] == null){
|
||||
String line = chunkReader[i].readLine();
|
||||
if (line != null){
|
||||
someFileStillHasRows=true;
|
||||
rows[i] = line;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// close all the files
|
||||
out.close();
|
||||
for(int i=0; i<chunkReader.length ; i++){
|
||||
chunkReader[i].close();
|
||||
}
|
||||
}
|
||||
catch (Exception ex){
|
||||
ex.printStackTrace();
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the chunk files and returns a LinkedList
|
||||
* with all the files
|
||||
* @return A linkedList with the files
|
||||
* @throws IOException Some kind of error
|
||||
*/
|
||||
private LinkedList<File> sortChunks() throws IOException{
|
||||
LinkedList<File> chunkFiles = new LinkedList<File>();
|
||||
LinkedList<String> chunk = new LinkedList<String>();
|
||||
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<String> readChunk(BufferedReader in) throws IOException{
|
||||
LinkedList<String> list = new LinkedList<String>();
|
||||
String tmp;
|
||||
for(int i=0; i<CHUNK_SIZE ;i++){
|
||||
tmp = in.readLine();
|
||||
if(tmp == null) break;
|
||||
list.add(tmp);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writs a chunk of strings to a file
|
||||
*
|
||||
* @param list The list to write down
|
||||
* @param file The file to write to
|
||||
* @throws IOException Some kind of error
|
||||
*/
|
||||
private void writeChunk(LinkedList<String> list, File file) throws IOException{
|
||||
BufferedWriter out = new BufferedWriter(new FileWriter(file));
|
||||
Iterator<String> it = list.iterator();
|
||||
while(it.hasNext()){
|
||||
out.write(it.next());
|
||||
out.newLine();
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
|
||||
private void removeFiles(LinkedList<File> list){
|
||||
Iterator<File> it = list.iterator();
|
||||
while(it.hasNext()){
|
||||
it.next().delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
106
src/zutil/algo/sort/QuickSort.java
Normal file
106
src/zutil/algo/sort/QuickSort.java
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
25
src/zutil/algo/sort/Randomizer.java
Normal file
25
src/zutil/algo/sort/Randomizer.java
Normal file
|
|
@ -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; i<size ;i++){
|
||||
list.swap(i, (int)(Math.random()*size));
|
||||
}
|
||||
}
|
||||
}
|
||||
67
src/zutil/algo/sort/SimpleSort.java
Normal file
67
src/zutil/algo/sort/SimpleSort.java
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
package zutil.algo.sort;
|
||||
|
||||
import zutil.algo.sort.sortable.SortableDataList;
|
||||
|
||||
/**
|
||||
* A collection of sorting algorithms for arrays of integers.
|
||||
*
|
||||
* @author Ziver Koc
|
||||
* @version 2006-10-31
|
||||
*/
|
||||
public class SimpleSort{
|
||||
|
||||
/**
|
||||
* Sort the elements in ascending order using selection sort.
|
||||
* This algorithm has time complexity Theta(n*n), where n is
|
||||
* the length of the array.
|
||||
*
|
||||
* @param list A list to sort.
|
||||
* @return The same array sorted in ascending order.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static SortableDataList selectionSort(SortableDataList list){
|
||||
int n = list.size();
|
||||
for (int i = 0; i < n - 1; i++) {
|
||||
// find index m of min element in v[i..n-1]
|
||||
int m = i;
|
||||
for (int j = i + 1; j < n; j++) {
|
||||
if (list.compare(j, m) < 0)
|
||||
m = j;
|
||||
}
|
||||
// swap v[i] and v[m]
|
||||
list.swap(i, m);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the elements in ascending order using insertionsort.
|
||||
*
|
||||
* @param A A list to sort.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static SortableDataList insertionSort(SortableDataList list){
|
||||
return insertionSort(list, 0, list.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the elements in ascending order using insertionsort.
|
||||
*
|
||||
* @param A An array of integers.
|
||||
* @param start The index to start from
|
||||
* @param stop The index to stop
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static SortableDataList insertionSort(SortableDataList list, int start, int stop){
|
||||
for(int i=start; i<stop ;i++){
|
||||
for(int j=i; j>start ;j--){
|
||||
if(list.compare(j, j-1) < 0){
|
||||
list.swap(j, j-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
42
src/zutil/algo/sort/sortable/SortableArrayList.java
Normal file
42
src/zutil/algo/sort/sortable/SortableArrayList.java
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
package zutil.algo.sort.sortable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class SortableArrayList<T> implements SortableDataList<T>{
|
||||
private ArrayList<T> list;
|
||||
|
||||
public SortableArrayList(ArrayList<T> 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
47
src/zutil/algo/sort/sortable/SortableComparableArray.java
Normal file
47
src/zutil/algo/sort/sortable/SortableComparableArray.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package zutil.algo.sort.sortable;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class SortableComparableArray implements SortableDataList<Comparable>{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
50
src/zutil/algo/sort/sortable/SortableDataList.java
Normal file
50
src/zutil/algo/sort/sortable/SortableDataList.java
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package zutil.algo.sort.sortable;
|
||||
|
||||
public interface SortableDataList<T>{
|
||||
|
||||
/**
|
||||
* 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 a<b ,
|
||||
* >0 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 a<b ,
|
||||
* >0 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);
|
||||
|
||||
}
|
||||
46
src/zutil/algo/sort/sortable/SortableIntArray.java
Normal file
46
src/zutil/algo/sort/sortable/SortableIntArray.java
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
package zutil.algo.sort.sortable;
|
||||
|
||||
public class SortableIntArray implements SortableDataList<Integer>{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
42
src/zutil/algo/sort/sortable/SortableLinkedList.java
Normal file
42
src/zutil/algo/sort/sortable/SortableLinkedList.java
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
package zutil.algo.sort.sortable;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class SortableLinkedList<T> implements SortableDataList<T>{
|
||||
private LinkedList<T> list;
|
||||
|
||||
public SortableLinkedList(LinkedList<T> 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
BIN
src/zutil/data/JavaConsole.png
Normal file
BIN
src/zutil/data/JavaConsole.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
76
src/zutil/db/MySQLConnection.java
Normal file
76
src/zutil/db/MySQLConnection.java
Normal file
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
}
|
||||
181
src/zutil/db/MySQLQueue.java
Normal file
181
src/zutil/db/MySQLQueue.java
Normal file
|
|
@ -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<E> implements Queue<E>{
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
210
src/zutil/image/ImageFilterProcessor.java
Normal file
210
src/zutil/image/ImageFilterProcessor.java
Normal file
|
|
@ -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<rows ;y++){
|
||||
// reading a row
|
||||
int[] aRow = new int[cols];
|
||||
for(int x=0; x<cols ;x++){
|
||||
int element = y * cols + x;
|
||||
aRow[x] = pixels[element];
|
||||
}
|
||||
|
||||
// Reading in the color data
|
||||
for(int x=0; x<cols ;x++){
|
||||
//Alpha data
|
||||
data[y][x][0] = (aRow[x] >> 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<rows ;y++){
|
||||
for(int x=0; x< cols ;x++){
|
||||
data[index] = ((pixels[y][x][0] << 24) & 0xFF000000)
|
||||
| ((pixels[y][x][1] << 16) & 0x00FF0000)
|
||||
| ((pixels[y][x][2] << 8) & 0x0000FF00)
|
||||
| ((pixels[y][x][3]) & 0x000000FF);
|
||||
index++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BufferedImage img = new BufferedImage(cols, rows, BufferedImage.TYPE_4BYTE_ABGR);
|
||||
img.setRGB(0, 0, cols, rows, data, 0, cols);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the given array to a new one that it returns
|
||||
* @param data The data to duplicate
|
||||
* @param cols The amount of columns
|
||||
* @param rows The amount of rows
|
||||
* @return The array copy
|
||||
*/
|
||||
public static int[][][] copyArray(int[][][] data,int cols,int rows){
|
||||
int[][][] copy = new int[rows][cols][4];
|
||||
for(int y=0; y<rows ;y++){
|
||||
for(int x=0; x<cols ;x++){
|
||||
copy[y][x][0] = data[y][x][0];
|
||||
copy[y][x][1] = data[y][x][1];
|
||||
copy[y][x][2] = data[y][x][2];
|
||||
copy[y][x][3] = data[y][x][3];
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method clips the values of the pixel so that they
|
||||
* are in the range 0-255
|
||||
* @param data The image data
|
||||
* @param cols The amount of columns
|
||||
* @param rows The amount of rows
|
||||
*/
|
||||
public static void clip(int[][][] data, int cols, int rows){
|
||||
for(int y=0; y<rows ;y++){
|
||||
for(int x=0; x<cols ;x++){
|
||||
data[y][x][1] = clip(data[y][x][1]);
|
||||
data[y][x][1] = clip(data[y][x][2]);
|
||||
data[y][x][1] = clip(data[y][x][3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method clips the values of a color so that it
|
||||
* is in the range 0-255
|
||||
* @param color
|
||||
* @return
|
||||
*/
|
||||
public static int clip(int color){
|
||||
if(color < 0)
|
||||
return 0;
|
||||
else if(color > 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);
|
||||
}
|
||||
170
src/zutil/image/ImageUtil.java
Normal file
170
src/zutil/image/ImageUtil.java
Normal file
|
|
@ -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<rows ;y++){
|
||||
for(int x=0; x<cols ;x++){
|
||||
if(data[y][x][1] > 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<rows ;y++){
|
||||
for(int x=0; x<cols ;x++){
|
||||
data[y][x][1] = (int)(data[y][x][1] * scale);
|
||||
data[y][x][2] = (int)(data[y][x][2] * scale);
|
||||
data[y][x][3] = (int)(data[y][x][3] * scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rms value of the image
|
||||
* (The RMS value is a measure of the width of the color distribution.)
|
||||
*
|
||||
* @param data The image data
|
||||
* @param cols The number of columns
|
||||
* @param rows The number of rows
|
||||
* @return The rms value for the image
|
||||
*/
|
||||
public static int rms(int[][][] data, int cols, int rows){
|
||||
int pixelCount = 0;
|
||||
long accum = 0;
|
||||
for(int y=0; y <rows ;y++){
|
||||
for(int x=0; x<cols ;x++){
|
||||
accum += data[y][x][1] * data[y][x][1];
|
||||
accum += data[y][x][2] * data[y][x][2];
|
||||
accum += data[y][x][3] * data[y][x][3];
|
||||
pixelCount += 3;
|
||||
}
|
||||
}
|
||||
int meanSquare = (int)(accum/pixelCount);
|
||||
int rms = (int)(Math.sqrt(meanSquare));
|
||||
return rms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies the given image data by the given value
|
||||
*
|
||||
* @param data The image data
|
||||
* @param cols The number of columns
|
||||
* @param rows The number of rows
|
||||
* @param scale The number to scale the image by
|
||||
*/
|
||||
public static void scale(int[][][] data, int cols, int rows, double scale){
|
||||
for(int y=0; y<rows ;y++){
|
||||
for(int x=0; x<cols ;x++){
|
||||
data[y][x][1] *= scale;
|
||||
data[y][x][2] *= scale;
|
||||
data[y][x][3] *= scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mean value of the given image data
|
||||
*
|
||||
* @param data The image data
|
||||
* @param cols The column count
|
||||
* @param rows The row count
|
||||
* @return The mean value of the image
|
||||
*/
|
||||
public static int meanValue(int[][][] data,int cols, int rows){
|
||||
int pixelCount = 0;
|
||||
long accum = 0;
|
||||
for(int y=0; y<rows ;y++){
|
||||
for(int x=0; x<cols ;x++){
|
||||
accum += data[y][x][1];
|
||||
accum += data[y][x][2];
|
||||
accum += data[y][x][3];
|
||||
pixelCount += 3;
|
||||
}
|
||||
}
|
||||
// calculate the mean value
|
||||
return (int)(accum/pixelCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the mean value to the image data
|
||||
*
|
||||
* @param data The image data
|
||||
* @param cols The number of columns
|
||||
* @param rows The number of rows
|
||||
* @param mean The mean value
|
||||
*/
|
||||
public static void addMeanValue(int[][][] data,int cols, int rows, int mean){
|
||||
for(int y=0; y<rows ;y++){
|
||||
for(int x=0; x<cols ;x++){
|
||||
data[y][x][1] += mean;
|
||||
data[y][x][2] += mean;
|
||||
data[y][x][3] += mean;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all the pixel data from the image to the new array
|
||||
*
|
||||
* @param data The data to copy
|
||||
* @param xStart X start position on the source
|
||||
* @param yStart Y start position on the source
|
||||
* @param width The amount of pixels to copy
|
||||
* @param hight The amount of pixels to copy
|
||||
* @return A copy of the data array
|
||||
*/
|
||||
public static int[][][] crop(int[][][] data, int xStart, int yStart, int width, int hight){
|
||||
return crop(data, xStart, yStart, null, 0, 0, width, hight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all the pixel data from the image to the new array
|
||||
*
|
||||
* @param data The data to copy
|
||||
* @param xData X start position in the source
|
||||
* @param yData Y start position in the source
|
||||
* @param crop The destination
|
||||
* @param xCrop X start position in the destination
|
||||
* @param yCrop Y start position in the destination
|
||||
* @param width The amount of pixels to copy
|
||||
* @param hight The amount of pixels to copy
|
||||
* @return A copy of the data array
|
||||
*/
|
||||
public static int[][][] crop(int[][][] data, int xData, int yData, int[][][] crop, int xCrop, int yCrop, int width, int hight){
|
||||
if(crop==null) crop = new int[width][hight][4];
|
||||
for(int y=0; y<width ;y++){
|
||||
for(int x=0; x<hight ;x++){
|
||||
crop[y+yData][x+xData][0] = data[y+yCrop][x+xCrop][0];
|
||||
crop[y+yData][x+xData][1] = data[y+yCrop][x+xCrop][1];
|
||||
crop[y+yData][x+xData][2] = data[y+yCrop][x+xCrop][2];
|
||||
crop[y+yData][x+xData][3] = data[y+yCrop][x+xCrop][3];
|
||||
}
|
||||
}
|
||||
return crop;
|
||||
}
|
||||
}
|
||||
88
src/zutil/image/filters/BlurFilter.java
Normal file
88
src/zutil/image/filters/BlurFilter.java
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
package zutil.image.filters;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import zutil.image.ImageFilterProcessor;
|
||||
import zutil.image.ImageUtil;
|
||||
import zutil.math.ZMath;
|
||||
|
||||
public class BlurFilter extends ImageFilterProcessor{
|
||||
private int blurValue;
|
||||
|
||||
/**
|
||||
* Creates a blur effect on the image
|
||||
* @param img The image to blur
|
||||
*/
|
||||
public BlurFilter(BufferedImage img){
|
||||
this(img, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a blur effect on the image
|
||||
* @param img The image to blur
|
||||
* @param blur The amount to blur
|
||||
*/
|
||||
public BlurFilter(BufferedImage img, int blur){
|
||||
super(img);
|
||||
blurValue = blur;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[][][] process(final int[][][] data, int cols, int rows) {
|
||||
int inputPeak = ImageUtil.peakValue(data, cols, rows);
|
||||
|
||||
int[][][] output = new int[rows][cols][4];
|
||||
//Perform the convolution one or more times
|
||||
// in succession
|
||||
for(int i=0; i<blurValue ;i++){
|
||||
//Iterate on each pixel as a registration
|
||||
// point.
|
||||
for(int y=1; y<rows-2 ;y++){
|
||||
setProgress(ZMath.percent(0, (blurValue-1)*(rows-3), i*(rows-3)+y));
|
||||
for(int x=0+1; x<cols-2 ;x++){
|
||||
int redSum =
|
||||
data[y - 1][x - 1][1] +
|
||||
data[y - 1][x - 0][1] +
|
||||
data[y - 1][x + 1][1] +
|
||||
data[y - 0][x - 1][1] +
|
||||
data[y - 0][x - 0][1] +
|
||||
data[y - 0][x + 1][1] +
|
||||
data[y + 1][x - 1][1] +
|
||||
data[y + 1][x - 0][1] +
|
||||
data[y + 1][x + 1][1];
|
||||
int greenSum =
|
||||
data[y - 1][x - 1][2] +
|
||||
data[y - 1][x - 0][2] +
|
||||
data[y - 1][x + 1][2] +
|
||||
data[y - 0][x - 1][2] +
|
||||
data[y - 0][x - 0][2] +
|
||||
data[y - 0][x + 1][2] +
|
||||
data[y + 1][x - 1][2] +
|
||||
data[y + 1][x - 0][2] +
|
||||
data[y + 1][x + 1][2];
|
||||
int blueSum =
|
||||
data[y - 1][x - 1][3] +
|
||||
data[y - 1][x - 0][3] +
|
||||
data[y - 1][x + 1][3] +
|
||||
data[y - 0][x - 1][3] +
|
||||
data[y - 0][x - 0][3] +
|
||||
data[y - 0][x + 1][3] +
|
||||
data[y + 1][x - 1][3] +
|
||||
data[y + 1][x - 0][3] +
|
||||
data[y + 1][x + 1][3];
|
||||
|
||||
output[y][x][0] = data[y][x][0];
|
||||
output[y][x][1] = redSum;
|
||||
output[y][x][2] = greenSum;
|
||||
output[y][x][3] = blueSum;
|
||||
}
|
||||
}
|
||||
|
||||
// getting the new peak value and normalizing the image
|
||||
int outputPeak = ImageUtil.peakValue(output, cols, rows);
|
||||
ImageUtil.normalize(output, cols, rows, ((double)inputPeak)/outputPeak );
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
90
src/zutil/image/filters/ColorIntensityFilter.java
Normal file
90
src/zutil/image/filters/ColorIntensityFilter.java
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
package zutil.image.filters;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import zutil.image.ImageFilterProcessor;
|
||||
import zutil.math.ZMath;
|
||||
|
||||
public class ColorIntensityFilter extends ImageFilterProcessor{
|
||||
private boolean invert;
|
||||
private int redScale;
|
||||
private int greenScale;
|
||||
private int blueScale;
|
||||
|
||||
public ColorIntensityFilter(BufferedImage img){
|
||||
this(img, 50, 50, 50, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ColorIntensityEffect object with the given values
|
||||
* @param img The image data
|
||||
* @param inv If the image color should be inverted
|
||||
*/
|
||||
public ColorIntensityFilter(BufferedImage img, boolean inv){
|
||||
this(img, 100, 100, 100, inv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ColorIntensityEffect object with the given values
|
||||
* @param img The image data
|
||||
* @param red The scale of red (0-100)
|
||||
* @param green The scale of green (0-100)
|
||||
* @param blue The scale of blue (0-100)
|
||||
*/
|
||||
public ColorIntensityFilter(BufferedImage img, int red, int green, int blue){
|
||||
this(img, red, green, blue, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ColorIntensityEffect object with the given values
|
||||
* @param img The image data
|
||||
* @param red The scale of red (0-100)
|
||||
* @param green The scale of green (0-100)
|
||||
* @param blue The scale of blue (0-100)
|
||||
* @param inv If the image color should be inverted
|
||||
*/
|
||||
public ColorIntensityFilter(BufferedImage img, int red, int green, int blue, boolean inv){
|
||||
super(img);
|
||||
invert = false;
|
||||
redScale = red;
|
||||
greenScale = green;
|
||||
blueScale = blue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[][][] process(final int[][][] data, int cols, int rows) {
|
||||
// making sure the scales are right
|
||||
if(redScale > 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<rows ;y++){
|
||||
setProgress(ZMath.percent(0, rows-1, y));
|
||||
for(int x=0; x<cols ;x++){
|
||||
if(!invert){
|
||||
// inversion
|
||||
output[y][x][0] = data[y][x][0];
|
||||
output[y][x][1] = 255 - data[y][x][1] * redScale/100;
|
||||
output[y][x][2] = 255 - data[y][x][2] * greenScale/100;
|
||||
output[y][x][3] = 255 - data[y][x][3] * blueScale/100;
|
||||
}
|
||||
else{
|
||||
output[y][x][0] = data[y][x][0];
|
||||
output[y][x][1] = data[y][x][1] * redScale/100;
|
||||
output[y][x][2] = data[y][x][2] * greenScale/100;
|
||||
output[y][x][3] = data[y][x][3] * blueScale/100;
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
47
src/zutil/image/filters/ContrastBrightnessFilter.java
Normal file
47
src/zutil/image/filters/ContrastBrightnessFilter.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package zutil.image.filters;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import zutil.image.ImageFilterProcessor;
|
||||
import zutil.image.ImageUtil;
|
||||
|
||||
public class ContrastBrightnessFilter extends ImageFilterProcessor{
|
||||
private double contrast;
|
||||
private double brightness;
|
||||
|
||||
/**
|
||||
* Creates a ContrastBrightnessEffect object with the given values
|
||||
* @param img The image to apply the effect to
|
||||
*/
|
||||
public ContrastBrightnessFilter(BufferedImage img){
|
||||
this(img, 3, 1.2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ContrastBrightnessEffect object with the given values
|
||||
* @param img The image to apply the effect to
|
||||
* @param con The contrast to apply
|
||||
* @param brig The brightness to apply
|
||||
*/
|
||||
public ContrastBrightnessFilter(BufferedImage img, double con, double brig){
|
||||
super(img);
|
||||
contrast = con;
|
||||
brightness = brig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[][][] process(final int[][][] data, int cols, int rows) {
|
||||
int mean = ImageUtil.meanValue(data, cols, rows);
|
||||
|
||||
int[][][] output = copyArray(data, cols, rows);
|
||||
|
||||
ImageUtil.addMeanValue(output, cols, rows, mean*(-1));
|
||||
ImageUtil.scale(output, cols, rows, contrast);
|
||||
ImageUtil.addMeanValue(output, cols, rows, (int)(brightness*mean));
|
||||
|
||||
clip(output , cols, rows);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
87
src/zutil/image/filters/DitheringFilter.java
Normal file
87
src/zutil/image/filters/DitheringFilter.java
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
package zutil.image.filters;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import zutil.image.ImageFilterProcessor;
|
||||
import zutil.math.ZMath;
|
||||
|
||||
|
||||
public class DitheringFilter extends ImageFilterProcessor{
|
||||
// default palette is black and white
|
||||
private int[][] palette = {
|
||||
{255,0,0,0},
|
||||
{255,255,255,255}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets up a default DitheringEffect
|
||||
*/
|
||||
public DitheringFilter(BufferedImage img){
|
||||
super(img);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Dithering Effect object
|
||||
* @param img The image to apply the effect on
|
||||
* @param palette The palette to use on the image
|
||||
* int[colorCount][4]
|
||||
* 0 -> 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<rows ;y++){
|
||||
setProgress(ZMath.percent(0, rows-1, y));
|
||||
for(int x=0; x<cols ;x++){
|
||||
currentPixel = output[y][x];
|
||||
index = findNearestColor(currentPixel, palette);
|
||||
output[y][x] = palette[index];
|
||||
|
||||
for (int i = 1; i < 4; i++) {
|
||||
error = currentPixel[i] - palette[index][i];
|
||||
if (x + 1 < cols) {
|
||||
output[y+0][x+1][i] = clip( output[y+0][x+1][i] + (error*7)/16 );
|
||||
}
|
||||
if (y + 1 < rows) {
|
||||
if (x - 1 > 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;
|
||||
}
|
||||
}
|
||||
171
src/zutil/image/filters/FaceDetectionFilter.java
Normal file
171
src/zutil/image/filters/FaceDetectionFilter.java
Normal file
|
|
@ -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<rows ;y++){
|
||||
for(int x=0; x<cols ;x++){
|
||||
textureMap[y][x][1] = Math.abs(IRgBy[y][x][1]-textureMap[y][x][1]);
|
||||
}
|
||||
}
|
||||
|
||||
median = new MedianFilter(null, 12*getSCALE(cols,rows), new boolean[]{false,true,false,false});
|
||||
textureMap = median.process(textureMap, cols, rows);
|
||||
setProgress(ZMath.percent(0, 4, 2));
|
||||
|
||||
//*********** Hue & Saturation *********
|
||||
int[][] skinMap = new int[rows][cols];
|
||||
int[][] hueMap = new int[rows][cols];
|
||||
int[][] saturationMap = new int[rows][cols];
|
||||
|
||||
int hue, saturation;
|
||||
for(int y=0; y<rows ;y++){
|
||||
for(int x=0; x<cols ;x++){
|
||||
// hue = (atan^2(Rg,By))
|
||||
hue = (int)( Math.atan2(IRgBy[y][x][2], IRgBy[y][x][3]) * 360/2*Math.PI);
|
||||
// saturation = sqrt(Rg^2+By^2)
|
||||
saturation = (int) Math.sqrt(IRgBy[y][x][2]*IRgBy[y][x][2] + IRgBy[y][x][3]*IRgBy[y][x][3]);
|
||||
|
||||
hueMap[y][x] = hue;
|
||||
saturationMap[y][x] = saturation;
|
||||
|
||||
// (1) texture<4.5, 120<160, 10<60
|
||||
// (2) texture<4.5, 150<180, 20<80
|
||||
if((textureMap[y][x][1] < 4.5 && (hue >= 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<rows ;y++){
|
||||
for(int x=0; x<cols ;x++){
|
||||
if(data[y][x] == 1){
|
||||
|
||||
for(int dy=y-radY; dy<y+radY ;dy++){
|
||||
for(int dx=x-radX; dx<x+radX ;dx++){
|
||||
if(dy >= 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<rows ;y++){
|
||||
for(int x=0; x<cols ;x++){
|
||||
output[y][x][0] = 255;
|
||||
output[y][x][channel] = (int) ZMath.percent(min, max, data[y][x]);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts RGB color to log-opponent (IRgBy) with the formula:
|
||||
* I= [L(R)+L(B)+L(G)]/3
|
||||
* Rg = L(R)-L(G)
|
||||
* By = L(B)-[L(G)+L(R)]/2
|
||||
*
|
||||
* @param data The RGB data
|
||||
* @param cols The number of columns
|
||||
* @param rows The number of rows
|
||||
* @return IRgBy data
|
||||
*/
|
||||
public int[][][] convertARGBToIRgBy(int[][][] data, int cols, int rows){
|
||||
int[][][] output = new int[rows][cols][4];
|
||||
|
||||
for(int y=0; y<rows ;y++){
|
||||
for(int x=0; x<cols ;x++){
|
||||
output[y][x][0] = data[y][x][0];
|
||||
// I= [L(R)+L(B)+L(G)]/3
|
||||
output[y][x][1] = (
|
||||
IRgByFunction(data[y][x][1]) +
|
||||
IRgByFunction(data[y][x][2]) +
|
||||
IRgByFunction(data[y][x][3])
|
||||
) / 3;
|
||||
// Rg = L(R)-L(G)
|
||||
output[y][x][2] = IRgByFunction(output[y][x][1]) - IRgByFunction(data[y][x][2]);
|
||||
// By = L(B)-[L(G)+L(R)]/2
|
||||
output[y][x][3] = IRgByFunction(output[y][x][3]) -
|
||||
(IRgByFunction(output[y][x][2]) - IRgByFunction(output[y][x][1])) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
// Helper function to convertToIRgBy()
|
||||
private int IRgByFunction(int value){
|
||||
return (int)(105*Math.log10(value+1));
|
||||
}
|
||||
|
||||
|
||||
private int getSCALE(int cols, int rows){
|
||||
return (cols+rows)/320;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Rectangle getFaceRectangle(){
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
169
src/zutil/image/filters/MedianFilter.java
Normal file
169
src/zutil/image/filters/MedianFilter.java
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
package zutil.image.filters;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import zutil.algo.sort.sortable.SortableDataList;
|
||||
import zutil.image.ImageFilterProcessor;
|
||||
import zutil.math.ZMath;
|
||||
|
||||
/**
|
||||
* The MedianFilter is used for noise reduction and things
|
||||
*
|
||||
* @author Ziver
|
||||
*/
|
||||
public class MedianFilter extends ImageFilterProcessor{
|
||||
private int windowSize;
|
||||
private boolean[] channels;
|
||||
|
||||
/**
|
||||
* Setup a default MedianFilter
|
||||
*
|
||||
* @param img The image to process
|
||||
*/
|
||||
public MedianFilter(BufferedImage img) {
|
||||
this(img, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a default MedianFilter
|
||||
*
|
||||
* @param img The image to process
|
||||
* @param pixels The size of the window
|
||||
*/
|
||||
public MedianFilter(BufferedImage img, int pixels) {
|
||||
this(img, pixels, new boolean[]{true,true,true,true});
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a default MedianFilter
|
||||
*
|
||||
* @param img The image to process
|
||||
* @param pixels The size of the window
|
||||
* @param channels Is a 4 element array for witch channels to use the filter on
|
||||
*/
|
||||
public MedianFilter(BufferedImage img, int pixels, boolean[] channels) {
|
||||
super(img);
|
||||
this.windowSize = pixels;
|
||||
this.channels = channels;
|
||||
}
|
||||
|
||||
/*
|
||||
edgex := (window width / 2) rounded down
|
||||
edgey := (window height / 2) rounded down
|
||||
for x from edgex to image width - edgex:
|
||||
for y from edgey to image height - edgey:
|
||||
colorArray[window width][window height];
|
||||
for fx from 0 to window width:
|
||||
for fy from 0 to window height:
|
||||
colorArray[fx][fy] := pixelvalue[x + fx - edgex][y + fy - edgey]
|
||||
Sort colorArray[][];
|
||||
pixelValue[x][y] := colorArray[window width / 2][window height / 2];
|
||||
*/
|
||||
@Override
|
||||
public int[][][] process(int[][][] data, int cols, int rows) {
|
||||
int[][][] output = new int[rows][cols][4];
|
||||
|
||||
int edgeX = windowSize / 2;
|
||||
int edgeY = windowSize / 2;
|
||||
|
||||
int[][] tmpArray = new int[4][256*2];
|
||||
int pixelCount = 0;
|
||||
for(int y=0; y<rows ;y++){
|
||||
setProgress(ZMath.percent(0, rows-1, y));
|
||||
for(int x=0; x<cols ;x++){
|
||||
|
||||
pixelCount = 0;
|
||||
for(int fy=0; fy<windowSize ;fy++){
|
||||
for(int fx=0; fx<windowSize ;fx++){
|
||||
if(y+fy-edgeY >= 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<median.length ;i++){
|
||||
sum += median[i];
|
||||
median[i] = 0;
|
||||
if(sum >= medianCount && ret == 0){
|
||||
ret = i-256;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
class SortableARGB implements SortableDataList<Integer>{
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
63
src/zutil/image/filters/ResizeImage.java
Normal file
63
src/zutil/image/filters/ResizeImage.java
Normal file
|
|
@ -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<width ;y++){
|
||||
setProgress(ZMath.percent(0, width-1, y));
|
||||
for(int x=0; x<hight ;x++){
|
||||
tmp[y][x][0] = data[(int)(y*yScale)][(int)(x*xScale)][0];
|
||||
tmp[y][x][1] = data[(int)(y*yScale)][(int)(x*xScale)][1];
|
||||
tmp[y][x][2] = data[(int)(y*yScale)][(int)(x*xScale)][2];
|
||||
tmp[y][x][3] = data[(int)(y*yScale)][(int)(x*xScale)][3];
|
||||
}
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
}
|
||||
73
src/zutil/image/filters/SpotLightFilter.java
Normal file
73
src/zutil/image/filters/SpotLightFilter.java
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
package zutil.image.filters;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import zutil.image.ImageFilterProcessor;
|
||||
import zutil.math.ZMath;
|
||||
|
||||
public class SpotLightFilter extends ImageFilterProcessor{
|
||||
private int radius;
|
||||
private int xPos;
|
||||
private int yPos;
|
||||
|
||||
/**
|
||||
* Sets up a default spotlight effect in
|
||||
* the middle of the image
|
||||
*/
|
||||
public SpotLightFilter(BufferedImage img){
|
||||
this(img, 100, -1, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a custom spotlight
|
||||
* @param r The radius of the spotlight in pixels
|
||||
*/
|
||||
public SpotLightFilter(BufferedImage img, int r){
|
||||
this(img, r, -1, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a custom spotlight
|
||||
* @param r The radius of the spotlight in pixels
|
||||
* @param x The x position of the spotlight, if -1 then it will be centered
|
||||
* @param y The y position of the spotlight, if -1 then it will be centered
|
||||
*/
|
||||
public SpotLightFilter(BufferedImage img, int r, int x, int y){
|
||||
super(img);
|
||||
radius = r;
|
||||
xPos = x;
|
||||
yPos = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[][][] process(final int[][][] data, int cols, int rows) {
|
||||
if(xPos < 0) xPos = cols/2;
|
||||
if(yPos < 0) yPos = rows/2;
|
||||
|
||||
int[][][] output = new int[rows][cols][4];
|
||||
double scale, dx, dy, distance;
|
||||
for(int y=0; y<rows ;y++){
|
||||
setProgress(ZMath.percent(0, rows-1, y));
|
||||
for(int x=0; x<cols ;x++){
|
||||
dx = x-xPos;
|
||||
dy = y-yPos;
|
||||
|
||||
distance = Math.sqrt(dx*dx+dy*dy);
|
||||
|
||||
if(distance > 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;
|
||||
}
|
||||
|
||||
}
|
||||
110
src/zutil/math/Tick.java
Normal file
110
src/zutil/math/Tick.java
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
src/zutil/math/ZMath.java
Normal file
16
src/zutil/math/ZMath.java
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
257
src/zutil/math/parser/MathParser.java
Normal file
257
src/zutil/math/parser/MathParser.java
Normal file
|
|
@ -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<tmp2 ;i++){
|
||||
ret *= tmp1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return math1.toString()+"^"+math2.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class EmptyMath extends MathOperation{
|
||||
public double exec() {
|
||||
return math1.exec();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return math1.toString();
|
||||
}
|
||||
}
|
||||
487
src/zutil/network/FTPClient.java
Normal file
487
src/zutil/network/FTPClient.java
Normal file
|
|
@ -0,0 +1,487 @@
|
|||
package zutil.network;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import javax.security.auth.login.AccountException;
|
||||
|
||||
import zutil.MultiPrintStream;
|
||||
|
||||
/**
|
||||
* A simple FTP client class
|
||||
*
|
||||
* @author Ziver
|
||||
*
|
||||
* http://en.wikipedia.org/wiki/List_of_FTP_commands
|
||||
* http://en.wikipedia.org/wiki/List_of_FTP_server_return_codes
|
||||
* http://www.ietf.org/rfc/rfc959.txt
|
||||
*
|
||||
* TODO: file info, rename, Active mode
|
||||
*/
|
||||
public class FTPClient extends Thread{
|
||||
public static final int FTP_ACTIVE = 0;
|
||||
public static final int FTP_PASSIVE = 1;
|
||||
public static final int FTP_PORT = 21;
|
||||
public static final int FTP_DATA_PORT = 20;
|
||||
public static final int FTP_NOOP_INT = 120;
|
||||
|
||||
//************** FTP Return Codes ******************
|
||||
public static final int FTPC_USER_OK = 331;
|
||||
public static final int FTPC_NEED_PASS = 331;
|
||||
public static final int FTPC_LOGIN_NO = 530;
|
||||
public static final int FTPC_LOGIN_OK = 230;
|
||||
|
||||
public static final int FTPC_ENTERING_PASSIVE = 227;
|
||||
public static final int FTPC_FILE_ACTION_OK = 250;
|
||||
public static final int FTPC_PATH_CREATED = 257;
|
||||
//***************************************************
|
||||
|
||||
private BufferedReader in;
|
||||
private PrintStream out;
|
||||
private Socket socket;
|
||||
private long last_sent;
|
||||
|
||||
public static void main(String[] args){
|
||||
try {
|
||||
FTPClient client = new FTPClient("koc.se", 21, "kth", "****", FTP_PASSIVE);
|
||||
client.createDir("./ziver/lol");
|
||||
client.removeDir("./ziver/lol");
|
||||
|
||||
MultiPrintStream.out.dump(client.getFileList("./ziver"));
|
||||
client.sendFile("./ziver/test.txt", "lol");
|
||||
MultiPrintStream.out.dump(client.getFileList("./ziver"));
|
||||
|
||||
MultiPrintStream.out.dump(client.getFile("./ziver/test.txt"));
|
||||
client.readCommand(true);
|
||||
|
||||
MultiPrintStream.out.println(client.getFileInfo("./ziver/test.txt"));
|
||||
|
||||
MultiPrintStream.out.dump(client.getFileList("./ziver"));
|
||||
client.removeFile("./ziver/test.txt");
|
||||
MultiPrintStream.out.dump(client.getFileList("./ziver"));
|
||||
|
||||
client.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a FTP connection and logs in
|
||||
*
|
||||
* @param url The address to server
|
||||
* @param port Port number
|
||||
* @param user User name
|
||||
* @param pass Password
|
||||
* @param connection_type Pasive or Active
|
||||
*/
|
||||
public FTPClient(String url, int port, String user, String pass, int connection_type) throws UnknownHostException, IOException, AccountException{
|
||||
socket = new Socket(url, port);
|
||||
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
out = new PrintStream(socket.getOutputStream());
|
||||
|
||||
readCommand(true);
|
||||
sendCommand("USER "+user);
|
||||
sendNoReplyCommand("PASS "+pass, false);
|
||||
System.out.println("PASS ***");
|
||||
String tmp = readMultipleCommands(true);
|
||||
if(parseReturnCode(tmp) == FTPC_LOGIN_NO){
|
||||
close();
|
||||
throw new AccountException(tmp);
|
||||
}
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
//**************************************************************************************
|
||||
//**************************************************************************************
|
||||
//********************************* Command channel ************************************
|
||||
|
||||
/**
|
||||
* Sends the given line to the server and returns a status integer
|
||||
*
|
||||
* @param cmd The command to send
|
||||
* @return The return code from the server
|
||||
* @throws IOException
|
||||
*/
|
||||
public synchronized int sendCommand(String cmd) throws IOException{
|
||||
return parseReturnCode(sendCommand(cmd, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the given line to the server and returns the last line
|
||||
*
|
||||
* @param cmd The command to send
|
||||
* @param print To print out the received lines
|
||||
* @return Last String line from the server
|
||||
* @throws IOException
|
||||
*/
|
||||
private synchronized String sendCommand(String cmd, boolean print) throws IOException{
|
||||
sendNoReplyCommand(cmd, print);
|
||||
return readCommand(print);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a given command and don't cares about the reply
|
||||
*
|
||||
* @param cmd The command
|
||||
* @param print If it should print to System.out
|
||||
* @throws IOException
|
||||
*/
|
||||
private synchronized void sendNoReplyCommand(String cmd, boolean print) throws IOException{
|
||||
out.println(cmd);
|
||||
last_sent = System.currentTimeMillis();
|
||||
if(print)System.out.println(cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads on line from the command channel
|
||||
*
|
||||
* @param print If the method should print the input line
|
||||
* @return The input line
|
||||
* @throws IOException
|
||||
*/
|
||||
private synchronized String readCommand(boolean print) throws IOException{
|
||||
String tmp = in.readLine();
|
||||
if(print)System.out.println(tmp);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads from the command channel until there are nothing
|
||||
* left to read and returns the last line
|
||||
* Multiple
|
||||
* @param print To print out the received lines
|
||||
* @return The last received line
|
||||
* @throws IOException
|
||||
*/
|
||||
private synchronized String readMultipleCommands(boolean print) throws IOException{
|
||||
String tmp = in.readLine();
|
||||
if(print)System.out.println(tmp);
|
||||
try{ Thread.sleep(500); }catch(Exception e){}
|
||||
while(in.ready()){
|
||||
tmp = in.readLine();
|
||||
if(print)System.out.println(tmp);
|
||||
try{ Thread.sleep(500); }catch(Exception e){}
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the return line from the server and returns the status code
|
||||
*
|
||||
* @param msg The message from the server
|
||||
* @return The status code
|
||||
* @throws IOException
|
||||
*/
|
||||
private synchronized int parseReturnCode(String msg){
|
||||
return Integer.parseInt(msg.substring(0, 3));
|
||||
}
|
||||
|
||||
//**************************************************************************************
|
||||
//**************************************************************************************
|
||||
//****************************** File system actions ************************************
|
||||
|
||||
/**
|
||||
* Returns a LinkedList with the names of all the files in the directory
|
||||
*
|
||||
* @param path Path to the files to be listed
|
||||
* @return LinkedList whit filenames
|
||||
* @throws IOException
|
||||
*/
|
||||
public LinkedList<String> getFileList(String path) throws IOException{
|
||||
LinkedList<String> list = new LinkedList<String>();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
73
src/zutil/network/ServerFind.java
Normal file
73
src/zutil/network/ServerFind.java
Normal file
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
50
src/zutil/network/ServerFindClient.java
Normal file
50
src/zutil/network/ServerFindClient.java
Normal file
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
134
src/zutil/network/UpdateClient.java
Normal file
134
src/zutil/network/UpdateClient.java
Normal file
|
|
@ -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<FileHash> 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();
|
||||
}
|
||||
}
|
||||
165
src/zutil/network/UpdateServer.java
Normal file
165
src/zutil/network/UpdateServer.java
Normal file
|
|
@ -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<FileHash> 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<FileHash> clientFileList = (ArrayList<FileHash>)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<FileHash> getFileList(String path) throws Exception{
|
||||
ArrayList<FileHash> fileHash = new ArrayList<FileHash>();
|
||||
|
||||
ArrayList<File> 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;
|
||||
}
|
||||
}
|
||||
232
src/zutil/network/Zupdater.java
Normal file
232
src/zutil/network/Zupdater.java
Normal file
|
|
@ -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.
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">
|
||||
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();
|
||||
}// </editor-fold>
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
28
src/zutil/network/http/HttpPage.java
Normal file
28
src/zutil/network/http/HttpPage.java
Normal file
|
|
@ -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<String,String> client_info,
|
||||
HashMap<String,String> session,
|
||||
HashMap<String,String> cookie,
|
||||
HashMap<String,String> request);
|
||||
}
|
||||
135
src/zutil/network/http/HttpPrintStream.java
Normal file
135
src/zutil/network/http/HttpPrintStream.java
Normal file
|
|
@ -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<String, String> cookie;
|
||||
private StringBuffer buffer;
|
||||
private boolean buffer_enabled;
|
||||
|
||||
public HttpPrintStream(OutputStream out) {
|
||||
super(out);
|
||||
|
||||
cookie = new HashMap<String, String>();
|
||||
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);}
|
||||
}
|
||||
282
src/zutil/network/http/HttpServer.java
Normal file
282
src/zutil/network/http/HttpServer.java
Normal file
|
|
@ -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<String,HttpPage> pages;
|
||||
private HttpPage defaultPage;
|
||||
private HashMap<String,HashMap<String,String>> 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<String,HttpPage>();
|
||||
sessions = new HashMap<String,HashMap<String,String>>();
|
||||
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<String,String> client_info = new HashMap<String,String>();
|
||||
HashMap<String,String> cookie = new HashMap<String,String>();
|
||||
HashMap<String,String> request = new HashMap<String,String>();
|
||||
|
||||
//**************************** 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<post_data_length ;i++){
|
||||
tmpb.append((char)in.read());
|
||||
}
|
||||
// get the variables
|
||||
parseVariables(tmpb.toString(), request);
|
||||
}
|
||||
else if(client_info.get("Content-Type").contains("multipart/form-data")){
|
||||
// TODO:
|
||||
throw new Exception("\"multipart/form-data\" Not implemented!!!");
|
||||
}
|
||||
}
|
||||
//*****************
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
try {
|
||||
out.sendHeader("HTTP/1.0 500 ERROR");
|
||||
} catch (Exception e1) {}
|
||||
out.println("500 Internal Error(Header: "+tmp+"): "+e.getMessage());
|
||||
}
|
||||
try {
|
||||
//**************************** HANDLE REQUEST *********************************
|
||||
// Get the client session or create one
|
||||
HashMap<String,String> 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<String,String>();
|
||||
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<String, String> 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<String, String> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
57
src/zutil/network/nio/NioClient.java
Normal file
57
src/zutil/network/nio/NioClient.java
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
433
src/zutil/network/nio/NioNetwork.java
Normal file
433
src/zutil/network/nio/NioNetwork.java
Normal file
|
|
@ -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<InetSocketAddress, ClientData> clients = new HashMap<InetSocketAddress, ClientData>();
|
||||
|
||||
// A list of PendingChange instances
|
||||
private List<ChangeRequest> pendingChanges = new LinkedList<ChangeRequest>();
|
||||
// Maps a SocketChannel to a list of ByteBuffer instances
|
||||
private Map<SocketChannel, List<ByteBuffer>> pendingData = new HashMap<SocketChannel, List<ByteBuffer>>();
|
||||
// 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<ByteBuffer> queue = pendingData.get(socket);
|
||||
if (queue == null) {
|
||||
queue = new ArrayList<ByteBuffer>();
|
||||
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<ChangeRequest> 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<SelectionKey> 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<ByteBuffer> queue = pendingData.get(socketChannel);
|
||||
if(queue == null){
|
||||
queue = new ArrayList<ByteBuffer>();
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
68
src/zutil/network/nio/NioServer.java
Normal file
68
src/zutil/network/nio/NioServer.java
Normal file
|
|
@ -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<InetSocketAddress> it = clients.keySet().iterator();
|
||||
while(it.hasNext()){
|
||||
send(it.next(), data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
45
src/zutil/network/nio/message/ChatMessage.java
Normal file
45
src/zutil/network/nio/message/ChatMessage.java
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
31
src/zutil/network/nio/message/GraphicsSyncMessage.java
Normal file
31
src/zutil/network/nio/message/GraphicsSyncMessage.java
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
16
src/zutil/network/nio/message/KeepAliveMessage.java
Normal file
16
src/zutil/network/nio/message/KeepAliveMessage.java
Normal file
|
|
@ -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;
|
||||
|
||||
}
|
||||
9
src/zutil/network/nio/message/Message.java
Normal file
9
src/zutil/network/nio/message/Message.java
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package zutil.network.nio.message;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Message implements Serializable{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
}
|
||||
34
src/zutil/network/nio/message/StringMessage.java
Normal file
34
src/zutil/network/nio/message/StringMessage.java
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
13
src/zutil/network/nio/message/SyncMessage.java
Normal file
13
src/zutil/network/nio/message/SyncMessage.java
Normal file
|
|
@ -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;
|
||||
}
|
||||
34
src/zutil/network/nio/message/type/EchoMessage.java
Normal file
34
src/zutil/network/nio/message/type/EchoMessage.java
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
|
||||
}
|
||||
12
src/zutil/network/nio/message/type/SystemMessage.java
Normal file
12
src/zutil/network/nio/message/type/SystemMessage.java
Normal file
|
|
@ -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 {
|
||||
|
||||
}
|
||||
12
src/zutil/network/nio/response/PrintRsp.java
Normal file
12
src/zutil/network/nio/response/PrintRsp.java
Normal file
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
43
src/zutil/network/nio/response/ResponseEvent.java
Normal file
43
src/zutil/network/nio/response/ResponseEvent.java
Normal file
|
|
@ -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);
|
||||
}
|
||||
41
src/zutil/network/nio/response/ResponseHandler.java
Normal file
41
src/zutil/network/nio/response/ResponseHandler.java
Normal file
|
|
@ -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<ResponseEvent> queue = new LinkedList<ResponseEvent>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/zutil/network/nio/server/ChangeRequest.java
Normal file
18
src/zutil/network/nio/server/ChangeRequest.java
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
29
src/zutil/network/nio/server/ClientData.java
Normal file
29
src/zutil/network/nio/server/ClientData.java
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
10
src/zutil/network/nio/service/ChatListener.java
Normal file
10
src/zutil/network/nio/service/ChatListener.java
Normal file
|
|
@ -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);
|
||||
}
|
||||
121
src/zutil/network/nio/service/ChatService.java
Normal file
121
src/zutil/network/nio/service/ChatService.java
Normal file
|
|
@ -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<String,LinkedList<SocketChannel>> rooms;
|
||||
private ChatListener listener;
|
||||
|
||||
public ChatService(NioNetwork nio){
|
||||
super(nio);
|
||||
rooms = new HashMap<String,LinkedList<SocketChannel>>();
|
||||
}
|
||||
|
||||
@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<SocketChannel> 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<SocketChannel>());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
25
src/zutil/network/nio/service/NetworkService.java
Normal file
25
src/zutil/network/nio/service/NetworkService.java
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
28
src/zutil/network/nio/service/sync/ObjectSync.java
Normal file
28
src/zutil/network/nio/service/sync/ObjectSync.java
Normal file
|
|
@ -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();
|
||||
}
|
||||
58
src/zutil/network/nio/service/sync/SyncService.java
Normal file
58
src/zutil/network/nio/service/sync/SyncService.java
Normal file
|
|
@ -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<String, ObjectSync> sync;
|
||||
|
||||
public SyncService(NioNetwork nio){
|
||||
super(nio);
|
||||
sync = new HashMap<String, ObjectSync>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
16
src/zutil/network/nio/worker/EchoWorker.java
Normal file
16
src/zutil/network/nio/worker/EchoWorker.java
Normal file
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
126
src/zutil/network/nio/worker/SystemWorker.java
Normal file
126
src/zutil/network/nio/worker/SystemWorker.java
Normal file
|
|
@ -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<Double, ResponseEvent> rspEvents = new HashMap<Double, ResponseEvent>();
|
||||
// Difren services listening on specific messages
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<Class, NetworkService> services = new HashMap<Class, NetworkService>();
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
34
src/zutil/network/nio/worker/ThreadedEventWorker.java
Normal file
34
src/zutil/network/nio/worker/ThreadedEventWorker.java
Normal file
|
|
@ -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);
|
||||
|
||||
}
|
||||
52
src/zutil/network/nio/worker/Worker.java
Normal file
52
src/zutil/network/nio/worker/Worker.java
Normal file
|
|
@ -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<WorkerDataEvent> queue = new LinkedList<WorkerDataEvent>();
|
||||
|
||||
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<WorkerDataEvent> 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();
|
||||
}
|
||||
18
src/zutil/network/nio/worker/WorkerDataEvent.java
Normal file
18
src/zutil/network/nio/worker/WorkerDataEvent.java
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
25
src/zutil/test/ConsoleTest.java
Normal file
25
src/zutil/test/ConsoleTest.java
Normal file
|
|
@ -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) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/zutil/test/EncryptionTest.java
Normal file
38
src/zutil/test/EncryptionTest.java
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
20
src/zutil/test/ExternalSortTest.java
Normal file
20
src/zutil/test/ExternalSortTest.java
Normal file
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/zutil/test/FileChangedTest.java
Normal file
29
src/zutil/test/FileChangedTest.java
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
26
src/zutil/test/FileFinderHasherTest.java
Normal file
26
src/zutil/test/FileFinderHasherTest.java
Normal file
|
|
@ -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<File> files = FileFinder.search(path);
|
||||
for(int i=0; i<files.size(); i++){
|
||||
try {
|
||||
System.out.println(
|
||||
FileFinder.relativePath(files.get(i), relativePath)+
|
||||
": "+Hasher.hash(files.get(i),"MD5"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
79
src/zutil/test/HTTPGuessTheNumber.java
Normal file
79
src/zutil/test/HTTPGuessTheNumber.java
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
package zutil.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
import zutil.network.http.HttpPage;
|
||||
import zutil.network.http.HttpPrintStream;
|
||||
import zutil.network.http.HttpServer;
|
||||
|
||||
public class HTTPGuessTheNumber implements HttpPage{
|
||||
|
||||
public static void main(String[] args) throws IOException{
|
||||
HttpServer server = new HttpServer("localhost", 80);
|
||||
server.setDefaultPage(new HTTPGuessTheNumber());
|
||||
server.run();
|
||||
}
|
||||
|
||||
public void respond(HttpPrintStream out,
|
||||
HashMap<String, String> client_info,
|
||||
HashMap<String, String> session, HashMap<String, String> cookie,
|
||||
HashMap<String, String> request) {
|
||||
|
||||
out.enableBuffering(true);
|
||||
out.println("<html>");
|
||||
out.println("<H2>Welcome To The Number Guess Game!</H2>");
|
||||
|
||||
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("</html>");
|
||||
return;
|
||||
}
|
||||
else if(guess > nummber){
|
||||
out.println("<b>To High</b><br>");
|
||||
if(Integer.parseInt(cookie.get("high")) > guess){
|
||||
out.setCookie("high", ""+guess);
|
||||
cookie.put("high", ""+guess);
|
||||
}
|
||||
}
|
||||
else{
|
||||
out.println("<b>To Low</b><br>");
|
||||
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("<form method='post'>");
|
||||
out.println(cookie.get("low")+" < X < "+cookie.get("high")+"<br>");
|
||||
out.println("Guess a number between 0 and 100:<br>");
|
||||
out.println("<input type='text' name='guess'>");
|
||||
out.println("<input type='hidden' name='test' value='test'>");
|
||||
out.println("<input type='submit' value='Guess'>");
|
||||
out.println("</form>");
|
||||
out.println("<script>document.all.guess.focus();</script>");
|
||||
//out.println("<b>DEBUG: nummber="+session.get("random_nummber")+"</b><br>");
|
||||
out.println("</html>");
|
||||
}
|
||||
|
||||
}
|
||||
116
src/zutil/test/ImageProcessorTest.java
Normal file
116
src/zutil/test/ImageProcessorTest.java
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
37
src/zutil/test/NetworkClientTest.java
Normal file
37
src/zutil/test/NetworkClientTest.java
Normal file
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
20
src/zutil/test/NetworkServerTest.java
Normal file
20
src/zutil/test/NetworkServerTest.java
Normal file
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/zutil/test/QuickSelectTest.java
Normal file
26
src/zutil/test/QuickSelectTest.java
Normal file
|
|
@ -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.length ;i++){
|
||||
System.out.println(array[i] +",");
|
||||
}
|
||||
}
|
||||
}
|
||||
137
src/zutil/test/QuickSortTest.java
Normal file
137
src/zutil/test/QuickSortTest.java
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
package zutil.test;
|
||||
import zutil.algo.sort.QuickSort;
|
||||
import zutil.algo.sort.sortable.SortableIntArray;
|
||||
import junit.framework.*;
|
||||
|
||||
public class QuickSortTest extends TestCase {
|
||||
public static boolean debug = false;
|
||||
//the size of the arrays to be tested
|
||||
private static final int[] cases = new int[]{10000,100000,1000000,10000000};
|
||||
//the type of array to be tested
|
||||
// 0 = random
|
||||
// 1 = mirror
|
||||
// 2 = sorted
|
||||
private static final int[] types = new int[]{0,1,2};
|
||||
//the strings for the diffrent arrays
|
||||
private static final String[] typesS = new String[]{"Random array","Mirrored array","Sorted array"};
|
||||
//the pivots that will be tested
|
||||
// 0 = random
|
||||
// 1 = median
|
||||
// 2 = middle
|
||||
private static final int[] pivots = new int[]{0,1,2};
|
||||
//the strings for the pivots
|
||||
private static final String[] pivotsS = new String[]{"Random pivot","Median pivot","Half pivot"};
|
||||
//the current array size index of cases
|
||||
private static int currentCase = 0;
|
||||
//the current type of arrays
|
||||
private static int typeCase = 0;
|
||||
//the current pivot to use
|
||||
private static int pivotCase = 0;
|
||||
//the current state of using insertionsort in quicksort
|
||||
private static boolean insertSort;
|
||||
//the temp array that will be sorted
|
||||
private int[] array;
|
||||
|
||||
|
||||
/**
|
||||
*The main method to run the test. was going to use junit but did
|
||||
*no find a way to loop the test like in this method.
|
||||
*/
|
||||
public static void main(String[] args){
|
||||
QuickSortTest test = new QuickSortTest("Test");
|
||||
insertSort = true;
|
||||
//the insertion sort tests loop
|
||||
for(int z=0; z<2 ; insertSort=false,z++){
|
||||
System.out.println("**************** Whit insertionSort: "+insertSort+" *****************");
|
||||
// the pivots tests loop
|
||||
for(pivotCase=0; pivotCase<pivots.length ;pivotCase++){
|
||||
System.out.println("********** "+pivotsS[pivots[pivotCase]]+" ***********");
|
||||
//the array size tests loop
|
||||
for(typeCase=0; typeCase<types.length ;typeCase++){
|
||||
currentCase = 0;
|
||||
System.out.println("**** "+typesS[types[typeCase]]+" ****");
|
||||
//the array size loop
|
||||
for(currentCase=0; currentCase<cases.length ;currentCase++){
|
||||
try{
|
||||
test.setUp();
|
||||
test.TestSort();
|
||||
test.tearDown();
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public QuickSortTest(String name){
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* setUp() method that initializes common objects
|
||||
*/
|
||||
public void setUp() throws Exception{
|
||||
super.setUp();
|
||||
array = new int[cases[currentCase]];
|
||||
|
||||
switch(types[typeCase]){
|
||||
//Randome Array test
|
||||
case 0:
|
||||
for(int i=0; i<array.length ;i++){
|
||||
array[i] = (int)(Math.random()*array.length*10);
|
||||
}
|
||||
break;
|
||||
//Mirrored Array test
|
||||
case 1:
|
||||
for(int i=0; i<array.length ;i++){
|
||||
array[i] = array.length-i;
|
||||
}
|
||||
break;
|
||||
//Sorted Array test
|
||||
case 2:
|
||||
for(int i=0; i<array.length ;i++){
|
||||
array[i] = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tearDown() method that cleanup the common objects
|
||||
*/
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
*Tests if the array is sorted
|
||||
*/
|
||||
public void TestSort() {
|
||||
long time = System.currentTimeMillis();
|
||||
if(debug){
|
||||
for(int i=0; i<array.length ;i++)
|
||||
System.out.print(array[i]+", ");
|
||||
System.out.println("");
|
||||
}
|
||||
QuickSort.sort(new SortableIntArray(array),pivotCase,insertSort);
|
||||
//Sort.insertionSort(array);
|
||||
System.out.print("*");
|
||||
//the time to sort
|
||||
System.out.println(array.length+" elements: "+
|
||||
((double)(System.currentTimeMillis()-time)/1000)+" sec("+
|
||||
(System.currentTimeMillis()-time)+" ms)");
|
||||
if(debug){
|
||||
for(int i=0; i<array.length ;i++)
|
||||
System.out.print(array[i]+", ");
|
||||
System.out.println("");
|
||||
}
|
||||
//checking if sorted correct
|
||||
for(int i=1; i<array.length ; i++){
|
||||
if(array[i-1] > array[i]){
|
||||
fail("Array not sorted!! ("+array[i-1]+" > "+array[i]+")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue