Changed tas to spaces
This commit is contained in:
parent
a938b70d57
commit
b1c53d88ae
196 changed files with 14016 additions and 14035 deletions
10
Zutil.iml
10
Zutil.iml
|
|
@ -45,15 +45,5 @@
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
|
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
|
||||||
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
|
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
|
||||||
<orderEntry type="library" name="Maven: com.carrotsearch:junit-benchmarks:0.7.2" level="project" />
|
<orderEntry type="library" name="Maven: com.carrotsearch:junit-benchmarks:0.7.2" level="project" />
|
||||||
<orderEntry type="library" name="Maven: commons-fileupload:commons-fileupload:1.2.1" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: commons-io:commons-io:2.5" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: dom4j:dom4j:1.6.1" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: xml-apis:xml-apis:1.0.b2" level="project" />
|
|
||||||
<orderEntry type="library" scope="PROVIDED" name="Maven: javax.servlet:javax.servlet-api:3.1.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: mysql:mysql-connector-java:5.1.36" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.xerial:sqlite-jdbc:3.8.11.2" level="project" />
|
|
||||||
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Maven: com.carrotsearch:junit-benchmarks:0.7.2" level="project" />
|
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
|
|
@ -40,203 +40,203 @@ import java.util.Random;
|
||||||
* Basic symmetric encryption example
|
* Basic symmetric encryption example
|
||||||
*/
|
*/
|
||||||
public class Encrypter {
|
public class Encrypter {
|
||||||
// Choices are available at: http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html
|
// Choices are available at: http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html
|
||||||
public enum Algorithm {
|
public enum Algorithm {
|
||||||
/** Advanced Encryption Standard as specified by NIST in FIPS 197. Also known as the Rijndael algorithm by Joan Daemen and Vincent Rijmen, AES is a 128-bit block cipher supporting keys of 128, 192, and 256 bits. **/
|
/** Advanced Encryption Standard as specified by NIST in FIPS 197. Also known as the Rijndael algorithm by Joan Daemen and Vincent Rijmen, AES is a 128-bit block cipher supporting keys of 128, 192, and 256 bits. **/
|
||||||
AES,
|
AES,
|
||||||
/** The AES key wrapping algorithm as described in RFC 3394. **/
|
/** The AES key wrapping algorithm as described in RFC 3394. **/
|
||||||
AESWrap,
|
AESWrap,
|
||||||
/** A stream cipher believed to be fully interoperable with the RC4 cipher developed by Ron Rivest. For more information, see K. Kaukonen and R. Thayer, "A Stream Cipher Encryption Algorithm 'Arcfour'", Internet Draft (expired), draft-kaukonen-cipher-arcfour-03.txt. **/
|
/** A stream cipher believed to be fully interoperable with the RC4 cipher developed by Ron Rivest. For more information, see K. Kaukonen and R. Thayer, "A Stream Cipher Encryption Algorithm 'Arcfour'", Internet Draft (expired), draft-kaukonen-cipher-arcfour-03.txt. **/
|
||||||
ARCFOUR,
|
ARCFOUR,
|
||||||
/** The Blowfish block cipher designed by Bruce Schneier. **/
|
/** The Blowfish block cipher designed by Bruce Schneier. **/
|
||||||
Blowfish,
|
Blowfish,
|
||||||
/** Counter/CBC Mode, as defined in NIST Special Publication SP 800-38C. **/
|
/** Counter/CBC Mode, as defined in NIST Special Publication SP 800-38C. **/
|
||||||
CCM,
|
CCM,
|
||||||
/** The Digital Encryption Standard as described in FIPS PUB 46-3. **/
|
/** The Digital Encryption Standard as described in FIPS PUB 46-3. **/
|
||||||
DES,
|
DES,
|
||||||
/** Triple DES Encryption (also known as DES-EDE, 3DES, or Triple-DES). Data is encrypted using the DES algorithm three separate times. It is first encrypted using the first subkey, then decrypted with the second subkey, and encrypted with the third subkey. **/
|
/** Triple DES Encryption (also known as DES-EDE, 3DES, or Triple-DES). Data is encrypted using the DES algorithm three separate times. It is first encrypted using the first subkey, then decrypted with the second subkey, and encrypted with the third subkey. **/
|
||||||
DESede,
|
DESede,
|
||||||
/** The DESede key wrapping algorithm as described in RFC 3217 . **/
|
/** The DESede key wrapping algorithm as described in RFC 3217 . **/
|
||||||
DESedeWrap,
|
DESedeWrap,
|
||||||
/** Elliptic Curve Integrated Encryption Scheme **/
|
/** Elliptic Curve Integrated Encryption Scheme **/
|
||||||
ECIES,
|
ECIES,
|
||||||
/** Galois/Counter Mode, as defined in NIST Special Publication SP 800-38D. **/
|
/** Galois/Counter Mode, as defined in NIST Special Publication SP 800-38D. **/
|
||||||
GCM,
|
GCM,
|
||||||
/** Variable-key-size encryption algorithms developed by Ron Rivest for RSA Data Security, Inc. **/
|
/** Variable-key-size encryption algorithms developed by Ron Rivest for RSA Data Security, Inc. **/
|
||||||
RC2,
|
RC2,
|
||||||
/** Variable-key-size encryption algorithms developed by Ron Rivest for RSA Data Security, Inc. (See note prior for ARCFOUR.) **/
|
/** Variable-key-size encryption algorithms developed by Ron Rivest for RSA Data Security, Inc. (See note prior for ARCFOUR.) **/
|
||||||
RC4,
|
RC4,
|
||||||
/** Variable-key-size encryption algorithms developed by Ron Rivest for RSA Data Security, Inc. **/
|
/** Variable-key-size encryption algorithms developed by Ron Rivest for RSA Data Security, Inc. **/
|
||||||
RC5,
|
RC5,
|
||||||
/** The RSA encryption algorithm as defined in PKCS #1 **/
|
/** The RSA encryption algorithm as defined in PKCS #1 **/
|
||||||
RSA
|
RSA
|
||||||
}
|
}
|
||||||
public enum Digest {
|
public enum Digest {
|
||||||
MD2,
|
MD2,
|
||||||
MD5,
|
MD5,
|
||||||
SHA1,
|
SHA1,
|
||||||
SHA256,
|
SHA256,
|
||||||
SHA384,
|
SHA384,
|
||||||
SHA512,
|
SHA512,
|
||||||
HmacMD5,
|
HmacMD5,
|
||||||
HmacSHA1,
|
HmacSHA1,
|
||||||
HmacSHA256,
|
HmacSHA256,
|
||||||
HmacSHA384,
|
HmacSHA384,
|
||||||
HmacSHA512
|
HmacSHA512
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 8-byte Salt
|
// 8-byte Salt
|
||||||
public static byte[] salt = {
|
public static byte[] salt = {
|
||||||
(byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32,
|
(byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32,
|
||||||
(byte)0x56, (byte)0x35, (byte)0xE3, (byte)0x03
|
(byte)0x56, (byte)0x35, (byte)0xE3, (byte)0x03
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
private Cipher encipher;
|
private Cipher encipher;
|
||||||
private Cipher decipher;
|
private Cipher decipher;
|
||||||
private Key key;
|
private Key key;
|
||||||
private AlgorithmParameterSpec paramSpec;
|
private AlgorithmParameterSpec paramSpec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a random key
|
* Generates a random key
|
||||||
* @param crypto is algorithm to encrypt/decrypt with
|
* @param crypto is algorithm to encrypt/decrypt with
|
||||||
*/
|
*/
|
||||||
public Encrypter(Algorithm crypto) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException{
|
public Encrypter(Algorithm crypto) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException{
|
||||||
KeyGenerator keygenerator = KeyGenerator.getInstance(crypto.toString());
|
KeyGenerator keygenerator = KeyGenerator.getInstance(crypto.toString());
|
||||||
|
|
||||||
key = keygenerator.generateKey();
|
key = keygenerator.generateKey();
|
||||||
encipher = Cipher.getInstance(key.getAlgorithm());
|
encipher = Cipher.getInstance(key.getAlgorithm());
|
||||||
decipher = Cipher.getInstance(key.getAlgorithm());
|
decipher = Cipher.getInstance(key.getAlgorithm());
|
||||||
encipher.init(Cipher.ENCRYPT_MODE, key);
|
encipher.init(Cipher.ENCRYPT_MODE, key);
|
||||||
decipher.init(Cipher.DECRYPT_MODE, key);
|
decipher.init(Cipher.DECRYPT_MODE, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses the given key for encryption
|
* Uses the given key for encryption
|
||||||
* @param key is an existing key to use for encrypting/decrypting
|
* @param key is an existing key to use for encrypting/decrypting
|
||||||
*/
|
*/
|
||||||
public Encrypter(Key key) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException{
|
public Encrypter(Key key) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException{
|
||||||
this.key = key;
|
this.key = key;
|
||||||
encipher = Cipher.getInstance(key.getAlgorithm());
|
encipher = Cipher.getInstance(key.getAlgorithm());
|
||||||
decipher = Cipher.getInstance(key.getAlgorithm());
|
decipher = Cipher.getInstance(key.getAlgorithm());
|
||||||
encipher.init(Cipher.ENCRYPT_MODE, key);
|
encipher.init(Cipher.ENCRYPT_MODE, key);
|
||||||
decipher.init(Cipher.DECRYPT_MODE, key);
|
decipher.init(Cipher.DECRYPT_MODE, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a encrypter with a passphrase.
|
* Creates a encrypter with a passphrase.
|
||||||
*
|
*
|
||||||
* @param stringKey is a passphrase to use as key
|
* @param stringKey is a passphrase to use as key
|
||||||
* @param crypto is algorithm to encrypt/decrypt with
|
* @param crypto is algorithm to encrypt/decrypt with
|
||||||
*/
|
*/
|
||||||
public Encrypter(String stringKey, Algorithm crypto) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException, InvalidKeyException {
|
public Encrypter(String stringKey, Algorithm crypto) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException, InvalidKeyException {
|
||||||
this(stringKey, Digest.HmacSHA1, crypto, 500,
|
this(stringKey, Digest.HmacSHA1, crypto, 500,
|
||||||
(crypto==Algorithm.DES ? 64 : 128));
|
(crypto==Algorithm.DES ? 64 : 128));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Encrypter(String stringKey, Digest digest, Algorithm crypto, int iteration, int keyBitSize) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException {
|
public Encrypter(String stringKey, Digest digest, Algorithm crypto, int iteration, int keyBitSize) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException {
|
||||||
// Install SunJCE provider
|
// Install SunJCE provider
|
||||||
Provider sunJce = new com.sun.crypto.provider.SunJCE();
|
Provider sunJce = new com.sun.crypto.provider.SunJCE();
|
||||||
Security.addProvider(sunJce);
|
Security.addProvider(sunJce);
|
||||||
|
|
||||||
// Generate the secret key specs.
|
// Generate the secret key specs.
|
||||||
//String instance = "PBEWith"+ digest +"And"+ crypto;
|
//String instance = "PBEWith"+ digest +"And"+ crypto;
|
||||||
String instance = "PBKDF2With"+ digest;
|
String instance = "PBKDF2With"+ digest;
|
||||||
SecretKeyFactory factory = SecretKeyFactory.getInstance(instance);
|
SecretKeyFactory factory = SecretKeyFactory.getInstance(instance);
|
||||||
KeySpec keySpec = new PBEKeySpec(stringKey.toCharArray(), salt, iteration, keyBitSize);
|
KeySpec keySpec = new PBEKeySpec(stringKey.toCharArray(), salt, iteration, keyBitSize);
|
||||||
SecretKey tmp = factory.generateSecret(keySpec);
|
SecretKey tmp = factory.generateSecret(keySpec);
|
||||||
key = new SecretKeySpec(tmp.getEncoded(), crypto.toString());
|
key = new SecretKeySpec(tmp.getEncoded(), crypto.toString());
|
||||||
//key = new SecretKeySpec(stringKey.getBytes(), crypto.toString());
|
//key = new SecretKeySpec(stringKey.getBytes(), crypto.toString());
|
||||||
|
|
||||||
encipher = Cipher.getInstance(key.getAlgorithm());
|
encipher = Cipher.getInstance(key.getAlgorithm());
|
||||||
decipher = Cipher.getInstance(key.getAlgorithm());
|
decipher = Cipher.getInstance(key.getAlgorithm());
|
||||||
encipher.init(Cipher.ENCRYPT_MODE, key);
|
encipher.init(Cipher.ENCRYPT_MODE, key);
|
||||||
decipher.init(Cipher.DECRYPT_MODE, key);
|
decipher.init(Cipher.DECRYPT_MODE, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypts the given data
|
* Encrypts the given data
|
||||||
*
|
*
|
||||||
* @param data is the data to encrypt
|
* @param data is the data to encrypt
|
||||||
* @return The encrypted data
|
* @return The encrypted data
|
||||||
*/
|
*/
|
||||||
public byte[] encrypt(byte[] data){
|
public byte[] encrypt(byte[] data){
|
||||||
try {
|
try {
|
||||||
byte[] encryption = new byte[encipher.getOutputSize(data.length)];
|
byte[] encryption = new byte[encipher.getOutputSize(data.length)];
|
||||||
int ctLength = encipher.update(data, 0, data.length, encryption, 0);
|
int ctLength = encipher.update(data, 0, data.length, encryption, 0);
|
||||||
|
|
||||||
ctLength += encipher.doFinal(encryption, ctLength);
|
ctLength += encipher.doFinal(encryption, ctLength);
|
||||||
return encryption;
|
return encryption;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds encryption to the OutputStream
|
* Adds encryption to the OutputStream
|
||||||
* @param out is the OutputStream to enable encryption on
|
* @param out is the OutputStream to enable encryption on
|
||||||
* @return A new encrypted OutputStream
|
* @return A new encrypted OutputStream
|
||||||
*/
|
*/
|
||||||
public OutputStream encrypt(OutputStream out) {
|
public OutputStream encrypt(OutputStream out) {
|
||||||
// Bytes written to out will be encrypted
|
// Bytes written to out will be encrypted
|
||||||
return new CipherOutputStream(out, encipher);
|
return new CipherOutputStream(out, encipher);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypts encrypted data
|
* Decrypts encrypted data
|
||||||
* @param encrypted is the encrypted data
|
* @param encrypted is the encrypted data
|
||||||
* @return The decrypted data
|
* @return The decrypted data
|
||||||
*/
|
*/
|
||||||
public byte[] decrypt(byte[] encrypted){
|
public byte[] decrypt(byte[] encrypted){
|
||||||
try {
|
try {
|
||||||
byte[] dataTmp = new byte[encrypted.length];
|
byte[] dataTmp = new byte[encrypted.length];
|
||||||
int ptLength = decipher.update(encrypted, 0, encrypted.length, dataTmp, 0);
|
int ptLength = decipher.update(encrypted, 0, encrypted.length, dataTmp, 0);
|
||||||
ptLength += decipher.doFinal(dataTmp, ptLength);
|
ptLength += decipher.doFinal(dataTmp, ptLength);
|
||||||
|
|
||||||
byte[] data = new byte[ptLength];
|
byte[] data = new byte[ptLength];
|
||||||
System.arraycopy(dataTmp, 0, data, 0, ptLength);
|
System.arraycopy(dataTmp, 0, data, 0, ptLength);
|
||||||
return data;
|
return data;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds decryption to the InputStream
|
* Adds decryption to the InputStream
|
||||||
* @param in is the InputStream to enable decryption on
|
* @param in is the InputStream to enable decryption on
|
||||||
* @return A new decrypted InputStream
|
* @return A new decrypted InputStream
|
||||||
*/
|
*/
|
||||||
public InputStream decrypt(InputStream in) {
|
public InputStream decrypt(InputStream in) {
|
||||||
// Bytes read from in will be decrypted
|
// Bytes read from in will be decrypted
|
||||||
return new CipherInputStream(in, decipher);
|
return new CipherInputStream(in, decipher);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The key for this encrypter
|
* @return The key for this encrypter
|
||||||
*/
|
*/
|
||||||
public Key getKey(){
|
public Key getKey(){
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the algorithm used by this encrypter
|
* @return the algorithm used by this encrypter
|
||||||
*/
|
*/
|
||||||
public String getAlgorithm(){
|
public String getAlgorithm(){
|
||||||
return key.getAlgorithm();
|
return key.getAlgorithm();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Randomizes the salt for the key
|
* Randomizes the salt for the key
|
||||||
*/
|
*/
|
||||||
public static void randomizeSalt(){
|
public static void randomizeSalt(){
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
random.nextBytes(salt);
|
random.nextBytes(salt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,133 +37,133 @@ import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
public class Hasher {
|
public class Hasher {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a hash of a file
|
* Returns a hash of a file
|
||||||
*
|
*
|
||||||
* @param file is the path to the file
|
* @param file is the path to the file
|
||||||
* @param hashType is the hash type
|
* @param hashType is the hash type
|
||||||
* @return a String with the hash
|
* @return a String with the hash
|
||||||
*/
|
*/
|
||||||
public static String hash(File file, String hashType) throws NoSuchAlgorithmException, IOException {
|
public static String hash(File file, String hashType) throws NoSuchAlgorithmException, IOException {
|
||||||
MessageDigest digest = MessageDigest.getInstance(hashType); //"MD5"
|
MessageDigest digest = MessageDigest.getInstance(hashType); //"MD5"
|
||||||
InputStream is = new FileInputStream(file);
|
InputStream is = new FileInputStream(file);
|
||||||
String output = "";
|
String output = "";
|
||||||
byte[] buffer = new byte[8192];
|
byte[] buffer = new byte[8192];
|
||||||
int read = 0;
|
int read = 0;
|
||||||
try {
|
try {
|
||||||
while( (read = is.read(buffer)) > 0) {
|
while( (read = is.read(buffer)) > 0) {
|
||||||
digest.update(buffer, 0, read);
|
digest.update(buffer, 0, read);
|
||||||
}
|
}
|
||||||
byte[] md5sum = digest.digest();
|
byte[] md5sum = digest.digest();
|
||||||
BigInteger bigInt = new BigInteger(1, md5sum);
|
BigInteger bigInt = new BigInteger(1, md5sum);
|
||||||
output = bigInt.toString(16);
|
output = bigInt.toString(16);
|
||||||
}
|
}
|
||||||
catch(IOException e) {
|
catch(IOException e) {
|
||||||
throw new RuntimeException("Unable to process file for "+hashType+" hash", e);
|
throw new RuntimeException("Unable to process file for "+hashType+" hash", e);
|
||||||
}
|
}
|
||||||
is.close();
|
is.close();
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the MD5 hash of the given object
|
* Returns the MD5 hash of the given object
|
||||||
*
|
*
|
||||||
* @param str is the String to hash
|
* @param str is the String to hash
|
||||||
* @return an String containing the hash
|
* @return an String containing the hash
|
||||||
*/
|
*/
|
||||||
public static String MD5(String str){
|
public static String MD5(String str){
|
||||||
try {
|
try {
|
||||||
return hash(str, "MD5");
|
return hash(str, "MD5");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the MD5 hash of the given object
|
* Returns the MD5 hash of the given object
|
||||||
*
|
*
|
||||||
* @param object is the object to hash
|
* @param object is the object to hash
|
||||||
* @return an String containing the hash
|
* @return an String containing the hash
|
||||||
*/
|
*/
|
||||||
public static String MD5(Serializable object){
|
public static String MD5(Serializable object){
|
||||||
try {
|
try {
|
||||||
return hash(object, "MD5");
|
return hash(object, "MD5");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the MD5 hash of the given file
|
|
||||||
*
|
|
||||||
* @param file is the file to hash
|
|
||||||
* @return an String containing the hash
|
|
||||||
*/
|
|
||||||
public static String MD5(File file) throws IOException{
|
|
||||||
try {
|
|
||||||
return hash(file, "MD5");
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the SHA-1 hash of the given object
|
* Returns the MD5 hash of the given file
|
||||||
*
|
*
|
||||||
* @param str is the String to hash
|
* @param file is the file to hash
|
||||||
* @return an String containing the hash
|
* @return an String containing the hash
|
||||||
*/
|
*/
|
||||||
public static String SHA1(String str){
|
public static String MD5(File file) throws IOException{
|
||||||
try {
|
try {
|
||||||
return hash(str, "SHA-1");
|
return hash(file, "MD5");
|
||||||
} catch (Exception e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the SHA-1 hash of the given object
|
/**
|
||||||
*
|
* Returns the SHA-1 hash of the given object
|
||||||
* @param object is the object to hash
|
*
|
||||||
* @return an String containing the hash
|
* @param str is the String to hash
|
||||||
*/
|
* @return an String containing the hash
|
||||||
public static String SHA1(Serializable object){
|
*/
|
||||||
try {
|
public static String SHA1(String str){
|
||||||
return hash(object, "SHA-1");
|
try {
|
||||||
} catch (Exception e) {
|
return hash(str, "SHA-1");
|
||||||
e.printStackTrace();
|
} catch (Exception e) {
|
||||||
}
|
e.printStackTrace();
|
||||||
return null;
|
}
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Returns the SHA-256 hash with a key for the given String
|
/**
|
||||||
*
|
* Returns the SHA-1 hash of the given object
|
||||||
* @param str is the String to hash
|
*
|
||||||
* @param key is the key to use with the hash
|
* @param object is the object to hash
|
||||||
* @return an String containing the hash
|
* @return an String containing the hash
|
||||||
*/
|
*/
|
||||||
public static String HMAC_SHA256(String str, String key){
|
public static String SHA1(Serializable object){
|
||||||
return HMAC("HmacSHA256", str.getBytes(), key.getBytes());
|
try {
|
||||||
}
|
return hash(object, "SHA-1");
|
||||||
|
} catch (Exception e) {
|
||||||
/**
|
e.printStackTrace();
|
||||||
* Returns a HMAC hash with a key for the given String
|
}
|
||||||
*
|
return null;
|
||||||
* @param algo specifies the algorithm to be used
|
}
|
||||||
* @param data is the String to hash
|
|
||||||
* @param key is the key to use with the hash
|
/**
|
||||||
* @return an String containing the hash
|
* Returns the SHA-256 hash with a key for the given String
|
||||||
*/
|
*
|
||||||
public static String HMAC(String algo, byte[] data, byte[] key){
|
* @param str is the String to hash
|
||||||
try {
|
* @param key is the key to use with the hash
|
||||||
// Get an hmac_sha1 key from the raw key bytes
|
* @return an String containing the hash
|
||||||
|
*/
|
||||||
|
public static String HMAC_SHA256(String str, String key){
|
||||||
|
return HMAC("HmacSHA256", str.getBytes(), key.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a HMAC hash with a key for the given String
|
||||||
|
*
|
||||||
|
* @param algo specifies the algorithm to be used
|
||||||
|
* @param data is the String to hash
|
||||||
|
* @param key is the key to use with the hash
|
||||||
|
* @return an String containing the hash
|
||||||
|
*/
|
||||||
|
public static String HMAC(String algo, byte[] data, byte[] key){
|
||||||
|
try {
|
||||||
|
// Get an hmac_sha1 key from the raw key bytes
|
||||||
SecretKeySpec signingKey = new SecretKeySpec(key, algo);
|
SecretKeySpec signingKey = new SecretKeySpec(key, algo);
|
||||||
|
|
||||||
// Get a MAC instance and initialize with the signing key
|
// Get a MAC instance and initialize with the signing key
|
||||||
|
|
@ -174,11 +174,11 @@ public class Hasher {
|
||||||
byte[] raw = mac.doFinal( data );
|
byte[] raw = mac.doFinal( data );
|
||||||
|
|
||||||
return Converter.toHexString(raw);
|
return Converter.toHexString(raw);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String PBKDF2(String data, String salt, int iterations){
|
public static String PBKDF2(String data, String salt, int iterations){
|
||||||
try {
|
try {
|
||||||
|
|
@ -196,97 +196,97 @@ public class Hasher {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Hashes the given String as UTF8
|
|
||||||
*
|
|
||||||
* @param object is the String
|
|
||||||
* @param hashType is the hash algorithm (MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512 )
|
|
||||||
* @return a hex String of the hash
|
|
||||||
*/
|
|
||||||
public static String hash(String object, String hashType) throws Exception {
|
|
||||||
return hash(object.getBytes(), hashType);//(new BASE64Encoder()).encode(raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the hash of the given object
|
|
||||||
*
|
|
||||||
* @param object is the object to hash
|
|
||||||
* @param hashType is the hash method (MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512 )
|
|
||||||
* @return an String containing the hash
|
|
||||||
*/
|
|
||||||
public static String hash(Serializable object, String hashType) throws Exception {
|
|
||||||
return hash(Converter.toBytes(object), hashType);//(new BASE64Encoder()).encode(raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hashes a given byte array
|
* Hashes the given String as UTF8
|
||||||
*
|
*
|
||||||
* @param data is the byte array to hash
|
* @param object is the String
|
||||||
* @param hashType is the hash method (MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512 )
|
* @param hashType is the hash algorithm (MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512 )
|
||||||
* @return an String containing the hash
|
* @return a hex String of the hash
|
||||||
* @throws Exception
|
*/
|
||||||
*/
|
public static String hash(String object, String hashType) throws Exception {
|
||||||
public static String hash(byte[] data, String hashType) throws Exception {
|
return hash(object.getBytes(), hashType);//(new BASE64Encoder()).encode(raw);
|
||||||
MessageDigest md = null;
|
}
|
||||||
md = MessageDigest.getInstance(hashType); //MD5 || SHA
|
|
||||||
md.update(data);
|
|
||||||
|
|
||||||
byte raw[] = md.digest();
|
/**
|
||||||
return Converter.toHexString(raw);//(new BASE64Encoder()).encode(raw);
|
* Returns the hash of the given object
|
||||||
}
|
*
|
||||||
|
* @param object is the object to hash
|
||||||
|
* @param hashType is the hash method (MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512 )
|
||||||
|
* @return an String containing the hash
|
||||||
|
*/
|
||||||
|
public static String hash(Serializable object, String hashType) throws Exception {
|
||||||
|
return hash(Converter.toBytes(object), hashType);//(new BASE64Encoder()).encode(raw);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MurmurHash2 ported from c++ source
|
* Hashes a given byte array
|
||||||
*
|
*
|
||||||
* @param object is the Key
|
* @param data is the byte array to hash
|
||||||
* @param seed is the seed
|
* @param hashType is the hash method (MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512 )
|
||||||
* @return A MurmurHash of the key
|
* @return an String containing the hash
|
||||||
*/
|
* @throws Exception
|
||||||
public static int MurmurHash(Serializable object, int seed) throws Exception{
|
*/
|
||||||
byte[] data = Converter.toBytes(object);
|
public static String hash(byte[] data, String hashType) throws Exception {
|
||||||
int length = data.length;
|
MessageDigest md = null;
|
||||||
|
md = MessageDigest.getInstance(hashType); //MD5 || SHA
|
||||||
|
md.update(data);
|
||||||
|
|
||||||
//Constants
|
byte raw[] = md.digest();
|
||||||
int m = 0x5bd1e995;
|
return Converter.toHexString(raw);//(new BASE64Encoder()).encode(raw);
|
||||||
int r = 24;
|
}
|
||||||
|
|
||||||
// Initialize the hash to a 'random' value
|
/**
|
||||||
int h = seed ^ length;
|
* MurmurHash2 ported from c++ source
|
||||||
|
*
|
||||||
|
* @param object is the Key
|
||||||
|
* @param seed is the seed
|
||||||
|
* @return A MurmurHash of the key
|
||||||
|
*/
|
||||||
|
public static int MurmurHash(Serializable object, int seed) throws Exception{
|
||||||
|
byte[] data = Converter.toBytes(object);
|
||||||
|
int length = data.length;
|
||||||
|
|
||||||
int i=0;
|
//Constants
|
||||||
for(; i+4<length ;i+=4){
|
int m = 0x5bd1e995;
|
||||||
// get the first 4 bytes
|
int r = 24;
|
||||||
int k = data[i+3] & 0xff;
|
|
||||||
k <<= 8;
|
|
||||||
k |= data[i+2] & 0xff;
|
|
||||||
k <<= 8;
|
|
||||||
k |= data[i+1] & 0xff;
|
|
||||||
k <<= 8;
|
|
||||||
k |= data[i+0] & 0xff;
|
|
||||||
|
|
||||||
k *= m;
|
// Initialize the hash to a 'random' value
|
||||||
k ^= k >>> r;
|
int h = seed ^ length;
|
||||||
k *= m;
|
|
||||||
|
|
||||||
h *= m;
|
int i=0;
|
||||||
h ^= k;
|
for(; i+4<length ;i+=4){
|
||||||
}
|
// get the first 4 bytes
|
||||||
|
int k = data[i+3] & 0xff;
|
||||||
|
k <<= 8;
|
||||||
|
k |= data[i+2] & 0xff;
|
||||||
|
k <<= 8;
|
||||||
|
k |= data[i+1] & 0xff;
|
||||||
|
k <<= 8;
|
||||||
|
k |= data[i+0] & 0xff;
|
||||||
|
|
||||||
// Handle the last few bytes of the input
|
k *= m;
|
||||||
i = length % 4;
|
k ^= k >>> r;
|
||||||
|
k *= m;
|
||||||
|
|
||||||
switch(i){
|
h *= m;
|
||||||
case 3: h ^= data[length-3] << 16;
|
h ^= k;
|
||||||
case 2: h ^= data[length-2] << 8;
|
}
|
||||||
case 1: h ^= data[length-1];
|
|
||||||
h *= m;
|
|
||||||
}
|
|
||||||
|
|
||||||
h ^= h >>> 13;
|
// Handle the last few bytes of the input
|
||||||
h *= m;
|
i = length % 4;
|
||||||
h ^= h >>> 15;
|
|
||||||
|
|
||||||
return h;
|
switch(i){
|
||||||
}
|
case 3: h ^= data[length-3] << 16;
|
||||||
|
case 2: h ^= data[length-2] << 8;
|
||||||
|
case 1: h ^= data[length-1];
|
||||||
|
h *= m;
|
||||||
|
}
|
||||||
|
|
||||||
|
h ^= h >>> 13;
|
||||||
|
h *= m;
|
||||||
|
h ^= h >>> 15;
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,17 +32,17 @@ package zutil;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public interface OneInstance {
|
public interface OneInstance {
|
||||||
/**
|
/**
|
||||||
* Checks if the application is already running
|
* Checks if the application is already running
|
||||||
*
|
*
|
||||||
* @return True if the file is locked else false
|
* @return True if the file is locked else false
|
||||||
*/
|
*/
|
||||||
public boolean check();
|
public boolean check();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locks the application so that another one can not run
|
* Locks the application so that another one can not run
|
||||||
*
|
*
|
||||||
* @return False if there are a error else true
|
* @return False if there are a error else true
|
||||||
*/
|
*/
|
||||||
public boolean lockApp();
|
public boolean lockApp();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,85 +37,85 @@ import java.nio.channels.OverlappingFileLockException;
|
||||||
* @author Ziver Koc
|
* @author Ziver Koc
|
||||||
*/
|
*/
|
||||||
public class OneInstanceFile implements OneInstance{
|
public class OneInstanceFile implements OneInstance{
|
||||||
private File file;
|
private File file;
|
||||||
private FileChannel channel;
|
private FileChannel channel;
|
||||||
private FileLock lock;
|
private FileLock lock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a OneApp class
|
* Creates a OneApp class
|
||||||
*
|
*
|
||||||
* @param filename The name of the file to be locked
|
* @param filename The name of the file to be locked
|
||||||
*/
|
*/
|
||||||
public OneInstanceFile(String filename){
|
public OneInstanceFile(String filename){
|
||||||
this.file = new File(System.getProperty("user.home"), filename);
|
this.file = new File(System.getProperty("user.home"), filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the file have already bean locked
|
* Checks if the file have already bean locked
|
||||||
*
|
*
|
||||||
* @return True if the file is locked else false
|
* @return True if the file is locked else false
|
||||||
*/
|
*/
|
||||||
public boolean check() {
|
public boolean check() {
|
||||||
boolean tmp = lockApp();
|
boolean tmp = lockApp();
|
||||||
if( tmp ) closeLock();
|
if( tmp ) closeLock();
|
||||||
return !tmp;
|
return !tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locks the file
|
* Locks the file
|
||||||
*
|
*
|
||||||
* @return False if there are a error else true
|
* @return False if there are a error else true
|
||||||
*/
|
*/
|
||||||
public boolean lockApp() {
|
public boolean lockApp() {
|
||||||
try {
|
try {
|
||||||
channel = new RandomAccessFile(file, "rw").getChannel();
|
channel = new RandomAccessFile(file, "rw").getChannel();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
lock = channel.tryLock();
|
lock = channel.tryLock();
|
||||||
}
|
}
|
||||||
catch (OverlappingFileLockException e) {
|
catch (OverlappingFileLockException e) {
|
||||||
// already locked by this application
|
// already locked by this application
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lock == null || lock.isShared()) {
|
if (lock == null || lock.isShared()) {
|
||||||
// already locked by another application
|
// already locked by another application
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread() {
|
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||||
// destroy the lock when the JVM is closing
|
// destroy the lock when the JVM is closing
|
||||||
public void run() {
|
public void run() {
|
||||||
closeLock();
|
closeLock();
|
||||||
deleteFile();
|
deleteFile();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
closeLock();
|
closeLock();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closeLock() {
|
private void closeLock() {
|
||||||
try {
|
try {
|
||||||
lock.release();
|
lock.release();
|
||||||
channel.close();
|
channel.close();
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteFile() {
|
private void deleteFile() {
|
||||||
try {
|
try {
|
||||||
file.delete();
|
file.delete();
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,62 +37,62 @@ import java.net.Socket;
|
||||||
* @author Ziver Koc
|
* @author Ziver Koc
|
||||||
*/
|
*/
|
||||||
public class OneInstanceNetwork extends Thread implements OneInstance{
|
public class OneInstanceNetwork extends Thread implements OneInstance{
|
||||||
private int port;
|
private int port;
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a One App objekt
|
|
||||||
*
|
|
||||||
* @param port The port to lock
|
|
||||||
*/
|
|
||||||
public OneInstanceNetwork(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
|
* Creates a One App objekt
|
||||||
*
|
*
|
||||||
* @return True if port is locked else false
|
* @param port The port to lock
|
||||||
*/
|
*/
|
||||||
public boolean check() {
|
public OneInstanceNetwork(int port){
|
||||||
try {
|
this.port = port;
|
||||||
Socket clientSocket = new Socket("localhost", port);
|
}
|
||||||
MultiPrintStream.out.println("Already running!!!");
|
|
||||||
clientSocket.close();
|
/**
|
||||||
return true;
|
* Starts the port lock
|
||||||
}
|
*
|
||||||
catch (Exception e) {
|
* @return Always true
|
||||||
return false;
|
*/
|
||||||
}
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,13 +32,13 @@ package zutil;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public interface ProgressListener<S,D> {
|
public interface ProgressListener<S,D> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called when the progress is updated
|
* This method is called when the progress is updated
|
||||||
*
|
*
|
||||||
* @param source is the source object of the progress
|
* @param source is the source object of the progress
|
||||||
* @param info is some information from the source object
|
* @param info is some information from the source object
|
||||||
* @param percent is the progress of the object (0-100)
|
* @param percent is the progress of the object (0-100)
|
||||||
*/
|
*/
|
||||||
public void progressUpdate(S source, D info, double percent);
|
public void progressUpdate(S source, D info, double percent);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,104 +38,104 @@ import java.util.LinkedList;
|
||||||
*/
|
*/
|
||||||
public class EuclideansAlgo {
|
public class EuclideansAlgo {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple Test
|
* Simple Test
|
||||||
* @param args
|
* @param args
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args){
|
public static void main(String[] args){
|
||||||
MultiPrintStream.out.println("*** Correct Answer: ");
|
MultiPrintStream.out.println("*** Correct Answer: ");
|
||||||
MultiPrintStream.out.println("java.util.LinkedList{0, 2, 1, 1, 1, 4, 12, 102, 1, 1, 2, 3, 2, 2, 36}");
|
MultiPrintStream.out.println("java.util.LinkedList{0, 2, 1, 1, 1, 4, 12, 102, 1, 1, 2, 3, 2, 2, 36}");
|
||||||
MultiPrintStream.out.println("GCD: 1");
|
MultiPrintStream.out.println("GCD: 1");
|
||||||
|
|
||||||
MultiPrintStream.out.println("*** Integer:");
|
|
||||||
MultiPrintStream.out.dump(calcGenerators(60728973, 160523347));
|
|
||||||
MultiPrintStream.out.println("GCD: "+calc(60728973, 160523347));
|
|
||||||
|
|
||||||
MultiPrintStream.out.println("*** BigInteger: ");
|
|
||||||
MultiPrintStream.out.dump(calcGenerators(new BigInteger("60728973"), new BigInteger("160523347")));
|
|
||||||
MultiPrintStream.out.println("GCD: "+calc(new BigInteger("60728973"), new BigInteger("160523347")));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs the Euclidean algorithm on the two input
|
|
||||||
* values.
|
|
||||||
*
|
|
||||||
* @param a is the first integer
|
|
||||||
* @param b is the second integer
|
|
||||||
* @return a integer containing the GCD of the integers
|
|
||||||
*/
|
|
||||||
public static int calc(int a, int b){
|
|
||||||
int t;
|
|
||||||
while( b != 0 ){
|
|
||||||
t = b;
|
|
||||||
b = a % b;
|
|
||||||
a = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return a;
|
MultiPrintStream.out.println("*** Integer:");
|
||||||
}
|
MultiPrintStream.out.dump(calcGenerators(60728973, 160523347));
|
||||||
|
MultiPrintStream.out.println("GCD: "+calc(60728973, 160523347));
|
||||||
/**
|
|
||||||
* Runs the Euclidean algorithm on the two input
|
|
||||||
* values.
|
|
||||||
*
|
|
||||||
* @param a is the first BigInteger
|
|
||||||
* @param b is the second BigInteger
|
|
||||||
* @return a BigInteger containing the GCD of the BigIntegers
|
|
||||||
*/
|
|
||||||
public static BigInteger calc(BigInteger a, BigInteger b){
|
|
||||||
BigInteger t;
|
|
||||||
|
|
||||||
while( !b.equals(BigInteger.ZERO) ){
|
|
||||||
t = b;
|
|
||||||
b = a.mod( b );
|
|
||||||
a = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return a;
|
MultiPrintStream.out.println("*** BigInteger: ");
|
||||||
}
|
MultiPrintStream.out.dump(calcGenerators(new BigInteger("60728973"), new BigInteger("160523347")));
|
||||||
|
MultiPrintStream.out.println("GCD: "+calc(new BigInteger("60728973"), new BigInteger("160523347")));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the Euclidean algorithm on the two input
|
* Runs the Euclidean algorithm on the two input
|
||||||
* values to find the generators for the values.
|
* values.
|
||||||
*
|
*
|
||||||
* @param a is the first integer
|
* @param a is the first integer
|
||||||
* @param b is the second integer
|
* @param b is the second integer
|
||||||
* @return a list of integers that is generators for a and b
|
* @return a integer containing the GCD of the integers
|
||||||
*/
|
*/
|
||||||
public static LinkedList<Integer> calcGenerators(int a, int b){
|
public static int calc(int a, int b){
|
||||||
LinkedList<Integer> list = new LinkedList<Integer>();
|
int t;
|
||||||
int t;
|
while( b != 0 ){
|
||||||
|
t = b;
|
||||||
while( b != 0 ){
|
b = a % b;
|
||||||
list.add( a/b );
|
a = t;
|
||||||
t = b;
|
}
|
||||||
b = a % b;
|
|
||||||
a = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs the Euclidean algorithm on the two input
|
|
||||||
* values to find the generators for the values.
|
|
||||||
*
|
|
||||||
* @param a is the first BigInteger
|
|
||||||
* @param b is the second BigInteger
|
|
||||||
* @return a list of BigIntegers that is generators of a and b
|
|
||||||
*/
|
|
||||||
public static LinkedList<BigInteger> calcGenerators(BigInteger a, BigInteger b){
|
|
||||||
LinkedList<BigInteger> list = new LinkedList<BigInteger>();
|
|
||||||
BigInteger t;
|
|
||||||
|
|
||||||
while( !b.equals(BigInteger.ZERO) ){
|
|
||||||
list.add( new BigInteger("0").add( a.divide( b ) ) );
|
|
||||||
t = b;
|
|
||||||
b = a.mod( b );
|
|
||||||
a = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the Euclidean algorithm on the two input
|
||||||
|
* values.
|
||||||
|
*
|
||||||
|
* @param a is the first BigInteger
|
||||||
|
* @param b is the second BigInteger
|
||||||
|
* @return a BigInteger containing the GCD of the BigIntegers
|
||||||
|
*/
|
||||||
|
public static BigInteger calc(BigInteger a, BigInteger b){
|
||||||
|
BigInteger t;
|
||||||
|
|
||||||
|
while( !b.equals(BigInteger.ZERO) ){
|
||||||
|
t = b;
|
||||||
|
b = a.mod( b );
|
||||||
|
a = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the Euclidean algorithm on the two input
|
||||||
|
* values to find the generators for the values.
|
||||||
|
*
|
||||||
|
* @param a is the first integer
|
||||||
|
* @param b is the second integer
|
||||||
|
* @return a list of integers that is generators for a and b
|
||||||
|
*/
|
||||||
|
public static LinkedList<Integer> calcGenerators(int a, int b){
|
||||||
|
LinkedList<Integer> list = new LinkedList<Integer>();
|
||||||
|
int t;
|
||||||
|
|
||||||
|
while( b != 0 ){
|
||||||
|
list.add( a/b );
|
||||||
|
t = b;
|
||||||
|
b = a % b;
|
||||||
|
a = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the Euclidean algorithm on the two input
|
||||||
|
* values to find the generators for the values.
|
||||||
|
*
|
||||||
|
* @param a is the first BigInteger
|
||||||
|
* @param b is the second BigInteger
|
||||||
|
* @return a list of BigIntegers that is generators of a and b
|
||||||
|
*/
|
||||||
|
public static LinkedList<BigInteger> calcGenerators(BigInteger a, BigInteger b){
|
||||||
|
LinkedList<BigInteger> list = new LinkedList<BigInteger>();
|
||||||
|
BigInteger t;
|
||||||
|
|
||||||
|
while( !b.equals(BigInteger.ZERO) ){
|
||||||
|
list.add( new BigInteger("0").add( a.divide( b ) ) );
|
||||||
|
t = b;
|
||||||
|
b = a.mod( b );
|
||||||
|
a = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,76 +36,76 @@ import java.math.BigInteger;
|
||||||
* @see <a href="http://en.wikipedia.org/wiki/Shanks-Tonelli_algorithm">Wikipedia</a>
|
* @see <a href="http://en.wikipedia.org/wiki/Shanks-Tonelli_algorithm">Wikipedia</a>
|
||||||
*/
|
*/
|
||||||
public class ShanksTonelliAlgo {
|
public class ShanksTonelliAlgo {
|
||||||
public static BigInteger calc(BigInteger n, BigInteger p){
|
public static BigInteger calc(BigInteger n, BigInteger p){
|
||||||
|
|
||||||
BigInteger nOrg = n;
|
|
||||||
BigInteger S = null, V, R, U, X;
|
|
||||||
BigInteger ONE = BigInteger.ONE;
|
|
||||||
BigInteger TWO = BigInteger.valueOf( 2 );
|
|
||||||
BigInteger Q = p.add( ONE ).divide( TWO );
|
|
||||||
|
|
||||||
switch( p.mod( BigInteger.valueOf(4) ).intValue() ){
|
BigInteger nOrg = n;
|
||||||
case 3:
|
BigInteger S = null, V, R, U, X;
|
||||||
S = n.pow( Q.divide( TWO ).intValue() ).mod( p );
|
BigInteger ONE = BigInteger.ONE;
|
||||||
break;
|
BigInteger TWO = BigInteger.valueOf( 2 );
|
||||||
case 1:
|
BigInteger Q = p.add( ONE ).divide( TWO );
|
||||||
S = ONE;
|
|
||||||
n = n.subtract( ONE );
|
|
||||||
while (n.divide( p ).compareTo( ONE ) == 0) {
|
|
||||||
S = S.add( ONE );
|
|
||||||
//n = (n-2s+1) mod p
|
|
||||||
n = n.subtract( TWO.multiply( S ) ).add( ONE ).mod( p );
|
|
||||||
if (n.compareTo( BigInteger.ZERO ) == 0){
|
|
||||||
return S;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Q = Q.divide( TWO );
|
|
||||||
V = ONE;
|
|
||||||
R = S;
|
|
||||||
U = ONE;
|
|
||||||
while (Q.compareTo( BigInteger.ZERO ) > 0) {
|
|
||||||
X = R.pow(2).subtract( n.multiply( U.pow(2) ) ).mod( p );
|
|
||||||
U = TWO.multiply( R ).multiply( U ).mod( p );
|
|
||||||
R = X;
|
|
||||||
if ( Q.testBit(0) ){
|
|
||||||
X = S.multiply( R ).subtract( n.multiply(V).multiply(U) ).mod( p );
|
|
||||||
V = V.multiply(R).add( S.multiply(U) ).mod( p );
|
|
||||||
S = X;
|
|
||||||
}
|
|
||||||
Q = Q.divide( TWO );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( S != null && S.multiply( S ).mod( p ).compareTo( nOrg ) != 0 ){
|
switch( p.mod( BigInteger.valueOf(4) ).intValue() ){
|
||||||
return null;
|
case 3:
|
||||||
}
|
S = n.pow( Q.divide( TWO ).intValue() ).mod( p );
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
S = ONE;
|
||||||
|
n = n.subtract( ONE );
|
||||||
|
while (n.divide( p ).compareTo( ONE ) == 0) {
|
||||||
|
S = S.add( ONE );
|
||||||
|
//n = (n-2s+1) mod p
|
||||||
|
n = n.subtract( TWO.multiply( S ) ).add( ONE ).mod( p );
|
||||||
|
if (n.compareTo( BigInteger.ZERO ) == 0){
|
||||||
|
return S;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Q = Q.divide( TWO );
|
||||||
|
V = ONE;
|
||||||
|
R = S;
|
||||||
|
U = ONE;
|
||||||
|
while (Q.compareTo( BigInteger.ZERO ) > 0) {
|
||||||
|
X = R.pow(2).subtract( n.multiply( U.pow(2) ) ).mod( p );
|
||||||
|
U = TWO.multiply( R ).multiply( U ).mod( p );
|
||||||
|
R = X;
|
||||||
|
if ( Q.testBit(0) ){
|
||||||
|
X = S.multiply( R ).subtract( n.multiply(V).multiply(U) ).mod( p );
|
||||||
|
V = V.multiply(R).add( S.multiply(U) ).mod( p );
|
||||||
|
S = X;
|
||||||
|
}
|
||||||
|
Q = Q.divide( TWO );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return S;
|
if( S != null && S.multiply( S ).mod( p ).compareTo( nOrg ) != 0 ){
|
||||||
/*
|
return null;
|
||||||
|
}
|
||||||
//p-1 = Q*2^S
|
|
||||||
BigInteger S = null, Q = null, R = null, V = null, W = null;
|
|
||||||
|
|
||||||
//Q = ( 2^S )/( 1-p );
|
return S;
|
||||||
p-1 = ( 2^S )/( 1-p ) * 2^S;
|
/*
|
||||||
|
|
||||||
// R = n^( (Q+1)/2 ) mod p
|
//p-1 = Q*2^S
|
||||||
R = n.pow( Q.add(BigInteger.ONE).divide(BigInteger.valueOf(2)).intValue() ).mod( p );
|
BigInteger S = null, Q = null, R = null, V = null, W = null;
|
||||||
// V = W^Q mod p
|
|
||||||
V = W.pow( Q.intValue() ).mod( p );
|
|
||||||
|
|
||||||
for(int i=S.intValue(); true ;){
|
//Q = ( 2^S )/( 1-p );
|
||||||
while( true ){
|
p-1 = ( 2^S )/( 1-p ) * 2^S;
|
||||||
i--;
|
|
||||||
// 1 = ( ( R^2 * n^-1 )^2^i ) mod p
|
|
||||||
if( ( R.pow(2).multiply( n.pow(-1) ) ).pow( (int)Math.pow(2, i) ).mod( p ).compareTo( BigInteger.ONE ) == 0 )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(i == 0) return R;
|
// R = n^( (Q+1)/2 ) mod p
|
||||||
//R = ( RV^(2^(S-i-1)) ) mod p
|
R = n.pow( Q.add(BigInteger.ONE).divide(BigInteger.valueOf(2)).intValue() ).mod( p );
|
||||||
else R = ( R.multiply( V.pow( (int)Math.pow( 2, S.intValue()-i-1) ) )).mod( p );
|
// V = W^Q mod p
|
||||||
}
|
V = W.pow( Q.intValue() ).mod( p );
|
||||||
*/
|
|
||||||
}
|
for(int i=S.intValue(); true ;){
|
||||||
|
while( true ){
|
||||||
|
i--;
|
||||||
|
// 1 = ( ( R^2 * n^-1 )^2^i ) mod p
|
||||||
|
if( ( R.pow(2).multiply( n.pow(-1) ) ).pow( (int)Math.pow(2, i) ).mod( p ).compareTo( BigInteger.ONE ) == 0 )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i == 0) return R;
|
||||||
|
//R = ( RV^(2^(S-i-1)) ) mod p
|
||||||
|
else R = ( R.multiply( V.pow( (int)Math.pow( 2, S.intValue()-i-1) ) )).mod( p );
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,56 +38,56 @@ import java.util.LinkedList;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class WienersAlgo {
|
public class WienersAlgo {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the Wieners algorithm for the given values.
|
* Runs the Wieners algorithm for the given values.
|
||||||
*
|
*
|
||||||
* @param n is the first value
|
* @param n is the first value
|
||||||
* @param e is the second value
|
* @param e is the second value
|
||||||
* @return a BigInteger array of length two.
|
* @return a BigInteger array of length two.
|
||||||
* First index is p and second is q.
|
* First index is p and second is q.
|
||||||
* If no value was found then it returns null.
|
* If no value was found then it returns null.
|
||||||
*/
|
*/
|
||||||
public static BigInteger[] calc(BigInteger n, BigInteger e){
|
public static BigInteger[] calc(BigInteger n, BigInteger e){
|
||||||
BigInteger[] ret = null;
|
BigInteger[] ret = null;
|
||||||
|
|
||||||
LinkedList<BigInteger> gen = EuclideansAlgo.calcGenerators(e, n);
|
LinkedList<BigInteger> gen = EuclideansAlgo.calcGenerators(e, n);
|
||||||
|
|
||||||
BigInteger c0 = BigInteger.ONE;
|
BigInteger c0 = BigInteger.ONE;
|
||||||
BigInteger c1 = gen.poll();
|
BigInteger c1 = gen.poll();
|
||||||
BigInteger d0 = BigInteger.ZERO;
|
BigInteger d0 = BigInteger.ZERO;
|
||||||
BigInteger d1 = BigInteger.ONE;
|
BigInteger d1 = BigInteger.ONE;
|
||||||
|
|
||||||
BigInteger t, n1, g;
|
BigInteger t, n1, g;
|
||||||
while(!gen.isEmpty()){
|
while(!gen.isEmpty()){
|
||||||
g = gen.poll();
|
g = gen.poll();
|
||||||
|
|
||||||
t = c1;
|
t = c1;
|
||||||
c1 = g.multiply( c1 ).add( c0 );
|
c1 = g.multiply( c1 ).add( c0 );
|
||||||
c0 = t;
|
c0 = t;
|
||||||
|
|
||||||
t = d1;
|
t = d1;
|
||||||
d1 = g.multiply( d1 ).add( d0 );
|
d1 = g.multiply( d1 ).add( d0 );
|
||||||
d0 = t;
|
d0 = t;
|
||||||
|
|
||||||
// (d1*e-1) % c1 == 0
|
// (d1*e-1) % c1 == 0
|
||||||
n1 = d1.multiply( e ).subtract( BigInteger.ONE );
|
n1 = d1.multiply( e ).subtract( BigInteger.ONE );
|
||||||
if( n1.mod( c1 ).equals( BigInteger.ZERO ) ){
|
if( n1.mod( c1 ).equals( BigInteger.ZERO ) ){
|
||||||
n1 = n1.divide( c1 );
|
n1 = n1.divide( c1 );
|
||||||
|
|
||||||
// x^2 - ( n - n1 +1 )x + n = 0
|
// x^2 - ( n - n1 +1 )x + n = 0
|
||||||
ret = ZMath.pqFormula(
|
ret = ZMath.pqFormula(
|
||||||
n.subtract( n1 ).add( BigInteger.ONE ).negate(),
|
n.subtract( n1 ).add( BigInteger.ONE ).negate(),
|
||||||
n);
|
n);
|
||||||
|
|
||||||
if(ret[0].compareTo( BigInteger.ZERO ) >= 0 &&
|
if(ret[0].compareTo( BigInteger.ZERO ) >= 0 &&
|
||||||
ret[1].compareTo( BigInteger.ZERO ) >= 0 &&
|
ret[1].compareTo( BigInteger.ZERO ) >= 0 &&
|
||||||
ret[0].multiply( ret[1] ).equals( n )){
|
ret[0].multiply( ret[1] ).equals( n )){
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,42 +30,42 @@ import java.util.Queue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that uses BFS to find a path
|
* A class that uses BFS to find a path
|
||||||
*
|
*
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class BreadthFirstSearch implements PathFinder{
|
public class BreadthFirstSearch implements PathFinder{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the first path to the destination
|
* Returns the first path to the destination
|
||||||
*
|
*
|
||||||
* @param start is the start Node
|
* @param start is the start Node
|
||||||
* @param stop is the goal Node
|
* @param stop is the goal Node
|
||||||
* @return A list with the path
|
* @return A list with the path
|
||||||
*/
|
*/
|
||||||
public LinkedList<PathNode> find(PathNode start, PathNode stop){
|
public LinkedList<PathNode> find(PathNode start, PathNode stop){
|
||||||
Queue<PathNode> queue = new LinkedList<PathNode>();
|
Queue<PathNode> queue = new LinkedList<PathNode>();
|
||||||
HashSet<PathNode> visited = new HashSet<PathNode>();
|
HashSet<PathNode> visited = new HashSet<PathNode>();
|
||||||
|
|
||||||
queue.add(start);
|
queue.add(start);
|
||||||
visited.add( start );
|
visited.add( start );
|
||||||
|
|
||||||
PathNode tmp;
|
PathNode tmp;
|
||||||
while(!queue.isEmpty()){
|
while(!queue.isEmpty()){
|
||||||
tmp = queue.poll();
|
tmp = queue.poll();
|
||||||
|
|
||||||
for(PathNode next : tmp.getNeighbors()){
|
for(PathNode next : tmp.getNeighbors()){
|
||||||
if(!visited.contains( next ) && tmp.getNeighborCost(next) > 0){
|
if(!visited.contains( next ) && tmp.getNeighborCost(next) > 0){
|
||||||
queue.add(next);
|
queue.add(next);
|
||||||
visited.add( next );
|
visited.add( next );
|
||||||
next.setParentNeighbor(tmp);
|
next.setParentNeighbor(tmp);
|
||||||
|
|
||||||
if(next.equals(stop)){
|
if(next.equals(stop)){
|
||||||
return stop.traversTo(start);
|
return stop.traversTo(start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LinkedList<PathNode>();
|
return new LinkedList<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,42 +33,42 @@ import java.util.LinkedList;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class DepthFirstSearch {
|
public class DepthFirstSearch {
|
||||||
private HashSet<PathNode> visited = new HashSet<PathNode>();
|
private HashSet<PathNode> visited = new HashSet<PathNode>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the first path to the destination
|
* Returns the first path to the destination
|
||||||
*
|
*
|
||||||
* @param start Start Node
|
* @param start Start Node
|
||||||
* @param stop Stop Node
|
* @param stop Stop Node
|
||||||
* @return A list with the path
|
* @return A list with the path
|
||||||
*/
|
*/
|
||||||
public LinkedList<PathNode> find(PathNode start, PathNode stop){
|
public LinkedList<PathNode> find(PathNode start, PathNode stop){
|
||||||
visited.clear();
|
visited.clear();
|
||||||
PathNode node = dfs(start, stop);
|
PathNode node = dfs(start, stop);
|
||||||
return node.traversTo( start );
|
return node.traversTo( start );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The DepthFirstSearch algorithm
|
* The DepthFirstSearch algorithm
|
||||||
* @param node The node to search from
|
* @param node The node to search from
|
||||||
* @return The stop PathNode if a path was found else null
|
* @return The stop PathNode if a path was found else null
|
||||||
*/
|
*/
|
||||||
private PathNode dfs(PathNode node, PathNode stop){
|
private PathNode dfs(PathNode node, PathNode stop){
|
||||||
visited.add( node );
|
visited.add( node );
|
||||||
if(node.equals(stop)){
|
if(node.equals(stop)){
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(PathNode next : node.getNeighbors()){
|
for(PathNode next : node.getNeighbors()){
|
||||||
if(!visited.contains( next ) && node.getNeighborCost(next) > 0){
|
if(!visited.contains( next ) && node.getNeighborCost(next) > 0){
|
||||||
next.setParentNeighbor(node);
|
next.setParentNeighbor(node);
|
||||||
PathNode tmp = dfs(next, stop);
|
PathNode tmp = dfs(next, stop);
|
||||||
if(tmp != null){
|
if(tmp != null){
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,117 +25,117 @@
|
||||||
package zutil.algo.path;
|
package zutil.algo.path;
|
||||||
|
|
||||||
public class DynamicProgramming {
|
public class DynamicProgramming {
|
||||||
public static char[][] words = new char[][]{
|
public static char[][] words = new char[][]{
|
||||||
"bibba".toCharArray(),
|
"bibba".toCharArray(),
|
||||||
"bitas".toCharArray(),
|
"bitas".toCharArray(),
|
||||||
"brott".toCharArray(),
|
"brott".toCharArray(),
|
||||||
"bl<EFBFBD>ja".toCharArray(),
|
"bl<EFBFBD>ja".toCharArray(),
|
||||||
"boson".toCharArray()
|
"boson".toCharArray()
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void main(String[] args){
|
public static void main(String[] args){
|
||||||
new DynamicProgramming().search();
|
new DynamicProgramming().search();
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
||||||
int search(words[][][])
|
int search(words[][][])
|
||||||
matrix[][][] = 0
|
matrix[][][] = 0
|
||||||
shortest = -1
|
shortest = -1
|
||||||
|
|
||||||
for w=0->length(words)
|
for w=0->length(words)
|
||||||
for y=0->length(words)
|
for y=0->length(words)
|
||||||
for x=0->length(words)
|
for x=0->length(words)
|
||||||
// f<EFBFBD>rsta raden i matrisen
|
// f<EFBFBD>rsta raden i matrisen
|
||||||
if y == 0
|
if y == 0
|
||||||
// finns f<EFBFBD>rsta bokstaven i r<EFBFBD>tt position i f<EFBFBD>rsta ordet?
|
// finns f<EFBFBD>rsta bokstaven i r<EFBFBD>tt position i f<EFBFBD>rsta ordet?
|
||||||
if words[0][x] != words[w][0]
|
if words[0][x] != words[w][0]
|
||||||
matrix[w][y][x] = -1
|
matrix[w][y][x] = -1
|
||||||
else
|
else
|
||||||
matrix[w][y][x] = 0
|
matrix[w][y][x] = 0
|
||||||
else
|
else
|
||||||
// om f<EFBFBD>reg<EFBFBD>ende <EFBFBD>r negativ s<EFBFBD>tt nuvarande till negativ
|
// om f<EFBFBD>reg<EFBFBD>ende <EFBFBD>r negativ s<EFBFBD>tt nuvarande till negativ
|
||||||
if matrix[w][y-1][x] < 0
|
if matrix[w][y-1][x] < 0
|
||||||
matrix[w][y-1][x] = -1
|
matrix[w][y-1][x] = -1
|
||||||
// h<EFBFBD>r s<EFBFBD> h<EFBFBD>nder det riktiga i algoritmen
|
// h<EFBFBD>r s<EFBFBD> h<EFBFBD>nder det riktiga i algoritmen
|
||||||
else
|
else
|
||||||
tmp = minstaForskjutning(words[y], words[w][y], x)
|
tmp = minstaForskjutning(words[y], words[w][y], x)
|
||||||
if tmp >= 0
|
if tmp >= 0
|
||||||
matrix[w][y][x] = matrix[w][y-1][x] + tmp
|
matrix[w][y][x] = matrix[w][y-1][x] + tmp
|
||||||
else
|
else
|
||||||
matrix[w][y][x] = -1
|
matrix[w][y][x] = -1
|
||||||
// kolla om det <EFBFBD>r sista raden i matrisen
|
// kolla om det <EFBFBD>r sista raden i matrisen
|
||||||
if y == length(matrix)
|
if y == length(matrix)
|
||||||
if (tmp < shortest || shortest < 0) && tmp >= 0
|
if (tmp < shortest || shortest < 0) && tmp >= 0
|
||||||
shortest = tmp;
|
shortest = tmp;
|
||||||
|
|
||||||
return shortest
|
return shortest
|
||||||
|
|
||||||
int minstaForskjutning(word[], find, index){
|
int minstaForskjutning(word[], find, index){
|
||||||
minsta = -1
|
minsta = -1
|
||||||
for i=0->length(word)
|
for i=0->length(word)
|
||||||
if word[i] == cfind && (abs(index-i) < minsta || minsta < 0)
|
if word[i] == cfind && (abs(index-i) < minsta || minsta < 0)
|
||||||
minsta = abs(index-i)
|
minsta = abs(index-i)
|
||||||
|
|
||||||
return minsta
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
public int search(){
|
return minsta
|
||||||
int[][][] matrix = new int[words.length][words.length][words.length];
|
|
||||||
int shortest = -1;
|
|
||||||
|
|
||||||
for(int w=0; w<words.length ;w++){ //lodr<EFBFBD>ta ordet
|
*/
|
||||||
System.out.print("\n\n"+new String(words[w])+"\n ");
|
|
||||||
for(int y=0; y<words.length ;y++){ // v<EFBFBD>gr<EFBFBD>ta ordet
|
|
||||||
System.out.print("\n"+ new String(words[y])+": ");
|
|
||||||
for(int x=0; x<words.length ;x++){ // psition i y
|
|
||||||
// f<EFBFBD>rsta v<EFBFBD>gr<EFBFBD>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<EFBFBD>gr<EFBFBD>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);
|
public int search(){
|
||||||
return shortest;
|
int[][][] matrix = new int[words.length][words.length][words.length];
|
||||||
}
|
int shortest = -1;
|
||||||
|
|
||||||
private int minstaForskjutning(char[] word, char cfind, int index){
|
for(int w=0; w<words.length ;w++){ //lodr<EFBFBD>ta ordet
|
||||||
int minsta = -1;
|
System.out.print("\n\n"+new String(words[w])+"\n ");
|
||||||
for(int i=0; i<word.length ;i++){
|
for(int y=0; y<words.length ;y++){ // v<EFBFBD>gr<EFBFBD>ta ordet
|
||||||
if(word[i] == cfind && (Math.abs(index-i)<minsta || minsta<0)){
|
System.out.print("\n"+ new String(words[y])+": ");
|
||||||
minsta = Math.abs(index-i);
|
for(int x=0; x<words.length ;x++){ // psition i y
|
||||||
}
|
// f<EFBFBD>rsta v<EFBFBD>gr<EFBFBD>ta ordet
|
||||||
}
|
if(y == 0){
|
||||||
return minsta;
|
if(words[0][x] != words[w][0]){
|
||||||
}
|
matrix[w][y][x] = -1;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
matrix[w][y][x] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//resten av de v<EFBFBD>gr<EFBFBD>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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,13 @@ import java.util.LinkedList;
|
||||||
*/
|
*/
|
||||||
public interface PathFinder {
|
public interface PathFinder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the search for the path from the start
|
* Starts the search for the path from the start
|
||||||
* node to the goal.
|
* node to the goal.
|
||||||
*
|
*
|
||||||
* @param start is the starting point of the search
|
* @param start is the starting point of the search
|
||||||
* @param goal is the search goal
|
* @param goal is the search goal
|
||||||
* @return a LinkedList of the path, empty list if no path was found
|
* @return a LinkedList of the path, empty list if no path was found
|
||||||
*/
|
*/
|
||||||
public LinkedList<PathNode> find(PathNode start, PathNode goal);
|
public LinkedList<PathNode> find(PathNode start, PathNode goal);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,32 +29,32 @@ import java.util.LinkedList;
|
||||||
|
|
||||||
public interface PathNode {
|
public interface PathNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return an Iterator with all its neighbors
|
* @return an Iterator with all its neighbors
|
||||||
*/
|
*/
|
||||||
public Iterable<PathNode> getNeighbors();
|
public Iterable<PathNode> getNeighbors();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param neighbor is the neighbor
|
* @param neighbor is the neighbor
|
||||||
* @return the cost to the neighbor
|
* @return the cost to the neighbor
|
||||||
*/
|
*/
|
||||||
public int getNeighborCost(PathNode neighbor);
|
public int getNeighborCost(PathNode neighbor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the parent node to this one
|
* Sets the parent node to this one
|
||||||
*/
|
*/
|
||||||
public void setParentNeighbor(PathNode parent);
|
public void setParentNeighbor(PathNode parent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the parent node
|
* @return the parent node
|
||||||
*/
|
*/
|
||||||
public PathNode getParentNeighbor();
|
public PathNode getParentNeighbor();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Traverses the parent tree and returns the path.
|
* Traverses the parent tree and returns the path.
|
||||||
*
|
*
|
||||||
* @param goal is the node to reach
|
* @param goal is the node to reach
|
||||||
* @return the path to the goal, empty list if there is no goal
|
* @return the path to the goal, empty list if there is no goal
|
||||||
*/
|
*/
|
||||||
public LinkedList<PathNode> traversTo(PathNode goal);
|
public LinkedList<PathNode> traversTo(PathNode goal);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,32 +33,32 @@ import java.util.LinkedList;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class StandardPathNode implements PathNode{
|
public class StandardPathNode implements PathNode{
|
||||||
private HashMap<PathNode,Integer> neighbors;
|
private HashMap<PathNode,Integer> neighbors;
|
||||||
private PathNode parent;
|
private PathNode parent;
|
||||||
|
|
||||||
public StandardPathNode(){
|
|
||||||
neighbors = new HashMap<PathNode,Integer>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNeighborCost(PathNode neighbor) {
|
public StandardPathNode(){
|
||||||
return neighbors.get(neighbor);
|
neighbors = new HashMap<PathNode,Integer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterable<PathNode> getNeighbors() {
|
public int getNeighborCost(PathNode neighbor) {
|
||||||
return neighbors.keySet();
|
return neighbors.get(neighbor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PathNode getParentNeighbor() {
|
public Iterable<PathNode> getNeighbors() {
|
||||||
return parent;
|
return neighbors.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setParentNeighbor(PathNode parent) {
|
public PathNode getParentNeighbor() {
|
||||||
this.parent = parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LinkedList<PathNode> traversTo(PathNode goal) {
|
public void setParentNeighbor(PathNode parent) {
|
||||||
LinkedList<PathNode> path = new LinkedList<PathNode>();
|
this.parent = parent;
|
||||||
PathNode current = this;
|
}
|
||||||
|
|
||||||
|
public LinkedList<PathNode> traversTo(PathNode goal) {
|
||||||
|
LinkedList<PathNode> path = new LinkedList<PathNode>();
|
||||||
|
PathNode current = this;
|
||||||
while(current != null){
|
while(current != null){
|
||||||
path.addFirst(current);
|
path.addFirst(current);
|
||||||
current = current.getParentNeighbor();
|
current = current.getParentNeighbor();
|
||||||
|
|
@ -68,6 +68,6 @@ public class StandardPathNode implements PathNode{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new LinkedList<PathNode>();
|
return new LinkedList<PathNode>();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,57 +36,57 @@ import zutil.algo.sort.sortable.SortableDataList;
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
public class QuickSelect {
|
public class QuickSelect {
|
||||||
|
|
||||||
public static Object find(SortableDataList list, int k){
|
public static Object find(SortableDataList list, int k){
|
||||||
return find(list, k, 0, list.size()-1);
|
return find(list, k, 0, list.size()-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
function select(list, k, left, right)
|
function select(list, k, left, right)
|
||||||
select a pivot value list[pivotIndex]
|
select a pivot value list[pivotIndex]
|
||||||
pivotNewIndex := partition(list, left, right, pivotIndex)
|
pivotNewIndex := partition(list, left, right, pivotIndex)
|
||||||
if k = pivotNewIndex
|
if k = pivotNewIndex
|
||||||
return list[k]
|
return list[k]
|
||||||
else if k < pivotNewIndex
|
else if k < pivotNewIndex
|
||||||
return select(list, k, left, pivotNewIndex-1)
|
return select(list, k, left, pivotNewIndex-1)
|
||||||
else
|
else
|
||||||
return select(list, k, pivotNewIndex+1, right)
|
return select(list, k, pivotNewIndex+1, right)
|
||||||
*/
|
*/
|
||||||
public static Object find(SortableDataList list, int k, int left, int right){
|
public static Object find(SortableDataList list, int k, int left, int right){
|
||||||
// select a pivot
|
// select a pivot
|
||||||
int pivot = right/2;
|
int pivot = right/2;
|
||||||
int newPivot = partition(list, left, right, pivot);
|
int newPivot = partition(list, left, right, pivot);
|
||||||
if(k == newPivot)
|
if(k == newPivot)
|
||||||
return list.get(k);
|
return list.get(k);
|
||||||
else if(k < newPivot)
|
else if(k < newPivot)
|
||||||
return find(list, k, left, newPivot-1);
|
return find(list, k, left, newPivot-1);
|
||||||
else
|
else
|
||||||
return find(list, k, newPivot+1, right);
|
return find(list, k, newPivot+1, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
function partition(list, left, right, pivotIndex)
|
function partition(list, left, right, pivotIndex)
|
||||||
pivotValue := list[pivotIndex]
|
pivotValue := list[pivotIndex]
|
||||||
swap list[pivotIndex] and list[right] // Move pivot to end
|
swap list[pivotIndex] and list[right] // Move pivot to end
|
||||||
storeIndex := left
|
storeIndex := left
|
||||||
for i from left to right-1
|
for i from left to right-1
|
||||||
if list[i] < pivotValue
|
if list[i] < pivotValue
|
||||||
swap list[storeIndex] and list[i]
|
swap list[storeIndex] and list[i]
|
||||||
storeIndex := storeIndex + 1
|
storeIndex := storeIndex + 1
|
||||||
swap list[right] and list[storeIndex] // Move pivot to its final place
|
swap list[right] and list[storeIndex] // Move pivot to its final place
|
||||||
return storeIndex
|
return storeIndex
|
||||||
*/
|
*/
|
||||||
private static int partition(SortableDataList list, int left, int right, int pivot){
|
private static int partition(SortableDataList list, int left, int right, int pivot){
|
||||||
Object pivotValue = list.get(pivot);
|
Object pivotValue = list.get(pivot);
|
||||||
list.swap(pivot, right);
|
list.swap(pivot, right);
|
||||||
int storeIndex = left;
|
int storeIndex = left;
|
||||||
for(int i=left; i<right ;i++){
|
for(int i=left; i<right ;i++){
|
||||||
if(list.compare(i, pivotValue) < 0){
|
if(list.compare(i, pivotValue) < 0){
|
||||||
list.swap(storeIndex, i);
|
list.swap(storeIndex, i);
|
||||||
storeIndex = storeIndex+1;
|
storeIndex = storeIndex+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list.swap(right, storeIndex);
|
list.swap(right, storeIndex);
|
||||||
return storeIndex;
|
return storeIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,233 +37,233 @@ import java.util.LinkedList;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class ExternalSort {
|
public class ExternalSort {
|
||||||
public static int CHUNK_SIZE = 100000;
|
public static int CHUNK_SIZE = 100000;
|
||||||
|
|
||||||
private BufferedReader in;
|
private BufferedReader in;
|
||||||
private File sortedFile;
|
private File sortedFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a ExternalSort object that sort a big file
|
* Creates a ExternalSort object that sort a big file
|
||||||
* with minimal use of ram
|
* with minimal use of ram
|
||||||
*
|
*
|
||||||
* @param orgFile File to sort
|
* @param orgFile File to sort
|
||||||
* @param sortedFile The sorted file
|
* @param sortedFile The sorted file
|
||||||
* @throws FileNotFoundException
|
* @throws FileNotFoundException
|
||||||
*/
|
*/
|
||||||
public ExternalSort(File orgFile, File sortedFile) throws FileNotFoundException{
|
public ExternalSort(File orgFile, File sortedFile) throws FileNotFoundException{
|
||||||
in = new BufferedReader(new FileReader(orgFile));
|
in = new BufferedReader(new FileReader(orgFile));
|
||||||
this.sortedFile = sortedFile;
|
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
|
* Creates a ExternalSort object that sort a big file
|
||||||
*
|
* with minimal use of ram
|
||||||
* @throws IOException Some kind of error
|
*
|
||||||
*/
|
* @param orgFile File to sort
|
||||||
public void sort() throws IOException{
|
* @param sortedFile The sorted file
|
||||||
// sorting the chunks
|
* @param chunk The chunk size
|
||||||
LinkedList<File> chunkFiles = sortChunks();
|
* @throws FileNotFoundException
|
||||||
|
*/
|
||||||
|
public ExternalSort(File orgFile, File sortedFile, int chunk) throws FileNotFoundException{
|
||||||
|
in = new BufferedReader(new FileReader(orgFile));
|
||||||
|
this.sortedFile = sortedFile;
|
||||||
|
CHUNK_SIZE = chunk;
|
||||||
|
}
|
||||||
|
|
||||||
//merging the chunks
|
/**
|
||||||
mergeFiles(chunkFiles);
|
* Sorts the given file
|
||||||
|
*
|
||||||
|
* @throws IOException Some kind of error
|
||||||
|
*/
|
||||||
|
public void sort() throws IOException{
|
||||||
|
// sorting the chunks
|
||||||
|
LinkedList<File> chunkFiles = sortChunks();
|
||||||
|
|
||||||
//removing the chunks
|
//merging the chunks
|
||||||
removeFiles(chunkFiles);
|
mergeFiles(chunkFiles);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
//removing the chunks
|
||||||
* Merges all the files to one
|
removeFiles(chunkFiles);
|
||||||
* @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;
|
/**
|
||||||
|
* 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));
|
||||||
|
|
||||||
for (int i=0; i<files.size(); i++){
|
boolean someFileStillHasRows = false;
|
||||||
chunkReader[i] = new BufferedReader(new FileReader(files.get(i)));
|
|
||||||
|
|
||||||
// get the first row
|
for (int i=0; i<files.size(); i++){
|
||||||
String line = chunkReader[i].readLine();
|
chunkReader[i] = new BufferedReader(new FileReader(files.get(i)));
|
||||||
if (line != null){
|
|
||||||
rows[i] = line;
|
|
||||||
someFileStillHasRows = true;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
rows[i] = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
// 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];
|
String row;
|
||||||
if (row!=null) {
|
while (someFileStillHasRows){
|
||||||
min = row;
|
String min;
|
||||||
minIndex = 0;
|
int minIndex = 0;
|
||||||
}
|
|
||||||
else {
|
|
||||||
min = null;
|
|
||||||
minIndex = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check which one is minimum
|
row = rows[0];
|
||||||
for(int i=1; i<rows.length ;i++){
|
if (row!=null) {
|
||||||
row = rows[i];
|
min = row;
|
||||||
if (min!=null) {
|
minIndex = 0;
|
||||||
if(row!=null && row.compareTo(min) < 0){
|
}
|
||||||
minIndex = i;
|
else {
|
||||||
min = row;
|
min = null;
|
||||||
}
|
minIndex = -1;
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
if(row!=null){
|
|
||||||
min = row;
|
|
||||||
minIndex = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (minIndex < 0) {
|
// check which one is minimum
|
||||||
someFileStillHasRows = false;
|
for(int i=1; i<rows.length ;i++){
|
||||||
}
|
row = rows[i];
|
||||||
else{
|
if (min!=null) {
|
||||||
// write to the sorted file
|
if(row!=null && row.compareTo(min) < 0){
|
||||||
out.append(rows[minIndex]);
|
minIndex = i;
|
||||||
out.newLine();
|
min = row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(row!=null){
|
||||||
|
min = row;
|
||||||
|
minIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// get another row from the file that had the min
|
if (minIndex < 0) {
|
||||||
String line = chunkReader[minIndex].readLine();
|
someFileStillHasRows = false;
|
||||||
if (line != null){
|
}
|
||||||
rows[minIndex] = line;
|
else{
|
||||||
}
|
// write to the sorted file
|
||||||
else{
|
out.append(rows[minIndex]);
|
||||||
rows[minIndex] = null;
|
out.newLine();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
// get another row from the file that had the min
|
||||||
if (!someFileStillHasRows){
|
String line = chunkReader[minIndex].readLine();
|
||||||
//write the last one not covered above
|
if (line != null){
|
||||||
for(int i=0; i<rows.length ; i++){
|
rows[minIndex] = line;
|
||||||
if (rows[i] == null){
|
}
|
||||||
String line = chunkReader[i].readLine();
|
else{
|
||||||
if (line != null){
|
rows[minIndex] = 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// check if one still has rows
|
||||||
* Sorts the chunk files and returns a LinkedList
|
someFileStillHasRows = false;
|
||||||
* with all the files
|
for(int i=0; i<rows.length ; i++){
|
||||||
* @return A linkedList with the files
|
if(rows[i] != null){
|
||||||
* @throws IOException Some kind of error
|
if (minIndex < 0){
|
||||||
*/
|
throw(new IOException("Error sorting!!!"));
|
||||||
private LinkedList<File> sortChunks() throws IOException{
|
}
|
||||||
LinkedList<File> chunkFiles = new LinkedList<File>();
|
someFileStillHasRows = true;
|
||||||
LinkedList<String> chunk = new LinkedList<String>();
|
break;
|
||||||
do{
|
}
|
||||||
chunk = readChunk(in);
|
}
|
||||||
|
|
||||||
//QuickSort.sort(new SortableLinkedList(chunk));
|
// check the actual files one more time
|
||||||
Collections.sort(chunk);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
File file = new File("extsort"+chunkFiles.size()+".txt");
|
/**
|
||||||
chunkFiles.add(file);
|
* Sorts the chunk files and returns a LinkedList
|
||||||
writeChunk(chunk,file);
|
* with all the files
|
||||||
}while(!chunk.isEmpty());
|
* @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);
|
||||||
|
|
||||||
return chunkFiles;
|
//QuickSort.sort(new SortableLinkedList(chunk));
|
||||||
}
|
Collections.sort(chunk);
|
||||||
|
|
||||||
/**
|
File file = new File("extsort"+chunkFiles.size()+".txt");
|
||||||
* Reads in a chunk of rows into a LinkedList
|
chunkFiles.add(file);
|
||||||
*
|
writeChunk(chunk,file);
|
||||||
* @param list The list to populate
|
}while(!chunk.isEmpty());
|
||||||
* @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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return chunkFiles;
|
||||||
* 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();
|
* Reads in a chunk of rows into a LinkedList
|
||||||
while(it.hasNext()){
|
*
|
||||||
it.next().delete();
|
* @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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,131 +29,131 @@ import zutil.algo.sort.sortable.SortableDataList;
|
||||||
|
|
||||||
public class MergeSort{
|
public class MergeSort{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorts the given list with Merge sort
|
* Sorts the given list with Merge sort
|
||||||
*
|
*
|
||||||
* @param list is the list to sort
|
* @param list is the list to sort
|
||||||
*/
|
*/
|
||||||
public static void sort(int[] list){
|
public static void sort(int[] list){
|
||||||
if(list == null)
|
if(list == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sort(list, 0, list.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
sort(list, 0, list.length);
|
||||||
* This method is the array splitting method
|
}
|
||||||
* that recursively splits the array in two.
|
|
||||||
*
|
|
||||||
* @param list is the list to sort
|
|
||||||
* @param start is the starting index of the sub list
|
|
||||||
* @param stop is the end index of the sub list
|
|
||||||
*/
|
|
||||||
protected static void sort(int[] list, int start, int stop){
|
|
||||||
if(stop-start <= 1) return;
|
|
||||||
|
|
||||||
int pivot = start+(stop-start)/2;
|
/**
|
||||||
sort(list, start, pivot);
|
* This method is the array splitting method
|
||||||
sort(list, pivot, stop);
|
* that recursively splits the array in two.
|
||||||
|
*
|
||||||
|
* @param list is the list to sort
|
||||||
|
* @param start is the starting index of the sub list
|
||||||
|
* @param stop is the end index of the sub list
|
||||||
|
*/
|
||||||
|
protected static void sort(int[] list, int start, int stop){
|
||||||
|
if(stop-start <= 1) return;
|
||||||
|
|
||||||
merge(list, start, stop, pivot);
|
int pivot = start+(stop-start)/2;
|
||||||
}
|
sort(list, start, pivot);
|
||||||
|
sort(list, pivot, stop);
|
||||||
|
|
||||||
/**
|
merge(list, start, stop, pivot);
|
||||||
* This method is the merger, after the array
|
}
|
||||||
* has been split this method will merge the
|
|
||||||
* two parts of the array and sort it.
|
|
||||||
*
|
|
||||||
* @param list is the list to merge
|
|
||||||
* @param start is the start of the first sublist
|
|
||||||
* @param stop is the end of the second sublist
|
|
||||||
* @param pivot is the end index for the first list and the beginning of the second.
|
|
||||||
*/
|
|
||||||
protected static void merge(int[] list, int start, int stop, int pivot){
|
|
||||||
int length = pivot-start;
|
|
||||||
int[] tmp = new int[stop-start];
|
|
||||||
|
|
||||||
for(int i=0; i<tmp.length ;++i){
|
/**
|
||||||
tmp[i] = list[start+i];
|
* This method is the merger, after the array
|
||||||
}
|
* has been split this method will merge the
|
||||||
|
* two parts of the array and sort it.
|
||||||
|
*
|
||||||
|
* @param list is the list to merge
|
||||||
|
* @param start is the start of the first sublist
|
||||||
|
* @param stop is the end of the second sublist
|
||||||
|
* @param pivot is the end index for the first list and the beginning of the second.
|
||||||
|
*/
|
||||||
|
protected static void merge(int[] list, int start, int stop, int pivot){
|
||||||
|
int length = pivot-start;
|
||||||
|
int[] tmp = new int[stop-start];
|
||||||
|
|
||||||
int index1 = 0;
|
for(int i=0; i<tmp.length ;++i){
|
||||||
int index2 = length;
|
tmp[i] = list[start+i];
|
||||||
for(int i=start; i<stop ;++i){
|
}
|
||||||
if( index2 < stop-start && (index1 >= length || tmp[index1] > tmp[index2]) ){
|
|
||||||
list[i] = tmp[index2];
|
|
||||||
++index2;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
list[i] = tmp[index1];
|
|
||||||
++index1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sorts the given list with Merge sort,
|
|
||||||
* this is slower than the one with int[] array
|
|
||||||
*
|
|
||||||
* @param list is the list to sort
|
|
||||||
*/
|
|
||||||
public static void sort(SortableDataList<?> list){
|
|
||||||
if(list == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sort(list, 0, list.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
int index1 = 0;
|
||||||
* This method is the array splitting method
|
int index2 = length;
|
||||||
* that recursively splits the array in two.
|
for(int i=start; i<stop ;++i){
|
||||||
*
|
if( index2 < stop-start && (index1 >= length || tmp[index1] > tmp[index2]) ){
|
||||||
* @param list is the list to sort
|
list[i] = tmp[index2];
|
||||||
* @param start is the starting index of the sub list
|
++index2;
|
||||||
* @param stop is the end index of the sub list
|
}
|
||||||
*/
|
else {
|
||||||
protected static void sort(SortableDataList<?> list, int start, int stop){
|
list[i] = tmp[index1];
|
||||||
if(stop-start <= 1) return;
|
++index1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int pivot = start+(stop-start)/2;
|
|
||||||
sort(list, start, pivot);
|
|
||||||
sort(list, pivot, stop);
|
|
||||||
|
|
||||||
merge(list, start, stop, pivot);
|
/**
|
||||||
}
|
* Sorts the given list with Merge sort,
|
||||||
|
* this is slower than the one with int[] array
|
||||||
|
*
|
||||||
|
* @param list is the list to sort
|
||||||
|
*/
|
||||||
|
public static void sort(SortableDataList<?> list){
|
||||||
|
if(list == null)
|
||||||
|
return;
|
||||||
|
|
||||||
/**
|
sort(list, 0, list.size());
|
||||||
* This method is the merger, after the array
|
}
|
||||||
* has been split this method will merge the
|
|
||||||
* two parts of the array and sort it.
|
|
||||||
* @param <T>
|
|
||||||
*
|
|
||||||
* @param list is the list to merge
|
|
||||||
* @param start is the start of the first sublist
|
|
||||||
* @param stop is the end of the second sublist
|
|
||||||
* @param pivot is the end index for the first list and the beginning of the second.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
|
||||||
protected static <T> void merge(SortableDataList<T> list, int start, int stop, int pivot){
|
|
||||||
int length = pivot-start;
|
|
||||||
Object[] tmp = new Object[stop-start];
|
|
||||||
|
|
||||||
for(int i=0; i<tmp.length ;++i){
|
/**
|
||||||
tmp[i] = list.get( start+i );
|
* This method is the array splitting method
|
||||||
}
|
* that recursively splits the array in two.
|
||||||
|
*
|
||||||
|
* @param list is the list to sort
|
||||||
|
* @param start is the starting index of the sub list
|
||||||
|
* @param stop is the end index of the sub list
|
||||||
|
*/
|
||||||
|
protected static void sort(SortableDataList<?> list, int start, int stop){
|
||||||
|
if(stop-start <= 1) return;
|
||||||
|
|
||||||
int index1 = 0;
|
int pivot = start+(stop-start)/2;
|
||||||
int index2 = length;
|
sort(list, start, pivot);
|
||||||
for(int i=start; i<stop ;++i){
|
sort(list, pivot, stop);
|
||||||
if( index2 < stop-start && (index1 >= length || ((Comparable)tmp[index1]).compareTo(tmp[index2]) > 0 )){
|
|
||||||
list.set(i, (T)tmp[index2]);
|
merge(list, start, stop, pivot);
|
||||||
++index2;
|
}
|
||||||
}
|
|
||||||
else {
|
/**
|
||||||
list.set(i, (T)tmp[index1]);
|
* This method is the merger, after the array
|
||||||
++index1;
|
* has been split this method will merge the
|
||||||
}
|
* two parts of the array and sort it.
|
||||||
}
|
* @param <T>
|
||||||
}
|
*
|
||||||
|
* @param list is the list to merge
|
||||||
|
* @param start is the start of the first sublist
|
||||||
|
* @param stop is the end of the second sublist
|
||||||
|
* @param pivot is the end index for the first list and the beginning of the second.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
|
protected static <T> void merge(SortableDataList<T> list, int start, int stop, int pivot){
|
||||||
|
int length = pivot-start;
|
||||||
|
Object[] tmp = new Object[stop-start];
|
||||||
|
|
||||||
|
for(int i=0; i<tmp.length ;++i){
|
||||||
|
tmp[i] = list.get( start+i );
|
||||||
|
}
|
||||||
|
|
||||||
|
int index1 = 0;
|
||||||
|
int index2 = length;
|
||||||
|
for(int i=start; i<stop ;++i){
|
||||||
|
if( index2 < stop-start && (index1 >= length || ((Comparable)tmp[index1]).compareTo(tmp[index2]) > 0 )){
|
||||||
|
list.set(i, (T)tmp[index2]);
|
||||||
|
++index2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
list.set(i, (T)tmp[index1]);
|
||||||
|
++index1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,17 +33,17 @@ import zutil.algo.sort.sortable.SortableDataList;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class QuickSort{
|
public class QuickSort{
|
||||||
public static final int RANDOM_PIVOT = 0;
|
public static final int RANDOM_PIVOT = 0;
|
||||||
public static final int MEDIAN_PIVOT = 1;
|
public static final int MEDIAN_PIVOT = 1;
|
||||||
public static final int MIDDLE_PIVOT = 2;
|
public static final int MIDDLE_PIVOT = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort the elements in ascending order using Quicksort.
|
* Sort the elements in ascending order using Quicksort.
|
||||||
*
|
*
|
||||||
* @param list is the list to sort.
|
* @param list is the list to sort.
|
||||||
*/
|
*/
|
||||||
public static void sort(SortableDataList<?> list){
|
public static void sort(SortableDataList<?> list){
|
||||||
sort(list, 0, list.size()-1, MIDDLE_PIVOT, true);
|
sort(list, 0, list.size()-1, MIDDLE_PIVOT, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -53,10 +53,10 @@ public class QuickSort{
|
||||||
* @param type is the type of pivot
|
* @param type is the type of pivot
|
||||||
* @param insert is if insertion sort will be used
|
* @param insert is if insertion sort will be used
|
||||||
*/
|
*/
|
||||||
public static void sort(SortableDataList<?> list, int type, boolean insert){
|
public static void sort(SortableDataList<?> list, int type, boolean insert){
|
||||||
sort(list, 0, list.size()-1, type, insert);
|
sort(list, 0, list.size()-1, type, insert);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort the elements in ascending order using Quicksort.
|
* Sort the elements in ascending order using Quicksort.
|
||||||
* Reference: http://www.inf.fh-flensburg.de/lang/algorithmen/sortieren/quick/quicken.htm
|
* Reference: http://www.inf.fh-flensburg.de/lang/algorithmen/sortieren/quick/quicken.htm
|
||||||
|
|
@ -67,59 +67,59 @@ public class QuickSort{
|
||||||
* @param stop is the index to stop
|
* @param stop is the index to stop
|
||||||
* @param type is the type of pivot to use
|
* @param type is the type of pivot to use
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
public static void sort(SortableDataList list, int start, int stop, int type, boolean insertionSort){
|
public static void sort(SortableDataList list, int start, int stop, int type, boolean insertionSort){
|
||||||
if(stop-start <= 15 && insertionSort){
|
if(stop-start <= 15 && insertionSort){
|
||||||
SimpleSort.insertionSort( list, start, stop);
|
SimpleSort.insertionSort( list, start, stop);
|
||||||
}
|
}
|
||||||
int pivotIndex = pivot(list,start,stop,type);
|
int pivotIndex = pivot(list,start,stop,type);
|
||||||
Object pivot = list.get(pivotIndex);
|
Object pivot = list.get(pivotIndex);
|
||||||
int left=start, right=stop;
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
do{
|
||||||
|
while(list.compare(left, pivot) < 0){
|
||||||
|
left++;
|
||||||
|
}
|
||||||
|
while(list.compare(right, pivot) > 0){
|
||||||
|
right--;
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
if(left <= right){
|
||||||
private static int pivot(SortableDataList<?> list, int start, int stop,int type){
|
list.swap(left, right);
|
||||||
switch(type){
|
left++;
|
||||||
case RANDOM_PIVOT:
|
right--;
|
||||||
return start+(int)(Math.random()*(stop-start));
|
}
|
||||||
case MEDIAN_PIVOT:
|
}while(left <= right);
|
||||||
Comparable[] i = new Comparable[]{
|
|
||||||
(Comparable)list.get(0),
|
if(start < right){
|
||||||
(Comparable)list.get(list.size()/2),
|
sort(list, start, right, type, insertionSort);
|
||||||
(Comparable)list.get(list.size()-1)};
|
}
|
||||||
SimpleSort.insertionSort(new SortableComparableArray(i));
|
if(left < stop){
|
||||||
if(i[i.length/2].compareTo(list.get(start)) == 0)
|
sort(list, left, stop, type, insertionSort);
|
||||||
return start;
|
}
|
||||||
else if(i[i.length/2].compareTo(list.get(stop)) == 0)
|
|
||||||
return stop;
|
}
|
||||||
else
|
|
||||||
return start+(stop-start)/2;
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
case MIDDLE_PIVOT:
|
private static int pivot(SortableDataList<?> list, int start, int stop,int type){
|
||||||
return (start+stop)/2;
|
switch(type){
|
||||||
}
|
case RANDOM_PIVOT:
|
||||||
return 0;
|
return start+(int)(Math.random()*(stop-start));
|
||||||
|
case MEDIAN_PIVOT:
|
||||||
|
Comparable[] i = new Comparable[]{
|
||||||
|
(Comparable)list.get(0),
|
||||||
|
(Comparable)list.get(list.size()/2),
|
||||||
|
(Comparable)list.get(list.size()-1)};
|
||||||
|
SimpleSort.insertionSort(new SortableComparableArray(i));
|
||||||
|
if(i[i.length/2].compareTo(list.get(start)) == 0)
|
||||||
|
return start;
|
||||||
|
else if(i[i.length/2].compareTo(list.get(stop)) == 0)
|
||||||
|
return stop;
|
||||||
|
else
|
||||||
|
return start+(stop-start)/2;
|
||||||
|
case MIDDLE_PIVOT:
|
||||||
|
return (start+stop)/2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,16 +33,16 @@ import zutil.algo.sort.sortable.SortableDataList;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class Randomizer {
|
public class Randomizer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Randomizes the index of all the elements
|
* Randomizes the index of all the elements
|
||||||
* @param list The list
|
* @param list The list
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "rawtypes" })
|
@SuppressWarnings({ "rawtypes" })
|
||||||
public static void sort(SortableDataList list){
|
public static void sort(SortableDataList list){
|
||||||
int size = list.size();
|
int size = list.size();
|
||||||
for(int i=0; i<size ;i++){
|
for(int i=0; i<size ;i++){
|
||||||
list.swap(i, (int)(Math.random()*size));
|
list.swap(i, (int)(Math.random()*size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,42 +28,39 @@ import java.util.ArrayList;
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
public class SortableArrayList<T> implements SortableDataList<T>{
|
public class SortableArrayList<T> implements SortableDataList<T>{
|
||||||
private ArrayList<T> list;
|
private ArrayList<T> list;
|
||||||
|
|
||||||
public SortableArrayList(ArrayList<T> list){
|
|
||||||
this.list = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T get(int i) {
|
public SortableArrayList(ArrayList<T> list){
|
||||||
return list.get(i);
|
this.list = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(int i, T o){
|
|
||||||
list.set(i, o);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int size() {
|
public T get(int i) {
|
||||||
return list.size();
|
return list.get(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void swap(int a, int b) {
|
public void set(int i, T o){
|
||||||
T temp = list.get(a);
|
list.set(i, o);
|
||||||
list.set(a, list.get(b));
|
}
|
||||||
list.set(b, temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int compare(int a, int b) {
|
|
||||||
Comparable aa = (Comparable)list.get(a);
|
|
||||||
Comparable bb = (Comparable)list.get(b);
|
|
||||||
return aa.compareTo(bb);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int compare(int a, T b) {
|
public int size() {
|
||||||
Comparable aa = (Comparable)list.get(a);
|
return list.size();
|
||||||
Comparable bb = (Comparable)b;
|
}
|
||||||
return aa.compareTo(bb);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void swap(int a, int b) {
|
||||||
|
T temp = list.get(a);
|
||||||
|
list.set(a, list.get(b));
|
||||||
|
list.set(b, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compare(int a, int b) {
|
||||||
|
Comparable aa = (Comparable)list.get(a);
|
||||||
|
Comparable bb = (Comparable)list.get(b);
|
||||||
|
return aa.compareTo(bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compare(int a, T b) {
|
||||||
|
Comparable aa = (Comparable)list.get(a);
|
||||||
|
Comparable bb = (Comparable)b;
|
||||||
|
return aa.compareTo(bb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,50 +26,47 @@ package zutil.algo.sort.sortable;
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
public class SortableComparableArray implements SortableDataList<Comparable>{
|
public class SortableComparableArray implements SortableDataList<Comparable>{
|
||||||
private Comparable[] list;
|
private Comparable[] list;
|
||||||
|
|
||||||
public SortableComparableArray(Comparable[] list){
|
|
||||||
this.list = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Comparable get(int i) {
|
|
||||||
return list[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void set(int i, Comparable o){
|
|
||||||
list[i] = o;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int size() {
|
public SortableComparableArray(Comparable[] list){
|
||||||
return list.length;
|
this.list = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void swap(int a, int b) {
|
public Comparable get(int i) {
|
||||||
Comparable temp = list[a];
|
return list[i];
|
||||||
list[a] = list[b];
|
}
|
||||||
list[b] = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int compare(int a, int b) {
|
public void set(int i, Comparable o){
|
||||||
if(list[a].compareTo(list[b]) < 0){
|
list[i] = o;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
else if(list[a].compareTo(list[b]) > 0){
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int compare(int a, Comparable b) {
|
public int size() {
|
||||||
if(list[a].compareTo(b) < 0){
|
return list.length;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
else if(list[a].compareTo(b) > 0){
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,49 +25,49 @@
|
||||||
package zutil.algo.sort.sortable;
|
package zutil.algo.sort.sortable;
|
||||||
|
|
||||||
public class SortableIntArray implements SortableDataList<Integer>{
|
public class SortableIntArray implements SortableDataList<Integer>{
|
||||||
private int[] list;
|
private int[] list;
|
||||||
|
|
||||||
public SortableIntArray(int[] list){
|
|
||||||
this.list = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer get(int i) {
|
|
||||||
return list[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void set(int i, Integer o){
|
public SortableIntArray(int[] list){
|
||||||
list[i] = o;
|
this.list = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
|
||||||
return list.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void swap(int a, int b) {
|
public Integer get(int i) {
|
||||||
int temp = list[a];
|
return list[i];
|
||||||
list[a] = list[b];
|
}
|
||||||
list[b] = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int compare(int a, int b) {
|
public void set(int i, Integer o){
|
||||||
if(list[a] < list[b]){
|
list[i] = o;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
else if(list[a] > list[b]){
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int compare(int a, Integer b) {
|
public int size() {
|
||||||
if(list[a] < b){
|
return list.length;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
else if(list[a] > b){
|
public void swap(int a, int b) {
|
||||||
return 1;
|
int temp = list[a];
|
||||||
}
|
list[a] = list[b];
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,42 +28,42 @@ import java.util.LinkedList;
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
public class SortableLinkedList<T> implements SortableDataList<T>{
|
public class SortableLinkedList<T> implements SortableDataList<T>{
|
||||||
private LinkedList<T> list;
|
private LinkedList<T> list;
|
||||||
|
|
||||||
public SortableLinkedList(LinkedList<T> list){
|
|
||||||
this.list = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T get(int i) {
|
public SortableLinkedList(LinkedList<T> list){
|
||||||
return list.get(i);
|
this.list = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(int i, T o){
|
|
||||||
list.set(i, o);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int size() {
|
public T get(int i) {
|
||||||
return list.size();
|
return list.get(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void set(int i, T o){
|
||||||
|
list.set(i, o);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compare(int a, int b) {
|
||||||
|
Comparable aa = (Comparable)list.get(a);
|
||||||
|
Comparable bb = (Comparable)list.get(b);
|
||||||
|
return aa.compareTo(bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compare(int a, T b) {
|
||||||
|
Comparable aa = (Comparable)list.get(a);
|
||||||
|
Comparable bb = (Comparable)b;
|
||||||
|
return aa.compareTo(bb);
|
||||||
|
}
|
||||||
|
|
||||||
public void swap(int a, int b) {
|
|
||||||
T temp = list.get(a);
|
|
||||||
list.set(a, list.get(b));
|
|
||||||
list.set(b, temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int compare(int a, int b) {
|
|
||||||
Comparable aa = (Comparable)list.get(a);
|
|
||||||
Comparable bb = (Comparable)list.get(b);
|
|
||||||
return aa.compareTo(bb);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int compare(int a, T b) {
|
|
||||||
Comparable aa = (Comparable)list.get(a);
|
|
||||||
Comparable bb = (Comparable)b;
|
|
||||||
return aa.compareTo(bb);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,61 +33,61 @@ import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class Converter {
|
public class Converter {
|
||||||
private Converter(){}
|
private Converter(){}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an object to an array of bytes.
|
* Converts an object to an array of bytes.
|
||||||
*
|
*
|
||||||
* @param object the object to convert.
|
* @param object the object to convert.
|
||||||
* @return the associated byte array.
|
* @return the associated byte array.
|
||||||
*/
|
*/
|
||||||
public static byte[] toBytes(Object object) throws IOException{
|
public static byte[] toBytes(Object object) throws IOException{
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
|
||||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||||
oos.writeObject(object);
|
oos.writeObject(object);
|
||||||
oos.flush();
|
oos.flush();
|
||||||
oos.close();
|
oos.close();
|
||||||
|
|
||||||
return baos.toByteArray();
|
return baos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a Integer to an byte array
|
* Converts a Integer to an byte array
|
||||||
*
|
*
|
||||||
* @param num is the number to convert
|
* @param num is the number to convert
|
||||||
* @return a byte array of four bytes
|
* @return a byte array of four bytes
|
||||||
*/
|
*/
|
||||||
public static byte[] toBytes(int num){
|
public static byte[] toBytes(int num){
|
||||||
return new byte[]{
|
return new byte[]{
|
||||||
(byte)(num & 0xff),
|
(byte)(num & 0xff),
|
||||||
(byte)((num >> 8)& 0xff),
|
(byte)((num >> 8)& 0xff),
|
||||||
(byte)((num >> 16)& 0xff),
|
(byte)((num >> 16)& 0xff),
|
||||||
(byte)((num >> 24)& 0xff)};
|
(byte)((num >> 24)& 0xff)};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a char array to a byte array.
|
* Converts a char array to a byte array.
|
||||||
*
|
*
|
||||||
* @return a byte array with the same binary value as the char.
|
* @return a byte array with the same binary value as the char.
|
||||||
*/
|
*/
|
||||||
public static byte[] toBytes(char[] arr){
|
public static byte[] toBytes(char[] arr){
|
||||||
byte[] ret = new byte[arr.length];
|
byte[] ret = new byte[arr.length];
|
||||||
for (int i=0; i<arr.length; ++i)
|
for (int i=0; i<arr.length; ++i)
|
||||||
ret[i] = (byte) (arr[i] & 0xFF);
|
ret[i] = (byte) (arr[i] & 0xFF);
|
||||||
//System.arraycopy(arr, 0, ret, 0, arr.length); // does not work if char value is largen than 128
|
//System.arraycopy(arr, 0, ret, 0, arr.length); // does not work if char value is largen than 128
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a Integer to a byte
|
* Converts a Integer to a byte
|
||||||
*
|
*
|
||||||
* @param num is the number to convert
|
* @param num is the number to convert
|
||||||
* @return a byte value of the integer
|
* @return a byte value of the integer
|
||||||
*/
|
*/
|
||||||
public static byte toByte(int num){
|
public static byte toByte(int num){
|
||||||
return (byte)(num & 0xff);
|
return (byte)(num & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts hex string to a byte array
|
* Converts hex string to a byte array
|
||||||
|
|
@ -110,76 +110,76 @@ public class Converter {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts hex chars to a byte
|
* Converts hex chars to a byte
|
||||||
*
|
*
|
||||||
* @param quad1 is the first hex value
|
* @param quad1 is the first hex value
|
||||||
* @param quad2 is the second hex value
|
* @param quad2 is the second hex value
|
||||||
* @return a byte that corresponds to the hex
|
* @return a byte that corresponds to the hex
|
||||||
*/
|
*/
|
||||||
public static byte hexToByte( char quad1, char quad2){
|
public static byte hexToByte( char quad1, char quad2){
|
||||||
byte b = hexToByte( quad2 );
|
byte b = hexToByte( quad2 );
|
||||||
b |= hexToByte( quad1 ) << 4;
|
b |= hexToByte( quad1 ) << 4;
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a hex chars to a byte
|
|
||||||
*
|
|
||||||
* @param hex is the hex value
|
|
||||||
* @return a byte that corresponds to the hex
|
|
||||||
* @throws IllegalArgumentException if hex is not a valid hex character
|
|
||||||
*/
|
|
||||||
public static byte hexToByte( char hex ) throws IllegalArgumentException{
|
|
||||||
switch( Character.toLowerCase(hex) ){
|
|
||||||
case '0': return 0x00;
|
|
||||||
case '1': return 0x01;
|
|
||||||
case '2': return 0x02;
|
|
||||||
case '3': return 0x03;
|
|
||||||
case '4': return 0x04;
|
|
||||||
case '5': return 0x05;
|
|
||||||
case '6': return 0x06;
|
|
||||||
case '7': return 0x07;
|
|
||||||
case '8': return 0x08;
|
|
||||||
case '9': return 0x09;
|
|
||||||
case 'a': return 0x0a;
|
|
||||||
case 'b': return 0x0b;
|
|
||||||
case 'c': return 0x0c;
|
|
||||||
case 'd': return 0x0d;
|
|
||||||
case 'e': return 0x0e;
|
|
||||||
case 'f': return 0x0f;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("'"+hex+"' is an illegal hex character only 0-9 and a-f characters allowed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an array of bytes back to its constituent object. The
|
* Converts a hex chars to a byte
|
||||||
* input array is assumed to have been created from the original object.
|
*
|
||||||
*
|
* @param hex is the hex value
|
||||||
* @param bytes the byte array to convert.
|
* @return a byte that corresponds to the hex
|
||||||
* @return the associated object.
|
* @throws IllegalArgumentException if hex is not a valid hex character
|
||||||
*/
|
*/
|
||||||
public static Object toObject(byte[] bytes) throws Exception{
|
public static byte hexToByte( char hex ) throws IllegalArgumentException{
|
||||||
Object object;
|
switch( Character.toLowerCase(hex) ){
|
||||||
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
|
case '0': return 0x00;
|
||||||
object = ois.readObject();
|
case '1': return 0x01;
|
||||||
ois.close();
|
case '2': return 0x02;
|
||||||
|
case '3': return 0x03;
|
||||||
|
case '4': return 0x04;
|
||||||
|
case '5': return 0x05;
|
||||||
|
case '6': return 0x06;
|
||||||
|
case '7': return 0x07;
|
||||||
|
case '8': return 0x08;
|
||||||
|
case '9': return 0x09;
|
||||||
|
case 'a': return 0x0a;
|
||||||
|
case 'b': return 0x0b;
|
||||||
|
case 'c': return 0x0c;
|
||||||
|
case 'd': return 0x0d;
|
||||||
|
case 'e': return 0x0e;
|
||||||
|
case 'f': return 0x0f;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("'"+hex+"' is an illegal hex character only 0-9 and a-f characters allowed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return object;
|
/**
|
||||||
}
|
* 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) throws Exception{
|
||||||
|
Object object;
|
||||||
|
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
|
||||||
|
object = ois.readObject();
|
||||||
|
ois.close();
|
||||||
|
|
||||||
/**
|
return object;
|
||||||
* Reads the first Java Serialized object from a stream.
|
}
|
||||||
*
|
|
||||||
* @param input the stream to read from
|
/**
|
||||||
* @return an parsed object.
|
* Reads the first Java Serialized object from a stream.
|
||||||
*/
|
*
|
||||||
public static Object toObject(InputStream input) throws Exception{
|
* @param input the stream to read from
|
||||||
ObjectInputStream ois = new ObjectInputStream(input);
|
* @return an parsed object.
|
||||||
// Don't close the stream as it will close the underlying stream.
|
*/
|
||||||
return ois.readObject();
|
public static Object toObject(InputStream input) throws Exception{
|
||||||
}
|
ObjectInputStream ois = new ObjectInputStream(input);
|
||||||
|
// Don't close the stream as it will close the underlying stream.
|
||||||
|
return ois.readObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -188,122 +188,122 @@ public class Converter {
|
||||||
* @param raw the byte array to convert
|
* @param raw the byte array to convert
|
||||||
* @return a bit String
|
* @return a bit String
|
||||||
*/
|
*/
|
||||||
public static String toBitString(byte raw){
|
public static String toBitString(byte raw){
|
||||||
StringBuilder str = new StringBuilder(8);
|
StringBuilder str = new StringBuilder(8);
|
||||||
for (int i=0; i<8; ++i) {
|
for (int i=0; i<8; ++i) {
|
||||||
str.append(raw & 0x01);
|
str.append(raw & 0x01);
|
||||||
raw >>>= 1;
|
raw >>>= 1;
|
||||||
}
|
}
|
||||||
return str.reverse().toString();
|
return str.reverse().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** array needed for byteToHex */
|
/** array needed for byteToHex */
|
||||||
private static char[] HEX_CHARS = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
|
private static char[] HEX_CHARS = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
|
||||||
/**
|
/**
|
||||||
* Converts a byte Array to a Hex String
|
* Converts a byte Array to a Hex String
|
||||||
*
|
*
|
||||||
* @param raw the byte array to convert
|
* @param raw the byte array to convert
|
||||||
* @return a hex String
|
* @return a hex String
|
||||||
*/
|
*/
|
||||||
public static String toHexString(byte[][] raw){
|
public static String toHexString(byte[][] raw){
|
||||||
StringBuffer ret = new StringBuffer();
|
StringBuffer ret = new StringBuffer();
|
||||||
|
|
||||||
for(byte[] a : raw){
|
|
||||||
for(byte b : a){
|
|
||||||
ret.append(HEX_CHARS[(int) (b >>> 0x04)& 0x0F ]);
|
|
||||||
ret.append(HEX_CHARS[(int) b & 0x0F ]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret.toString();
|
for(byte[] a : raw){
|
||||||
}
|
for(byte b : a){
|
||||||
|
ret.append(HEX_CHARS[(int) (b >>> 0x04)& 0x0F ]);
|
||||||
|
ret.append(HEX_CHARS[(int) b & 0x0F ]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static String toHexStringByColumn(byte[][] raw){
|
return ret.toString();
|
||||||
StringBuffer ret = new StringBuffer();
|
}
|
||||||
|
|
||||||
for(int col=0; col<raw[0].length ;col++){
|
|
||||||
for(int row=0; row<raw.length ;row++){
|
|
||||||
ret.append(HEX_CHARS[(int) (raw[row][col] >>> 0x04)& 0x0F ]);
|
|
||||||
ret.append(HEX_CHARS[(int) raw[row][col] & 0x0F ]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret.toString();
|
public static String toHexStringByColumn(byte[][] raw){
|
||||||
}
|
StringBuffer ret = new StringBuffer();
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a byte Array to a Hex String
|
|
||||||
*
|
|
||||||
* @param raw the byte array to convert
|
|
||||||
* @return a hex String
|
|
||||||
*/
|
|
||||||
public static String toHexString(byte[] raw){
|
|
||||||
StringBuffer ret = new StringBuffer();
|
|
||||||
|
|
||||||
for(byte b : raw){
|
for(int col=0; col<raw[0].length ;col++){
|
||||||
ret.append(HEX_CHARS[(int) (b >>> 0x04)& 0x0F ]);
|
for(int row=0; row<raw.length ;row++){
|
||||||
ret.append(HEX_CHARS[(int) b & 0x0F ]);
|
ret.append(HEX_CHARS[(int) (raw[row][col] >>> 0x04)& 0x0F ]);
|
||||||
}
|
ret.append(HEX_CHARS[(int) raw[row][col] & 0x0F ]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret.toString();
|
return ret.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a byte to a Hex String
|
* Converts a byte Array to a Hex String
|
||||||
*
|
*
|
||||||
* @param raw the byte to convert
|
* @param raw the byte array to convert
|
||||||
* @return a hex String
|
* @return a hex String
|
||||||
*/
|
*/
|
||||||
public static String toHexString(byte raw){
|
public static String toHexString(byte[] raw){
|
||||||
String ret = ""+HEX_CHARS[(int) (raw >>> 0x04)& 0x0F ];
|
StringBuffer ret = new StringBuffer();
|
||||||
ret += ""+HEX_CHARS[(int) raw & 0x0F ];
|
|
||||||
|
|
||||||
return ret;
|
for(byte b : raw){
|
||||||
}
|
ret.append(HEX_CHARS[(int) (b >>> 0x04)& 0x0F ]);
|
||||||
|
ret.append(HEX_CHARS[(int) b & 0x0F ]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
return ret.toString();
|
||||||
* Converts the given byte to a String with 1's and 0's
|
}
|
||||||
*
|
|
||||||
* @param raw the byte to convert
|
|
||||||
* @return a String with 1's and 0's
|
|
||||||
*/
|
|
||||||
public static String toString(byte raw){
|
|
||||||
StringBuffer ret = new StringBuffer();
|
|
||||||
for(int i=128; i>0 ;i=( i<1 ? i=0 : i/2 ) ){
|
|
||||||
ret.append(( (raw & i) == 0 ? '0' : '1'));
|
|
||||||
}
|
|
||||||
return ret.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the given byte array to a String with 1's and 0's
|
* Converts a byte to a Hex String
|
||||||
*
|
*
|
||||||
* @param raw the byte array to convert
|
* @param raw the byte to convert
|
||||||
* @return a String with 1's and 0's
|
* @return a hex String
|
||||||
*/
|
*/
|
||||||
public static String toString(byte[] raw){
|
public static String toHexString(byte raw){
|
||||||
StringBuffer ret = new StringBuffer();
|
String ret = ""+HEX_CHARS[(int) (raw >>> 0x04)& 0x0F ];
|
||||||
for(byte b : raw){
|
ret += ""+HEX_CHARS[(int) raw & 0x0F ];
|
||||||
for(int i=128; i>0 ;i=( i<1 ? i=0 : i/2 ) ){
|
|
||||||
ret.append(( (b & i) == 0 ? '0' : '1'));
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return ret.toString();
|
/**
|
||||||
}
|
* Converts the given byte to a String with 1's and 0's
|
||||||
|
*
|
||||||
|
* @param raw the byte to convert
|
||||||
|
* @return a String with 1's and 0's
|
||||||
|
*/
|
||||||
|
public static String toString(byte raw){
|
||||||
|
StringBuffer ret = new StringBuffer();
|
||||||
|
for(int i=128; i>0 ;i=( i<1 ? i=0 : i/2 ) ){
|
||||||
|
ret.append(( (raw & i) == 0 ? '0' : '1'));
|
||||||
|
}
|
||||||
|
return ret.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given byte array to a String with 1's and 0's
|
||||||
|
*
|
||||||
|
* @param raw the byte array to convert
|
||||||
|
* @return a String with 1's and 0's
|
||||||
|
*/
|
||||||
|
public static String toString(byte[] raw){
|
||||||
|
StringBuffer ret = new StringBuffer();
|
||||||
|
for(byte b : raw){
|
||||||
|
for(int i=128; i>0 ;i=( i<1 ? i=0 : i/2 ) ){
|
||||||
|
ret.append(( (b & i) == 0 ? '0' : '1'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret.toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a comma separated string with key and value pairs
|
* Generates a comma separated string with key and value pairs
|
||||||
*
|
*
|
||||||
* @return a comma separated String
|
* @return a comma separated String
|
||||||
*/
|
*/
|
||||||
public static String toString(Map map){
|
public static String toString(Map map){
|
||||||
StringBuilder tmp = new StringBuilder();
|
StringBuilder tmp = new StringBuilder();
|
||||||
tmp.append("{");
|
tmp.append("{");
|
||||||
Iterator<Object> it = map.keySet().iterator();
|
Iterator<Object> it = map.keySet().iterator();
|
||||||
while(it.hasNext()){
|
while(it.hasNext()){
|
||||||
Object key = it.next();
|
Object key = it.next();
|
||||||
Object value = map.get(key);
|
Object value = map.get(key);
|
||||||
tmp.append(key);
|
tmp.append(key);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
if (value instanceof String)
|
if (value instanceof String)
|
||||||
tmp.append(": \"").append(value).append("\"");
|
tmp.append(": \"").append(value).append("\"");
|
||||||
|
|
@ -313,158 +313,158 @@ public class Converter {
|
||||||
else
|
else
|
||||||
tmp.append("null");
|
tmp.append("null");
|
||||||
|
|
||||||
if(it.hasNext())
|
if(it.hasNext())
|
||||||
tmp.append(", ");
|
tmp.append(", ");
|
||||||
}
|
}
|
||||||
tmp.append('}');
|
tmp.append('}');
|
||||||
return tmp.toString();
|
return tmp.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a BitSet to a Integer
|
* Converts a BitSet to a Integer
|
||||||
*
|
*
|
||||||
* @param bits the BitSet to convert
|
* @param bits the BitSet to convert
|
||||||
* @return a Integer
|
* @return a Integer
|
||||||
*/
|
*/
|
||||||
public static int toInt(BitSet bits){
|
public static int toInt(BitSet bits){
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
for (int i = bits.nextSetBit(0); i >= 0; i = bits.nextSetBit(i+1)) {
|
for (int i = bits.nextSetBit(0); i >= 0; i = bits.nextSetBit(i+1)) {
|
||||||
ret += Math.pow(2, i);
|
ret += Math.pow(2, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a boolean array(bit sequence whit most significant bit at index 0) to a Integer
|
|
||||||
*
|
|
||||||
* @param bits the boolean array to convert
|
|
||||||
* @return a Integer
|
|
||||||
*/
|
|
||||||
public static int toInt(boolean[] bits){
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
for (int i = bits.length-1; i >= 0; i--) {
|
/**
|
||||||
if(bits[i])ret += Math.pow(2, bits.length-i-1);
|
* Converts a boolean array(bit sequence whit most significant bit at index 0) to a Integer
|
||||||
}
|
*
|
||||||
|
* @param bits the boolean array to convert
|
||||||
|
* @return a Integer
|
||||||
|
*/
|
||||||
|
public static int toInt(boolean[] bits){
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
return ret;
|
for (int i = bits.length-1; i >= 0; i--) {
|
||||||
}
|
if(bits[i])ret += Math.pow(2, bits.length-i-1);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Converts a byte to a integer
|
|
||||||
*
|
|
||||||
* @param b is the byte to convert
|
|
||||||
* @return the integer value of the byte
|
|
||||||
*/
|
|
||||||
public static int toInt(byte b){
|
|
||||||
return (int)(b & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return ret;
|
||||||
* Converts a dynamic sized byte array to a integer
|
}
|
||||||
*
|
|
||||||
* @param b is the byte array of size 1-4
|
|
||||||
* @return the int value of the byte array
|
|
||||||
*/
|
|
||||||
public static int toInt(byte[] b){
|
|
||||||
int i = 0;
|
|
||||||
switch (b.length){
|
|
||||||
default:
|
|
||||||
case 4: i |= 0xFF000000 & (b[3] << 24);
|
|
||||||
case 3: i |= 0x00FF0000 & (b[2] << 16);
|
|
||||||
case 2: i |= 0x0000FF00 & (b[1] << 8);
|
|
||||||
case 1: i |= 0x000000FF & b[0];
|
|
||||||
case 0: break;
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a Integer to a BitSet
|
* Converts a byte to a integer
|
||||||
*
|
*
|
||||||
* @param num the Integer to convert
|
* @param b is the byte to convert
|
||||||
* @return a BitSet object
|
* @return the integer value of the byte
|
||||||
*/
|
*/
|
||||||
public static BitSet toBitSet(int num){
|
public static int toInt(byte b){
|
||||||
BitSet ret = new BitSet();
|
return (int)(b & 0xff);
|
||||||
String tmp = Integer.toBinaryString(num);
|
}
|
||||||
|
|
||||||
for(int i=0; i<tmp.length() ;i++){
|
/**
|
||||||
ret.set(i , tmp.charAt(tmp.length()-i-1) != '0');
|
* Converts a dynamic sized byte array to a integer
|
||||||
}
|
*
|
||||||
return ret;
|
* @param b is the byte array of size 1-4
|
||||||
}
|
* @return the int value of the byte array
|
||||||
|
*/
|
||||||
|
public static int toInt(byte[] b){
|
||||||
|
int i = 0;
|
||||||
|
switch (b.length){
|
||||||
|
default:
|
||||||
|
case 4: i |= 0xFF000000 & (b[3] << 24);
|
||||||
|
case 3: i |= 0x00FF0000 & (b[2] << 16);
|
||||||
|
case 2: i |= 0x0000FF00 & (b[1] << 8);
|
||||||
|
case 1: i |= 0x000000FF & b[0];
|
||||||
|
case 0: break;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a given String to a specified class
|
* Converts a Integer to a BitSet
|
||||||
*
|
*
|
||||||
* @param <T> is the resulting class
|
* @param num the Integer to convert
|
||||||
* @param data is the String data to be converted
|
* @return a BitSet object
|
||||||
* @param c is the class to convert to
|
*/
|
||||||
* @return a instance of the class with the value in the string or null if there was an problem
|
public static BitSet toBitSet(int num){
|
||||||
*/
|
BitSet ret = new BitSet();
|
||||||
@SuppressWarnings("unchecked")
|
String tmp = Integer.toBinaryString(num);
|
||||||
public static <T> T fromString(String data, Class<T> c){
|
|
||||||
if(data == null || data.isEmpty())
|
for(int i=0; i<tmp.length() ;i++){
|
||||||
return null;
|
ret.set(i , tmp.charAt(tmp.length()-i-1) != '0');
|
||||||
try{
|
}
|
||||||
if( c == String.class) return (T) data;
|
return ret;
|
||||||
else if(c == Integer.class) return (T) new Integer(data);
|
}
|
||||||
else if(c == int.class) return (T) new Integer(data);
|
|
||||||
else if(c == Long.class) return (T) new Long(data);
|
|
||||||
else if(c == long.class) return (T) new Long(data);
|
/**
|
||||||
else if(c == Float.class) return (T) new Float(data);
|
* Converts a given String to a specified class
|
||||||
else if(c == float.class) return (T) new Float(data);
|
*
|
||||||
else if(c == Double.class) return (T) new Double(data);
|
* @param <T> is the resulting class
|
||||||
else if(c == double.class) return (T) new Double(data);
|
* @param data is the String data to be converted
|
||||||
else if(c == Boolean.class) return (T) new Boolean(data);
|
* @param c is the class to convert to
|
||||||
else if(c == boolean.class) return (T) new Boolean(data);
|
* @return a instance of the class with the value in the string or null if there was an problem
|
||||||
else if(c == Byte.class) return (T) new Byte(data);
|
*/
|
||||||
else if(c == byte.class) return (T) new Byte(data);
|
@SuppressWarnings("unchecked")
|
||||||
else if(byte[].class.isAssignableFrom(c))
|
public static <T> T fromString(String data, Class<T> c){
|
||||||
return (T) Base64Decoder.decode(data);
|
if(data == null || data.isEmpty())
|
||||||
}catch(Exception e){
|
return null;
|
||||||
e.printStackTrace();
|
try{
|
||||||
}
|
if( c == String.class) return (T) data;
|
||||||
return null;
|
else if(c == Integer.class) return (T) new Integer(data);
|
||||||
}
|
else if(c == int.class) return (T) new Integer(data);
|
||||||
|
else if(c == Long.class) return (T) new Long(data);
|
||||||
/**
|
else if(c == long.class) return (T) new Long(data);
|
||||||
* Replaces reserved and unsafe characters in URLs with hex values
|
else if(c == Float.class) return (T) new Float(data);
|
||||||
*/
|
else if(c == float.class) return (T) new Float(data);
|
||||||
public static String urlEncode( String str ){
|
else if(c == Double.class) return (T) new Double(data);
|
||||||
StringBuilder out = new StringBuilder();
|
else if(c == double.class) return (T) new Double(data);
|
||||||
for( char c : str.toCharArray() ){
|
else if(c == Boolean.class) return (T) new Boolean(data);
|
||||||
if( c>='0' && c<='9' || c>='A' && c<='Z' || c>='a' && c<='z' ||
|
else if(c == boolean.class) return (T) new Boolean(data);
|
||||||
c=='$' || c=='-' || c=='_' || c=='.' || c=='+' || c=='!' ||
|
else if(c == Byte.class) return (T) new Byte(data);
|
||||||
c=='*' || c=='\'' || c=='(' || c==')' || c==',' )
|
else if(c == byte.class) return (T) new Byte(data);
|
||||||
out.append( c );
|
else if(byte[].class.isAssignableFrom(c))
|
||||||
else{
|
return (T) Base64Decoder.decode(data);
|
||||||
out.append( '%' ).append( toHexString((byte)c) );
|
}catch(Exception e){
|
||||||
}
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
return out.toString();
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Replaces reserved and unsafe characters in URLs with hex values
|
||||||
* Replaces hex values from a URL with the proper characters
|
*/
|
||||||
*/
|
public static String urlEncode( String str ){
|
||||||
public static String urlDecode( String str ){
|
StringBuilder out = new StringBuilder();
|
||||||
StringBuilder out = new StringBuilder();
|
for( char c : str.toCharArray() ){
|
||||||
char[] array = str.toCharArray();
|
if( c>='0' && c<='9' || c>='A' && c<='Z' || c>='a' && c<='z' ||
|
||||||
for( int i=0; i<array.length ;i++ ){
|
c=='$' || c=='-' || c=='_' || c=='.' || c=='+' || c=='!' ||
|
||||||
char c = array[i];
|
c=='*' || c=='\'' || c=='(' || c==')' || c==',' )
|
||||||
if( c == '%' && i+2<array.length ){
|
out.append( c );
|
||||||
out.append( (char)hexToByte( array[++i], array[++i]) );
|
else{
|
||||||
}
|
out.append( '%' ).append( toHexString((byte)c) );
|
||||||
else
|
}
|
||||||
out.append( c );
|
}
|
||||||
}
|
|
||||||
|
return out.toString();
|
||||||
return out.toString();
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* Replaces hex values from a URL with the proper characters
|
||||||
|
*/
|
||||||
|
public static String urlDecode( String str ){
|
||||||
|
StringBuilder out = new StringBuilder();
|
||||||
|
char[] array = str.toCharArray();
|
||||||
|
for( int i=0; i<array.length ;i++ ){
|
||||||
|
char c = array[i];
|
||||||
|
if( c == '%' && i+2<array.length ){
|
||||||
|
out.append( (char)hexToByte( array[++i], array[++i]) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
out.append( c );
|
||||||
|
}
|
||||||
|
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,90 +27,90 @@ package zutil.converter;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
public class NumberToWordsConverter {
|
public class NumberToWordsConverter {
|
||||||
|
|
||||||
private static final String ZERO_STRINGS = "zero";
|
private static final String ZERO_STRINGS = "zero";
|
||||||
// Indexes to lookup
|
// Indexes to lookup
|
||||||
private static final int[] NUMERIC_INDEXES = new int[]{
|
private static final int[] NUMERIC_INDEXES = new int[]{
|
||||||
9,/*1000 000 000*/
|
9,/*1000 000 000*/
|
||||||
6,/*1000 000*/
|
6,/*1000 000*/
|
||||||
3,/*1000*/
|
3,/*1000*/
|
||||||
2 /*100*/};
|
2 /*100*/};
|
||||||
private static final HashMap<Long, String> NUMERIC_STRINGS;
|
private static final HashMap<Long, String> NUMERIC_STRINGS;
|
||||||
static{
|
static{
|
||||||
NUMERIC_STRINGS = new HashMap<>();
|
NUMERIC_STRINGS = new HashMap<>();
|
||||||
NUMERIC_STRINGS.put(1l, "one");
|
NUMERIC_STRINGS.put(1l, "one");
|
||||||
NUMERIC_STRINGS.put(2l, "two");
|
NUMERIC_STRINGS.put(2l, "two");
|
||||||
NUMERIC_STRINGS.put(3l, "three");
|
NUMERIC_STRINGS.put(3l, "three");
|
||||||
NUMERIC_STRINGS.put(4l, "four");
|
NUMERIC_STRINGS.put(4l, "four");
|
||||||
NUMERIC_STRINGS.put(5l, "five");
|
NUMERIC_STRINGS.put(5l, "five");
|
||||||
NUMERIC_STRINGS.put(6l, "six");
|
NUMERIC_STRINGS.put(6l, "six");
|
||||||
NUMERIC_STRINGS.put(7l, "seven");
|
NUMERIC_STRINGS.put(7l, "seven");
|
||||||
NUMERIC_STRINGS.put(8l, "eight");
|
NUMERIC_STRINGS.put(8l, "eight");
|
||||||
NUMERIC_STRINGS.put(9l, "nine");
|
NUMERIC_STRINGS.put(9l, "nine");
|
||||||
NUMERIC_STRINGS.put(10l, "ten");
|
NUMERIC_STRINGS.put(10l, "ten");
|
||||||
NUMERIC_STRINGS.put(11l, "eleven");
|
NUMERIC_STRINGS.put(11l, "eleven");
|
||||||
NUMERIC_STRINGS.put(12l, "twelve");
|
NUMERIC_STRINGS.put(12l, "twelve");
|
||||||
NUMERIC_STRINGS.put(13l, "thirteen");
|
NUMERIC_STRINGS.put(13l, "thirteen");
|
||||||
NUMERIC_STRINGS.put(14l, "fourteen");
|
NUMERIC_STRINGS.put(14l, "fourteen");
|
||||||
NUMERIC_STRINGS.put(15l, "fifteen");
|
NUMERIC_STRINGS.put(15l, "fifteen");
|
||||||
NUMERIC_STRINGS.put(16l, "sixteen");
|
NUMERIC_STRINGS.put(16l, "sixteen");
|
||||||
NUMERIC_STRINGS.put(17l, "seventeen");
|
NUMERIC_STRINGS.put(17l, "seventeen");
|
||||||
NUMERIC_STRINGS.put(18l, "eightteen");
|
NUMERIC_STRINGS.put(18l, "eightteen");
|
||||||
NUMERIC_STRINGS.put(19l, "nineteen");
|
NUMERIC_STRINGS.put(19l, "nineteen");
|
||||||
|
|
||||||
NUMERIC_STRINGS.put(20l, "twenty");
|
NUMERIC_STRINGS.put(20l, "twenty");
|
||||||
NUMERIC_STRINGS.put(30l, "thirty");
|
NUMERIC_STRINGS.put(30l, "thirty");
|
||||||
NUMERIC_STRINGS.put(40l, "forty");
|
NUMERIC_STRINGS.put(40l, "forty");
|
||||||
NUMERIC_STRINGS.put(50l, "fifty");
|
NUMERIC_STRINGS.put(50l, "fifty");
|
||||||
NUMERIC_STRINGS.put(60l, "sixty");
|
NUMERIC_STRINGS.put(60l, "sixty");
|
||||||
NUMERIC_STRINGS.put(70l, "seventy");
|
NUMERIC_STRINGS.put(70l, "seventy");
|
||||||
NUMERIC_STRINGS.put(80l, "eighty");
|
NUMERIC_STRINGS.put(80l, "eighty");
|
||||||
NUMERIC_STRINGS.put(90l, "ninety");
|
NUMERIC_STRINGS.put(90l, "ninety");
|
||||||
|
|
||||||
NUMERIC_STRINGS.put(100l, "hundred");
|
NUMERIC_STRINGS.put(100l, "hundred");
|
||||||
NUMERIC_STRINGS.put(1_000l, "thousand");
|
NUMERIC_STRINGS.put(1_000l, "thousand");
|
||||||
NUMERIC_STRINGS.put(1000_000l, "million");
|
NUMERIC_STRINGS.put(1000_000l, "million");
|
||||||
NUMERIC_STRINGS.put(1000_000_000l, "billion");
|
NUMERIC_STRINGS.put(1000_000_000l, "billion");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given an integer in the range -20 to 20 will return a String with
|
* Given an integer in the range -20 to 20 will return a String with
|
||||||
* that number converted to words. For example, an input of 15 results in
|
* that number converted to words. For example, an input of 15 results in
|
||||||
* an output of "fifteen". An input of -4 returns "minus four".
|
* an output of "fifteen". An input of -4 returns "minus four".
|
||||||
*
|
*
|
||||||
* @param num a number to be converted to words.
|
* @param num a number to be converted to words.
|
||||||
* @return the number as words.
|
* @return the number as words.
|
||||||
*/
|
*/
|
||||||
public String convert(int num) {
|
public String convert(int num) {
|
||||||
if (num == 0)
|
if (num == 0)
|
||||||
return ZERO_STRINGS;
|
return ZERO_STRINGS;
|
||||||
|
|
||||||
long tmpNum = num;
|
long tmpNum = num;
|
||||||
StringBuilder buffer = new StringBuilder();
|
StringBuilder buffer = new StringBuilder();
|
||||||
if (tmpNum < 0){ // Negative number
|
if (tmpNum < 0){ // Negative number
|
||||||
tmpNum *= -1;
|
tmpNum *= -1;
|
||||||
buffer.append("minus ");
|
buffer.append("minus ");
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i : NUMERIC_INDEXES){
|
for(int i : NUMERIC_INDEXES){
|
||||||
long pow = (int)Math.pow(10, i);
|
long pow = (int)Math.pow(10, i);
|
||||||
if (tmpNum >= pow){
|
if (tmpNum >= pow){
|
||||||
long numberAtIndex = tmpNum/pow; // The number at position 3
|
long numberAtIndex = tmpNum/pow; // The number at position 3
|
||||||
tmpNum -= numberAtIndex*pow;
|
tmpNum -= numberAtIndex*pow;
|
||||||
buffer.append( convert((int)numberAtIndex) ).append(" ");
|
buffer.append( convert((int)numberAtIndex) ).append(" ");
|
||||||
buffer.append( NUMERIC_STRINGS.get( pow ) ).append(" ");
|
buffer.append( NUMERIC_STRINGS.get( pow ) ).append(" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tmpNum >= 20){ // second number in the integer
|
if (tmpNum >= 20){ // second number in the integer
|
||||||
long numberAtIndex = ((tmpNum % 100)/10)*10; // The number at position 2
|
long numberAtIndex = ((tmpNum % 100)/10)*10; // The number at position 2
|
||||||
tmpNum -= numberAtIndex;
|
tmpNum -= numberAtIndex;
|
||||||
buffer.append( NUMERIC_STRINGS.get(numberAtIndex) ).append(" ");
|
buffer.append( NUMERIC_STRINGS.get(numberAtIndex) ).append(" ");
|
||||||
}
|
}
|
||||||
if (NUMERIC_STRINGS.containsKey(tmpNum))
|
if (NUMERIC_STRINGS.containsKey(tmpNum))
|
||||||
buffer.append(NUMERIC_STRINGS.get(tmpNum));
|
buffer.append(NUMERIC_STRINGS.get(tmpNum));
|
||||||
return buffer.toString().trim();
|
return buffer.toString().trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,48 +25,48 @@
|
||||||
package zutil.converter;
|
package zutil.converter;
|
||||||
|
|
||||||
public class WGS84Converter {
|
public class WGS84Converter {
|
||||||
public static void main(String[] args){
|
public static void main(String[] args){
|
||||||
System.out.println(toWGS84Decimal("N 59<35> 47' 43\"")+" "+toWGS84Decimal(" E 17<31> 42' 55\""));
|
System.out.println(toWGS84Decimal("N 59<35> 47' 43\"")+" "+toWGS84Decimal(" E 17<31> 42' 55\""));
|
||||||
System.out.println(toWGS84Decimal("55<EFBFBD> 0' 0\"")+" "+toWGS84Decimal("68<EFBFBD> 59' 59,999\""));
|
System.out.println(toWGS84Decimal("55<EFBFBD> 0' 0\"")+" "+toWGS84Decimal("68<EFBFBD> 59' 59,999\""));
|
||||||
System.out.println(toWGS84Decimal("55<EFBFBD> 0.001'")+" "+toWGS84Decimal("68<EFBFBD> 59.999'"));
|
System.out.println(toWGS84Decimal("55<EFBFBD> 0.001'")+" "+toWGS84Decimal("68<EFBFBD> 59.999'"));
|
||||||
System.out.println(toWGS84Decimal("3444.0000S")+" "+toWGS84Decimal("13521.0000E"));
|
System.out.println(toWGS84Decimal("3444.0000S")+" "+toWGS84Decimal("13521.0000E"));
|
||||||
System.out.println(toWGS84Decimal("-44.0001")+" "+toWGS84Decimal("521.0001"));
|
System.out.println(toWGS84Decimal("-44.0001")+" "+toWGS84Decimal("521.0001"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an WGS84 coordinate to an WGS84 decimal coordinate
|
* Converts an WGS84 coordinate to an WGS84 decimal coordinate
|
||||||
*
|
*
|
||||||
* @param coordinate is the coordinate to convert
|
* @param coordinate is the coordinate to convert
|
||||||
* @return the new coordinate in decimal degrees, returns 0 if conversions fails
|
* @return the new coordinate in decimal degrees, returns 0 if conversions fails
|
||||||
*/
|
*/
|
||||||
public static float toWGS84Decimal(String coordinate){
|
public static float toWGS84Decimal(String coordinate){
|
||||||
float deg=0, min=0, sec=0, neg=1;
|
float deg=0, min=0, sec=0, neg=1;
|
||||||
coordinate = coordinate.trim().replaceAll(",", ".").toUpperCase();
|
coordinate = coordinate.trim().replaceAll(",", ".").toUpperCase();
|
||||||
if(coordinate.contains("S") || coordinate.contains("W"))
|
if(coordinate.contains("S") || coordinate.contains("W"))
|
||||||
neg = -1;
|
neg = -1;
|
||||||
|
|
||||||
// 55<EFBFBD> 0' 68<EFBFBD> 59,999 or 55<EFBFBD> 0' 0" 68<36> 59' 59,999"
|
// 55<EFBFBD> 0' 68<EFBFBD> 59,999 or 55<EFBFBD> 0' 0" 68<36> 59' 59,999"
|
||||||
if(coordinate.matches("[NSWE ]? ?[0-9]{1,3}<7D> [0-9]{1,2}.?[0-9]*'[ 0-9.\\\"]*")){
|
if(coordinate.matches("[NSWE ]? ?[0-9]{1,3}<7D> [0-9]{1,2}.?[0-9]*'[ 0-9.\\\"]*")){
|
||||||
coordinate = coordinate.replaceAll("[NSEW<45>'\\\"]", "").trim();
|
coordinate = coordinate.replaceAll("[NSEW<45>'\\\"]", "").trim();
|
||||||
String[] tmp = coordinate.split(" ");
|
String[] tmp = coordinate.split(" ");
|
||||||
deg = Float.parseFloat(tmp[0]);
|
deg = Float.parseFloat(tmp[0]);
|
||||||
min = Float.parseFloat(tmp[1]);
|
min = Float.parseFloat(tmp[1]);
|
||||||
if(tmp.length > 2){
|
if(tmp.length > 2){
|
||||||
sec = Float.parseFloat(tmp[2]);
|
sec = Float.parseFloat(tmp[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 3444.0000S 13521.0000E
|
// 3444.0000S 13521.0000E
|
||||||
else if(coordinate.matches("[0-9]{4,5}.[0-9]*[NSEW]{1}")){
|
else if(coordinate.matches("[0-9]{4,5}.[0-9]*[NSEW]{1}")){
|
||||||
coordinate = coordinate.replaceAll("[NS EW]", "");
|
coordinate = coordinate.replaceAll("[NS EW]", "");
|
||||||
float tmpf = Float.parseFloat(coordinate);
|
float tmpf = Float.parseFloat(coordinate);
|
||||||
deg = (int)(tmpf/100);
|
deg = (int)(tmpf/100);
|
||||||
min = tmpf-(deg*100);
|
min = tmpf-(deg*100);
|
||||||
}
|
}
|
||||||
// 55.0 68.99999
|
// 55.0 68.99999
|
||||||
else if(coordinate.matches("\\-?[0-9]{2,3}.[0-9]*")){
|
else if(coordinate.matches("\\-?[0-9]{2,3}.[0-9]*")){
|
||||||
return Float.parseFloat(coordinate);
|
return Float.parseFloat(coordinate);
|
||||||
}
|
}
|
||||||
|
|
||||||
return neg*(deg + min/60 + sec/3600);
|
return neg*(deg + min/60 + sec/3600);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,162 +37,162 @@ import java.util.TimerTask;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class DBConnectionPool extends TimerTask implements Closeable{
|
public class DBConnectionPool extends TimerTask implements Closeable{
|
||||||
public static final long DEFAULT_TIMEOUT = 10*60*60*1000; // 10 minutes;
|
public static final long DEFAULT_TIMEOUT = 10*60*60*1000; // 10 minutes;
|
||||||
public static final int DEFAULT_MAX_SIZE = 5;
|
public static final int DEFAULT_MAX_SIZE = 5;
|
||||||
|
|
||||||
// DB details
|
|
||||||
private DBMS dbms;
|
|
||||||
private String url;
|
|
||||||
private String db;
|
|
||||||
private String user;
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
// Pool details
|
// DB details
|
||||||
private int max_conn;
|
private DBMS dbms;
|
||||||
private long timeout;
|
private String url;
|
||||||
private Timer timeout_timer;
|
private String db;
|
||||||
|
private String user;
|
||||||
|
private String password;
|
||||||
|
|
||||||
protected class PoolItem{
|
// Pool details
|
||||||
public DBConnection conn;
|
private int max_conn;
|
||||||
public long timestamp;
|
private long timeout;
|
||||||
|
private Timer timeout_timer;
|
||||||
|
|
||||||
public boolean equals(Object o){
|
protected class PoolItem{
|
||||||
return conn.equals(o);
|
public DBConnection conn;
|
||||||
}
|
public long timestamp;
|
||||||
}
|
|
||||||
|
|
||||||
// The pool
|
public boolean equals(Object o){
|
||||||
private LinkedList<PoolItem> inusePool;
|
return conn.equals(o);
|
||||||
private LinkedList<PoolItem> readyPool;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
// The pool
|
||||||
* Creates a new pool of DB connections
|
private LinkedList<PoolItem> inusePool;
|
||||||
*
|
private LinkedList<PoolItem> readyPool;
|
||||||
* @param dbms is the DB type
|
|
||||||
* @param url is the URL to the DB
|
|
||||||
* @param db is the name of the database
|
|
||||||
* @param user is the user name to the DB
|
|
||||||
* @param password is the password to the DB
|
|
||||||
*/
|
|
||||||
public DBConnectionPool(DBMS dbms, String url, String db, String user, String password) throws Exception{
|
|
||||||
this.dbms = dbms;
|
|
||||||
this.url = url;
|
|
||||||
this.db = db;
|
|
||||||
this.user = user;
|
|
||||||
this.password = password;
|
|
||||||
|
|
||||||
inusePool = new LinkedList<PoolItem>();
|
/**
|
||||||
readyPool = new LinkedList<PoolItem>();
|
* Creates a new pool of DB connections
|
||||||
|
*
|
||||||
this.setTimeout(DEFAULT_TIMEOUT);
|
* @param dbms is the DB type
|
||||||
this.setMaxSize(DEFAULT_MAX_SIZE);
|
* @param url is the URL to the DB
|
||||||
}
|
* @param db is the name of the database
|
||||||
|
* @param user is the user name to the DB
|
||||||
|
* @param password is the password to the DB
|
||||||
|
*/
|
||||||
|
public DBConnectionPool(DBMS dbms, String url, String db, String user, String password) throws Exception{
|
||||||
|
this.dbms = dbms;
|
||||||
|
this.url = url;
|
||||||
|
this.db = db;
|
||||||
|
this.user = user;
|
||||||
|
this.password = password;
|
||||||
|
|
||||||
/**
|
inusePool = new LinkedList<PoolItem>();
|
||||||
* Registers a Connection to the pool
|
readyPool = new LinkedList<PoolItem>();
|
||||||
*
|
|
||||||
* @param conn is the Connection to register
|
|
||||||
*/
|
|
||||||
protected void addConnection(DBConnection conn){
|
|
||||||
PoolItem item = new PoolItem();
|
|
||||||
item.conn = conn;
|
|
||||||
readyPool.addLast(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
this.setTimeout(DEFAULT_TIMEOUT);
|
||||||
* Removes an connection from the pool
|
this.setMaxSize(DEFAULT_MAX_SIZE);
|
||||||
*
|
}
|
||||||
* @param conn is the connection to remove
|
|
||||||
*/
|
|
||||||
protected void removeConnection(DBConnection conn){
|
|
||||||
inusePool.remove(conn);
|
|
||||||
readyPool.remove(conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lease one connection from the pool
|
* Registers a Connection to the pool
|
||||||
*
|
*
|
||||||
* @return an DB connection or null if the pool is empty
|
* @param conn is the Connection to register
|
||||||
*/
|
*/
|
||||||
public synchronized DBConnection getConnection() throws Exception{
|
protected void addConnection(DBConnection conn){
|
||||||
if(readyPool.isEmpty()){
|
PoolItem item = new PoolItem();
|
||||||
if( size() < max_conn ){
|
item.conn = conn;
|
||||||
DBConnection conn = new DBConnection(dbms, url, db, user, password);
|
readyPool.addLast(item);
|
||||||
conn.setPool( this );
|
}
|
||||||
addConnection( conn );
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
PoolItem item = readyPool.poll();
|
|
||||||
inusePool.addLast(item);
|
|
||||||
item.timestamp = System.currentTimeMillis();
|
|
||||||
return item.conn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the Connection as not used
|
* Removes an connection from the pool
|
||||||
*
|
*
|
||||||
* @param conn is the connection that is not used anymore
|
* @param conn is the connection to remove
|
||||||
*/
|
*/
|
||||||
protected synchronized void releaseConnection(DBConnection conn){
|
protected void removeConnection(DBConnection conn){
|
||||||
int index = inusePool.indexOf(conn);
|
inusePool.remove(conn);
|
||||||
PoolItem item = inusePool.remove(index);
|
readyPool.remove(conn);
|
||||||
readyPool.addLast(item);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the current size of the pool
|
* Lease one connection from the pool
|
||||||
*/
|
*
|
||||||
public int size(){
|
* @return an DB connection or null if the pool is empty
|
||||||
return inusePool.size() + readyPool.size();
|
*/
|
||||||
}
|
public synchronized DBConnection getConnection() throws Exception{
|
||||||
|
if(readyPool.isEmpty()){
|
||||||
|
if( size() < max_conn ){
|
||||||
|
DBConnection conn = new DBConnection(dbms, url, db, user, password);
|
||||||
|
conn.setPool( this );
|
||||||
|
addConnection( conn );
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
PoolItem item = readyPool.poll();
|
||||||
|
inusePool.addLast(item);
|
||||||
|
item.timestamp = System.currentTimeMillis();
|
||||||
|
return item.conn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes all the connections
|
* Registers the Connection as not used
|
||||||
*/
|
*
|
||||||
public synchronized void close(){
|
* @param conn is the connection that is not used anymore
|
||||||
for( PoolItem item : inusePool ){
|
*/
|
||||||
item.conn.forceClose();
|
protected synchronized void releaseConnection(DBConnection conn){
|
||||||
}
|
int index = inusePool.indexOf(conn);
|
||||||
inusePool.clear();
|
PoolItem item = inusePool.remove(index);
|
||||||
for( PoolItem item : readyPool ){
|
readyPool.addLast(item);
|
||||||
item.conn.forceClose();
|
}
|
||||||
}
|
|
||||||
readyPool.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the max size of the pool
|
* @return the current size of the pool
|
||||||
*/
|
*/
|
||||||
public void setMaxSize(int max){
|
public int size(){
|
||||||
this.max_conn = max;
|
return inusePool.size() + readyPool.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the timeout of the Connections
|
* Closes all the connections
|
||||||
*/
|
*/
|
||||||
public synchronized void setTimeout(long timeout){
|
public synchronized void close(){
|
||||||
this.timeout = timeout;
|
for( PoolItem item : inusePool ){
|
||||||
if(timeout_timer!=null)
|
item.conn.forceClose();
|
||||||
timeout_timer.cancel();
|
}
|
||||||
timeout_timer = new Timer();
|
inusePool.clear();
|
||||||
timeout_timer.schedule(this, 0, timeout / 2);
|
for( PoolItem item : readyPool ){
|
||||||
}
|
item.conn.forceClose();
|
||||||
|
}
|
||||||
|
readyPool.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks every DB connection if they are valid and has not timed out
|
* Set the max size of the pool
|
||||||
*/
|
*/
|
||||||
public void run(){
|
public void setMaxSize(int max){
|
||||||
long stale = System.currentTimeMillis() - timeout;
|
this.max_conn = max;
|
||||||
|
}
|
||||||
|
|
||||||
for(PoolItem item : inusePool){
|
/**
|
||||||
if( !item.conn.valid() && stale > item.timestamp ) {
|
* Sets the timeout of the Connections
|
||||||
removeConnection(item.conn);
|
*/
|
||||||
item.conn.forceClose();
|
public synchronized void setTimeout(long timeout){
|
||||||
}
|
this.timeout = timeout;
|
||||||
}
|
if(timeout_timer!=null)
|
||||||
}
|
timeout_timer.cancel();
|
||||||
|
timeout_timer = new Timer();
|
||||||
|
timeout_timer.schedule(this, 0, timeout / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks every DB connection if they are valid and has not timed out
|
||||||
|
*/
|
||||||
|
public void run(){
|
||||||
|
long stale = System.currentTimeMillis() - timeout;
|
||||||
|
|
||||||
|
for(PoolItem item : inusePool){
|
||||||
|
if( !item.conn.valid() && stale > item.timestamp ) {
|
||||||
|
removeConnection(item.conn);
|
||||||
|
item.conn.forceClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,168 +49,168 @@ import java.util.Queue;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DBQueue<E> implements Queue<E>{
|
public class DBQueue<E> implements Queue<E>{
|
||||||
private DBConnection db;
|
private DBConnection db;
|
||||||
private String table;
|
private String table;
|
||||||
|
|
||||||
/**
|
|
||||||
* Initiates the queue.<br>
|
|
||||||
*
|
|
||||||
* @param db is the connection to the DB
|
|
||||||
* @param table is the name of the table
|
|
||||||
*/
|
|
||||||
public DBQueue(DBConnection db, String table){
|
|
||||||
this.db = db;
|
|
||||||
this.table = table;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean add(Object arg0){
|
/**
|
||||||
try {
|
* Initiates the queue.<br>
|
||||||
PreparedStatement sql = db.getPreparedStatement("INSERT INTO ? (data) VALUES(?)");
|
*
|
||||||
|
* @param db is the connection to the DB
|
||||||
|
* @param table is the name of the table
|
||||||
|
*/
|
||||||
|
public DBQueue(DBConnection db, String table){
|
||||||
|
this.db = db;
|
||||||
|
this.table = table;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean add(Object arg0){
|
||||||
|
try {
|
||||||
|
PreparedStatement sql = db.getPreparedStatement("INSERT INTO ? (data) VALUES(?)");
|
||||||
sql.setObject(1, table);
|
sql.setObject(1, table);
|
||||||
sql.setObject(2, arg0);
|
sql.setObject(2, arg0);
|
||||||
DBConnection.exec(sql);
|
DBConnection.exec(sql);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace(MultiPrintStream.out);
|
e.printStackTrace(MultiPrintStream.out);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public E element() {
|
|
||||||
return peek();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean offer(Object arg0) {
|
public E element() {
|
||||||
return add(arg0);
|
return peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized E peek() {
|
public boolean offer(Object arg0) {
|
||||||
try {
|
return add(arg0);
|
||||||
return db.exec("SELECT * FROM "+table+" LIMIT 1", new SQLResultHandler<E>(){
|
}
|
||||||
public E handleQueryResult(Statement stmt, ResultSet rs) throws SQLException{
|
|
||||||
if (rs.next())
|
|
||||||
try {
|
|
||||||
return (E) Converter.toObject(rs.getBytes("data"));
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace(MultiPrintStream.out);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace(MultiPrintStream.out);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized E poll() {
|
public synchronized E peek() {
|
||||||
try {
|
try {
|
||||||
return db.exec("SELECT * FROM "+table+" LIMIT 1", new SQLResultHandler<E>(){
|
return db.exec("SELECT * FROM "+table+" LIMIT 1", new SQLResultHandler<E>(){
|
||||||
public E handleQueryResult(Statement stmt, ResultSet rs) {
|
public E handleQueryResult(Statement stmt, ResultSet rs) throws SQLException{
|
||||||
try{
|
if (rs.next())
|
||||||
if (rs.next()) {
|
try {
|
||||||
db.exec("DELETE FROM "+table+" WHERE id="+rs.getInt("id")+" LIMIT 1");
|
return (E) Converter.toObject(rs.getBytes("data"));
|
||||||
return (E) Converter.toObject(rs.getBytes("data"));
|
} catch (Exception e) {
|
||||||
}
|
e.printStackTrace(MultiPrintStream.out);
|
||||||
}catch(Exception e){
|
}
|
||||||
e.printStackTrace(MultiPrintStream.out);
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
});
|
||||||
}
|
} catch (Exception e) {
|
||||||
});
|
e.printStackTrace(MultiPrintStream.out);
|
||||||
} catch (Exception e) {
|
}
|
||||||
e.printStackTrace(MultiPrintStream.out);
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public E remove() {
|
public synchronized E poll() {
|
||||||
return poll();
|
try {
|
||||||
}
|
return db.exec("SELECT * FROM "+table+" LIMIT 1", new SQLResultHandler<E>(){
|
||||||
|
public E handleQueryResult(Statement stmt, ResultSet rs) {
|
||||||
|
try{
|
||||||
|
if (rs.next()) {
|
||||||
|
db.exec("DELETE FROM "+table+" WHERE id="+rs.getInt("id")+" LIMIT 1");
|
||||||
|
return (E) Converter.toObject(rs.getBytes("data"));
|
||||||
|
}
|
||||||
|
}catch(Exception e){
|
||||||
|
e.printStackTrace(MultiPrintStream.out);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace(MultiPrintStream.out);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean addAll(Collection<? extends E> arg0) {
|
public E remove() {
|
||||||
// TODO Auto-generated method stub
|
return poll();
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
public boolean addAll(Collection<? extends E> arg0) {
|
||||||
try {
|
// TODO Auto-generated method stub
|
||||||
db.exec("TRUNCATE TABLE `"+table+"`");
|
return false;
|
||||||
} catch (SQLException e) {
|
}
|
||||||
e.printStackTrace(MultiPrintStream.out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean contains(Object arg0) {
|
public void clear() {
|
||||||
try {
|
try {
|
||||||
return db.exec("SELECT data FROM "+table+" WHERE data='"+Converter.toBytes(arg0)+"' LIMIT 1", new SQLResultHandler<Boolean>(){
|
db.exec("TRUNCATE TABLE `"+table+"`");
|
||||||
public Boolean handleQueryResult(Statement stmt, ResultSet rs) throws SQLException{
|
} catch (SQLException e) {
|
||||||
return rs.next();
|
e.printStackTrace(MultiPrintStream.out);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace(MultiPrintStream.out);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean containsAll(Collection<?> arg0) {
|
public boolean contains(Object arg0) {
|
||||||
// TODO Auto-generated method stub
|
try {
|
||||||
return false;
|
return db.exec("SELECT data FROM "+table+" WHERE data='"+Converter.toBytes(arg0)+"' LIMIT 1", new SQLResultHandler<Boolean>(){
|
||||||
}
|
public Boolean handleQueryResult(Statement stmt, ResultSet rs) throws SQLException{
|
||||||
|
return rs.next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace(MultiPrintStream.out);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean containsAll(Collection<?> arg0) {
|
||||||
return (peek() != null);
|
// TODO Auto-generated method stub
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public Iterator<E> iterator() {
|
public boolean isEmpty() {
|
||||||
// TODO: Auto-generated method stub
|
return (peek() != null);
|
||||||
return null;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized boolean remove(Object arg0) {
|
public Iterator<E> iterator() {
|
||||||
try {
|
// TODO: Auto-generated method stub
|
||||||
db.exec("DELETE FROM "+table+" WHERE data='"+Converter.toBytes(arg0)+"' LIMIT 1");
|
return null;
|
||||||
return true;
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace(MultiPrintStream.out);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized boolean removeAll(Collection<?> arg0) {
|
public synchronized boolean remove(Object arg0) {
|
||||||
// TODO Auto-generated method stub
|
try {
|
||||||
return false;
|
db.exec("DELETE FROM "+table+" WHERE data='"+Converter.toBytes(arg0)+"' LIMIT 1");
|
||||||
}
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace(MultiPrintStream.out);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean retainAll(Collection<?> arg0) {
|
public synchronized boolean removeAll(Collection<?> arg0) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
public boolean retainAll(Collection<?> arg0) {
|
||||||
try {
|
// TODO Auto-generated method stub
|
||||||
return db.exec("SELECT count(*) FROM "+table, new SQLResultHandler<Integer>(){
|
return false;
|
||||||
public Integer handleQueryResult(Statement stmt, ResultSet rs) throws SQLException{
|
}
|
||||||
if (rs.next())
|
|
||||||
return rs.getInt(1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace(MultiPrintStream.out);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public E[] toArray() {
|
public int size() {
|
||||||
// TODO Auto-generated method stub
|
try {
|
||||||
return null;
|
return db.exec("SELECT count(*) FROM "+table, new SQLResultHandler<Integer>(){
|
||||||
}
|
public Integer handleQueryResult(Statement stmt, ResultSet rs) throws SQLException{
|
||||||
|
if (rs.next())
|
||||||
|
return rs.getInt(1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace(MultiPrintStream.out);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public E[] toArray(Object[] arg0) {
|
public E[] toArray() {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public E[] toArray(Object[] arg0) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,393 +32,393 @@ import java.util.LinkedList;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class SQLQuery {
|
public class SQLQuery {
|
||||||
protected static abstract class SQLQueryItem{
|
protected static abstract class SQLQueryItem{
|
||||||
SQLQueryItem root;
|
SQLQueryItem root;
|
||||||
|
|
||||||
protected SQLQueryItem(){}
|
|
||||||
|
|
||||||
protected void setRoot(SQLQueryItem root){
|
|
||||||
this.root = root;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void build(StringBuilder query);
|
|
||||||
|
|
||||||
public String toString(){
|
|
||||||
StringBuilder query = new StringBuilder();
|
|
||||||
root.build(query);
|
|
||||||
return query.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//*******************************************
|
protected SQLQueryItem(){}
|
||||||
// Main Types
|
|
||||||
/**
|
|
||||||
* <XMP>
|
|
||||||
* SELECT
|
|
||||||
* [ALL | DISTINCT | DISTINCTROW ]
|
|
||||||
* [FROM table_references
|
|
||||||
* [WHERE where_condition]
|
|
||||||
* [GROUP BY {col_name | expr | position}
|
|
||||||
* [ASC | DESC], ... [WITH ROLLUP]]
|
|
||||||
* [HAVING where_condition]
|
|
||||||
* [ORDER BY {col_name | expr | position}
|
|
||||||
* [ASC | DESC], ...]
|
|
||||||
* [LIMIT {[offset,] row_count | row_count OFFSET offset}]
|
|
||||||
* </XMP>
|
|
||||||
*/
|
|
||||||
public static class SQLSelect extends SQLQueryItem{
|
|
||||||
String[] params;
|
|
||||||
SQLFrom from;
|
|
||||||
|
|
||||||
/**
|
protected void setRoot(SQLQueryItem root){
|
||||||
* @param params is the columns that you want out of the SELECT query, leave empty for all columns
|
this.root = root;
|
||||||
*/
|
}
|
||||||
protected SQLSelect(String ...params ){
|
|
||||||
setRoot(this);
|
protected abstract void build(StringBuilder query);
|
||||||
this.params = params;
|
|
||||||
}
|
public String toString(){
|
||||||
|
StringBuilder query = new StringBuilder();
|
||||||
protected void build(StringBuilder query) {
|
root.build(query);
|
||||||
query.append("SELECT ");
|
return query.toString();
|
||||||
if( params == null || params.length <= 0 )
|
}
|
||||||
query.append("*");
|
}
|
||||||
else{
|
|
||||||
for(int i=0; i<params.length ;i++){
|
//*******************************************
|
||||||
query.append(params[i]);
|
// Main Types
|
||||||
if( i != params.length-1 )
|
/**
|
||||||
query.append(",");
|
* <XMP>
|
||||||
}
|
* SELECT
|
||||||
}
|
* [ALL | DISTINCT | DISTINCTROW ]
|
||||||
if( from != null )
|
* [FROM table_references
|
||||||
from.build( query );
|
* [WHERE where_condition]
|
||||||
}
|
* [GROUP BY {col_name | expr | position}
|
||||||
|
* [ASC | DESC], ... [WITH ROLLUP]]
|
||||||
public SQLFrom FROM(String ...tables){
|
* [HAVING where_condition]
|
||||||
return from = new SQLFrom(this, tables);
|
* [ORDER BY {col_name | expr | position}
|
||||||
}
|
* [ASC | DESC], ...]
|
||||||
}
|
* [LIMIT {[offset,] row_count | row_count OFFSET offset}]
|
||||||
|
* </XMP>
|
||||||
/*
|
*/
|
||||||
* <XMP>
|
public static class SQLSelect extends SQLQueryItem{
|
||||||
* UPDATE [LOW_PRIORITY] [IGNORE] table_reference
|
String[] params;
|
||||||
* SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...
|
SQLFrom from;
|
||||||
* [WHERE where_condition]
|
|
||||||
* [ORDER BY ...]
|
/**
|
||||||
* [LIMIT row_count]
|
* @param params is the columns that you want out of the SELECT query, leave empty for all columns
|
||||||
* </XMP>
|
*/
|
||||||
*/
|
protected SQLSelect(String ...params ){
|
||||||
public static class SQLUpdate extends SQLQueryItem{
|
setRoot(this);
|
||||||
protected SQLUpdate(){
|
this.params = params;
|
||||||
setRoot(this);
|
}
|
||||||
}
|
|
||||||
|
protected void build(StringBuilder query) {
|
||||||
protected void build(StringBuilder query) {
|
query.append("SELECT ");
|
||||||
|
if( params == null || params.length <= 0 )
|
||||||
}
|
query.append("*");
|
||||||
}
|
else{
|
||||||
|
for(int i=0; i<params.length ;i++){
|
||||||
/*
|
query.append(params[i]);
|
||||||
* <XMP>
|
if( i != params.length-1 )
|
||||||
* INSERT [INTO] tbl_name
|
query.append(",");
|
||||||
* SET col_name={expr | DEFAULT}, ...
|
}
|
||||||
*
|
}
|
||||||
* INSERT [INTO] tbl_name [(col_name,...)]
|
if( from != null )
|
||||||
* {VALUES | VALUE} ({expr | DEFAULT},...),(...),...
|
from.build( query );
|
||||||
* </XMP>
|
}
|
||||||
*/
|
|
||||||
public static class SQLInsert extends SQLQueryItem{
|
public SQLFrom FROM(String ...tables){
|
||||||
protected SQLInsert(){
|
return from = new SQLFrom(this, tables);
|
||||||
setRoot(this);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void build(StringBuilder query) {
|
/*
|
||||||
|
* <XMP>
|
||||||
}
|
* UPDATE [LOW_PRIORITY] [IGNORE] table_reference
|
||||||
}
|
* SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...
|
||||||
|
* [WHERE where_condition]
|
||||||
/*
|
* [ORDER BY ...]
|
||||||
* <XMP>
|
* [LIMIT row_count]
|
||||||
* DELETE FROM tbl_name
|
* </XMP>
|
||||||
* [WHERE where_condition]
|
*/
|
||||||
* [ORDER BY ...]
|
public static class SQLUpdate extends SQLQueryItem{
|
||||||
* [LIMIT row_count]
|
protected SQLUpdate(){
|
||||||
* </XMP>
|
setRoot(this);
|
||||||
*/
|
}
|
||||||
public static class SQLDelete extends SQLQueryItem{
|
|
||||||
protected SQLDelete(){
|
protected void build(StringBuilder query) {
|
||||||
setRoot(this);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
protected void build(StringBuilder query) {
|
|
||||||
|
/*
|
||||||
}
|
* <XMP>
|
||||||
}
|
* INSERT [INTO] tbl_name
|
||||||
|
* SET col_name={expr | DEFAULT}, ...
|
||||||
//*******************************************
|
*
|
||||||
// Sub Types
|
* INSERT [INTO] tbl_name [(col_name,...)]
|
||||||
public static class SQLFrom extends SQLQueryItem{
|
* {VALUES | VALUE} ({expr | DEFAULT},...),(...),...
|
||||||
LinkedList<String> tables = new LinkedList<String>();
|
* </XMP>
|
||||||
SQLQueryItem next;
|
*/
|
||||||
|
public static class SQLInsert extends SQLQueryItem{
|
||||||
|
protected SQLInsert(){
|
||||||
|
setRoot(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void build(StringBuilder query) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* <XMP>
|
||||||
|
* DELETE FROM tbl_name
|
||||||
|
* [WHERE where_condition]
|
||||||
|
* [ORDER BY ...]
|
||||||
|
* [LIMIT row_count]
|
||||||
|
* </XMP>
|
||||||
|
*/
|
||||||
|
public static class SQLDelete extends SQLQueryItem{
|
||||||
|
protected SQLDelete(){
|
||||||
|
setRoot(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void build(StringBuilder query) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//*******************************************
|
||||||
|
// Sub Types
|
||||||
|
public static class SQLFrom extends SQLQueryItem{
|
||||||
|
LinkedList<String> tables = new LinkedList<String>();
|
||||||
|
SQLQueryItem next;
|
||||||
|
|
||||||
|
protected SQLFrom(SQLQueryItem root, String ...tables){
|
||||||
|
setRoot(root);
|
||||||
|
for( String table : tables )
|
||||||
|
this.tables.add(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SQLFrom NATURAL_JOIN(String table){
|
||||||
|
return joinLastTable("NATURAL JOIN", table);
|
||||||
|
}
|
||||||
|
public SQLFrom NATURAL_JOIN(String ...tables){
|
||||||
|
return joinTable("NATURAL JOIN", tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SQLFrom JOIN(String table){
|
||||||
|
return joinLastTable("JOIN", table);
|
||||||
|
}
|
||||||
|
public SQLFrom JOIN(String ...tables){
|
||||||
|
return joinTable("JOIN", tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SQLFrom UNION(String table){
|
||||||
|
return joinLastTable("UNION", table);
|
||||||
|
}
|
||||||
|
public SQLFrom UNION(String ...tables){
|
||||||
|
return joinTable("UNION", tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SQLFrom joinLastTable(String type, String table){
|
||||||
|
String last = tables.getLast();
|
||||||
|
tables.removeLast();
|
||||||
|
tables.add(
|
||||||
|
new StringBuilder(last).append(" ").append(type).append(" ").append(table).toString());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SQLFrom joinTable(String type, String[] tables){
|
||||||
|
if( tables.length < 2 )
|
||||||
|
return this;
|
||||||
|
StringBuilder str = new StringBuilder();
|
||||||
|
for(int i=0; i<tables.length ;i++){
|
||||||
|
str.append(tables[i]);
|
||||||
|
if( i != tables.length-1 )
|
||||||
|
str.append(' ').append(type).append(' ');
|
||||||
|
}
|
||||||
|
this.tables.add(str.toString());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SQLWhere WHERE(){
|
||||||
|
return (SQLWhere) (next = new SQLWhere(root));
|
||||||
|
}
|
||||||
|
public SQLGroupBy GROUP_BY( String ...cols ){
|
||||||
|
return (SQLGroupBy) (next = new SQLGroupBy(root, cols));
|
||||||
|
}
|
||||||
|
public SQLOrderBy ORDER_BY( String ...cols ){
|
||||||
|
return (SQLOrderBy) (next = new SQLOrderBy(root, cols));
|
||||||
|
}
|
||||||
|
public SQLLimit LIMIT( long count ){
|
||||||
|
return (SQLLimit) (next = new SQLLimit(root, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void build(StringBuilder query) {
|
||||||
|
query.append(" FROM ");
|
||||||
|
if( tables.isEmpty() )
|
||||||
|
throw new RuntimeException("The FROM query item must have at least 1 table!");
|
||||||
|
for(int i=0; i<tables.size() ;i++){
|
||||||
|
query.append(tables.get(i));
|
||||||
|
if( i != tables.size()-1 )
|
||||||
|
query.append(", ");
|
||||||
|
}
|
||||||
|
if( next != null ) next.build( query );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//*******************************************
|
||||||
|
// Condition Types
|
||||||
|
public static class SQLWhere extends SQLQueryItem{
|
||||||
|
LinkedList<String> conds = new LinkedList<String>();
|
||||||
|
SQLQueryItem next;
|
||||||
|
|
||||||
|
protected SQLWhere(SQLQueryItem root){
|
||||||
|
setRoot(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Equals (arg1 = arg2)
|
||||||
|
*/
|
||||||
|
public SQLWhere EQ(String arg1, String arg2){
|
||||||
|
return cond("=", arg1, arg2);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Not Equal (arg1 != arg2)
|
||||||
|
*/
|
||||||
|
public SQLWhere NE(String arg1, String arg2){
|
||||||
|
return cond("!=", arg1, arg2);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Less than (arg1 < arg2)
|
||||||
|
*/
|
||||||
|
public SQLWhere LT(String arg1, String arg2){
|
||||||
|
return cond("<", arg1, arg2);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Greater than (arg1 > arg2)
|
||||||
|
*/
|
||||||
|
public SQLWhere GT(String arg1, String arg2){
|
||||||
|
return cond(">", arg1, arg2);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Less than or equal (arg1 <= arg2)
|
||||||
|
*/
|
||||||
|
public SQLWhere LE(String arg1, String arg2){
|
||||||
|
return cond("<=", arg1, arg2);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Greater than or equal (arg1 >= arg2)
|
||||||
|
*/
|
||||||
|
public SQLWhere GE(String arg1, String arg2){
|
||||||
|
return cond(">=", arg1, arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SQLWhere cond(String cond, String arg1, String arg2){
|
||||||
|
conds.add(
|
||||||
|
//new StringBuilder(arg1).append(cond).append('\"').append(arg2).append('\"').toString());
|
||||||
|
new StringBuilder(arg1).append(cond).append(arg2).toString());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public SQLGroupBy GROUP_BY( String ...cols ){
|
||||||
|
return (SQLGroupBy) (next = new SQLGroupBy(root, cols));
|
||||||
|
}
|
||||||
|
public SQLOrderBy ORDER_BY( String ...cols ){
|
||||||
|
return (SQLOrderBy) (next = new SQLOrderBy(root, cols));
|
||||||
|
}
|
||||||
|
public SQLLimit LIMIT( long count ){
|
||||||
|
return (SQLLimit) (next = new SQLLimit(root, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void build(StringBuilder query) {
|
||||||
|
query.append(" WHERE ");
|
||||||
|
if( conds.isEmpty() )
|
||||||
|
throw new RuntimeException("The WHERE query item must hav atleast 1 condition!");
|
||||||
|
for(int i=0; i<conds.size() ;i++){
|
||||||
|
query.append(conds.get(i));
|
||||||
|
if( i != conds.size()-1 )
|
||||||
|
query.append(" AND ");
|
||||||
|
}
|
||||||
|
if( next != null ) next.build( query );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//*******************************************
|
||||||
|
// Sorting Types
|
||||||
|
public abstract static class SQLGroupOrderBy<T> extends SQLQueryItem{
|
||||||
|
protected String[] cols;
|
||||||
|
protected String end;
|
||||||
|
SQLQueryItem next;
|
||||||
|
|
||||||
|
protected SQLGroupOrderBy(SQLQueryItem root, String ...cols){
|
||||||
|
setRoot(root);
|
||||||
|
this.cols = cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T ASC(){
|
||||||
|
end = "ASC";
|
||||||
|
return (T)this;
|
||||||
|
}
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T DESC(){
|
||||||
|
end = "DESC";
|
||||||
|
return (T)this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void build(String op, StringBuilder query) {
|
||||||
|
query.append(' ').append(op).append(' ');
|
||||||
|
if( cols == null || cols.length <= 0 )
|
||||||
|
throw new RuntimeException("The "+op+" query item must hav atleast 1 column!");
|
||||||
|
for(int i=0; i<cols.length ;i++){
|
||||||
|
query.append( cols[i] );
|
||||||
|
if( i != cols.length-1 )
|
||||||
|
query.append(",");
|
||||||
|
}
|
||||||
|
if( end != null ) query.append(' ').append( end );
|
||||||
|
if( next != null ) next.build( query );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SQLGroupBy extends SQLGroupOrderBy<SQLGroupBy>{
|
||||||
|
|
||||||
|
protected SQLGroupBy(SQLQueryItem root, String ...cols){
|
||||||
|
super( root, cols );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public SQLOrderBy ORDER_BY( String ...cols ){
|
||||||
|
return (SQLOrderBy) (next = new SQLOrderBy(root, cols));
|
||||||
|
}
|
||||||
|
public SQLLimit LIMIT( long count ){
|
||||||
|
return (SQLLimit) (next = new SQLLimit(root, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void build(StringBuilder query) {
|
||||||
|
build("GROUP BY", query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static class SQLOrderBy extends SQLGroupOrderBy<SQLOrderBy>{
|
||||||
|
|
||||||
|
protected SQLOrderBy(SQLQueryItem root, String ...cols){
|
||||||
|
super( root, cols );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public SQLLimit LIMIT( long count ){
|
||||||
|
return (SQLLimit) (next = new SQLLimit(root, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void build(StringBuilder query) {
|
||||||
|
build("ORDER BY", query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SQLLimit extends SQLQueryItem{
|
||||||
|
long start;
|
||||||
|
Long count;
|
||||||
|
|
||||||
|
protected SQLLimit(SQLQueryItem root, long start){
|
||||||
|
setRoot( root );
|
||||||
|
this.start = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SQLLimit TO( long count ){
|
||||||
|
this.count = count;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void build(StringBuilder query) {
|
||||||
|
query.append(" LIMIT ").append( start );
|
||||||
|
if( count != null ) query.append(' ').append( count );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//*******************************************
|
||||||
|
public static SQLSelect SELECT( String ...params ){
|
||||||
|
return new SQLSelect( params );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SQLUpdate UPDATE(){
|
||||||
|
return new SQLUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SQLInsert INSERT(){
|
||||||
|
return new SQLInsert();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SQLDelete DELETE(){
|
||||||
|
return new SQLDelete();
|
||||||
|
}
|
||||||
|
|
||||||
protected SQLFrom(SQLQueryItem root, String ...tables){
|
|
||||||
setRoot(root);
|
|
||||||
for( String table : tables )
|
|
||||||
this.tables.add(table);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SQLFrom NATURAL_JOIN(String table){
|
|
||||||
return joinLastTable("NATURAL JOIN", table);
|
|
||||||
}
|
|
||||||
public SQLFrom NATURAL_JOIN(String ...tables){
|
|
||||||
return joinTable("NATURAL JOIN", tables);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SQLFrom JOIN(String table){
|
|
||||||
return joinLastTable("JOIN", table);
|
|
||||||
}
|
|
||||||
public SQLFrom JOIN(String ...tables){
|
|
||||||
return joinTable("JOIN", tables);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SQLFrom UNION(String table){
|
|
||||||
return joinLastTable("UNION", table);
|
|
||||||
}
|
|
||||||
public SQLFrom UNION(String ...tables){
|
|
||||||
return joinTable("UNION", tables);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SQLFrom joinLastTable(String type, String table){
|
|
||||||
String last = tables.getLast();
|
|
||||||
tables.removeLast();
|
|
||||||
tables.add(
|
|
||||||
new StringBuilder(last).append(" ").append(type).append(" ").append(table).toString());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SQLFrom joinTable(String type, String[] tables){
|
|
||||||
if( tables.length < 2 )
|
|
||||||
return this;
|
|
||||||
StringBuilder str = new StringBuilder();
|
|
||||||
for(int i=0; i<tables.length ;i++){
|
|
||||||
str.append(tables[i]);
|
|
||||||
if( i != tables.length-1 )
|
|
||||||
str.append(' ').append(type).append(' ');
|
|
||||||
}
|
|
||||||
this.tables.add(str.toString());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SQLWhere WHERE(){
|
|
||||||
return (SQLWhere) (next = new SQLWhere(root));
|
|
||||||
}
|
|
||||||
public SQLGroupBy GROUP_BY( String ...cols ){
|
|
||||||
return (SQLGroupBy) (next = new SQLGroupBy(root, cols));
|
|
||||||
}
|
|
||||||
public SQLOrderBy ORDER_BY( String ...cols ){
|
|
||||||
return (SQLOrderBy) (next = new SQLOrderBy(root, cols));
|
|
||||||
}
|
|
||||||
public SQLLimit LIMIT( long count ){
|
|
||||||
return (SQLLimit) (next = new SQLLimit(root, count));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void build(StringBuilder query) {
|
|
||||||
query.append(" FROM ");
|
|
||||||
if( tables.isEmpty() )
|
|
||||||
throw new RuntimeException("The FROM query item must have at least 1 table!");
|
|
||||||
for(int i=0; i<tables.size() ;i++){
|
|
||||||
query.append(tables.get(i));
|
|
||||||
if( i != tables.size()-1 )
|
|
||||||
query.append(", ");
|
|
||||||
}
|
|
||||||
if( next != null ) next.build( query );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//*******************************************
|
|
||||||
// Condition Types
|
|
||||||
public static class SQLWhere extends SQLQueryItem{
|
|
||||||
LinkedList<String> conds = new LinkedList<String>();
|
|
||||||
SQLQueryItem next;
|
|
||||||
|
|
||||||
protected SQLWhere(SQLQueryItem root){
|
|
||||||
setRoot(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Equals (arg1 = arg2)
|
|
||||||
*/
|
|
||||||
public SQLWhere EQ(String arg1, String arg2){
|
|
||||||
return cond("=", arg1, arg2);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Not Equal (arg1 != arg2)
|
|
||||||
*/
|
|
||||||
public SQLWhere NE(String arg1, String arg2){
|
|
||||||
return cond("!=", arg1, arg2);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Less than (arg1 < arg2)
|
|
||||||
*/
|
|
||||||
public SQLWhere LT(String arg1, String arg2){
|
|
||||||
return cond("<", arg1, arg2);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Greater than (arg1 > arg2)
|
|
||||||
*/
|
|
||||||
public SQLWhere GT(String arg1, String arg2){
|
|
||||||
return cond(">", arg1, arg2);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Less than or equal (arg1 <= arg2)
|
|
||||||
*/
|
|
||||||
public SQLWhere LE(String arg1, String arg2){
|
|
||||||
return cond("<=", arg1, arg2);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Greater than or equal (arg1 >= arg2)
|
|
||||||
*/
|
|
||||||
public SQLWhere GE(String arg1, String arg2){
|
|
||||||
return cond(">=", arg1, arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SQLWhere cond(String cond, String arg1, String arg2){
|
|
||||||
conds.add(
|
|
||||||
//new StringBuilder(arg1).append(cond).append('\"').append(arg2).append('\"').toString());
|
|
||||||
new StringBuilder(arg1).append(cond).append(arg2).toString());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public SQLGroupBy GROUP_BY( String ...cols ){
|
|
||||||
return (SQLGroupBy) (next = new SQLGroupBy(root, cols));
|
|
||||||
}
|
|
||||||
public SQLOrderBy ORDER_BY( String ...cols ){
|
|
||||||
return (SQLOrderBy) (next = new SQLOrderBy(root, cols));
|
|
||||||
}
|
|
||||||
public SQLLimit LIMIT( long count ){
|
|
||||||
return (SQLLimit) (next = new SQLLimit(root, count));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void build(StringBuilder query) {
|
|
||||||
query.append(" WHERE ");
|
|
||||||
if( conds.isEmpty() )
|
|
||||||
throw new RuntimeException("The WHERE query item must hav atleast 1 condition!");
|
|
||||||
for(int i=0; i<conds.size() ;i++){
|
|
||||||
query.append(conds.get(i));
|
|
||||||
if( i != conds.size()-1 )
|
|
||||||
query.append(" AND ");
|
|
||||||
}
|
|
||||||
if( next != null ) next.build( query );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//*******************************************
|
|
||||||
// Sorting Types
|
|
||||||
public abstract static class SQLGroupOrderBy<T> extends SQLQueryItem{
|
|
||||||
protected String[] cols;
|
|
||||||
protected String end;
|
|
||||||
SQLQueryItem next;
|
|
||||||
|
|
||||||
protected SQLGroupOrderBy(SQLQueryItem root, String ...cols){
|
|
||||||
setRoot(root);
|
|
||||||
this.cols = cols;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public T ASC(){
|
|
||||||
end = "ASC";
|
|
||||||
return (T)this;
|
|
||||||
}
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public T DESC(){
|
|
||||||
end = "DESC";
|
|
||||||
return (T)this;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void build(String op, StringBuilder query) {
|
|
||||||
query.append(' ').append(op).append(' ');
|
|
||||||
if( cols == null || cols.length <= 0 )
|
|
||||||
throw new RuntimeException("The "+op+" query item must hav atleast 1 column!");
|
|
||||||
for(int i=0; i<cols.length ;i++){
|
|
||||||
query.append( cols[i] );
|
|
||||||
if( i != cols.length-1 )
|
|
||||||
query.append(",");
|
|
||||||
}
|
|
||||||
if( end != null ) query.append(' ').append( end );
|
|
||||||
if( next != null ) next.build( query );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SQLGroupBy extends SQLGroupOrderBy<SQLGroupBy>{
|
|
||||||
|
|
||||||
protected SQLGroupBy(SQLQueryItem root, String ...cols){
|
|
||||||
super( root, cols );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public SQLOrderBy ORDER_BY( String ...cols ){
|
|
||||||
return (SQLOrderBy) (next = new SQLOrderBy(root, cols));
|
|
||||||
}
|
|
||||||
public SQLLimit LIMIT( long count ){
|
|
||||||
return (SQLLimit) (next = new SQLLimit(root, count));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void build(StringBuilder query) {
|
|
||||||
build("GROUP BY", query);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static class SQLOrderBy extends SQLGroupOrderBy<SQLOrderBy>{
|
|
||||||
|
|
||||||
protected SQLOrderBy(SQLQueryItem root, String ...cols){
|
|
||||||
super( root, cols );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public SQLLimit LIMIT( long count ){
|
|
||||||
return (SQLLimit) (next = new SQLLimit(root, count));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void build(StringBuilder query) {
|
|
||||||
build("ORDER BY", query);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SQLLimit extends SQLQueryItem{
|
|
||||||
long start;
|
|
||||||
Long count;
|
|
||||||
|
|
||||||
protected SQLLimit(SQLQueryItem root, long start){
|
|
||||||
setRoot( root );
|
|
||||||
this.start = start;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SQLLimit TO( long count ){
|
|
||||||
this.count = count;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void build(StringBuilder query) {
|
|
||||||
query.append(" LIMIT ").append( start );
|
|
||||||
if( count != null ) query.append(' ').append( count );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//*******************************************
|
|
||||||
public static SQLSelect SELECT( String ...params ){
|
|
||||||
return new SQLSelect( params );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SQLUpdate UPDATE(){
|
|
||||||
return new SQLUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SQLInsert INSERT(){
|
|
||||||
return new SQLInsert();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SQLDelete DELETE(){
|
|
||||||
return new SQLDelete();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,11 @@ import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
|
|
||||||
public interface SQLResultHandler<T> {
|
public interface SQLResultHandler<T> {
|
||||||
/**
|
/**
|
||||||
* Is called to handle an result from an query.
|
* Is called to handle an result from an query.
|
||||||
*
|
*
|
||||||
* @param stmt is the query
|
* @param stmt is the query
|
||||||
* @param result is the ResultSet
|
* @param result is the ResultSet
|
||||||
*/
|
*/
|
||||||
public T handleQueryResult(Statement stmt, ResultSet result) throws SQLException;
|
public T handleQueryResult(Statement stmt, ResultSet result) throws SQLException;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ class DBBeanConfig{
|
||||||
private static HashMap<String,DBBeanConfig> beanConfigs = new HashMap<>();
|
private static HashMap<String,DBBeanConfig> beanConfigs = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
/** The name of the table in the DB **/
|
/** The name of the table in the DB **/
|
||||||
private String tableName;
|
private String tableName;
|
||||||
/** The name of the id column **/
|
/** The name of the id column **/
|
||||||
private String idColumnName;
|
private String idColumnName;
|
||||||
|
|
|
||||||
|
|
@ -39,111 +39,111 @@ import java.util.logging.Logger;
|
||||||
|
|
||||||
|
|
||||||
public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
|
public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
|
|
||||||
private Class<? extends DBBean> beanClass;
|
private Class<? extends DBBean> beanClass;
|
||||||
private DBBeanConfig beanConfig;
|
private DBBeanConfig beanConfig;
|
||||||
private DBConnection db;
|
private DBConnection db;
|
||||||
private boolean list;
|
private boolean list;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of this class that returns only one bean
|
* Creates a new instance of this class that returns only one bean
|
||||||
*
|
*
|
||||||
* @param cl is the DBBean class that will be parsed from the SQL result
|
* @param cl is the DBBean class that will be parsed from the SQL result
|
||||||
* @return a new instance of this class
|
* @return a new instance of this class
|
||||||
*/
|
*/
|
||||||
public static <C extends DBBean> DBBeanSQLResultHandler<C> create(Class<C> cl){
|
public static <C extends DBBean> DBBeanSQLResultHandler<C> create(Class<C> cl){
|
||||||
return new DBBeanSQLResultHandler<>(cl, null, false);
|
return new DBBeanSQLResultHandler<>(cl, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of this class that returns a bean with all its containing beans
|
* Creates a new instance of this class that returns a bean with all its containing beans
|
||||||
*
|
*
|
||||||
* @param cl is the DBBean class that will be parsed from the SQL result
|
* @param cl is the DBBean class that will be parsed from the SQL result
|
||||||
* @param db is the DB connection for loading internal beans
|
* @param db is the DB connection for loading internal beans
|
||||||
* @return a new instance of this class
|
* @return a new instance of this class
|
||||||
*/
|
*/
|
||||||
public static <C extends DBBean> DBBeanSQLResultHandler<C> create(Class<C> cl, DBConnection db){
|
public static <C extends DBBean> DBBeanSQLResultHandler<C> create(Class<C> cl, DBConnection db){
|
||||||
return new DBBeanSQLResultHandler<>(cl, db, false);
|
return new DBBeanSQLResultHandler<>(cl, db, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of this class that returns a list of beans
|
* Creates a new instance of this class that returns a list of beans
|
||||||
*
|
*
|
||||||
* @param cl is the DBBean class that will be parsed from the SQL result
|
* @param cl is the DBBean class that will be parsed from the SQL result
|
||||||
* @return a new instance of this class
|
* @return a new instance of this class
|
||||||
*/
|
*/
|
||||||
public static <C extends DBBean> DBBeanSQLResultHandler<List<C>> createList(Class<C> cl){
|
public static <C extends DBBean> DBBeanSQLResultHandler<List<C>> createList(Class<C> cl){
|
||||||
return new DBBeanSQLResultHandler<>(cl, null, true);
|
return new DBBeanSQLResultHandler<>(cl, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of this class that returns a list of beans with all the internal beans
|
* Creates a new instance of this class that returns a list of beans with all the internal beans
|
||||||
*
|
*
|
||||||
* @param cl is the DBBean class that will be parsed from the SQL result
|
* @param cl is the DBBean class that will be parsed from the SQL result
|
||||||
* @param db is the DB connection for loading internal beans
|
* @param db is the DB connection for loading internal beans
|
||||||
* @return a new instance of this class
|
* @return a new instance of this class
|
||||||
*/
|
*/
|
||||||
public static <C extends DBBean> DBBeanSQLResultHandler<List<C>> createList(Class<C> cl, DBConnection db){
|
public static <C extends DBBean> DBBeanSQLResultHandler<List<C>> createList(Class<C> cl, DBConnection db){
|
||||||
return new DBBeanSQLResultHandler<>(cl, db, true);
|
return new DBBeanSQLResultHandler<>(cl, db, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of this class
|
* Creates a new instance of this class
|
||||||
*
|
*
|
||||||
* @param cl is the DBBean class that will be parsed from the SQL result
|
* @param cl is the DBBean class that will be parsed from the SQL result
|
||||||
* @param db is the DB connection for loading internal beans, may be null to disable internal beans
|
* @param db is the DB connection for loading internal beans, may be null to disable internal beans
|
||||||
* @param list is if the handler should return a list of beans instead of one
|
* @param list is if the handler should return a list of beans instead of one
|
||||||
*/
|
*/
|
||||||
protected DBBeanSQLResultHandler(Class<? extends DBBean> cl, DBConnection db, boolean list) {
|
protected DBBeanSQLResultHandler(Class<? extends DBBean> cl, DBConnection db, boolean list) {
|
||||||
this.beanClass = cl;
|
this.beanClass = cl;
|
||||||
this.list = list;
|
this.list = list;
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.beanConfig = DBBeanConfig.getBeanConfig( cl );
|
this.beanConfig = DBBeanConfig.getBeanConfig( cl );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is called to handle a result from a query.
|
* Is called to handle a result from a query.
|
||||||
*
|
*
|
||||||
* @param stmt is the query
|
* @param stmt is the query
|
||||||
* @param result is the ResultSet
|
* @param result is the ResultSet
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public T handleQueryResult(Statement stmt, ResultSet result) throws SQLException{
|
public T handleQueryResult(Statement stmt, ResultSet result) throws SQLException{
|
||||||
if( list ){
|
if( list ){
|
||||||
List<DBBean> bean_list = new LinkedList<>();
|
List<DBBean> bean_list = new LinkedList<>();
|
||||||
while( result.next() ){
|
while( result.next() ){
|
||||||
DBBean obj = createBean(result);
|
DBBean obj = createBean(result);
|
||||||
bean_list.add( obj );
|
bean_list.add( obj );
|
||||||
}
|
}
|
||||||
return (T) bean_list;
|
return (T) bean_list;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if( result.next() ){
|
if( result.next() ){
|
||||||
return (T) createBean(result);
|
return (T) createBean(result);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new bean and assigns field values from the ResultSet
|
* Instantiates a new bean and assigns field values from the ResultSet
|
||||||
*
|
*
|
||||||
* @param result is where the field values for the bean will bee read from, the cursor should be in front of the data
|
* @param result is where the field values for the bean will bee read from, the cursor should be in front of the data
|
||||||
* @return a new instance of the bean
|
* @return a new instance of the bean
|
||||||
*/
|
*/
|
||||||
private DBBean createBean(ResultSet result) throws SQLException{
|
private DBBean createBean(ResultSet result) throws SQLException{
|
||||||
try {
|
try {
|
||||||
Long id = result.getLong( "id" );
|
Long id = result.getLong( "id" );
|
||||||
// Check cache first
|
// Check cache first
|
||||||
DBBean obj = DBBeanCache.get(beanClass, id);
|
DBBean obj = DBBeanCache.get(beanClass, id);
|
||||||
if ( obj == null ) {
|
if ( obj == null ) {
|
||||||
// Cache miss create a new bean
|
// Cache miss create a new bean
|
||||||
logger.fine("Creating new Bean(" + beanClass.getName() + ") with id: " + id);
|
logger.fine("Creating new Bean(" + beanClass.getName() + ") with id: " + id);
|
||||||
obj = beanClass.newInstance();
|
obj = beanClass.newInstance();
|
||||||
|
|
@ -155,23 +155,23 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
|
||||||
logger.finer("Bean(" + beanClass.getName() + ") cache to old for id: " + id);
|
logger.finer("Bean(" + beanClass.getName() + ") cache to old for id: " + id);
|
||||||
updateBean(result, obj);
|
updateBean(result, obj);
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw e;
|
throw e;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates an existing bean and assigns field values from the ResultSet
|
* Updates an existing bean and assigns field values from the ResultSet
|
||||||
*
|
*
|
||||||
* @param result is where the field values for the bean will be read from, the cursor should be in front of the data
|
* @param result is where the field values for the bean will be read from, the cursor should be in front of the data
|
||||||
* @param obj is the bean that will be updated
|
* @param obj is the bean that will be updated
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void updateBean(ResultSet result, DBBean obj) throws SQLException{
|
private void updateBean(ResultSet result, DBBean obj) throws SQLException{
|
||||||
if (obj.readLock.tryLock()) {
|
if (obj.readLock.tryLock()) {
|
||||||
try {
|
try {
|
||||||
logger.fine("Updating Bean("+ beanClass.getName() +") with id: "+ obj.getId());
|
logger.fine("Updating Bean("+ beanClass.getName() +") with id: "+ obj.getId());
|
||||||
// Read fields
|
// Read fields
|
||||||
|
|
@ -198,25 +198,25 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
|
||||||
DBBeanCache.add(obj);
|
DBBeanCache.add(obj);
|
||||||
|
|
||||||
// Read sub beans
|
// Read sub beans
|
||||||
if (db != null) {
|
if (db != null) {
|
||||||
for (DBBeanSubBeanConfig subBeanField : beanConfig.getSubBeans()) {
|
for (DBBeanSubBeanConfig subBeanField : beanConfig.getSubBeans()) {
|
||||||
DBBeanConfig subBeanConfig = subBeanField.getSubBeanConfig();
|
DBBeanConfig subBeanConfig = subBeanField.getSubBeanConfig();
|
||||||
|
|
||||||
// Load List from link table
|
// Load List from link table
|
||||||
String subSql = "SELECT subBeanTable.* FROM "+
|
String subSql = "SELECT subBeanTable.* FROM "+
|
||||||
subBeanField.getLinkTableName() +" as linkTable, "+
|
subBeanField.getLinkTableName() +" as linkTable, "+
|
||||||
subBeanConfig.getTableName() +" as subBeanTable " +
|
subBeanConfig.getTableName() +" as subBeanTable " +
|
||||||
"WHERE linkTable."+subBeanField.getParentIdColumnName()+"=? AND " +
|
"WHERE linkTable."+subBeanField.getParentIdColumnName()+"=? AND " +
|
||||||
"linkTable."+subBeanConfig.getIdColumnName()+"=subBeanTable."+subBeanConfig.getIdColumnName();
|
"linkTable."+subBeanConfig.getIdColumnName()+"=subBeanTable."+subBeanConfig.getIdColumnName();
|
||||||
logger.finest("List Load Query: " + subSql);
|
logger.finest("List Load Query: " + subSql);
|
||||||
PreparedStatement subStmt = db.getPreparedStatement(subSql);
|
PreparedStatement subStmt = db.getPreparedStatement(subSql);
|
||||||
subStmt.setObject(1, obj.getId());
|
subStmt.setObject(1, obj.getId());
|
||||||
List<? extends DBBean> list = DBConnection.exec(subStmt,
|
List<? extends DBBean> list = DBConnection.exec(subStmt,
|
||||||
DBBeanSQLResultHandler.createList(subBeanField.getSubBeanClass(), db));
|
DBBeanSQLResultHandler.createList(subBeanField.getSubBeanClass(), db));
|
||||||
subBeanField.setValue(obj, list);
|
subBeanField.setValue(obj, list);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
logger.warning("No DB available to read sub beans");
|
logger.warning("No DB available to read sub beans");
|
||||||
|
|
||||||
// Call post listener
|
// Call post listener
|
||||||
obj.postUpdateAction();
|
obj.postUpdateAction();
|
||||||
|
|
@ -227,7 +227,7 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T>{
|
||||||
obj.readLock.lock();
|
obj.readLock.lock();
|
||||||
obj.readLock.unlock();
|
obj.readLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,27 +41,27 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class ListSQLResult<T> implements SQLResultHandler<List<T>> {
|
public class ListSQLResult<T> implements SQLResultHandler<List<T>> {
|
||||||
|
|
||||||
private List<T> list;
|
private List<T> list;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new List.
|
* Creates a new List.
|
||||||
*/
|
*/
|
||||||
public ListSQLResult(){
|
public ListSQLResult(){
|
||||||
this.list = new ArrayList<>();
|
this.list = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses a existing list that items will be appended on.
|
* Uses a existing list that items will be appended on.
|
||||||
*/
|
*/
|
||||||
public ListSQLResult(List l){
|
public ListSQLResult(List l){
|
||||||
this.list = l;
|
this.list = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public List<T> handleQueryResult(Statement stmt, ResultSet result) throws SQLException{
|
|
||||||
while( result.next() )
|
|
||||||
list.add((T)result.getObject(1));
|
public List<T> handleQueryResult(Statement stmt, ResultSet result) throws SQLException{
|
||||||
return list;
|
while( result.next() )
|
||||||
}
|
list.add((T)result.getObject(1));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,30 +40,30 @@ import java.util.Properties;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class PropertiesSQLResult implements SQLResultHandler<Properties> {
|
public class PropertiesSQLResult implements SQLResultHandler<Properties> {
|
||||||
|
|
||||||
private Properties prop;
|
private Properties prop;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Properties object to be filled
|
* Creates a new Properties object to be filled
|
||||||
*/
|
*/
|
||||||
public PropertiesSQLResult(){
|
public PropertiesSQLResult(){
|
||||||
this.prop = new Properties();
|
this.prop = new Properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds data to a existing Properties object
|
* Adds data to a existing Properties object
|
||||||
*/
|
*/
|
||||||
public PropertiesSQLResult(Properties p){
|
public PropertiesSQLResult(Properties p){
|
||||||
this.prop = p;
|
this.prop = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is called to handle an result from an query.
|
* Is called to handle an result from an query.
|
||||||
*/
|
*/
|
||||||
public Properties handleQueryResult(Statement stmt, ResultSet result) throws SQLException{
|
public Properties handleQueryResult(Statement stmt, ResultSet result) throws SQLException{
|
||||||
while( result.next() )
|
while( result.next() )
|
||||||
prop.setProperty(result.getString(1), result.getString(2));
|
prop.setProperty(result.getString(1), result.getString(2));
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,16 +36,16 @@ import java.sql.Statement;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class SimpleSQLResult<T> implements SQLResultHandler<T> {
|
public class SimpleSQLResult<T> implements SQLResultHandler<T> {
|
||||||
/**
|
/**
|
||||||
* Is called to handle an result from an query.
|
* Is called to handle an result from an query.
|
||||||
*
|
*
|
||||||
* @param stmt is the query
|
* @param stmt is the query
|
||||||
* @param result is the ResultSet
|
* @param result is the ResultSet
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public T handleQueryResult(Statement stmt, ResultSet result) throws SQLException{
|
public T handleQueryResult(Statement stmt, ResultSet result) throws SQLException{
|
||||||
if( result.next() )
|
if( result.next() )
|
||||||
return (T) result.getObject(1);
|
return (T) result.getObject(1);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,163 +37,163 @@ import java.awt.image.BufferedImage;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public abstract class ImageFilterProcessor {
|
public abstract class ImageFilterProcessor {
|
||||||
private BufferedImage img;
|
private BufferedImage img;
|
||||||
private ProgressListener<ImageFilterProcessor,?> progress;
|
private ProgressListener<ImageFilterProcessor,?> progress;
|
||||||
|
|
||||||
public ImageFilterProcessor(BufferedImage img){
|
public ImageFilterProcessor(BufferedImage img){
|
||||||
this.img = img;
|
this.img = img;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the listener
|
|
||||||
* @param listener is the listener, null to disable the progress
|
|
||||||
*/
|
|
||||||
public void setProgressListener(ProgressListener<ImageFilterProcessor,?> listener){
|
|
||||||
this.progress = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the listener
|
|
||||||
*/
|
|
||||||
public ProgressListener<?,?> getProgressListener(){
|
|
||||||
return this.progress;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
* Sets the listener
|
||||||
*
|
* @param listener is the listener, null to disable the progress
|
||||||
* @return The Image with the effect
|
*/
|
||||||
*/
|
public void setProgressListener(ProgressListener<ImageFilterProcessor,?> listener){
|
||||||
public BufferedImage process() throws InterruptedException{
|
this.progress = listener;
|
||||||
int cols = img.getWidth();
|
}
|
||||||
int rows = img.getHeight();
|
|
||||||
|
|
||||||
if(cols < 0 || rows < 0){
|
/**
|
||||||
throw new InterruptedException("Image not Loaded!!!");
|
* Returns the listener
|
||||||
}
|
*/
|
||||||
|
public ProgressListener<?,?> getProgressListener(){
|
||||||
|
return this.progress;
|
||||||
|
}
|
||||||
|
|
||||||
// converts the img to raw data
|
/**
|
||||||
int[][][] data = convertToArray(img, cols, rows);
|
* Sets the progress in percent
|
||||||
//processes the image
|
*/
|
||||||
data = process(data);
|
protected void setProgress(double percent){
|
||||||
//converts back the image
|
if(progress != null) progress.progressUpdate(this, null, percent);
|
||||||
return convertToImage(data, data[0].length, data.length);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a Integer array with the pixel data of the image <XMP>
|
* Applies a effect to a given image
|
||||||
* int[row][col][4]
|
*
|
||||||
* 0 -> Alpha data
|
* @param effect The effect to use
|
||||||
* Red data
|
* @param img The image to process
|
||||||
* Green data
|
* @return The processed image
|
||||||
* 4 -> Blue data </XMP>
|
*/
|
||||||
*
|
public static ImageFilterProcessor getProcessor(String effect, BufferedImage img) throws InstantiationException, IllegalAccessException, ClassNotFoundException, InterruptedException{
|
||||||
* @param img is the image to convert
|
ImageFilterProcessor processor = (ImageFilterProcessor)Class.forName(effect).newInstance();
|
||||||
* @param cols is the columns of the image
|
processor.img = img;
|
||||||
* @param rows is the rows of the image
|
return processor;
|
||||||
* @return A is the integer array
|
}
|
||||||
*/
|
|
||||||
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++){
|
* Adds the chosen effect to the image
|
||||||
// reading a row
|
*
|
||||||
int[] aRow = new int[cols];
|
* @return The Image with the effect
|
||||||
for(int x=0; x<cols ;x++){
|
*/
|
||||||
int element = y * cols + x;
|
public BufferedImage process() throws InterruptedException{
|
||||||
aRow[x] = pixels[element];
|
int cols = img.getWidth();
|
||||||
}
|
int rows = img.getHeight();
|
||||||
|
|
||||||
// Reading in the color data
|
if(cols < 0 || rows < 0){
|
||||||
for(int x=0; x<cols ;x++){
|
throw new InterruptedException("Image not Loaded!!!");
|
||||||
//Alpha data
|
}
|
||||||
data[y][x][0] = ((aRow[x] >> 24) & 0xFF);
|
|
||||||
//Red data
|
// converts the img to raw data
|
||||||
data[y][x][1] = ((aRow[x] >> 16) & 0xFF);
|
int[][][] data = convertToArray(img, cols, rows);
|
||||||
//Green data
|
//processes the image
|
||||||
data[y][x][2] = ((aRow[x] >> 8) & 0xFF);
|
data = process(data);
|
||||||
//Blue data
|
//converts back the image
|
||||||
data[y][x][3] = ((aRow[x])& 0xFF);
|
return convertToImage(data, data[0].length, data.length);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return data;
|
/**
|
||||||
}
|
* Creates a Integer array with the pixel data of the image <XMP>
|
||||||
|
* int[row][col][4]
|
||||||
|
* 0 -> Alpha data
|
||||||
|
* Red data
|
||||||
|
* Green data
|
||||||
|
* 4 -> Blue data </XMP>
|
||||||
|
*
|
||||||
|
* @param img is the image to convert
|
||||||
|
* @param cols is the columns of the image
|
||||||
|
* @param rows is the rows of the image
|
||||||
|
* @return A is the integer array
|
||||||
|
*/
|
||||||
|
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
|
* Converts a pixel data array to a java Image object
|
||||||
*
|
*
|
||||||
* @param pixels is the pixel data array
|
* @param pixels is the pixel data array
|
||||||
* @param cols is the columns of the image
|
* @param cols is the columns of the image
|
||||||
* @param rows is the rows of the image
|
* @param rows is the rows of the image
|
||||||
* @return A Image
|
* @return A Image
|
||||||
*/
|
*/
|
||||||
public static BufferedImage convertToImage(int[][][] pixels, int cols, int rows){
|
public static BufferedImage convertToImage(int[][][] pixels, int cols, int rows){
|
||||||
int[] data = new int[cols * rows * 4];
|
int[] data = new int[cols * rows * 4];
|
||||||
|
|
||||||
//Move the data into the 1D array. Note the
|
//Move the data into the 1D array. Note the
|
||||||
// use of the bitwise OR operator and the
|
// use of the bitwise OR operator and the
|
||||||
// bitwise left-shift operators to put the
|
// bitwise left-shift operators to put the
|
||||||
// four 8-bit bytes into each int.
|
// four 8-bit bytes into each int.
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for(int y=0; y<rows ;y++){
|
for(int y=0; y<rows ;y++){
|
||||||
for(int x=0; x< cols ;x++){
|
for(int x=0; x< cols ;x++){
|
||||||
data[index] = ((pixels[y][x][0] << 24) & 0xFF000000)
|
data[index] = ((pixels[y][x][0] << 24) & 0xFF000000)
|
||||||
| ((pixels[y][x][1] << 16) & 0x00FF0000)
|
| ((pixels[y][x][1] << 16) & 0x00FF0000)
|
||||||
| ((pixels[y][x][2] << 8) & 0x0000FF00)
|
| ((pixels[y][x][2] << 8) & 0x0000FF00)
|
||||||
| ((pixels[y][x][3]) & 0x000000FF);
|
| ((pixels[y][x][3]) & 0x000000FF);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferedImage img = new BufferedImage(cols, rows, BufferedImage.TYPE_4BYTE_ABGR);
|
BufferedImage img = new BufferedImage(cols, rows, BufferedImage.TYPE_4BYTE_ABGR);
|
||||||
img.setRGB(0, 0, cols, rows, data, 0, cols);
|
img.setRGB(0, 0, cols, rows, data, 0, cols);
|
||||||
|
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the image thru the processor
|
* Runs the image thru the processor
|
||||||
*
|
*
|
||||||
* @param data is the raw image to apply the effect to. This will NOT be altered
|
* @param data is the raw image to apply the effect to. This will NOT be altered
|
||||||
*/
|
*/
|
||||||
public int[][][] process(int[][][] data){
|
public int[][][] process(int[][][] data){
|
||||||
return process(data, 0, 0, data[0].length, data.length);
|
return process(data, 0, 0, data[0].length, data.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The underlying effect is run here
|
* The underlying effect is run here
|
||||||
*
|
*
|
||||||
* @param data is the raw image to apply the effect to. This will NOT be altered
|
* @param data is the raw image to apply the effect to. This will NOT be altered
|
||||||
* @param startX is the x pixel of the image to start from
|
* @param startX is the x pixel of the image to start from
|
||||||
* @param startY is the y pixel of the image to start from
|
* @param startY is the y pixel of the image to start from
|
||||||
* @param stopX is the x pixel of the image to stop
|
* @param stopX is the x pixel of the image to stop
|
||||||
* @param stopY is the y pixel of the image to stop
|
* @param stopY is the y pixel of the image to stop
|
||||||
* @return either the modified data parameter or an new array
|
* @return either the modified data parameter or an new array
|
||||||
*/
|
*/
|
||||||
public abstract int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY);
|
public abstract int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,81 +35,81 @@ import java.awt.image.BufferedImage;
|
||||||
*/
|
*/
|
||||||
public class ImageUtil {
|
public class ImageUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resizes a BufferedImage
|
* Resizes a BufferedImage
|
||||||
*
|
*
|
||||||
* @param source is the image to resize
|
* @param source is the image to resize
|
||||||
* @param width is the wanted width
|
* @param width is the wanted width
|
||||||
* @param height is the wanted height
|
* @param height is the wanted height
|
||||||
* @param keep_aspect is if the aspect ratio of the image should be kept
|
* @param keep_aspect is if the aspect ratio of the image should be kept
|
||||||
* @return the resized image
|
* @return the resized image
|
||||||
*/
|
*/
|
||||||
public static BufferedImage scale(BufferedImage source, int width, int height, boolean keep_aspect){
|
public static BufferedImage scale(BufferedImage source, int width, int height, boolean keep_aspect){
|
||||||
double scale_width = (double)width / source.getWidth();
|
double scale_width = (double)width / source.getWidth();
|
||||||
double scale_height = (double)height / source.getHeight();
|
double scale_height = (double)height / source.getHeight();
|
||||||
|
|
||||||
// aspect calculation
|
// aspect calculation
|
||||||
if(keep_aspect){
|
if(keep_aspect){
|
||||||
if(scale_width * source.getHeight() > height){
|
if(scale_width * source.getHeight() > height){
|
||||||
scale_width = scale_height;
|
scale_width = scale_height;
|
||||||
}else{
|
}else{
|
||||||
scale_height = scale_width;
|
scale_height = scale_width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BufferedImage tmp = new BufferedImage(
|
BufferedImage tmp = new BufferedImage(
|
||||||
(int)(scale_width * source.getWidth()),
|
(int)(scale_width * source.getWidth()),
|
||||||
(int)(scale_height * source.getHeight()),
|
(int)(scale_height * source.getHeight()),
|
||||||
BufferedImage.TYPE_INT_RGB);
|
BufferedImage.TYPE_INT_RGB);
|
||||||
Graphics2D g2d = tmp.createGraphics();
|
Graphics2D g2d = tmp.createGraphics();
|
||||||
|
|
||||||
AffineTransform at = AffineTransform.getScaleInstance(scale_width, scale_height);
|
AffineTransform at = AffineTransform.getScaleInstance(scale_width, scale_height);
|
||||||
g2d.drawRenderedImage(source, at);
|
g2d.drawRenderedImage(source, at);
|
||||||
g2d.dispose();
|
g2d.dispose();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Crops a image to a specific aspect ration
|
* Crops a image to a specific aspect ration
|
||||||
*
|
*
|
||||||
* @param image is the actual image to crop
|
* @param image is the actual image to crop
|
||||||
* @param aspect is the aspect ratio to convert the image to
|
* @param aspect is the aspect ratio to convert the image to
|
||||||
* @return a new image with the specified aspect ratio
|
* @return a new image with the specified aspect ratio
|
||||||
*/
|
*/
|
||||||
public static BufferedImage cropToAspectRatio(BufferedImage image, float aspect){
|
public static BufferedImage cropToAspectRatio(BufferedImage image, float aspect){
|
||||||
int x = 0, y = 0;
|
int x = 0, y = 0;
|
||||||
int width = image.getWidth();
|
int width = image.getWidth();
|
||||||
int height = image.getHeight();
|
int height = image.getHeight();
|
||||||
|
|
||||||
// Check if the width is larger than the heigth
|
// Check if the width is larger than the heigth
|
||||||
if( width > height ){
|
if( width > height ){
|
||||||
width = (int) (height * aspect);
|
width = (int) (height * aspect);
|
||||||
x = image.getWidth()/2 - width/2;
|
x = image.getWidth()/2 - width/2;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
height = (int) (width * aspect);
|
height = (int) (width * aspect);
|
||||||
y = image.getHeight()/2 - height/2;
|
y = image.getHeight()/2 - height/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return image.getSubimage(x, y, width, height);
|
return image.getSubimage(x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function crops the image to the aspect ratio of
|
* This function crops the image to the aspect ratio of
|
||||||
* the width and height and then scales the image to the
|
* the width and height and then scales the image to the
|
||||||
* given values
|
* given values
|
||||||
*
|
*
|
||||||
* @param source is the image to resize
|
* @param source is the image to resize
|
||||||
* @param width is the wanted width
|
* @param width is the wanted width
|
||||||
* @param height is the wanted height
|
* @param height is the wanted height
|
||||||
* @return a new image with the specified width and height
|
* @return a new image with the specified width and height
|
||||||
*/
|
*/
|
||||||
public static BufferedImage cropScale(BufferedImage source, int width, int height){
|
public static BufferedImage cropScale(BufferedImage source, int width, int height){
|
||||||
float aspect = width/height;
|
float aspect = width/height;
|
||||||
BufferedImage tmp = cropToAspectRatio(source, aspect);
|
BufferedImage tmp = cropToAspectRatio(source, aspect);
|
||||||
tmp = scale(tmp, width, height, false);
|
tmp = scale(tmp, width, height, false);
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,87 +31,87 @@ import zutil.math.ZMath;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
public class BlurFilter extends ImageFilterProcessor{
|
public class BlurFilter extends ImageFilterProcessor{
|
||||||
private int blurValue;
|
private int blurValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a blur effect on the image
|
* Creates a blur effect on the image
|
||||||
* @param img The image to blur
|
* @param img The image to blur
|
||||||
*/
|
*/
|
||||||
public BlurFilter(BufferedImage img){
|
public BlurFilter(BufferedImage img){
|
||||||
this(img, 10);
|
this(img, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a blur effect on the image
|
* Creates a blur effect on the image
|
||||||
* @param img The image to blur
|
* @param img The image to blur
|
||||||
* @param blur The amount to blur
|
* @param blur The amount to blur
|
||||||
*/
|
*/
|
||||||
public BlurFilter(BufferedImage img, int blur){
|
public BlurFilter(BufferedImage img, int blur){
|
||||||
super(img);
|
super(img);
|
||||||
blurValue = blur;
|
blurValue = blur;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
|
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
|
||||||
int inputPeak = RAWImageUtil.getPeakValue(data);
|
int inputPeak = RAWImageUtil.getPeakValue(data);
|
||||||
|
|
||||||
int[][][] tmpData = new int[data.length][data[0].length][4];
|
int[][][] tmpData = new int[data.length][data[0].length][4];
|
||||||
int[][][] output = RAWImageUtil.copyArray(data);
|
int[][][] output = RAWImageUtil.copyArray(data);
|
||||||
//Perform the convolution one or more times in succession
|
//Perform the convolution one or more times in succession
|
||||||
int redSum, greenSum, blueSum, outputPeak;
|
int redSum, greenSum, blueSum, outputPeak;
|
||||||
for(int i=0; i<blurValue ;i++){
|
for(int i=0; i<blurValue ;i++){
|
||||||
//Iterate on each pixel as a registration point.
|
//Iterate on each pixel as a registration point.
|
||||||
for(int y=startY; y<stopY ;y++){
|
for(int y=startY; y<stopY ;y++){
|
||||||
setProgress(ZMath.percent(0, (blurValue-1)*(stopY-startY-2), i*(stopY-startY-2)+y));
|
setProgress(ZMath.percent(0, (blurValue-1)*(stopY-startY-2), i*(stopY-startY-2)+y));
|
||||||
for(int x=startX; x<stopX ;x++){
|
for(int x=startX; x<stopX ;x++){
|
||||||
if(x == 0 || x == output[0].length-1 || y == 0 || y == output.length-1){
|
if(x == 0 || x == output[0].length-1 || y == 0 || y == output.length-1){
|
||||||
redSum = output[y][x][1] * 9;
|
redSum = output[y][x][1] * 9;
|
||||||
greenSum = output[y][x][2] * 9;
|
greenSum = output[y][x][2] * 9;
|
||||||
blueSum = output[y][x][3] * 9;
|
blueSum = output[y][x][3] * 9;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
redSum =
|
redSum =
|
||||||
output[y - 1][x - 1][1] +
|
output[y - 1][x - 1][1] +
|
||||||
output[y - 1][x - 0][1] +
|
output[y - 1][x - 0][1] +
|
||||||
output[y - 1][x + 1][1] +
|
output[y - 1][x + 1][1] +
|
||||||
output[y - 0][x - 1][1] +
|
output[y - 0][x - 1][1] +
|
||||||
output[y - 0][x - 0][1] +
|
output[y - 0][x - 0][1] +
|
||||||
output[y - 0][x + 1][1] +
|
output[y - 0][x + 1][1] +
|
||||||
output[y + 1][x - 1][1] +
|
output[y + 1][x - 1][1] +
|
||||||
output[y + 1][x - 0][1] +
|
output[y + 1][x - 0][1] +
|
||||||
output[y + 1][x + 1][1];
|
output[y + 1][x + 1][1];
|
||||||
greenSum =
|
greenSum =
|
||||||
output[y - 1][x - 1][2] +
|
output[y - 1][x - 1][2] +
|
||||||
output[y - 1][x - 0][2] +
|
output[y - 1][x - 0][2] +
|
||||||
output[y - 1][x + 1][2] +
|
output[y - 1][x + 1][2] +
|
||||||
output[y - 0][x - 1][2] +
|
output[y - 0][x - 1][2] +
|
||||||
output[y - 0][x - 0][2] +
|
output[y - 0][x - 0][2] +
|
||||||
output[y - 0][x + 1][2] +
|
output[y - 0][x + 1][2] +
|
||||||
output[y + 1][x - 1][2] +
|
output[y + 1][x - 1][2] +
|
||||||
output[y + 1][x - 0][2] +
|
output[y + 1][x - 0][2] +
|
||||||
output[y + 1][x + 1][2];
|
output[y + 1][x + 1][2];
|
||||||
blueSum =
|
blueSum =
|
||||||
output[y - 1][x - 1][3] +
|
output[y - 1][x - 1][3] +
|
||||||
output[y - 1][x - 0][3] +
|
output[y - 1][x - 0][3] +
|
||||||
output[y - 1][x + 1][3] +
|
output[y - 1][x + 1][3] +
|
||||||
output[y - 0][x - 1][3] +
|
output[y - 0][x - 1][3] +
|
||||||
output[y - 0][x - 0][3] +
|
output[y - 0][x - 0][3] +
|
||||||
output[y - 0][x + 1][3] +
|
output[y - 0][x + 1][3] +
|
||||||
output[y + 1][x - 1][3] +
|
output[y + 1][x - 1][3] +
|
||||||
output[y + 1][x - 0][3] +
|
output[y + 1][x - 0][3] +
|
||||||
output[y + 1][x + 1][3];
|
output[y + 1][x + 1][3];
|
||||||
}
|
}
|
||||||
tmpData[y][x][0] = output[y][x][0];
|
tmpData[y][x][0] = output[y][x][0];
|
||||||
tmpData[y][x][1] = redSum;
|
tmpData[y][x][1] = redSum;
|
||||||
tmpData[y][x][2] = greenSum;
|
tmpData[y][x][2] = greenSum;
|
||||||
tmpData[y][x][3] = blueSum;
|
tmpData[y][x][3] = blueSum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getting the new peak value and normalizing the image
|
// getting the new peak value and normalizing the image
|
||||||
outputPeak = RAWImageUtil.getPeakValue(tmpData);
|
outputPeak = RAWImageUtil.getPeakValue(tmpData);
|
||||||
RAWImageUtil.normalize(output, tmpData, startX, startY, stopX, stopY, ((double)inputPeak)/outputPeak );
|
RAWImageUtil.normalize(output, tmpData, startX, startY, stopX, stopY, ((double)inputPeak)/outputPeak );
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,84 +30,84 @@ import zutil.math.ZMath;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
public class ColorIntensityFilter extends ImageFilterProcessor{
|
public class ColorIntensityFilter extends ImageFilterProcessor{
|
||||||
private boolean invert;
|
private boolean invert;
|
||||||
private double redScale;
|
private double redScale;
|
||||||
private double greenScale;
|
private double greenScale;
|
||||||
private double blueScale;
|
private double blueScale;
|
||||||
|
|
||||||
public ColorIntensityFilter(BufferedImage img){
|
public ColorIntensityFilter(BufferedImage img){
|
||||||
this(img, 0.2, 0.2, 0.2, false);
|
this(img, 0.2, 0.2, 0.2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a ColorIntensityEffect object with the given values
|
* Creates a ColorIntensityEffect object with the given values
|
||||||
* @param img The image data
|
* @param img The image data
|
||||||
* @param inv If the image color should be inverted
|
* @param inv If the image color should be inverted
|
||||||
*/
|
*/
|
||||||
public ColorIntensityFilter(BufferedImage img, boolean inv){
|
public ColorIntensityFilter(BufferedImage img, boolean inv){
|
||||||
this(img, 0.5, 0.5, 0.5, inv);
|
this(img, 0.5, 0.5, 0.5, inv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a ColorIntensityEffect object with the given values
|
* Creates a ColorIntensityEffect object with the given values
|
||||||
* @param img The image data
|
* @param img The image data
|
||||||
* @param red The scale of red (0-1)
|
* @param red The scale of red (0-1)
|
||||||
* @param green The scale of green (0-1)
|
* @param green The scale of green (0-1)
|
||||||
* @param blue The scale of blue (0-1)
|
* @param blue The scale of blue (0-1)
|
||||||
*/
|
*/
|
||||||
public ColorIntensityFilter(BufferedImage img, double red, double green, double blue){
|
public ColorIntensityFilter(BufferedImage img, double red, double green, double blue){
|
||||||
this(img, red, green, blue, false);
|
this(img, red, green, blue, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a ColorIntensityEffect object with the given values
|
* Creates a ColorIntensityEffect object with the given values
|
||||||
* @param img The image data
|
* @param img The image data
|
||||||
* @param red The scale of red (0-1)
|
* @param red The scale of red (0-1)
|
||||||
* @param green The scale of green (0-1)
|
* @param green The scale of green (0-1)
|
||||||
* @param blue The scale of blue (0-1)
|
* @param blue The scale of blue (0-1)
|
||||||
* @param inv If the image color should be inverted
|
* @param inv If the image color should be inverted
|
||||||
*/
|
*/
|
||||||
public ColorIntensityFilter(BufferedImage img, double red, double green, double blue, boolean inv){
|
public ColorIntensityFilter(BufferedImage img, double red, double green, double blue, boolean inv){
|
||||||
super(img);
|
super(img);
|
||||||
invert = false;
|
invert = false;
|
||||||
redScale = red;
|
redScale = red;
|
||||||
greenScale = green;
|
greenScale = green;
|
||||||
blueScale = blue;
|
blueScale = blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
|
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
|
||||||
int[][][] output = new int[data.length][data[0].length][4];
|
int[][][] output = new int[data.length][data[0].length][4];
|
||||||
// making sure the scales are right
|
// making sure the scales are right
|
||||||
if(redScale > 1) redScale = 1;
|
if(redScale > 1) redScale = 1;
|
||||||
else if(redScale < 0) redScale = 0;
|
else if(redScale < 0) redScale = 0;
|
||||||
|
|
||||||
if(greenScale > 1) greenScale = 1;
|
if(greenScale > 1) greenScale = 1;
|
||||||
else if(greenScale < 0) greenScale = 0;
|
else if(greenScale < 0) greenScale = 0;
|
||||||
|
|
||||||
if(blueScale > 1) blueScale = 1;
|
if(blueScale > 1) blueScale = 1;
|
||||||
else if(blueScale < 0) blueScale = 0;
|
else if(blueScale < 0) blueScale = 0;
|
||||||
|
|
||||||
// Applying the color intensity to the image
|
// Applying the color intensity to the image
|
||||||
for(int y=startY; y<stopY ;y++){
|
for(int y=startY; y<stopY ;y++){
|
||||||
setProgress(ZMath.percent(0, stopY-startY-1, y));
|
setProgress(ZMath.percent(0, stopY-startY-1, y));
|
||||||
for(int x=startX; x<stopX ;x++){
|
for(int x=startX; x<stopX ;x++){
|
||||||
if(!invert){
|
if(!invert){
|
||||||
// inversion
|
// inversion
|
||||||
output[y][x][0] = data[y][x][0];
|
output[y][x][0] = data[y][x][0];
|
||||||
output[y][x][1] = (int)( 255 - data[y][x][1] * redScale );
|
output[y][x][1] = (int)( 255 - data[y][x][1] * redScale );
|
||||||
output[y][x][2] = (int)( 255 - data[y][x][2] * greenScale );
|
output[y][x][2] = (int)( 255 - data[y][x][2] * greenScale );
|
||||||
output[y][x][3] = (int)( 255 - data[y][x][3] * blueScale );
|
output[y][x][3] = (int)( 255 - data[y][x][3] * blueScale );
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
output[y][x][0] = data[y][x][0];
|
output[y][x][0] = data[y][x][0];
|
||||||
output[y][x][1] = (int)( data[y][x][1] * redScale );
|
output[y][x][1] = (int)( data[y][x][1] * redScale );
|
||||||
output[y][x][2] = (int)( data[y][x][2] * greenScale );
|
output[y][x][2] = (int)( data[y][x][2] * greenScale );
|
||||||
output[y][x][3] = (int)( data[y][x][3] * blueScale );
|
output[y][x][3] = (int)( data[y][x][3] * blueScale );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,42 +30,42 @@ import zutil.image.RAWImageUtil;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
public class ContrastBrightnessFilter extends ImageFilterProcessor{
|
public class ContrastBrightnessFilter extends ImageFilterProcessor{
|
||||||
private double contrast;
|
private double contrast;
|
||||||
private double brightness;
|
private double brightness;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a ContrastBrightnessEffect object with the given values
|
* Creates a ContrastBrightnessEffect object with the given values
|
||||||
* @param img The image to apply the effect to
|
* @param img The image to apply the effect to
|
||||||
*/
|
*/
|
||||||
public ContrastBrightnessFilter(BufferedImage img){
|
public ContrastBrightnessFilter(BufferedImage img){
|
||||||
this(img, 3, 1.2);
|
this(img, 3, 1.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a ContrastBrightnessEffect object with the given values
|
* Creates a ContrastBrightnessEffect object with the given values
|
||||||
* @param img The image to apply the effect to
|
* @param img The image to apply the effect to
|
||||||
* @param con The contrast to apply
|
* @param con The contrast to apply
|
||||||
* @param brig The brightness to apply
|
* @param brig The brightness to apply
|
||||||
*/
|
*/
|
||||||
public ContrastBrightnessFilter(BufferedImage img, double con, double brig){
|
public ContrastBrightnessFilter(BufferedImage img, double con, double brig){
|
||||||
super(img);
|
super(img);
|
||||||
contrast = con;
|
contrast = con;
|
||||||
brightness = brig;
|
brightness = brig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
|
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
|
||||||
int mean = RAWImageUtil.getMeanValue(data);
|
int mean = RAWImageUtil.getMeanValue(data);
|
||||||
|
|
||||||
int[][][] output = RAWImageUtil.copyArray(data);
|
|
||||||
|
|
||||||
RAWImageUtil.addMeanValue(output, startX, startY, stopX, stopY, mean*(-1));
|
|
||||||
RAWImageUtil.scale(output, startX, startY, stopX, stopY, contrast);
|
|
||||||
RAWImageUtil.addMeanValue(output, startX, startY, stopX, stopY, (int)(brightness*mean));
|
|
||||||
|
|
||||||
RAWImageUtil.clip(output, startX, startY, stopX, stopY);
|
int[][][] output = RAWImageUtil.copyArray(data);
|
||||||
|
|
||||||
return output;
|
RAWImageUtil.addMeanValue(output, startX, startY, stopX, stopY, mean*(-1));
|
||||||
}
|
RAWImageUtil.scale(output, startX, startY, stopX, stopY, contrast);
|
||||||
|
RAWImageUtil.addMeanValue(output, startX, startY, stopX, stopY, (int)(brightness*mean));
|
||||||
|
|
||||||
|
RAWImageUtil.clip(output, startX, startY, stopX, stopY);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,72 +36,72 @@ import java.awt.image.BufferedImage;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class ConvolutionFilter extends ImageFilterProcessor{
|
public class ConvolutionFilter extends ImageFilterProcessor{
|
||||||
private double[][] kernel;
|
private double[][] kernel;
|
||||||
|
|
||||||
protected ConvolutionFilter(BufferedImage img) {
|
protected ConvolutionFilter(BufferedImage img) {
|
||||||
super(img);
|
super(img);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConvolutionFilter(double[][] kernel) {
|
|
||||||
this(null, kernel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies an Convolution kernel to the specified image
|
|
||||||
*
|
|
||||||
* @param img is the image
|
|
||||||
* @param kernel is the kernel to apply to the image
|
|
||||||
*/
|
|
||||||
public ConvolutionFilter(BufferedImage img, double[][] kernel) {
|
|
||||||
super(img);
|
|
||||||
this.kernel = kernel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public ConvolutionFilter(double[][] kernel) {
|
||||||
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
|
this(null, kernel);
|
||||||
if(kernel == null) this.kernel = generateKernel();
|
}
|
||||||
|
|
||||||
int[][][] tmpData = new int[data.length][data[0].length][4];
|
|
||||||
int xk_length = kernel[0].length;
|
|
||||||
int yk_length = kernel.length;
|
|
||||||
|
|
||||||
for(int y=startY; y<stopY ;y++){
|
/**
|
||||||
setProgress(ZMath.percent(0, (stopY-startY), y+1));
|
* Applies an Convolution kernel to the specified image
|
||||||
for(int x=startX; x<stopX ;x++){
|
*
|
||||||
tmpData[y][x][0] = data[y][x][0]; // alpha
|
* @param img is the image
|
||||||
|
* @param kernel is the kernel to apply to the image
|
||||||
for(int yk=0; yk<yk_length ;yk++){
|
*/
|
||||||
for(int xk=0; xk<xk_length ;xk++){
|
public ConvolutionFilter(BufferedImage img, double[][] kernel) {
|
||||||
if(0 <= y-yk_length/2+yk && y-yk_length/2+yk < data.length &&
|
super(img);
|
||||||
0 <= x-xk_length/2+xk && x-xk_length/2+xk < data[0].length){ // check that its not out of index
|
this.kernel = kernel;
|
||||||
tmpData[y][x][1] += data[y-yk_length/2+yk][x-xk_length/2+xk][1] * kernel[yk][xk];
|
}
|
||||||
tmpData[y][x][2] += data[y-yk_length/2+yk][x-xk_length/2+xk][2] * kernel[yk][xk];
|
|
||||||
tmpData[y][x][3] += data[y-yk_length/2+yk][x-xk_length/2+xk][3] * kernel[yk][xk];
|
@Override
|
||||||
}
|
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
|
||||||
}
|
if(kernel == null) this.kernel = generateKernel();
|
||||||
}
|
|
||||||
}
|
int[][][] tmpData = new int[data.length][data[0].length][4];
|
||||||
}
|
int xk_length = kernel[0].length;
|
||||||
|
int yk_length = kernel.length;
|
||||||
RAWImageUtil.clip(tmpData, startX, startY, stopX, stopY);
|
|
||||||
|
for(int y=startY; y<stopY ;y++){
|
||||||
return tmpData;
|
setProgress(ZMath.percent(0, (stopY-startY), y+1));
|
||||||
}
|
for(int x=startX; x<stopX ;x++){
|
||||||
|
tmpData[y][x][0] = data[y][x][0]; // alpha
|
||||||
/**
|
|
||||||
* Returns the kernel or null if it has not been generated yet.
|
for(int yk=0; yk<yk_length ;yk++){
|
||||||
*/
|
for(int xk=0; xk<xk_length ;xk++){
|
||||||
public double[][] getKernel(){
|
if(0 <= y-yk_length/2+yk && y-yk_length/2+yk < data.length &&
|
||||||
return kernel;
|
0 <= x-xk_length/2+xk && x-xk_length/2+xk < data[0].length){ // check that its not out of index
|
||||||
}
|
tmpData[y][x][1] += data[y-yk_length/2+yk][x-xk_length/2+xk][1] * kernel[yk][xk];
|
||||||
|
tmpData[y][x][2] += data[y-yk_length/2+yk][x-xk_length/2+xk][2] * kernel[yk][xk];
|
||||||
/**
|
tmpData[y][x][3] += data[y-yk_length/2+yk][x-xk_length/2+xk][3] * kernel[yk][xk];
|
||||||
* Should be overridden by a subclass
|
}
|
||||||
*
|
}
|
||||||
* @return an special generated kernel
|
}
|
||||||
*/
|
}
|
||||||
protected double[][] generateKernel(){
|
}
|
||||||
return null;
|
|
||||||
}
|
RAWImageUtil.clip(tmpData, startX, startY, stopX, stopY);
|
||||||
|
|
||||||
|
return tmpData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the kernel or null if it has not been generated yet.
|
||||||
|
*/
|
||||||
|
public double[][] getKernel(){
|
||||||
|
return kernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should be overridden by a subclass
|
||||||
|
*
|
||||||
|
* @return an special generated kernel
|
||||||
|
*/
|
||||||
|
protected double[][] generateKernel(){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,67 +32,67 @@ import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
|
||||||
public class DitheringFilter extends ImageFilterProcessor{
|
public class DitheringFilter extends ImageFilterProcessor{
|
||||||
// default palette is black and white
|
// default palette is black and white
|
||||||
private int[][] palette = {
|
private int[][] palette = {
|
||||||
{255,0,0,0},
|
{255,0,0,0},
|
||||||
{255,255,255,255}
|
{255,255,255,255}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up a default DitheringEffect
|
* Sets up a default DitheringEffect
|
||||||
*/
|
*/
|
||||||
public DitheringFilter(BufferedImage img){
|
public DitheringFilter(BufferedImage img){
|
||||||
super(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(int[][][] data, int startX, int startY, int stopX, int stopY) {
|
* Creates a Dithering Effect object
|
||||||
int error, index;
|
* @param img The image to apply the effect on
|
||||||
int[] currentPixel;
|
* @param palette The palette to use on the image
|
||||||
int[][][] output = RAWImageUtil.copyArray(data);
|
* int[colorCount][4]
|
||||||
|
* 0 -> Alpha data
|
||||||
for(int y=startY; y<stopY ;y++){
|
* Red data
|
||||||
setProgress(ZMath.percent(0, stopY-startY-1, y));
|
* Green data
|
||||||
for(int x=startX; x<stopX ;x++){
|
* 4 -> Blue data
|
||||||
currentPixel = output[y][x];
|
*/
|
||||||
index = findNearestColor(currentPixel, palette);
|
public DitheringFilter(BufferedImage img, int[][] palette){
|
||||||
output[y][x] = palette[index];
|
super(img);
|
||||||
|
this.palette = palette;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
|
||||||
|
int error, index;
|
||||||
|
int[] currentPixel;
|
||||||
|
int[][][] output = RAWImageUtil.copyArray(data);
|
||||||
|
|
||||||
|
for(int y=startY; y<stopY ;y++){
|
||||||
|
setProgress(ZMath.percent(0, stopY-startY-1, y));
|
||||||
|
for(int x=startX; x<stopX ;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 < output[0].length) {
|
||||||
|
output[y+0][x+1][i] = RAWImageUtil.clip( output[y+0][x+1][i] + (error*7)/16 );
|
||||||
|
}
|
||||||
|
if (y + 1 < data.length) {
|
||||||
|
if (x - 1 > 0)
|
||||||
|
output[y+1][x-1][i] = RAWImageUtil.clip( output[y+1][x-1][i] + (error*3)/16 );
|
||||||
|
output[y+1][x+0][i] = RAWImageUtil.clip( output[y+1][x+0][i] + (error*5)/16 );
|
||||||
|
if (x + 1 < data[0].length)
|
||||||
|
output[y+1][x+1][i] = RAWImageUtil.clip( output[y+1][x+1][i] + (error*1)/16 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 1; i < 4; i++) {
|
|
||||||
error = currentPixel[i] - palette[index][i];
|
|
||||||
if (x + 1 < output[0].length) {
|
|
||||||
output[y+0][x+1][i] = RAWImageUtil.clip( output[y+0][x+1][i] + (error*7)/16 );
|
|
||||||
}
|
|
||||||
if (y + 1 < data.length) {
|
|
||||||
if (x - 1 > 0)
|
|
||||||
output[y+1][x-1][i] = RAWImageUtil.clip( output[y+1][x-1][i] + (error*3)/16 );
|
|
||||||
output[y+1][x+0][i] = RAWImageUtil.clip( output[y+1][x+0][i] + (error*5)/16 );
|
|
||||||
if (x + 1 < data[0].length)
|
|
||||||
output[y+1][x+1][i] = RAWImageUtil.clip( output[y+1][x+1][i] + (error*1)/16 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int findNearestColor(int[] color, int[][] palette) {
|
private static int findNearestColor(int[] color, int[][] palette) {
|
||||||
int minDistanceSquared = 255*255 + 255*255 + 255*255 + 1;
|
int minDistanceSquared = 255*255 + 255*255 + 255*255 + 1;
|
||||||
int bestIndex = 0;
|
int bestIndex = 0;
|
||||||
|
|
|
||||||
|
|
@ -32,40 +32,40 @@ import java.awt.image.BufferedImage;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class GaussianBlurFilter extends ConvolutionFilter{
|
public class GaussianBlurFilter extends ConvolutionFilter{
|
||||||
private int size;
|
private int size;
|
||||||
private double sigma;
|
private double sigma;
|
||||||
|
|
||||||
public GaussianBlurFilter(BufferedImage img) {
|
public GaussianBlurFilter(BufferedImage img) {
|
||||||
this(img, 5, 1.4);
|
this(img, 5, 1.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GaussianBlurFilter(BufferedImage img, int size, double sigma) {
|
|
||||||
super(img);
|
|
||||||
this.size = size;
|
|
||||||
this.sigma = sigma;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected double[][] generateKernel(){
|
public GaussianBlurFilter(BufferedImage img, int size, double sigma) {
|
||||||
return gaussianFunction(size, size, sigma);
|
super(img);
|
||||||
}
|
this.size = size;
|
||||||
|
this.sigma = sigma;
|
||||||
/**
|
}
|
||||||
* Generates the kernel from the specified values
|
|
||||||
*/
|
|
||||||
public static double[][] gaussianFunction(int size_x, int size_y, double sigma){
|
|
||||||
double[][] kernel;
|
|
||||||
int center_x = size_x/2;
|
|
||||||
int center_y = size_y/2;
|
|
||||||
|
|
||||||
kernel = new double[size_y][size_x];
|
|
||||||
for(int y=0; y<size_y ;y++){
|
|
||||||
for(int x=0; x<size_x ;x++){
|
|
||||||
double tmp_x = (double)( (x-center_x)*(x-center_x) )/(2*sigma*sigma);
|
|
||||||
double tmp_y = (double)( (y-center_y)*(y-center_y) )/(2*sigma*sigma);
|
|
||||||
kernel[y][x] = 1.0/(2*Math.PI*sigma*sigma) * Math.exp( -(tmp_x + tmp_y) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return kernel;
|
protected double[][] generateKernel(){
|
||||||
}
|
return gaussianFunction(size, size, sigma);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the kernel from the specified values
|
||||||
|
*/
|
||||||
|
public static double[][] gaussianFunction(int size_x, int size_y, double sigma){
|
||||||
|
double[][] kernel;
|
||||||
|
int center_x = size_x/2;
|
||||||
|
int center_y = size_y/2;
|
||||||
|
|
||||||
|
kernel = new double[size_y][size_x];
|
||||||
|
for(int y=0; y<size_y ;y++){
|
||||||
|
for(int x=0; x<size_x ;x++){
|
||||||
|
double tmp_x = (double)( (x-center_x)*(x-center_x) )/(2*sigma*sigma);
|
||||||
|
double tmp_y = (double)( (y-center_y)*(y-center_y) )/(2*sigma*sigma);
|
||||||
|
kernel[y][x] = 1.0/(2*Math.PI*sigma*sigma) * Math.exp( -(tmp_x + tmp_y) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return kernel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,38 +32,38 @@ import java.awt.image.BufferedImage;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class MeanBlurFilter extends ConvolutionFilter{
|
public class MeanBlurFilter extends ConvolutionFilter{
|
||||||
private int windowSize;
|
private int windowSize;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup a default MedianFilter
|
* Setup a default MedianFilter
|
||||||
*
|
*
|
||||||
* @param img is the image to process
|
* @param img is the image to process
|
||||||
*/
|
*/
|
||||||
public MeanBlurFilter(BufferedImage img) {
|
public MeanBlurFilter(BufferedImage img) {
|
||||||
this(img, 10);
|
this(img, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup a default MedianFilter
|
* Setup a default MedianFilter
|
||||||
*
|
*
|
||||||
* @param img is the image to process
|
* @param img is the image to process
|
||||||
* @param pixels is the size of the window
|
* @param pixels is the size of the window
|
||||||
*/
|
*/
|
||||||
public MeanBlurFilter(BufferedImage img, int pixels) {
|
public MeanBlurFilter(BufferedImage img, int pixels) {
|
||||||
super(img);
|
super(img);
|
||||||
this.windowSize = pixels;
|
this.windowSize = pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected double[][] generateKernel(){
|
protected double[][] generateKernel(){
|
||||||
double[][] kernel = new double[windowSize][windowSize];
|
double[][] kernel = new double[windowSize][windowSize];
|
||||||
|
|
||||||
double mean = 1.0/(windowSize*windowSize);
|
double mean = 1.0/(windowSize*windowSize);
|
||||||
for(int y=0; y<windowSize ;y++){
|
for(int y=0; y<windowSize ;y++){
|
||||||
for(int x=0; x<windowSize ;x++){
|
for(int x=0; x<windowSize ;x++){
|
||||||
kernel[y][x] = mean;
|
kernel[y][x] = mean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return kernel;
|
return kernel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,42 +37,42 @@ import java.awt.image.BufferedImage;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class MedianFilter extends ImageFilterProcessor{
|
public class MedianFilter extends ImageFilterProcessor{
|
||||||
private int windowSize;
|
private int windowSize;
|
||||||
private boolean[] channels;
|
private boolean[] channels;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup a default MedianFilter
|
* Setup a default MedianFilter
|
||||||
*
|
*
|
||||||
* @param img The image to process
|
* @param img The image to process
|
||||||
*/
|
*/
|
||||||
public MedianFilter(BufferedImage img) {
|
public MedianFilter(BufferedImage img) {
|
||||||
this(img, 10);
|
this(img, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup a default MedianFilter
|
* Setup a default MedianFilter
|
||||||
*
|
*
|
||||||
* @param img The image to process
|
* @param img The image to process
|
||||||
* @param pixels The size of the window
|
* @param pixels The size of the window
|
||||||
*/
|
*/
|
||||||
public MedianFilter(BufferedImage img, int pixels) {
|
public MedianFilter(BufferedImage img, int pixels) {
|
||||||
this(img, pixels, new boolean[]{true,true,true,true});
|
this(img, pixels, new boolean[]{true,true,true,true});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup a default MedianFilter
|
* Setup a default MedianFilter
|
||||||
*
|
*
|
||||||
* @param img The image to process
|
* @param img The image to process
|
||||||
* @param pixels The size of the window
|
* @param pixels The size of the window
|
||||||
* @param channels Is a 4 element array for witch channels to use the filter on
|
* @param channels Is a 4 element array for witch channels to use the filter on
|
||||||
*/
|
*/
|
||||||
public MedianFilter(BufferedImage img, int pixels, boolean[] channels) {
|
public MedianFilter(BufferedImage img, int pixels, boolean[] channels) {
|
||||||
super(img);
|
super(img);
|
||||||
this.windowSize = pixels;
|
this.windowSize = pixels;
|
||||||
this.channels = channels;
|
this.channels = channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
edgex := (window width / 2) rounded down
|
edgex := (window width / 2) rounded down
|
||||||
edgey := (window height / 2) rounded down
|
edgey := (window height / 2) rounded down
|
||||||
for x from edgex to image width - edgex:
|
for x from edgex to image width - edgex:
|
||||||
|
|
@ -83,112 +83,112 @@ public class MedianFilter extends ImageFilterProcessor{
|
||||||
colorArray[fx][fy] := pixelvalue[x + fx - edgex][y + fy - edgey]
|
colorArray[fx][fy] := pixelvalue[x + fx - edgex][y + fy - edgey]
|
||||||
Sort colorArray[][];
|
Sort colorArray[][];
|
||||||
pixelValue[x][y] := colorArray[window width / 2][window height / 2];
|
pixelValue[x][y] := colorArray[window width / 2][window height / 2];
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
|
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
|
||||||
int[][][] tmpData = RAWImageUtil.copyArray(data);
|
int[][][] tmpData = RAWImageUtil.copyArray(data);
|
||||||
|
|
||||||
int edgeX = windowSize / 2;
|
int edgeX = windowSize / 2;
|
||||||
int edgeY = windowSize / 2;
|
int edgeY = windowSize / 2;
|
||||||
|
|
||||||
int[][] tmpArray = new int[4][256*2];
|
int[][] tmpArray = new int[4][256*2];
|
||||||
int pixelCount = 0;
|
int pixelCount = 0;
|
||||||
for(int y=startY; y<stopY ;y++){
|
for(int y=startY; y<stopY ;y++){
|
||||||
setProgress(ZMath.percent(0, stopY-startY-1, y));
|
setProgress(ZMath.percent(0, stopY-startY-1, y));
|
||||||
for(int x=startX; x<stopX ;x++){
|
for(int x=startX; x<stopX ;x++){
|
||||||
|
|
||||||
pixelCount = 0;
|
pixelCount = 0;
|
||||||
for(int fy=0; fy<windowSize ;fy++){
|
for(int fy=0; fy<windowSize ;fy++){
|
||||||
for(int fx=0; fx<windowSize ;fx++){
|
for(int fx=0; fx<windowSize ;fx++){
|
||||||
if(y+fy-edgeY >= 0 && y+fy-edgeY < data.length && x+fx-edgeX >= 0 && x+fx-edgeX < data[0].length){
|
if(y+fy-edgeY >= 0 && y+fy-edgeY < data.length && x+fx-edgeX >= 0 && x+fx-edgeX < data[0].length){
|
||||||
//colorArray[fx][fy] := pixelvalue[x + fx - edgex][y + fy - edgey]
|
//colorArray[fx][fy] := pixelvalue[x + fx - edgex][y + fy - edgey]
|
||||||
if(channels[0]) tmpArray[0][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][0] ) ]++;
|
if(channels[0]) tmpArray[0][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][0] ) ]++;
|
||||||
if(channels[1]) tmpArray[1][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][1] ) ]++;
|
if(channels[1]) tmpArray[1][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][1] ) ]++;
|
||||||
if(channels[2]) tmpArray[2][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][2] ) ]++;
|
if(channels[2]) tmpArray[2][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][2] ) ]++;
|
||||||
if(channels[3]) tmpArray[3][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][3] ) ]++;
|
if(channels[3]) tmpArray[3][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][3] ) ]++;
|
||||||
pixelCount++;
|
pixelCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(channels[0]) tmpData[y][x][0] = findMedian(tmpArray[0], pixelCount/2);
|
if(channels[0]) tmpData[y][x][0] = findMedian(tmpArray[0], pixelCount/2);
|
||||||
if(channels[1]) tmpData[y][x][1] = findMedian(tmpArray[1], pixelCount/2);
|
if(channels[1]) tmpData[y][x][1] = findMedian(tmpArray[1], pixelCount/2);
|
||||||
if(channels[2]) tmpData[y][x][2] = findMedian(tmpArray[2], pixelCount/2);
|
if(channels[2]) tmpData[y][x][2] = findMedian(tmpArray[2], pixelCount/2);
|
||||||
if(channels[3]) tmpData[y][x][3] = findMedian(tmpArray[3], pixelCount/2);
|
if(channels[3]) tmpData[y][x][3] = findMedian(tmpArray[3], pixelCount/2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmpData;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getMedianIndex(int i){
|
return tmpData;
|
||||||
if(i < 0) return Math.abs(i);
|
}
|
||||||
else return i+256;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int findMedian(int[] median, int medianCount){
|
private int getMedianIndex(int i){
|
||||||
int sum = 0;
|
if(i < 0) return Math.abs(i);
|
||||||
int ret = 0;
|
else return i+256;
|
||||||
for(int i=0; i<median.length ;i++){
|
}
|
||||||
sum += median[i];
|
|
||||||
median[i] = 0;
|
|
||||||
if(sum >= medianCount && ret == 0){
|
|
||||||
ret = i-256;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
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>{
|
class SortableARGB implements SortableDataList<Integer>{
|
||||||
private int[][][] data;
|
private int[][][] data;
|
||||||
private int cols;
|
private int cols;
|
||||||
private int rows;
|
private int rows;
|
||||||
private int channel;
|
private int channel;
|
||||||
|
|
||||||
public SortableARGB(int[][][] data, int cols, int rows, int channel){
|
public SortableARGB(int[][][] data, int cols, int rows, int channel){
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.cols = cols;
|
this.cols = cols;
|
||||||
this.rows = rows;
|
this.rows = rows;
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compare(int a, int b) {
|
public int compare(int a, int b) {
|
||||||
return compare(a, data[ getY(b) ][ getX(b) ][ channel ]);
|
return compare(a, data[ getY(b) ][ getX(b) ][ channel ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compare(int a, Integer b) {
|
public int compare(int a, Integer b) {
|
||||||
return ((Integer)data[ getY(a) ][ getX(a) ][ channel ]).compareTo(b);
|
return ((Integer)data[ getY(a) ][ getX(a) ][ channel ]).compareTo(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer get(int i) {
|
public Integer get(int i) {
|
||||||
return data[ getY(i) ][ getX(i) ][ channel ];
|
return data[ getY(i) ][ getX(i) ][ channel ];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(int i, Integer o){
|
|
||||||
data[ getY(i) ][ getX(i) ][ channel ] = o;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int size() {
|
public void set(int i, Integer o){
|
||||||
return cols * rows;
|
data[ getY(i) ][ getX(i) ][ channel ] = o;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void swap(int a, int b) {
|
public int size() {
|
||||||
int tmp = data[ getY(a) ][ getX(a) ][ channel ];
|
return cols * rows;
|
||||||
data[ getY(a) ][ getX(a) ][ channel ] = data[ getY(b) ][ getX(b) ][ channel ];
|
}
|
||||||
data[ getY(b) ][ getX(b) ][ channel ] = tmp;
|
|
||||||
}
|
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){
|
private int getX(int a){
|
||||||
return a % cols;
|
return a % cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getY(int a){
|
private int getY(int a){
|
||||||
return a / cols;
|
return a / cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,58 +30,58 @@ import zutil.math.ZMath;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
public class ResizeImage extends ImageFilterProcessor{
|
public class ResizeImage extends ImageFilterProcessor{
|
||||||
private int width;
|
private int width;
|
||||||
private int height;
|
private int height;
|
||||||
|
|
||||||
private int[][][] newData;
|
private int[][][] newData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will create a ResizeImage object and fix the height with the aspect
|
* Will create a ResizeImage object and fix the height with the aspect
|
||||||
* of the width
|
* of the width
|
||||||
*
|
*
|
||||||
* @param img The image to resize
|
* @param img The image to resize
|
||||||
* @param w The new width
|
* @param w The new width
|
||||||
*/
|
*/
|
||||||
public ResizeImage(BufferedImage img, int w){
|
public ResizeImage(BufferedImage img, int w){
|
||||||
this(img, w, -1);
|
this(img, w, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will create a ResizeImage object
|
* Will create a ResizeImage object
|
||||||
*
|
*
|
||||||
* @param img The image to resize
|
* @param img The image to resize
|
||||||
* @param w The new width if -1 then it will be scaled whit aspect of the hight
|
* @param w The new width if -1 then it will be scaled whit aspect of the hight
|
||||||
* @param h The new height if -1 then it will be scaled whit aspect of the width
|
* @param h The new height if -1 then it will be scaled whit aspect of the width
|
||||||
*/
|
*/
|
||||||
public ResizeImage(BufferedImage img, int w, int h){
|
public ResizeImage(BufferedImage img, int w, int h){
|
||||||
super(img);
|
super(img);
|
||||||
width = w;
|
width = w;
|
||||||
height = h;
|
height = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[][][] process(final int[][][] data, int startX, int startY, int stopX, int stopY) {
|
public int[][][] process(final int[][][] data, int startX, int startY, int stopX, int stopY) {
|
||||||
if(width < 1){
|
if(width < 1){
|
||||||
height = (int)(((double)width/(stopX-startX))*(stopY-startY));
|
height = (int)(((double)width/(stopX-startX))*(stopY-startY));
|
||||||
}
|
}
|
||||||
else if(height < 1){
|
else if(height < 1){
|
||||||
width = (int)(((double)height/(stopY-startY))*(stopX-startY));
|
width = (int)(((double)height/(stopY-startY))*(stopX-startY));
|
||||||
}
|
}
|
||||||
|
|
||||||
newData = new int[height][width][4];
|
newData = new int[height][width][4];
|
||||||
double xScale = ((double)(stopX-startX)/width);
|
double xScale = ((double)(stopX-startX)/width);
|
||||||
double yScale = ((double)(stopY-startY)/height);
|
double yScale = ((double)(stopY-startY)/height);
|
||||||
|
|
||||||
for(int y=0; y<width ;y++){
|
for(int y=0; y<width ;y++){
|
||||||
setProgress(ZMath.percent(0, width-1, y));
|
setProgress(ZMath.percent(0, width-1, y));
|
||||||
for(int x=0; x<height ;x++){
|
for(int x=0; x<height ;x++){
|
||||||
newData[y][x][0] = data[(int)(y*yScale)][(int)(x*xScale)][0];
|
newData[y][x][0] = data[(int)(y*yScale)][(int)(x*xScale)][0];
|
||||||
newData[y][x][1] = data[(int)(y*yScale)][(int)(x*xScale)][1];
|
newData[y][x][1] = data[(int)(y*yScale)][(int)(x*xScale)][1];
|
||||||
newData[y][x][2] = data[(int)(y*yScale)][(int)(x*xScale)][2];
|
newData[y][x][2] = data[(int)(y*yScale)][(int)(x*xScale)][2];
|
||||||
newData[y][x][3] = data[(int)(y*yScale)][(int)(x*xScale)][3];
|
newData[y][x][3] = data[(int)(y*yScale)][(int)(x*xScale)][3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return newData;
|
return newData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,53 +36,51 @@ import java.awt.image.BufferedImage;
|
||||||
* INFO: http://en.wikipedia.org/wiki/Sobel_operator
|
* INFO: http://en.wikipedia.org/wiki/Sobel_operator
|
||||||
*/
|
*/
|
||||||
public class SobelEdgeDetectionFilter extends ImageFilterProcessor{
|
public class SobelEdgeDetectionFilter extends ImageFilterProcessor{
|
||||||
private static final double[][] xG_kernel = new double[][]{
|
private static final double[][] xG_kernel = new double[][]{
|
||||||
{+1, 0, -1},
|
{+1, 0, -1},
|
||||||
{+2, 0, -2},
|
{+2, 0, -2},
|
||||||
{+1, 0, -1}
|
{+1, 0, -1}
|
||||||
};
|
};
|
||||||
private static final double[][] yG_kernel = new double[][]{
|
private static final double[][] yG_kernel = new double[][]{
|
||||||
{+1, +2, +1},
|
{+1, +2, +1},
|
||||||
{ 0, 0, 0},
|
{ 0, 0, 0},
|
||||||
{-1, -2, -1}
|
{-1, -2, -1}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
public SobelEdgeDetectionFilter(BufferedImage img) {
|
|
||||||
super(img);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
|
public SobelEdgeDetectionFilter(BufferedImage img) {
|
||||||
ConvolutionFilter conv = new ConvolutionFilter(xG_kernel);
|
super(img);
|
||||||
int[][][] xG = conv.process(data, startX, startY, stopX, stopY);
|
}
|
||||||
setProgress(33);
|
|
||||||
|
@Override
|
||||||
conv = new ConvolutionFilter(yG_kernel);
|
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
|
||||||
int[][][] yG = conv.process(data, startX, startY, stopX, stopY);
|
ConvolutionFilter conv = new ConvolutionFilter(xG_kernel);
|
||||||
setProgress(66);
|
int[][][] xG = conv.process(data, startX, startY, stopX, stopY);
|
||||||
|
setProgress(33);
|
||||||
int[][][] output = new int[data.length][data[0].length][4];
|
|
||||||
for(int y=startY; y<stopY ;y++){
|
conv = new ConvolutionFilter(yG_kernel);
|
||||||
setProgress(66+ZMath.percent(0, (stopY-startY), y+1)/100*34);
|
int[][][] yG = conv.process(data, startX, startY, stopX, stopY);
|
||||||
for(int x=startX; x<stopX ;x++){
|
setProgress(66);
|
||||||
output[y][x][0] = data[y][x][0];
|
|
||||||
output[y][x][1] = (int)Math.sqrt( xG[y][x][1]*xG[y][x][1] + yG[y][x][1]*yG[y][x][1] );
|
int[][][] output = new int[data.length][data[0].length][4];
|
||||||
output[y][x][2] = (int)Math.sqrt( xG[y][x][2]*xG[y][x][2] + yG[y][x][2]*yG[y][x][2] );
|
for(int y=startY; y<stopY ;y++){
|
||||||
output[y][x][3] = (int)Math.sqrt( xG[y][x][3]*xG[y][x][3] + yG[y][x][3]*yG[y][x][3] );
|
setProgress(66+ZMath.percent(0, (stopY-startY), y+1)/100*34);
|
||||||
/*
|
for(int x=startX; x<stopX ;x++){
|
||||||
output[y][x][1] = Math.abs( xG[y][x][1] ) + Math.abs(yG[y][x][1] );
|
output[y][x][0] = data[y][x][0];
|
||||||
output[y][x][2] = Math.abs( xG[y][x][2] ) + Math.abs(yG[y][x][2] );
|
output[y][x][1] = (int)Math.sqrt( xG[y][x][1]*xG[y][x][1] + yG[y][x][1]*yG[y][x][1] );
|
||||||
output[y][x][3] = Math.abs( xG[y][x][3] ) + Math.abs(yG[y][x][3] );
|
output[y][x][2] = (int)Math.sqrt( xG[y][x][2]*xG[y][x][2] + yG[y][x][2]*yG[y][x][2] );
|
||||||
*/
|
output[y][x][3] = (int)Math.sqrt( xG[y][x][3]*xG[y][x][3] + yG[y][x][3]*yG[y][x][3] );
|
||||||
}
|
/*
|
||||||
}
|
output[y][x][1] = Math.abs( xG[y][x][1] ) + Math.abs(yG[y][x][1] );
|
||||||
|
output[y][x][2] = Math.abs( xG[y][x][2] ) + Math.abs(yG[y][x][2] );
|
||||||
// gradient's direction:
|
output[y][x][3] = Math.abs( xG[y][x][3] ) + Math.abs(yG[y][x][3] );
|
||||||
// 0 = arctan( yG/xG )
|
*/
|
||||||
|
}
|
||||||
return output;
|
}
|
||||||
}
|
|
||||||
|
// gradient's direction:
|
||||||
|
// 0 = arctan( yG/xG )
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,69 +31,69 @@ import zutil.math.ZMath;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
public class SpotLightFilter extends ImageFilterProcessor{
|
public class SpotLightFilter extends ImageFilterProcessor{
|
||||||
private int radius;
|
private int radius;
|
||||||
private int xPos;
|
private int xPos;
|
||||||
private int yPos;
|
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
|
* Sets up a default spotlight effect in
|
||||||
* @param r The radius of the spotlight in pixels
|
* the middle of the image
|
||||||
*/
|
*/
|
||||||
public SpotLightFilter(BufferedImage img, int r){
|
public SpotLightFilter(BufferedImage img){
|
||||||
this(img, r, -1, -1);
|
this(img, 100, -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(int[][][] data, int startX, int startY, int stopX, int stopY) {
|
* Sets up a custom spotlight
|
||||||
if(xPos < 0) xPos = data[0].length/2;
|
* @param r The radius of the spotlight in pixels
|
||||||
if(yPos < 0) yPos = data.length/2;
|
*/
|
||||||
|
public SpotLightFilter(BufferedImage img, int r){
|
||||||
int[][][] output = new int[data.length][data[0].length][4];
|
this(img, r, -1, -1);
|
||||||
|
}
|
||||||
double scale, dx, dy, distance;
|
|
||||||
for(int y=startY; y<stopY ;y++){
|
/**
|
||||||
setProgress(ZMath.percent(0, (stopY-startY)-1, y));
|
* Sets up a custom spotlight
|
||||||
for(int x=startX; x<stopX ;x++){
|
* @param r The radius of the spotlight in pixels
|
||||||
dx = x-xPos;
|
* @param x The x position of the spotlight, if -1 then it will be centered
|
||||||
dy = y-yPos;
|
* @param y The y position of the spotlight, if -1 then it will be centered
|
||||||
|
*/
|
||||||
distance = Math.sqrt(dx*dx+dy*dy);
|
public SpotLightFilter(BufferedImage img, int r, int x, int y){
|
||||||
|
super(img);
|
||||||
if(distance > radius){
|
radius = r;
|
||||||
scale = 0;
|
xPos = x;
|
||||||
}
|
yPos = y;
|
||||||
else{
|
}
|
||||||
scale = 1-(distance/radius);
|
|
||||||
}
|
@Override
|
||||||
|
public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) {
|
||||||
output[y][x][0] = data[y][x][0];
|
if(xPos < 0) xPos = data[0].length/2;
|
||||||
output[y][x][1] = RAWImageUtil.clip((int)(scale * data[y][x][1]));
|
if(yPos < 0) yPos = data.length/2;
|
||||||
output[y][x][2] = RAWImageUtil.clip((int)(scale * data[y][x][2]));
|
|
||||||
output[y][x][3] = RAWImageUtil.clip((int)(scale * data[y][x][3]));
|
int[][][] output = new int[data.length][data[0].length][4];
|
||||||
}
|
|
||||||
}
|
double scale, dx, dy, distance;
|
||||||
return output;
|
for(int y=startY; y<stopY ;y++){
|
||||||
}
|
setProgress(ZMath.percent(0, (stopY-startY)-1, y));
|
||||||
|
for(int x=startX; x<stopX ;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] = RAWImageUtil.clip((int)(scale * data[y][x][1]));
|
||||||
|
output[y][x][2] = RAWImageUtil.clip((int)(scale * data[y][x][2]));
|
||||||
|
output[y][x][3] = RAWImageUtil.clip((int)(scale * data[y][x][3]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,23 +33,23 @@ import java.io.InputStream;
|
||||||
* until it gets to a boundary and will return -1 (end of stream).
|
* until it gets to a boundary and will return -1 (end of stream).
|
||||||
* The stream will not return any data until the {@link #next()}
|
* The stream will not return any data until the {@link #next()}
|
||||||
* method is called.
|
* method is called.
|
||||||
*
|
*
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class BufferedBoundaryInputStream extends FilterInputStream{
|
public class BufferedBoundaryInputStream extends FilterInputStream{
|
||||||
/** The size of the buffer in bytes */
|
/** The size of the buffer in bytes */
|
||||||
protected static final int DEFAULT_BUF_SIZE = 8192;
|
protected static final int DEFAULT_BUF_SIZE = 8192;
|
||||||
|
|
||||||
/** The raw buffer */
|
/** The raw buffer */
|
||||||
private byte buffer[];
|
private byte buffer[];
|
||||||
/** The current position in the buffer */
|
/** The current position in the buffer */
|
||||||
private int buf_pos = 0;
|
private int buf_pos = 0;
|
||||||
/** The end position of the buffer */
|
/** The end position of the buffer */
|
||||||
private int buf_end = 0;
|
private int buf_end = 0;
|
||||||
/** Boundary position, 0< means no boundary found */
|
/** Boundary position, 0< means no boundary found */
|
||||||
private int buf_bound_pos = -1;
|
private int buf_bound_pos = -1;
|
||||||
/** The boundary (the delimiter) */
|
/** The boundary (the delimiter) */
|
||||||
private byte[] boundary;
|
private byte[] boundary;
|
||||||
/** The position in the buffer where user has marked, -1 if no mark is set **/
|
/** The position in the buffer where user has marked, -1 if no mark is set **/
|
||||||
private int buf_mark = -1;
|
private int buf_mark = -1;
|
||||||
|
|
@ -57,77 +57,76 @@ public class BufferedBoundaryInputStream extends FilterInputStream{
|
||||||
private int buf_mark_limit = 0;
|
private int buf_mark_limit = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a instance of this class with a default buffer size of 64K
|
* Creates a instance of this class with a default buffer size of 64K
|
||||||
*
|
*
|
||||||
* @param in is the InputStream that the buffer will use
|
* @param in is the InputStream that the buffer will use
|
||||||
*/
|
*/
|
||||||
public BufferedBoundaryInputStream(InputStream in){
|
public BufferedBoundaryInputStream(InputStream in){
|
||||||
this(in, DEFAULT_BUF_SIZE);
|
this(in, DEFAULT_BUF_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a instance of this class
|
* Creates a instance of this class
|
||||||
*
|
*
|
||||||
* @param in is the InputStream that the buffer will use
|
* @param in is the InputStream that the buffer will use
|
||||||
* @param buf_size speifies the buffer size
|
* @param buf_size speifies the buffer size
|
||||||
*/
|
*/
|
||||||
public BufferedBoundaryInputStream(InputStream in, int buf_size){
|
public BufferedBoundaryInputStream(InputStream in, int buf_size){
|
||||||
super(in);
|
super(in);
|
||||||
buffer = new byte[buf_size];
|
buffer = new byte[buf_size];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
/**
|
|
||||||
* @return the next byte from the stream or -1 if EOF or stream has encountered a boundary
|
* @return the next byte from the stream or -1 if EOF or stream has encountered a boundary
|
||||||
*/
|
*/
|
||||||
public int read() throws IOException{
|
public int read() throws IOException{
|
||||||
if (fillBuffer() < 0)
|
if (fillBuffer() < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if(isOnBoundary())
|
if(isOnBoundary())
|
||||||
return -1; // boundary
|
return -1; // boundary
|
||||||
return buffer[buf_pos++];
|
return buffer[buf_pos++];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fills the given array with data from the buffer
|
* Fills the given array with data from the buffer
|
||||||
*
|
*
|
||||||
* @param b is the array that will be filled
|
* @param b is the array that will be filled
|
||||||
* @return the amount of bytes read or -1 if EOF or stream is on a boundary
|
|
||||||
*/
|
|
||||||
public int read(byte b[]) throws IOException {
|
|
||||||
return read(b, 0, b.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads a given length of bytes from the buffer
|
|
||||||
*
|
|
||||||
* @param b is the array that will be filled
|
|
||||||
* @param off is the offset in the array
|
|
||||||
* @param len is the amount to read
|
|
||||||
* @return the amount of bytes read or -1 if EOF or stream is on a boundary
|
* @return the amount of bytes read or -1 if EOF or stream is on a boundary
|
||||||
*/
|
*/
|
||||||
public int read(byte b[], int off, int len) throws IOException {
|
public int read(byte b[]) throws IOException {
|
||||||
|
return read(b, 0, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a given length of bytes from the buffer
|
||||||
|
*
|
||||||
|
* @param b is the array that will be filled
|
||||||
|
* @param off is the offset in the array
|
||||||
|
* @param len is the amount to read
|
||||||
|
* @return the amount of bytes read or -1 if EOF or stream is on a boundary
|
||||||
|
*/
|
||||||
|
public int read(byte b[], int off, int len) throws IOException {
|
||||||
if (fillBuffer() < 0)
|
if (fillBuffer() < 0)
|
||||||
return -1; // EOF
|
return -1; // EOF
|
||||||
if (isOnBoundary())
|
if (isOnBoundary())
|
||||||
return -1; // boundary
|
return -1; // boundary
|
||||||
|
|
||||||
// The request is larger then the buffer size
|
// The request is larger then the buffer size
|
||||||
int leftover = available();
|
int leftover = available();
|
||||||
if (len > leftover)
|
if (len > leftover)
|
||||||
len = leftover;
|
len = leftover;
|
||||||
|
|
||||||
// the boundary is in the read range
|
// the boundary is in the read range
|
||||||
if (buf_pos < buf_bound_pos && buf_bound_pos < buf_pos+len)
|
if (buf_pos < buf_bound_pos && buf_bound_pos < buf_pos+len)
|
||||||
len = buf_bound_pos - buf_pos;
|
len = buf_bound_pos - buf_pos;
|
||||||
|
|
||||||
System.arraycopy(buffer, buf_pos, b, off, len);
|
System.arraycopy(buffer, buf_pos, b, off, len);
|
||||||
buf_pos += len;
|
buf_pos += len;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -157,76 +156,76 @@ public class BufferedBoundaryInputStream extends FilterInputStream{
|
||||||
/**
|
/**
|
||||||
* Skips over the closest boundary
|
* Skips over the closest boundary
|
||||||
*/
|
*/
|
||||||
public void next() throws IOException {
|
public void next() throws IOException {
|
||||||
// read data until we find the next boundary or get to the end of the stream
|
// read data until we find the next boundary or get to the end of the stream
|
||||||
if (buf_bound_pos < 0) {
|
if (buf_bound_pos < 0) {
|
||||||
while (fillBuffer() >= 0 && buf_bound_pos < 0)
|
while (fillBuffer() >= 0 && buf_bound_pos < 0)
|
||||||
buf_pos = buf_end;
|
buf_pos = buf_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf_bound_pos >= 0){ // is boundary in buffer?
|
if (buf_bound_pos >= 0){ // is boundary in buffer?
|
||||||
buf_pos += boundary.length;
|
buf_pos += boundary.length;
|
||||||
findNextBoundary();
|
findNextBoundary();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Skips a specific amounts of bytes in the buffer.
|
/**
|
||||||
* Note that his method does not check for boundaries
|
* Skips a specific amounts of bytes in the buffer.
|
||||||
|
* Note that his method does not check for boundaries
|
||||||
* and it will only skip in the local buffer.
|
* and it will only skip in the local buffer.
|
||||||
*
|
*
|
||||||
* @param n the number of bytes to be skipped.
|
* @param n the number of bytes to be skipped.
|
||||||
* @return the actual number of bytes skipped,
|
* @return the actual number of bytes skipped,
|
||||||
* 0 if it has reach the end of the buffer but does not mean end of stream.
|
* 0 if it has reach the end of the buffer but does not mean end of stream.
|
||||||
*/
|
*/
|
||||||
public long skip(long n) throws IOException {
|
public long skip(long n) throws IOException {
|
||||||
int leftover = available();
|
int leftover = available();
|
||||||
if(n > leftover){
|
if(n > leftover){
|
||||||
buf_pos = buf_end;
|
buf_pos = buf_end;
|
||||||
return leftover;
|
return leftover;
|
||||||
}
|
}
|
||||||
return buf_pos += n;
|
return buf_pos += n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the boundary for the stream
|
|
||||||
*/
|
|
||||||
public void setBoundary(String b){
|
|
||||||
this.boundary = b.getBytes();
|
|
||||||
findNextBoundary(); // redo the search with the new boundary
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the boundary for the stream
|
|
||||||
*/
|
|
||||||
public void setBoundary(byte[] b){
|
|
||||||
boundary = new byte[b.length];
|
|
||||||
System.arraycopy(b, 0, boundary, 0, b.length);
|
|
||||||
findNextBoundary(); // redo the search with the new boundary
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return an estimate of the number of bytes that can be read (or skipped
|
/**
|
||||||
* over) from this buffered input stream without blocking.
|
* Sets the boundary for the stream
|
||||||
*/
|
*/
|
||||||
public int available() throws IOException {
|
public void setBoundary(String b){
|
||||||
if (super.available() <= 0)
|
this.boundary = b.getBytes();
|
||||||
return buf_end - buf_pos; // return the whole stream as there are no more boundaries
|
findNextBoundary(); // redo the search with the new boundary
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the boundary for the stream
|
||||||
|
*/
|
||||||
|
public void setBoundary(byte[] b){
|
||||||
|
boundary = new byte[b.length];
|
||||||
|
System.arraycopy(b, 0, boundary, 0, b.length);
|
||||||
|
findNextBoundary(); // redo the search with the new boundary
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return an estimate of the number of bytes that can be read (or skipped
|
||||||
|
* over) from this buffered input stream without blocking.
|
||||||
|
*/
|
||||||
|
public int available() throws IOException {
|
||||||
|
if (super.available() <= 0)
|
||||||
|
return buf_end - buf_pos; // return the whole stream as there are no more boundaries
|
||||||
else if (buf_end < boundary.length)
|
else if (buf_end < boundary.length)
|
||||||
return 0; // we need a safety block in case boundary is split
|
return 0; // we need a safety block in case boundary is split
|
||||||
return buf_end - boundary.length - buf_pos;
|
return buf_end - boundary.length - buf_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true for BufferedBoundaryInputStream
|
* @return true for BufferedBoundaryInputStream
|
||||||
*/
|
*/
|
||||||
public boolean markSupported(){
|
public boolean markSupported(){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See {@link InputStream#mark(int)} for details
|
* See {@link InputStream#mark(int)} for details
|
||||||
|
|
|
||||||
|
|
@ -36,221 +36,221 @@ import java.io.RandomAccessFile;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class BufferedRandomAccessFile extends RandomAccessFile{
|
public class BufferedRandomAccessFile extends RandomAccessFile{
|
||||||
// The size of the buffer in Byte
|
// The size of the buffer in Byte
|
||||||
private int BUF_SIZE = 64*1024;
|
private int BUF_SIZE = 64*1024;
|
||||||
|
|
||||||
// The Buffer
|
// The Buffer
|
||||||
byte buffer[];
|
byte buffer[];
|
||||||
// The end of the buffer
|
// The end of the buffer
|
||||||
int buf_end = 0;
|
int buf_end = 0;
|
||||||
// The position in the buffer
|
// The position in the buffer
|
||||||
int buf_pos = 0;
|
int buf_pos = 0;
|
||||||
// The real file pointer position where the buffer starts
|
// The real file pointer position where the buffer starts
|
||||||
long file_pos = 0;
|
long file_pos = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a instance of this buffer
|
* Create a instance of this buffer
|
||||||
*
|
*
|
||||||
* @param filename is the file to read from
|
* @param filename is the file to read from
|
||||||
* @param mode as in {@link java.io.RandomAccessFile#RandomAccessFile(File file, String mode)}
|
* @param mode as in {@link java.io.RandomAccessFile#RandomAccessFile(File file, String mode)}
|
||||||
*/
|
*/
|
||||||
public BufferedRandomAccessFile(String filename, String mode) throws IOException{
|
public BufferedRandomAccessFile(String filename, String mode) throws IOException{
|
||||||
this(new File(filename), mode);
|
this(new File(filename), mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a instance of this buffer
|
|
||||||
*
|
|
||||||
* @param file is the file to read from
|
|
||||||
* @param mode as in {@link java.io.RandomAccessFile#RandomAccessFile(File file, String mode)}
|
|
||||||
*/
|
|
||||||
public BufferedRandomAccessFile(File file, String mode) throws IOException{
|
|
||||||
super(file,mode);
|
|
||||||
invalidate();
|
|
||||||
buffer = new byte[BUF_SIZE];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a instance of this buffer
|
|
||||||
*
|
|
||||||
* @param filename is the file to read from
|
|
||||||
* @param mode as in {@link java.io.RandomAccessFile#RandomAccessFile(File file, String mode)}
|
|
||||||
* @param bufsize is the buffer size in bytes
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public BufferedRandomAccessFile(String filename, String mode, int bufsize) throws IOException{
|
|
||||||
this(new File(filename), mode, bufsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a instance of this buffer
|
|
||||||
*
|
|
||||||
* @param file is the file to read from
|
|
||||||
* @param mode as in {@link java.io.RandomAccessFile#RandomAccessFile(File file, String mode)}
|
|
||||||
* @param bufsize is the buffer size in bytes
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public BufferedRandomAccessFile(File file, String mode, int bufsize) throws IOException{
|
|
||||||
super(file,mode);
|
|
||||||
invalidate();
|
|
||||||
BUF_SIZE = bufsize;
|
|
||||||
buffer = new byte[BUF_SIZE];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads in data from the file to the buffer
|
* Create a instance of this buffer
|
||||||
*
|
*
|
||||||
* @return the buffer
|
* @param file is the file to read from
|
||||||
* @throws IOException
|
* @param mode as in {@link java.io.RandomAccessFile#RandomAccessFile(File file, String mode)}
|
||||||
*/
|
*/
|
||||||
private int fillBuffer() throws IOException {
|
public BufferedRandomAccessFile(File file, String mode) throws IOException{
|
||||||
int n = super.read(buffer, 0, BUF_SIZE );
|
super(file,mode);
|
||||||
if(n >= 0) {
|
invalidate();
|
||||||
file_pos +=n;
|
buffer = new byte[BUF_SIZE];
|
||||||
buf_end = n;
|
}
|
||||||
buf_pos = 0;
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the buffer
|
* Create a instance of this buffer
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @param filename is the file to read from
|
||||||
*/
|
* @param mode as in {@link java.io.RandomAccessFile#RandomAccessFile(File file, String mode)}
|
||||||
private void invalidate() throws IOException {
|
* @param bufsize is the buffer size in bytes
|
||||||
buf_end = 0;
|
* @throws IOException
|
||||||
buf_pos = 0;
|
*/
|
||||||
file_pos = super.getFilePointer();
|
public BufferedRandomAccessFile(String filename, String mode, int bufsize) throws IOException{
|
||||||
}
|
this(new File(filename), mode, bufsize);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the next byte in the buffer
|
* Create a instance of this buffer
|
||||||
*/
|
*
|
||||||
public final int read() throws IOException{
|
* @param file is the file to read from
|
||||||
if(buf_pos >= buf_end) {
|
* @param mode as in {@link java.io.RandomAccessFile#RandomAccessFile(File file, String mode)}
|
||||||
if(fillBuffer() < 0)
|
* @param bufsize is the buffer size in bytes
|
||||||
return -1;
|
* @throws IOException
|
||||||
}
|
*/
|
||||||
if(buf_end == 0) {
|
public BufferedRandomAccessFile(File file, String mode, int bufsize) throws IOException{
|
||||||
return -1;
|
super(file,mode);
|
||||||
} else {
|
invalidate();
|
||||||
buf_pos++;
|
BUF_SIZE = bufsize;
|
||||||
return buffer[buf_pos-1];
|
buffer = new byte[BUF_SIZE];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fills the given array with data from the buffer
|
|
||||||
*
|
|
||||||
* @param b is the array that will be filled
|
|
||||||
* @return the amount of bytes read or -1 if eof
|
|
||||||
*/
|
|
||||||
public int read(byte b[]) throws IOException {
|
|
||||||
return read(b, 0, b.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads a given length of bytes from the buffer
|
|
||||||
*
|
|
||||||
* @param b is the array that will be filled
|
|
||||||
* @param off is the offset in the array
|
|
||||||
* @param len is the amount to read
|
|
||||||
* @return the amount of bytes read or -1 if eof
|
|
||||||
*/
|
|
||||||
public int read(byte b[], int off, int len) throws IOException {
|
|
||||||
if(buf_pos >= buf_end) {
|
|
||||||
if(fillBuffer() < 0)
|
|
||||||
return -1; // EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy from buffer
|
|
||||||
int leftover = buf_end - buf_pos;
|
|
||||||
if(len <= leftover) {
|
|
||||||
System.arraycopy(buffer, buf_pos, b, off, len);
|
|
||||||
buf_pos += len;
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
System.arraycopy(buffer, buf_pos, b, off, leftover);
|
|
||||||
int n = super.read(b, off+leftover, len-leftover );
|
|
||||||
fillBuffer();
|
|
||||||
if( n >= 0 )
|
|
||||||
return leftover + n;
|
|
||||||
return leftover;
|
|
||||||
/*for(int i = 0; i < len; i++) {
|
|
||||||
int c = this.read();
|
|
||||||
if(c != -1)
|
|
||||||
b[off+i] = (byte)c;
|
|
||||||
else {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return len;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the file pointer in the file
|
* Reads in data from the file to the buffer
|
||||||
*/
|
*
|
||||||
public long getFilePointer() throws IOException{
|
* @return the buffer
|
||||||
long l = file_pos;
|
* @throws IOException
|
||||||
return (l - buf_end + buf_pos) ;
|
*/
|
||||||
}
|
private int fillBuffer() throws IOException {
|
||||||
|
int n = super.read(buffer, 0, BUF_SIZE );
|
||||||
/**
|
if(n >= 0) {
|
||||||
* Changes the file pointer to another position
|
file_pos +=n;
|
||||||
*
|
buf_end = n;
|
||||||
* @param pos The position to move the pointer to
|
buf_pos = 0;
|
||||||
*/
|
}
|
||||||
public void seek(long pos) throws IOException {
|
return n;
|
||||||
int n = (int)(file_pos - pos);
|
}
|
||||||
if(n >= 0 && n <= buf_end) {
|
|
||||||
buf_pos = buf_end - n;
|
|
||||||
} else {
|
|
||||||
super.seek(pos);
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is a replacement for readLine()
|
* Resets the buffer
|
||||||
*
|
*
|
||||||
* @return the next line in the file
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public final String readNextLine() throws IOException {
|
private void invalidate() throws IOException {
|
||||||
String str = null;
|
buf_end = 0;
|
||||||
if(buf_end-buf_pos <= 0) {
|
buf_pos = 0;
|
||||||
if(fillBuffer() < 0) {
|
file_pos = super.getFilePointer();
|
||||||
throw new IOException("Error filling buffer!");
|
}
|
||||||
}
|
|
||||||
}
|
/**
|
||||||
int lineend = -1;
|
* @return the next byte in the buffer
|
||||||
for(int i = buf_pos; i < buf_end; i++) {
|
*/
|
||||||
if(buffer[i] == '\n') {
|
public final int read() throws IOException{
|
||||||
lineend = i;
|
if(buf_pos >= buf_end) {
|
||||||
break;
|
if(fillBuffer() < 0)
|
||||||
}
|
return -1;
|
||||||
}
|
}
|
||||||
if(lineend < 0) {
|
if(buf_end == 0) {
|
||||||
StringBuffer input = new StringBuffer(256);
|
return -1;
|
||||||
int c;
|
} else {
|
||||||
while (((c = read()) != -1) && (c != '\n')) {
|
buf_pos++;
|
||||||
input.append((char)c);
|
return buffer[buf_pos-1];
|
||||||
}
|
}
|
||||||
if ((c == -1) && (input.length() == 0)) {
|
}
|
||||||
return null;
|
|
||||||
}
|
/**
|
||||||
return input.toString();
|
* Fills the given array with data from the buffer
|
||||||
}
|
*
|
||||||
|
* @param b is the array that will be filled
|
||||||
if(lineend > 0 && buffer[lineend-1] == '\r'){
|
* @return the amount of bytes read or -1 if eof
|
||||||
str = new String(buffer, buf_pos, lineend - buf_pos -1);
|
*/
|
||||||
}
|
public int read(byte b[]) throws IOException {
|
||||||
else {
|
return read(b, 0, b.length);
|
||||||
str = new String(buffer, buf_pos, lineend - buf_pos);
|
}
|
||||||
}
|
|
||||||
buf_pos = lineend +1;
|
/**
|
||||||
return str;
|
* Reads a given length of bytes from the buffer
|
||||||
}
|
*
|
||||||
|
* @param b is the array that will be filled
|
||||||
|
* @param off is the offset in the array
|
||||||
|
* @param len is the amount to read
|
||||||
|
* @return the amount of bytes read or -1 if eof
|
||||||
|
*/
|
||||||
|
public int read(byte b[], int off, int len) throws IOException {
|
||||||
|
if(buf_pos >= buf_end) {
|
||||||
|
if(fillBuffer() < 0)
|
||||||
|
return -1; // EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy from buffer
|
||||||
|
int leftover = buf_end - buf_pos;
|
||||||
|
if(len <= leftover) {
|
||||||
|
System.arraycopy(buffer, buf_pos, b, off, len);
|
||||||
|
buf_pos += len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.arraycopy(buffer, buf_pos, b, off, leftover);
|
||||||
|
int n = super.read(b, off+leftover, len-leftover );
|
||||||
|
fillBuffer();
|
||||||
|
if( n >= 0 )
|
||||||
|
return leftover + n;
|
||||||
|
return leftover;
|
||||||
|
/*for(int i = 0; i < len; i++) {
|
||||||
|
int c = this.read();
|
||||||
|
if(c != -1)
|
||||||
|
b[off+i] = (byte)c;
|
||||||
|
else {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the file pointer in the file
|
||||||
|
*/
|
||||||
|
public long getFilePointer() throws IOException{
|
||||||
|
long l = file_pos;
|
||||||
|
return (l - buf_end + buf_pos) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the file pointer to another position
|
||||||
|
*
|
||||||
|
* @param pos The position to move the pointer to
|
||||||
|
*/
|
||||||
|
public void seek(long pos) throws IOException {
|
||||||
|
int n = (int)(file_pos - pos);
|
||||||
|
if(n >= 0 && n <= buf_end) {
|
||||||
|
buf_pos = buf_end - n;
|
||||||
|
} else {
|
||||||
|
super.seek(pos);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is a replacement for readLine()
|
||||||
|
*
|
||||||
|
* @return the next line in the file
|
||||||
|
*/
|
||||||
|
public final String readNextLine() throws IOException {
|
||||||
|
String str = null;
|
||||||
|
if(buf_end-buf_pos <= 0) {
|
||||||
|
if(fillBuffer() < 0) {
|
||||||
|
throw new IOException("Error filling buffer!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int lineend = -1;
|
||||||
|
for(int i = buf_pos; i < buf_end; i++) {
|
||||||
|
if(buffer[i] == '\n') {
|
||||||
|
lineend = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(lineend < 0) {
|
||||||
|
StringBuffer input = new StringBuffer(256);
|
||||||
|
int c;
|
||||||
|
while (((c = read()) != -1) && (c != '\n')) {
|
||||||
|
input.append((char)c);
|
||||||
|
}
|
||||||
|
if ((c == -1) && (input.length() == 0)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return input.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lineend > 0 && buffer[lineend-1] == '\r'){
|
||||||
|
str = new String(buffer, buf_pos, lineend - buf_pos -1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
str = new String(buffer, buf_pos, lineend - buf_pos);
|
||||||
|
}
|
||||||
|
buf_pos = lineend +1;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,137 +29,137 @@ import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class DynamicByteArrayStream extends InputStream{
|
public class DynamicByteArrayStream extends InputStream{
|
||||||
/** The byte array container */
|
/** The byte array container */
|
||||||
private ArrayList<byte[]> bytes;
|
private ArrayList<byte[]> bytes;
|
||||||
/** Current virtual position of the stream */
|
/** Current virtual position of the stream */
|
||||||
private int globalPos;
|
private int globalPos;
|
||||||
/** Current virtual size of the stream */
|
/** Current virtual size of the stream */
|
||||||
private int globalSize;
|
private int globalSize;
|
||||||
/** Points the current byte array index */
|
/** Points the current byte array index */
|
||||||
private int globalArrayIndex;
|
private int globalArrayIndex;
|
||||||
/** Points to a local index in the current byte array */
|
/** Points to a local index in the current byte array */
|
||||||
private int localArrayOffset;
|
private int localArrayOffset;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance of DynamicByteArrayStream
|
* Create a new instance of DynamicByteArrayStream
|
||||||
*/
|
*/
|
||||||
public DynamicByteArrayStream(){
|
public DynamicByteArrayStream(){
|
||||||
bytes = new ArrayList<byte[]>();
|
bytes = new ArrayList<byte[]>();
|
||||||
globalPos = 0;
|
globalPos = 0;
|
||||||
globalSize = 0;
|
globalSize = 0;
|
||||||
globalArrayIndex = 0;
|
globalArrayIndex = 0;
|
||||||
localArrayOffset = 0;
|
localArrayOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append an byte array to the stream
|
* Append an byte array to the stream
|
||||||
*
|
*
|
||||||
* @param b is the byte array to add.
|
* @param b is the byte array to add.
|
||||||
*/
|
*/
|
||||||
public synchronized void append(byte[] b){
|
public synchronized void append(byte[] b){
|
||||||
bytes.add(b);
|
bytes.add(b);
|
||||||
globalSize += b.length;
|
globalSize += b.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Append an byte array to the stream.
|
|
||||||
* NOTE: This function will copy data.
|
|
||||||
*
|
|
||||||
* @param b is the byte array to add
|
|
||||||
* @param offset is the offset in the byte array
|
|
||||||
* @param length is the amount of data to add
|
|
||||||
*/
|
|
||||||
public synchronized void append(byte[] b, int offset, int length){
|
|
||||||
byte[] new_b = new byte[length];
|
|
||||||
System.arraycopy(b, offset, new_b, 0, length);
|
|
||||||
bytes.add(new_b);
|
|
||||||
globalSize += length;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public synchronized int read() throws IOException {
|
* Append an byte array to the stream.
|
||||||
if(globalPos >= globalSize) return -1;
|
* NOTE: This function will copy data.
|
||||||
|
*
|
||||||
int ret = bytes.get(globalArrayIndex)[localArrayOffset] & 0xff;
|
* @param b is the byte array to add
|
||||||
globalPos++;
|
* @param offset is the offset in the byte array
|
||||||
localArrayOffset++;
|
* @param length is the amount of data to add
|
||||||
if(localArrayOffset >= bytes.get(globalArrayIndex).length){
|
*/
|
||||||
globalArrayIndex++;
|
public synchronized void append(byte[] b, int offset, int length){
|
||||||
localArrayOffset = 0;
|
byte[] new_b = new byte[length];
|
||||||
}
|
System.arraycopy(b, offset, new_b, 0, length);
|
||||||
return ret;
|
bytes.add(new_b);
|
||||||
}
|
globalSize += length;
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized int read(byte b[], int off, int len) {
|
@Override
|
||||||
if(len <= 0) return 0;
|
public synchronized int read() throws IOException {
|
||||||
if(globalPos >= globalSize) return -1;
|
if(globalPos >= globalSize) return -1;
|
||||||
|
|
||||||
|
int ret = bytes.get(globalArrayIndex)[localArrayOffset] & 0xff;
|
||||||
|
globalPos++;
|
||||||
|
localArrayOffset++;
|
||||||
|
if(localArrayOffset >= bytes.get(globalArrayIndex).length){
|
||||||
|
globalArrayIndex++;
|
||||||
|
localArrayOffset = 0;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int read(byte b[], int off, int len) {
|
||||||
|
if(len <= 0) return 0;
|
||||||
|
if(globalPos >= globalSize) return -1;
|
||||||
|
|
||||||
int bytes_read=0;
|
int bytes_read=0;
|
||||||
if(globalPos+len >= globalSize) len = globalSize - globalPos;
|
if(globalPos+len >= globalSize) len = globalSize - globalPos;
|
||||||
while(bytes_read<len){
|
while(bytes_read<len){
|
||||||
byte[] src = bytes.get(globalArrayIndex);
|
byte[] src = bytes.get(globalArrayIndex);
|
||||||
// Read length is LONGER than local array
|
// Read length is LONGER than local array
|
||||||
if(localArrayOffset +len-bytes_read > src.length){
|
if(localArrayOffset +len-bytes_read > src.length){
|
||||||
int length = src.length- localArrayOffset;
|
int length = src.length- localArrayOffset;
|
||||||
System.arraycopy(src, localArrayOffset, b, off+bytes_read, length);
|
System.arraycopy(src, localArrayOffset, b, off+bytes_read, length);
|
||||||
|
|
||||||
localArrayOffset = 0;
|
localArrayOffset = 0;
|
||||||
globalArrayIndex++;
|
globalArrayIndex++;
|
||||||
bytes_read += length;
|
bytes_read += length;
|
||||||
}
|
}
|
||||||
// Read length is SHORTER than local array
|
// Read length is SHORTER than local array
|
||||||
else{
|
else{
|
||||||
int length = len-bytes_read;
|
int length = len-bytes_read;
|
||||||
System.arraycopy(src, localArrayOffset, b, off+bytes_read, length);
|
System.arraycopy(src, localArrayOffset, b, off+bytes_read, length);
|
||||||
|
|
||||||
localArrayOffset += length;
|
|
||||||
bytes_read += length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
globalPos += len;
|
|
||||||
return bytes_read;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized int available() {
|
localArrayOffset += length;
|
||||||
return globalSize - globalPos;
|
bytes_read += length;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
globalPos += len;
|
||||||
|
return bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
public synchronized int available() {
|
||||||
* Clears this stream from the byte arrays
|
return globalSize - globalPos;
|
||||||
*/
|
}
|
||||||
public synchronized void clear(){
|
|
||||||
globalSize = 0;
|
|
||||||
reset();
|
|
||||||
bytes.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void reset() {
|
|
||||||
globalArrayIndex = 0;
|
|
||||||
localArrayOffset = 0;
|
|
||||||
globalPos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() throws IOException {
|
/**
|
||||||
clear();
|
* Clears this stream from the byte arrays
|
||||||
}
|
*/
|
||||||
|
public synchronized void clear(){
|
||||||
/**
|
globalSize = 0;
|
||||||
* @return all of the buffers content as a byte array.
|
reset();
|
||||||
*/
|
bytes.clear();
|
||||||
public byte[] getBytes(){
|
}
|
||||||
byte[] data = new byte[globalSize];
|
|
||||||
this.read(data, 0, globalSize);
|
public synchronized void reset() {
|
||||||
return data;
|
globalArrayIndex = 0;
|
||||||
}
|
localArrayOffset = 0;
|
||||||
|
globalPos = 0;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* WARNING: This function might return a malformed String.
|
public void close() throws IOException {
|
||||||
*
|
clear();
|
||||||
* @return all the contents of the buffers as a String.
|
}
|
||||||
*/
|
|
||||||
public String toString(){
|
/**
|
||||||
|
* @return all of the buffers content as a byte array.
|
||||||
|
*/
|
||||||
|
public byte[] getBytes(){
|
||||||
|
byte[] data = new byte[globalSize];
|
||||||
|
this.read(data, 0, globalSize);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WARNING: This function might return a malformed String.
|
||||||
|
*
|
||||||
|
* @return all the contents of the buffers as a String.
|
||||||
|
*/
|
||||||
|
public String toString(){
|
||||||
return new String( this.getBytes() );
|
return new String( this.getBytes() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,24 +45,24 @@ public class IOUtil {
|
||||||
return readContent(stream, false);
|
return readContent(stream, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads and returns all the content of a stream.
|
* Reads and returns all the content of a stream.
|
||||||
*
|
*
|
||||||
* @param stream
|
* @param stream
|
||||||
* @param close true if the stream should be closed at the end
|
* @param close true if the stream should be closed at the end
|
||||||
* @return a byte array with the stream contents
|
* @return a byte array with the stream contents
|
||||||
*/
|
*/
|
||||||
public static byte[] readContent(InputStream stream, boolean close) throws IOException{
|
public static byte[] readContent(InputStream stream, boolean close) throws IOException{
|
||||||
DynamicByteArrayStream dyn_buff = new DynamicByteArrayStream();
|
DynamicByteArrayStream dyn_buff = new DynamicByteArrayStream();
|
||||||
byte[] buff = new byte[8192];
|
byte[] buff = new byte[8192];
|
||||||
int len = 0;
|
int len = 0;
|
||||||
while((len = stream.read(buff)) != -1){
|
while((len = stream.read(buff)) != -1){
|
||||||
dyn_buff.append(buff, 0, len);
|
dyn_buff.append(buff, 0, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close) stream.close();
|
if (close) stream.close();
|
||||||
return dyn_buff.getBytes();
|
return dyn_buff.getBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads and returns all the content of a stream as a String.
|
* Reads and returns all the content of a stream as a String.
|
||||||
|
|
|
||||||
|
|
@ -36,27 +36,27 @@ import java.io.InputStream;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class InputStreamCloser extends InputStream{
|
public class InputStreamCloser extends InputStream{
|
||||||
private Closeable[] c;
|
private Closeable[] c;
|
||||||
private InputStream in;
|
private InputStream in;
|
||||||
|
|
||||||
public InputStreamCloser(InputStream in, Closeable... c){
|
|
||||||
this.c = c;
|
|
||||||
this.in = in;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() throws IOException {
|
public InputStreamCloser(InputStream in, Closeable... c){
|
||||||
in.close();
|
this.c = c;
|
||||||
for (Closeable stream : c)
|
this.in = in;
|
||||||
stream.close();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Mirror functions
|
public void close() throws IOException {
|
||||||
public int read() throws IOException { return in.read(); }
|
in.close();
|
||||||
public int read(byte b[]) throws IOException { return in.read(b); }
|
for (Closeable stream : c)
|
||||||
public int read(byte b[], int off, int len) throws IOException { return in.read(b, off, len); }
|
stream.close();
|
||||||
public long skip(long n) throws IOException { return in.skip(n); }
|
}
|
||||||
public int available() throws IOException { return in.available(); }
|
|
||||||
public synchronized void mark(int readlimit) { in.mark(readlimit); }
|
// Mirror functions
|
||||||
public synchronized void reset() throws IOException { in.reset(); }
|
public int read() throws IOException { return in.read(); }
|
||||||
public boolean markSupported() { return in.markSupported(); }
|
public int read(byte b[]) throws IOException { return in.read(b); }
|
||||||
|
public int read(byte b[], int off, int len) throws IOException { return in.read(b, off, len); }
|
||||||
|
public long skip(long n) throws IOException { return in.skip(n); }
|
||||||
|
public int available() throws IOException { return in.available(); }
|
||||||
|
public synchronized void mark(int readlimit) { in.mark(readlimit); }
|
||||||
|
public synchronized void reset() throws IOException { in.reset(); }
|
||||||
|
public boolean markSupported() { return in.markSupported(); }
|
||||||
}
|
}
|
||||||
|
|
@ -41,154 +41,154 @@ import java.util.Map;
|
||||||
* this class can print strings to multiple PrintStreams
|
* this class can print strings to multiple PrintStreams
|
||||||
*/
|
*/
|
||||||
public class MultiPrintStream extends PrintStream {
|
public class MultiPrintStream extends PrintStream {
|
||||||
//the print streams that will print
|
//the print streams that will print
|
||||||
private ArrayList<PrintStream> streams;
|
private ArrayList<PrintStream> streams;
|
||||||
//a instance of this class
|
//a instance of this class
|
||||||
public static MultiPrintStream out = new MultiPrintStream();
|
public static MultiPrintStream out = new MultiPrintStream();
|
||||||
|
|
||||||
public MultiPrintStream(){
|
public MultiPrintStream(){
|
||||||
super(new PrintStream(System.out));
|
super(new PrintStream(System.out));
|
||||||
streams = new ArrayList<PrintStream>();
|
streams = new ArrayList<PrintStream>();
|
||||||
streams.add(new PrintStream(System.out));
|
streams.add(new PrintStream(System.out));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This constructor makes a simple PrintStream that prints to the console and to a file
|
* This constructor makes a simple PrintStream that prints to the console and to a file
|
||||||
* @param file is the file name to output to
|
* @param file is the file name to output to
|
||||||
*/
|
*/
|
||||||
public MultiPrintStream(String file){
|
public MultiPrintStream(String file){
|
||||||
super(new PrintStream(System.out));
|
super(new PrintStream(System.out));
|
||||||
try {
|
try {
|
||||||
streams = new ArrayList<PrintStream>();
|
streams = new ArrayList<PrintStream>();
|
||||||
streams.add(new PrintStream(System.out));
|
streams.add(new PrintStream(System.out));
|
||||||
streams.add(new PrintStream(new File(file)));
|
streams.add(new PrintStream(new File(file)));
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
System.out.println("Error when declaring PrintStream!!");
|
System.out.println("Error when declaring PrintStream!!");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This constructor takes a array of PrintStreams to be used
|
* This constructor takes a array of PrintStreams to be used
|
||||||
* @param streams is a array of the streams that will be used
|
* @param streams is a array of the streams that will be used
|
||||||
*/
|
*/
|
||||||
public MultiPrintStream(PrintStream[] streams){
|
public MultiPrintStream(PrintStream[] streams){
|
||||||
super(streams[0]);
|
super(streams[0]);
|
||||||
this.streams = new ArrayList<PrintStream>();
|
this.streams = new ArrayList<PrintStream>();
|
||||||
for(int i=0; i<streams.length ;i++){
|
for(int i=0; i<streams.length ;i++){
|
||||||
this.streams.add(streams[i]);
|
this.streams.add(streams[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This constructor takes a array of PrintStreams to be used
|
* This constructor takes a array of PrintStreams to be used
|
||||||
* @param instanceStream is a array of the streams that will be used
|
* @param instanceStream is a array of the streams that will be used
|
||||||
*/
|
*/
|
||||||
public static void makeInstance(MultiPrintStream instanceStream){
|
public static void makeInstance(MultiPrintStream instanceStream){
|
||||||
out = instanceStream;
|
out = instanceStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a PrintStream to the list of streams
|
* Adds a PrintStream to the list of streams
|
||||||
* @param p is the PrintStream to add
|
* @param p is the PrintStream to add
|
||||||
*/
|
*/
|
||||||
public void addPrintStream(PrintStream p){
|
public void addPrintStream(PrintStream p){
|
||||||
streams.add(p);
|
streams.add(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a PrintStream from the list
|
* Remove a PrintStream from the list
|
||||||
* @param p is the PrintStream to remove
|
* @param p is the PrintStream to remove
|
||||||
*/
|
*/
|
||||||
public void removePrintStream(PrintStream p){
|
public void removePrintStream(PrintStream p){
|
||||||
streams.remove(p);
|
streams.remove(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a PrintStream from the list
|
* Remove a PrintStream from the list
|
||||||
* @param p is the index of the PrintStream to remove
|
* @param p is the index of the PrintStream to remove
|
||||||
*/
|
*/
|
||||||
public void removePrintStream(int p){
|
public void removePrintStream(int p){
|
||||||
streams.remove(p);
|
streams.remove(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* writes to all the PrintStreams
|
* writes to all the PrintStreams
|
||||||
*/
|
*/
|
||||||
public void write(int b) {
|
public void write(int b) {
|
||||||
for(int i=0; i<streams.size() ;i++)
|
for(int i=0; i<streams.size() ;i++)
|
||||||
streams.get(i).write(b);
|
streams.get(i).write(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* writes to all the PrintStreams
|
|
||||||
*/
|
|
||||||
public void write(byte buf[], int off, int len){
|
|
||||||
for(int i=0; i<streams.size() ;i++)
|
|
||||||
streams.get(i).write(buf, off, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints with a new line to all the PrintStreams
|
|
||||||
*/
|
|
||||||
public void println(String s){
|
|
||||||
for(int i=0; i<streams.size() ;i++)
|
|
||||||
streams.get(i).println(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints to all the PrintStreams
|
* writes to all the PrintStreams
|
||||||
*/
|
*/
|
||||||
public void print(String s){
|
public void write(byte buf[], int off, int len){
|
||||||
for(int i=0; i<streams.size() ;i++)
|
for(int i=0; i<streams.size() ;i++)
|
||||||
streams.get(i).print(s);
|
streams.get(i).write(buf, off, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void println(){ println("");}
|
/**
|
||||||
public void println(boolean x){ println(String.valueOf(x));}
|
* Prints with a new line to all the PrintStreams
|
||||||
public void println(char x){ println(String.valueOf(x));}
|
*/
|
||||||
public void println(char[] x){ println(new String(x));}
|
public void println(String s){
|
||||||
public void println(double x){ println(String.valueOf(x));}
|
for(int i=0; i<streams.size() ;i++)
|
||||||
public void println(float x){ println(String.valueOf(x));}
|
streams.get(i).println(s);
|
||||||
public void println(int x){ println(String.valueOf(x));}
|
}
|
||||||
public void println(long x){ println(String.valueOf(x));}
|
|
||||||
public void println(Object x){ println(String.valueOf(x));}
|
|
||||||
|
|
||||||
public void print(boolean x){ print(String.valueOf(x));}
|
/**
|
||||||
public void print(char x){ print(String.valueOf(x));}
|
* Prints to all the PrintStreams
|
||||||
public void print(char[] x){ print(new String(x));}
|
*/
|
||||||
public void print(double x){ print(String.valueOf(x));}
|
public void print(String s){
|
||||||
public void print(float x){ print(String.valueOf(x));}
|
for(int i=0; i<streams.size() ;i++)
|
||||||
public void print(int x){ print(String.valueOf(x));}
|
streams.get(i).print(s);
|
||||||
public void print(long x){ print(String.valueOf(x));}
|
}
|
||||||
public void print(Object x){ print(String.valueOf(x));}
|
|
||||||
|
public void println(){ println("");}
|
||||||
|
public void println(boolean x){ println(String.valueOf(x));}
|
||||||
|
public void println(char x){ println(String.valueOf(x));}
|
||||||
|
public void println(char[] x){ println(new String(x));}
|
||||||
|
public void println(double x){ println(String.valueOf(x));}
|
||||||
|
public void println(float x){ println(String.valueOf(x));}
|
||||||
|
public void println(int x){ println(String.valueOf(x));}
|
||||||
|
public void println(long x){ println(String.valueOf(x));}
|
||||||
|
public void println(Object x){ println(String.valueOf(x));}
|
||||||
|
|
||||||
|
public void print(boolean x){ print(String.valueOf(x));}
|
||||||
|
public void print(char x){ print(String.valueOf(x));}
|
||||||
|
public void print(char[] x){ print(new String(x));}
|
||||||
|
public void print(double x){ print(String.valueOf(x));}
|
||||||
|
public void print(float x){ print(String.valueOf(x));}
|
||||||
|
public void print(int x){ print(String.valueOf(x));}
|
||||||
|
public void print(long x){ print(String.valueOf(x));}
|
||||||
|
public void print(Object x){ print(String.valueOf(x));}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public boolean checkError(){
|
public boolean checkError(){
|
||||||
for(int i=0; i<streams.size() ;i++)
|
for(int i=0; i<streams.size() ;i++)
|
||||||
if(streams.get(i).checkError())
|
if(streams.get(i).checkError())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* closes all the PrintStreams
|
* closes all the PrintStreams
|
||||||
*/
|
*/
|
||||||
public void close(){
|
public void close(){
|
||||||
for(int i=0; i<streams.size() ;i++)
|
for(int i=0; i<streams.size() ;i++)
|
||||||
streams.get(i).close();
|
streams.get(i).close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link #dump(Object, int)} but prints to this OutputStream.
|
* Same as {@link #dump(Object, int)} but prints to this OutputStream.
|
||||||
*
|
*
|
||||||
* @param o is the Object to dump
|
* @param o is the Object to dump
|
||||||
*/
|
*/
|
||||||
public void dump(Object o){
|
public void dump(Object o){
|
||||||
println(dumpToString( o, 1));
|
println(dumpToString( o, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link #dump(Object, int)} but prints to this OutputStream.
|
* Same as {@link #dump(Object, int)} but prints to this OutputStream.
|
||||||
|
|
@ -200,15 +200,15 @@ public class MultiPrintStream extends PrintStream {
|
||||||
println(dumpToString( o, depth));
|
println(dumpToString( o, depth));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link #dump(Object, int)}
|
* Same as {@link #dump(Object, int)}
|
||||||
*
|
*
|
||||||
* @param o is the Object to dump
|
* @param o is the Object to dump
|
||||||
* @return a String with all the printed data
|
* @return a String with all the printed data
|
||||||
*/
|
*/
|
||||||
public static String dumpToString(Object o) {
|
public static String dumpToString(Object o) {
|
||||||
return dumpToString(o, 1);
|
return dumpToString(o, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dumps the content of:
|
* Dumps the content of:
|
||||||
|
|
@ -225,157 +225,157 @@ public class MultiPrintStream extends PrintStream {
|
||||||
public static String dumpToString(Object o, int depth) {
|
public static String dumpToString(Object o, int depth) {
|
||||||
return dumpToString(o, "", depth);
|
return dumpToString(o, "", depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* See {@link #dumpToString(Object)}
|
|
||||||
*
|
|
||||||
* @param o is the Object to dump
|
|
||||||
* @param head is the string that will be put in front of every line
|
|
||||||
* @param depth sets the object dump depth, the object recursion depth
|
|
||||||
* @return A String with all the printed data
|
|
||||||
*/
|
|
||||||
|
|
||||||
private static String dumpToString(Object o , String head, int depth) {
|
/**
|
||||||
if(o == null)
|
* See {@link #dumpToString(Object)}
|
||||||
return "NULL";
|
*
|
||||||
StringBuffer buffer = new StringBuffer();
|
* @param o is the Object to dump
|
||||||
Class<?> oClass = o.getClass();
|
* @param head is the string that will be put in front of every line
|
||||||
buffer.append( oClass.getName() );
|
* @param depth sets the object dump depth, the object recursion depth
|
||||||
String nextHead = head + "\t";
|
* @return A String with all the printed data
|
||||||
// Prints out Arrays
|
*/
|
||||||
if ( oClass.isArray() ) {
|
|
||||||
buffer.append( "[" );
|
private static String dumpToString(Object o , String head, int depth) {
|
||||||
for ( int i=0; i<Array.getLength(o) ;i++ ) {
|
if(o == null)
|
||||||
Object value = Array.get(o,i);
|
return "NULL";
|
||||||
buffer.append("\n");
|
StringBuffer buffer = new StringBuffer();
|
||||||
buffer.append(nextHead);
|
Class<?> oClass = o.getClass();
|
||||||
buffer.append( (dumbCapable(value, depth-1) ?
|
buffer.append( oClass.getName() );
|
||||||
|
String nextHead = head + "\t";
|
||||||
|
// Prints out Arrays
|
||||||
|
if ( oClass.isArray() ) {
|
||||||
|
buffer.append( "[" );
|
||||||
|
for ( int i=0; i<Array.getLength(o) ;i++ ) {
|
||||||
|
Object value = Array.get(o,i);
|
||||||
|
buffer.append("\n");
|
||||||
|
buffer.append(nextHead);
|
||||||
|
buffer.append( (dumbCapable(value, depth-1) ?
|
||||||
dumpToString(value, nextHead, depth-1) : value) );
|
dumpToString(value, nextHead, depth-1) : value) );
|
||||||
if ( i+1<Array.getLength(o) )
|
if ( i+1<Array.getLength(o) )
|
||||||
buffer.append( "," );
|
buffer.append( "," );
|
||||||
}
|
}
|
||||||
buffer.append( "\n" );
|
buffer.append( "\n" );
|
||||||
buffer.append(head);
|
buffer.append(head);
|
||||||
buffer.append( "]" );
|
buffer.append( "]" );
|
||||||
}
|
}
|
||||||
// Prints out a list
|
// Prints out a list
|
||||||
else if(o instanceof Collection){
|
else if(o instanceof Collection){
|
||||||
Iterator<?> it = ((Collection<?>)o).iterator();
|
Iterator<?> it = ((Collection<?>)o).iterator();
|
||||||
buffer.append( "[" );
|
buffer.append( "[" );
|
||||||
while(it.hasNext()){
|
while(it.hasNext()){
|
||||||
Object value = it.next();
|
Object value = it.next();
|
||||||
buffer.append("\n");
|
buffer.append("\n");
|
||||||
buffer.append(nextHead);
|
buffer.append(nextHead);
|
||||||
buffer.append( (dumbCapable(value, depth-1) ?
|
buffer.append( (dumbCapable(value, depth-1) ?
|
||||||
dumpToString(value, nextHead, depth-1) : value) );
|
dumpToString(value, nextHead, depth-1) : value) );
|
||||||
if(it.hasNext())
|
if(it.hasNext())
|
||||||
buffer.append( "," );
|
buffer.append( "," );
|
||||||
}
|
}
|
||||||
buffer.append( "\n" );
|
buffer.append( "\n" );
|
||||||
buffer.append(head);
|
buffer.append(head);
|
||||||
buffer.append( "]" );
|
buffer.append( "]" );
|
||||||
}
|
}
|
||||||
// Prints out a Map
|
// Prints out a Map
|
||||||
else if(o instanceof Map){
|
else if(o instanceof Map){
|
||||||
Iterator<?> it = ((Map<?,?>)o).keySet().iterator();
|
Iterator<?> it = ((Map<?,?>)o).keySet().iterator();
|
||||||
buffer.append( "{" );
|
buffer.append( "{" );
|
||||||
while(it.hasNext()){
|
while(it.hasNext()){
|
||||||
Object key = it.next();
|
Object key = it.next();
|
||||||
Object value = ((Map<?,?>)o).get(key);
|
Object value = ((Map<?,?>)o).get(key);
|
||||||
buffer.append("\n");
|
buffer.append("\n");
|
||||||
buffer.append(nextHead);
|
buffer.append(nextHead);
|
||||||
buffer.append( key );
|
buffer.append( key );
|
||||||
buffer.append( "=>" );
|
buffer.append( "=>" );
|
||||||
buffer.append( (dumbCapable(value, depth-1) ?
|
buffer.append( (dumbCapable(value, depth-1) ?
|
||||||
dumpToString(value, nextHead, depth-1) : value) );
|
dumpToString(value, nextHead, depth-1) : value) );
|
||||||
if(it.hasNext())
|
if(it.hasNext())
|
||||||
buffer.append( "," );
|
buffer.append( "," );
|
||||||
}
|
}
|
||||||
buffer.append( "\n" );
|
buffer.append( "\n" );
|
||||||
buffer.append(head);
|
buffer.append(head);
|
||||||
buffer.append( "}" );
|
buffer.append( "}" );
|
||||||
}
|
}
|
||||||
// Prints out data from InputStream
|
// Prints out data from InputStream
|
||||||
else if(o instanceof InputStream){
|
else if(o instanceof InputStream){
|
||||||
buffer.append( " =>{\n" );
|
buffer.append( " =>{\n" );
|
||||||
try {
|
try {
|
||||||
InputStream in = (InputStream)o;
|
InputStream in = (InputStream)o;
|
||||||
int tmp;
|
int tmp;
|
||||||
while((tmp = in.read()) != -1){
|
while((tmp = in.read()) != -1){
|
||||||
buffer.append(nextHead);
|
buffer.append(nextHead);
|
||||||
buffer.append( (char)tmp );
|
buffer.append( (char)tmp );
|
||||||
}
|
}
|
||||||
in.close();
|
in.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
buffer.append( "\n" );
|
buffer.append( "\n" );
|
||||||
buffer.append(head);
|
buffer.append(head);
|
||||||
buffer.append( "}" );
|
buffer.append( "}" );
|
||||||
}
|
}
|
||||||
// Prints out data from InputStream
|
// Prints out data from InputStream
|
||||||
else if(o instanceof Reader){
|
else if(o instanceof Reader){
|
||||||
buffer.append( " =>{\n" );
|
buffer.append( " =>{\n" );
|
||||||
try {
|
try {
|
||||||
Reader in = (Reader)o;
|
Reader in = (Reader)o;
|
||||||
int tmp;
|
int tmp;
|
||||||
while((tmp = in.read()) != -1){
|
while((tmp = in.read()) != -1){
|
||||||
buffer.append(nextHead);
|
buffer.append(nextHead);
|
||||||
buffer.append( (char)tmp );
|
buffer.append( (char)tmp );
|
||||||
}
|
}
|
||||||
in.close();
|
in.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
buffer.append( "\n" );
|
buffer.append( "\n" );
|
||||||
buffer.append(head);
|
buffer.append(head);
|
||||||
buffer.append( "}" );
|
buffer.append( "}" );
|
||||||
}
|
}
|
||||||
// Prints out Object properties
|
// Prints out Object properties
|
||||||
else{
|
else{
|
||||||
buffer.append( "{" );
|
buffer.append( "{" );
|
||||||
while ( oClass != null ) {
|
while ( oClass != null ) {
|
||||||
Field[] fields = oClass.getDeclaredFields();
|
Field[] fields = oClass.getDeclaredFields();
|
||||||
for ( int i=0; i<fields.length; i++ ) {
|
for ( int i=0; i<fields.length; i++ ) {
|
||||||
if (Modifier.isFinal(fields[i].getModifiers())) // Skip constants
|
if (Modifier.isFinal(fields[i].getModifiers())) // Skip constants
|
||||||
continue;
|
continue;
|
||||||
fields[i].setAccessible( true );
|
fields[i].setAccessible( true );
|
||||||
buffer.append("\n");
|
buffer.append("\n");
|
||||||
buffer.append(nextHead);
|
buffer.append(nextHead);
|
||||||
//buffer.append( fields[i].getType().getSimpleName() );
|
//buffer.append( fields[i].getType().getSimpleName() );
|
||||||
//buffer.append( " " );
|
//buffer.append( " " );
|
||||||
buffer.append( fields[i].getName() );
|
buffer.append( fields[i].getName() );
|
||||||
buffer.append( " = " );
|
buffer.append( " = " );
|
||||||
try {
|
try {
|
||||||
Object value = fields[i].get(o);
|
Object value = fields[i].get(o);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
buffer.append( (dumbCapable(value, depth-1) ?
|
buffer.append( (dumbCapable(value, depth-1) ?
|
||||||
dumpToString(value, nextHead, depth-1) : value) );
|
dumpToString(value, nextHead, depth-1) : value) );
|
||||||
}
|
}
|
||||||
} catch ( IllegalAccessException e ) {}
|
} catch ( IllegalAccessException e ) {}
|
||||||
if ( i+1<fields.length )
|
if ( i+1<fields.length )
|
||||||
buffer.append( "," );
|
buffer.append( "," );
|
||||||
}
|
}
|
||||||
oClass = oClass.getSuperclass();
|
oClass = oClass.getSuperclass();
|
||||||
}
|
}
|
||||||
buffer.append( "\n" );
|
buffer.append( "\n" );
|
||||||
buffer.append(head);
|
buffer.append(head);
|
||||||
buffer.append( "}" );
|
buffer.append( "}" );
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An helper function for the dump function.
|
* An helper function for the dump function.
|
||||||
*/
|
*/
|
||||||
private static boolean dumbCapable(Object o, int depth){
|
private static boolean dumbCapable(Object o, int depth){
|
||||||
if (depth <= 0)
|
if (depth <= 0)
|
||||||
return false;
|
return false;
|
||||||
if (o == null)
|
if (o == null)
|
||||||
return false;
|
return false;
|
||||||
if (ClassUtil.isPrimitive(o.getClass()) || ClassUtil.isWrapper(o.getClass()))
|
if (ClassUtil.isPrimitive(o.getClass()) || ClassUtil.isWrapper(o.getClass()))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,30 +34,30 @@ import java.nio.charset.StandardCharsets;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class StringInputStream extends InputStream{
|
public class StringInputStream extends InputStream{
|
||||||
// The buffer
|
// The buffer
|
||||||
protected StringBuilder buffer;
|
protected StringBuilder buffer;
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an new instance of this class
|
|
||||||
*/
|
|
||||||
public StringInputStream(){
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringInputStream(String data) {
|
|
||||||
clear();
|
|
||||||
add(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an estimate of the number of bytes
|
* Creates an new instance of this class
|
||||||
* that can be read (or skipped over) from this
|
*/
|
||||||
* input stream without blocking by the next
|
public StringInputStream(){
|
||||||
* invocation of a method for this input stream.
|
clear();
|
||||||
*/
|
}
|
||||||
public int available(){
|
|
||||||
return buffer.length();
|
public StringInputStream(String data) {
|
||||||
}
|
clear();
|
||||||
|
add(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an estimate of the number of bytes
|
||||||
|
* that can be read (or skipped over) from this
|
||||||
|
* input stream without blocking by the next
|
||||||
|
* invocation of a method for this input stream.
|
||||||
|
*/
|
||||||
|
public int available(){
|
||||||
|
return buffer.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -65,36 +65,36 @@ public class StringInputStream extends InputStream{
|
||||||
*/
|
*/
|
||||||
public int read(){
|
public int read(){
|
||||||
if(buffer.length() == 0)
|
if(buffer.length() == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int ret = buffer.charAt( 0 );
|
int ret = buffer.charAt( 0 );
|
||||||
buffer.deleteCharAt( 0 );
|
buffer.deleteCharAt( 0 );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads some number of bytes from the input stream
|
* Reads some number of bytes from the input stream
|
||||||
* and stores them into the buffer array b.
|
* and stores them into the buffer array b.
|
||||||
*/
|
*/
|
||||||
public int read(byte[] b){
|
public int read(byte[] b){
|
||||||
return read( b, 0, b.length );
|
return read( b, 0, b.length );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads up to len bytes of data from the input stream
|
* Reads up to len bytes of data from the input stream
|
||||||
* into an array of bytes.
|
* into an array of bytes.
|
||||||
*/
|
*/
|
||||||
public int read(byte[] b, int off, int len){
|
public int read(byte[] b, int off, int len){
|
||||||
if(buffer.length() == 0)
|
if(buffer.length() == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if( buffer.length() < len ){
|
if( buffer.length() < len ){
|
||||||
len = buffer.length();
|
len = buffer.length();
|
||||||
}
|
}
|
||||||
byte[] btmp = buffer.substring(0, len).getBytes(StandardCharsets.ISO_8859_1);
|
byte[] btmp = buffer.substring(0, len).getBytes(StandardCharsets.ISO_8859_1);
|
||||||
System.arraycopy(btmp, 0, b, off, len);
|
System.arraycopy(btmp, 0, b, off, len);
|
||||||
buffer.delete(0, len);
|
buffer.delete(0, len);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -105,39 +105,39 @@ public class StringInputStream extends InputStream{
|
||||||
* @param n is the amount characters to skip
|
* @param n is the amount characters to skip
|
||||||
*/
|
*/
|
||||||
public long skip(long n){
|
public long skip(long n){
|
||||||
if( buffer.length() < n ){
|
if( buffer.length() < n ){
|
||||||
int len = buffer.length();
|
int len = buffer.length();
|
||||||
buffer.delete(0, len);
|
buffer.delete(0, len);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
buffer.delete(0, (int) n);
|
buffer.delete(0, (int) n);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests if this input stream supports the mark and
|
* Tests if this input stream supports the mark and
|
||||||
* reset methods.
|
* reset methods.
|
||||||
*/
|
*/
|
||||||
public boolean markSupported(){
|
public boolean markSupported(){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes this input stream and releases any system
|
* Closes this input stream and releases any system
|
||||||
* resources associated with the stream.
|
* resources associated with the stream.
|
||||||
*/
|
*/
|
||||||
public void close(){
|
public void close(){
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear(){
|
public void clear(){
|
||||||
buffer = new StringBuilder();
|
buffer = new StringBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add( String data ){
|
public void add( String data ){
|
||||||
buffer.append( data );
|
buffer.append( data );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,11 @@ import java.io.File;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public interface FileChangeListener{
|
public interface FileChangeListener{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called when there is a change in a file
|
* This method is called when there is a change in a file
|
||||||
*
|
*
|
||||||
* @param file The file that has changed
|
* @param file The file that has changed
|
||||||
*/
|
*/
|
||||||
public void fileChangedEvent(File file);
|
public void fileChangedEvent(File file);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,67 +35,67 @@ import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipFile;
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
public class FileSearcher implements Iterable<FileSearcher.FileSearchItem>{
|
public class FileSearcher implements Iterable<FileSearcher.FileSearchItem>{
|
||||||
// Constants
|
// Constants
|
||||||
private static final List<String> compressedFileExtensions = Arrays.asList(new String[]{
|
private static final List<String> compressedFileExtensions = Arrays.asList(new String[]{
|
||||||
"jar", "zip"
|
"jar", "zip"
|
||||||
});
|
});
|
||||||
|
|
||||||
// Constructor params
|
// Constructor params
|
||||||
private File root;
|
private File root;
|
||||||
|
|
||||||
// Search parameters
|
// Search parameters
|
||||||
private String fileName = null;
|
private String fileName = null;
|
||||||
private String extension = null;
|
private String extension = null;
|
||||||
private boolean recursive = false;
|
private boolean recursive = false;
|
||||||
//private int depth;
|
//private int depth;
|
||||||
private boolean searchFiles = true;
|
private boolean searchFiles = true;
|
||||||
private boolean searchFolders = true;
|
private boolean searchFolders = true;
|
||||||
private boolean searchCompressedFiles = false;
|
private boolean searchCompressedFiles = false;
|
||||||
|
|
||||||
|
|
||||||
public FileSearcher(File root){
|
public FileSearcher(File root){
|
||||||
this.root = root;
|
this.root = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param file Sets the exact file name to search for (includes extension)
|
* @param file Sets the exact file name to search for (includes extension)
|
||||||
*/
|
*/
|
||||||
public void setFileName(String file){
|
public void setFileName(String file){
|
||||||
fileName = file;
|
fileName = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the file extensions to search for (should not include . at the beginning)
|
* Sets the file extensions to search for (should not include . at the beginning)
|
||||||
*/
|
*/
|
||||||
public void setExtension(String ext){
|
public void setExtension(String ext){
|
||||||
extension = ext;
|
extension = ext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines if the search should go into sub-folders
|
* Defines if the search should go into sub-folders
|
||||||
*/
|
*/
|
||||||
public void setRecursive(boolean recursive){
|
public void setRecursive(boolean recursive){
|
||||||
this.recursive = recursive;
|
this.recursive = recursive;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets how deep into folders the search should go
|
* Sets how deep into folders the search should go
|
||||||
* (Recursion needs to be enabled for this attribute to be used)
|
* (Recursion needs to be enabled for this attribute to be used)
|
||||||
*/
|
*/
|
||||||
//public void setDepth(int depth){
|
//public void setDepth(int depth){
|
||||||
// this.depth = depth;
|
// this.depth = depth;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets if the searcher should match to files.
|
* Sets if the searcher should match to files.
|
||||||
|
*/
|
||||||
|
public void searchFiles(boolean searchFiles){
|
||||||
|
this.searchFiles = searchFiles;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sets if the searcher should match to folders.
|
||||||
*/
|
*/
|
||||||
public void searchFiles(boolean searchFiles){
|
|
||||||
this.searchFiles = searchFiles;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Sets if the searcher should match to folders.
|
|
||||||
*/
|
|
||||||
public void searchFolders(boolean searchFolders){
|
public void searchFolders(boolean searchFolders){
|
||||||
this.searchFolders = searchFolders;
|
this.searchFolders = searchFolders;
|
||||||
}
|
}
|
||||||
|
|
@ -103,85 +103,85 @@ public class FileSearcher implements Iterable<FileSearcher.FileSearchItem>{
|
||||||
* Sets if the searcher should go into compressed files.
|
* Sets if the searcher should go into compressed files.
|
||||||
*/
|
*/
|
||||||
public void searchCompressedFiles(boolean searchCompressedFiles){
|
public void searchCompressedFiles(boolean searchCompressedFiles){
|
||||||
this.searchCompressedFiles = searchCompressedFiles;
|
this.searchCompressedFiles = searchCompressedFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<FileSearchItem> iterator() {
|
public Iterator<FileSearchItem> iterator() {
|
||||||
return new FileSearchIterator();
|
return new FileSearchIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected class FileSearchIterator implements Iterator<FileSearchItem>{
|
protected class FileSearchIterator implements Iterator<FileSearchItem>{
|
||||||
private ArrayList<FileSearchItem> fileList;
|
private ArrayList<FileSearchItem> fileList;
|
||||||
private int index;
|
private int index;
|
||||||
private FileSearchItem nextItem;
|
private FileSearchItem nextItem;
|
||||||
|
|
||||||
public FileSearchIterator(){
|
public FileSearchIterator(){
|
||||||
fileList = new ArrayList<FileSearchItem>();
|
fileList = new ArrayList<FileSearchItem>();
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
||||||
addFiles(new FileSearchFileItem(root), root.list());
|
addFiles(new FileSearchFileItem(root), root.list());
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return nextItem != null;
|
return nextItem != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove() {
|
public void remove() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileSearchItem next() {
|
public FileSearchItem next() {
|
||||||
// Temporarily save the current file
|
// Temporarily save the current file
|
||||||
FileSearchItem ret = nextItem;
|
FileSearchItem ret = nextItem;
|
||||||
|
|
||||||
// Find the next file
|
// Find the next file
|
||||||
for(; index <fileList.size(); index++){
|
for(; index <fileList.size(); index++){
|
||||||
FileSearchItem file = fileList.get(index);
|
FileSearchItem file = fileList.get(index);
|
||||||
//#### FOLDERS
|
//#### FOLDERS
|
||||||
if(recursive && file.isDirectory()){
|
if(recursive && file.isDirectory()){
|
||||||
addFiles(file, file.listFiles());
|
addFiles(file, file.listFiles());
|
||||||
if(searchFolders) {
|
if(searchFolders) {
|
||||||
if(fileName == null) // Match all folders
|
if(fileName == null) // Match all folders
|
||||||
break;
|
break;
|
||||||
else if(file.getName().equalsIgnoreCase(fileName))
|
else if(file.getName().equalsIgnoreCase(fileName))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//#### COMPRESSED FILES
|
//#### COMPRESSED FILES
|
||||||
else if(searchCompressedFiles && file.isFile() &&
|
else if(searchCompressedFiles && file.isFile() &&
|
||||||
compressedFileExtensions.contains(
|
compressedFileExtensions.contains(
|
||||||
FileUtil.getFileExtension(file.getName()).toLowerCase())){
|
FileUtil.getFileExtension(file.getName()).toLowerCase())){
|
||||||
try {
|
try {
|
||||||
ZipFile zipFile = new ZipFile(file.getPath());
|
ZipFile zipFile = new ZipFile(file.getPath());
|
||||||
Enumeration<? extends ZipEntry> e = zipFile.entries();
|
Enumeration<? extends ZipEntry> e = zipFile.entries();
|
||||||
while(e.hasMoreElements()){
|
while(e.hasMoreElements()){
|
||||||
ZipEntry entry = e.nextElement();
|
ZipEntry entry = e.nextElement();
|
||||||
fileList.add(new FileSearchZipItem(file.getPath(), entry));
|
fileList.add(new FileSearchZipItem(file.getPath(), entry));
|
||||||
}
|
}
|
||||||
zipFile.close();
|
zipFile.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//#### REGULAR FILES
|
//#### REGULAR FILES
|
||||||
else if(searchFiles && file.isFile()){
|
else if(searchFiles && file.isFile()){
|
||||||
if(extension == null && fileName == null) // Should we match all files
|
if(extension == null && fileName == null) // Should we match all files
|
||||||
break;
|
break;
|
||||||
else if(extension != null &&
|
else if(extension != null &&
|
||||||
FileUtil.getFileExtension(file.getName()).equalsIgnoreCase(extension))
|
FileUtil.getFileExtension(file.getName()).equalsIgnoreCase(extension))
|
||||||
break;
|
break;
|
||||||
else if(fileName != null &&
|
else if(fileName != null &&
|
||||||
file.getName().equalsIgnoreCase(fileName))
|
file.getName().equalsIgnoreCase(fileName))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(index <fileList.size()) {
|
if(index <fileList.size()) {
|
||||||
nextItem = fileList.get(index);
|
nextItem = fileList.get(index);
|
||||||
|
|
@ -190,84 +190,84 @@ public class FileSearcher implements Iterable<FileSearcher.FileSearchItem>{
|
||||||
else
|
else
|
||||||
nextItem = null;
|
nextItem = null;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addFiles(FileSearchItem root, String[] list){
|
private void addFiles(FileSearchItem root, String[] list){
|
||||||
if(root instanceof FileSearchFileItem) {
|
if(root instanceof FileSearchFileItem) {
|
||||||
for (String file : list) {
|
for (String file : list) {
|
||||||
fileList.add(new FileSearchFileItem(
|
fileList.add(new FileSearchFileItem(
|
||||||
new File(((FileSearchFileItem)root).file, file)));
|
new File(((FileSearchFileItem)root).file, file)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public interface FileSearchItem{
|
public interface FileSearchItem{
|
||||||
/** @return a file or folder name **/
|
/** @return a file or folder name **/
|
||||||
public String getName();
|
public String getName();
|
||||||
/** @return a path to the file or folder, in case of a compressed file the path to the package will be returned **/
|
/** @return a path to the file or folder, in case of a compressed file the path to the package will be returned **/
|
||||||
public String getPath();
|
public String getPath();
|
||||||
|
|
||||||
public boolean isCompressed();
|
public boolean isCompressed();
|
||||||
public boolean isFile();
|
public boolean isFile();
|
||||||
public boolean isDirectory();
|
public boolean isDirectory();
|
||||||
|
|
||||||
/** @return an InputStream if this is a file otherwise null **/
|
/** @return an InputStream if this is a file otherwise null **/
|
||||||
public InputStream getInputStream() throws IOException;
|
public InputStream getInputStream() throws IOException;
|
||||||
/** @return an String array with all files if this is a folder otherwise null **/
|
/** @return an String array with all files if this is a folder otherwise null **/
|
||||||
public String[] listFiles();
|
public String[] listFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected static class FileSearchFileItem implements FileSearchItem{
|
protected static class FileSearchFileItem implements FileSearchItem{
|
||||||
private File file;
|
private File file;
|
||||||
|
|
||||||
protected FileSearchFileItem(File file){
|
protected FileSearchFileItem(File file){
|
||||||
this.file = file;
|
this.file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() { return file.getName(); }
|
public String getName() { return file.getName(); }
|
||||||
public String getPath() { return file.getAbsolutePath(); }
|
public String getPath() { return file.getAbsolutePath(); }
|
||||||
|
|
||||||
public boolean isCompressed() { return false; }
|
public boolean isCompressed() { return false; }
|
||||||
public boolean isFile() { return file.isFile(); }
|
public boolean isFile() { return file.isFile(); }
|
||||||
public boolean isDirectory() { return file.isDirectory(); }
|
public boolean isDirectory() { return file.isDirectory(); }
|
||||||
|
|
||||||
public InputStream getInputStream() throws IOException { return new FileInputStream(file); }
|
public InputStream getInputStream() throws IOException { return new FileInputStream(file); }
|
||||||
public String[] listFiles() { return file.list(); }
|
public String[] listFiles() { return file.list(); }
|
||||||
|
|
||||||
public File getFile() { return file; }
|
public File getFile() { return file; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class FileSearchZipItem implements FileSearchItem{
|
protected static class FileSearchZipItem implements FileSearchItem{
|
||||||
private String zipFile;
|
private String zipFile;
|
||||||
private ZipEntry entry;
|
private ZipEntry entry;
|
||||||
private String fileName;
|
private String fileName;
|
||||||
|
|
||||||
protected FileSearchZipItem(String file, ZipEntry entry){
|
protected FileSearchZipItem(String file, ZipEntry entry){
|
||||||
this.zipFile = file;
|
this.zipFile = file;
|
||||||
this.entry = entry;
|
this.entry = entry;
|
||||||
this.fileName = new File(entry.getName()).getName();
|
this.fileName = new File(entry.getName()).getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() { return fileName; }
|
public String getName() { return fileName; }
|
||||||
public String getPath() { return "zip://"+zipFile+":"+entry.getName(); }
|
public String getPath() { return "zip://"+zipFile+":"+entry.getName(); }
|
||||||
|
|
||||||
public boolean isCompressed() { return true; }
|
public boolean isCompressed() { return true; }
|
||||||
public boolean isFile() { return !entry.isDirectory(); }
|
public boolean isFile() { return !entry.isDirectory(); }
|
||||||
public boolean isDirectory() { return entry.isDirectory(); }
|
public boolean isDirectory() { return entry.isDirectory(); }
|
||||||
|
|
||||||
public InputStream getInputStream() throws IOException {
|
public InputStream getInputStream() throws IOException {
|
||||||
ZipFile zip = new ZipFile(zipFile);
|
ZipFile zip = new ZipFile(zipFile);
|
||||||
return new InputStreamCloser(zip.getInputStream(entry), zip);
|
return new InputStreamCloser(zip.getInputStream(entry), zip);
|
||||||
}
|
}
|
||||||
public String[] listFiles() { return null; }
|
public String[] listFiles() { return null; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -39,53 +39,53 @@ import java.util.TimerTask;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class FileWatcher extends TimerTask{
|
public class FileWatcher extends TimerTask{
|
||||||
private FileChangeListener listener;
|
private FileChangeListener listener;
|
||||||
private long lastChanged;
|
private long lastChanged;
|
||||||
private File file;
|
private File file;
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a watcher for the given file whit the check
|
|
||||||
* interval of 1 second
|
|
||||||
*
|
|
||||||
* @param file is 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 is the file
|
|
||||||
* @param intervall is 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() {
|
* Creates a watcher for the given file whit the check
|
||||||
if (lastChanged != file.lastModified()) {
|
* interval of 1 second
|
||||||
lastChanged = file.lastModified();
|
*
|
||||||
if(listener != null){
|
* @param file is the file to check
|
||||||
listener.fileChangedEvent(file);
|
* @throws FileNotFoundException
|
||||||
}
|
*/
|
||||||
else{
|
public FileWatcher(File file) throws FileNotFoundException{
|
||||||
MultiPrintStream.out.println("File Changed: "+file);
|
this(file, 1000);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
/**
|
||||||
|
* Creates a watcher for the given file whit the given
|
||||||
|
* check interval
|
||||||
|
*
|
||||||
|
* @param file is the file
|
||||||
|
* @param intervall is 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,126 +36,126 @@ import zutil.parser.DataNode.DataType;
|
||||||
* uploaded file.
|
* uploaded file.
|
||||||
*/
|
*/
|
||||||
public class FileUploadListener implements ProgressListener{
|
public class FileUploadListener implements ProgressListener{
|
||||||
public static enum Status{
|
public static enum Status{
|
||||||
Initializing,
|
Initializing,
|
||||||
Uploading,
|
Uploading,
|
||||||
Processing,
|
Processing,
|
||||||
Done,
|
Done,
|
||||||
Error
|
Error
|
||||||
}
|
}
|
||||||
|
|
||||||
private String id;
|
|
||||||
private volatile Status status;
|
|
||||||
private volatile String filename;
|
|
||||||
private volatile String message;
|
|
||||||
private volatile long bytes = 0l;
|
|
||||||
private volatile long length = 0l;
|
|
||||||
private volatile int item = 0;
|
|
||||||
private volatile long time;
|
|
||||||
|
|
||||||
// Speed
|
|
||||||
private volatile int speed;
|
|
||||||
private volatile long speedRead;
|
|
||||||
private volatile long speedTime;
|
|
||||||
|
|
||||||
public FileUploadListener(){
|
|
||||||
id = ""+(int)(Math.random()*Integer.MAX_VALUE);
|
|
||||||
status = Status.Initializing;
|
|
||||||
filename = "";
|
|
||||||
message = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update(long pBytesRead, long pContentLength, int pItems) {
|
|
||||||
if(pContentLength < 0) this.length = pBytesRead;
|
|
||||||
else this.length = pContentLength;
|
|
||||||
this.bytes = pBytesRead;
|
|
||||||
this.item = pItems;
|
|
||||||
|
|
||||||
// Calculate Speed
|
|
||||||
if(speedTime == 0 || speedTime+1000 < System.currentTimeMillis() || pBytesRead == pContentLength){
|
|
||||||
speedTime = System.currentTimeMillis();
|
|
||||||
speed = (int)(pBytesRead-speedRead);
|
|
||||||
speedRead = pBytesRead;
|
|
||||||
}
|
|
||||||
//try{Thread.sleep(10);}catch(Exception e){}
|
|
||||||
|
|
||||||
// Set Status
|
private String id;
|
||||||
status = Status.Uploading;
|
private volatile Status status;
|
||||||
time = System.currentTimeMillis();
|
private volatile String filename;
|
||||||
}
|
private volatile String message;
|
||||||
|
private volatile long bytes = 0l;
|
||||||
protected void setFileName(String filename){
|
private volatile long length = 0l;
|
||||||
this.filename = filename;
|
private volatile int item = 0;
|
||||||
}
|
private volatile long time;
|
||||||
protected void setStatus(Status status){
|
|
||||||
this.status = status;
|
|
||||||
time = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
protected void setMessage(String msg){
|
|
||||||
this.message = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String getID(){
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFilename() {
|
|
||||||
return filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getBytesRead() {
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getContentLength() {
|
// Speed
|
||||||
return length;
|
private volatile int speed;
|
||||||
}
|
private volatile long speedRead;
|
||||||
|
private volatile long speedTime;
|
||||||
|
|
||||||
public long getItem() {
|
public FileUploadListener(){
|
||||||
return item;
|
id = ""+(int)(Math.random()*Integer.MAX_VALUE);
|
||||||
}
|
status = Status.Initializing;
|
||||||
|
filename = "";
|
||||||
public Status getStatus(){
|
message = "";
|
||||||
return status;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
protected long getTime(){
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getMessage(){
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bytes per second
|
|
||||||
*/
|
|
||||||
public int getSpeed(){
|
|
||||||
return speed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
public void update(long pBytesRead, long pContentLength, int pItems) {
|
||||||
* Calculate the percent complete
|
if(pContentLength < 0) this.length = pBytesRead;
|
||||||
*/
|
else this.length = pContentLength;
|
||||||
public int getPercentComplete(){
|
this.bytes = pBytesRead;
|
||||||
if(length == 0)
|
this.item = pItems;
|
||||||
return 0;
|
|
||||||
return (int)((100 * bytes) / length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataNode getJSON() {
|
// Calculate Speed
|
||||||
DataNode node = new DataNode( DataType.Map );
|
if(speedTime == 0 || speedTime+1000 < System.currentTimeMillis() || pBytesRead == pContentLength){
|
||||||
node.set("id", id);
|
speedTime = System.currentTimeMillis();
|
||||||
|
speed = (int)(pBytesRead-speedRead);
|
||||||
node.set("status", status.toString());
|
speedRead = pBytesRead;
|
||||||
node.set("message", message.replaceAll("\"", "\\\"") );
|
}
|
||||||
node.set("filename", filename);
|
//try{Thread.sleep(10);}catch(Exception e){}
|
||||||
node.set("percent", getPercentComplete());
|
|
||||||
|
// Set Status
|
||||||
node.set("uploaded", StringUtil.formatByteSizeToString(bytes));
|
status = Status.Uploading;
|
||||||
node.set("total", StringUtil.formatByteSizeToString(length));
|
time = System.currentTimeMillis();
|
||||||
node.set("speed", StringUtil.formatByteSizeToString(speed)+"/s");
|
}
|
||||||
return node;
|
|
||||||
}
|
protected void setFileName(String filename){
|
||||||
|
this.filename = filename;
|
||||||
|
}
|
||||||
|
protected void setStatus(Status status){
|
||||||
|
this.status = status;
|
||||||
|
time = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
protected void setMessage(String msg){
|
||||||
|
this.message = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getID(){
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFilename() {
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getBytesRead() {
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getContentLength() {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status getStatus(){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected long getTime(){
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getMessage(){
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bytes per second
|
||||||
|
*/
|
||||||
|
public int getSpeed(){
|
||||||
|
return speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the percent complete
|
||||||
|
*/
|
||||||
|
public int getPercentComplete(){
|
||||||
|
if(length == 0)
|
||||||
|
return 0;
|
||||||
|
return (int)((100 * bytes) / length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataNode getJSON() {
|
||||||
|
DataNode node = new DataNode( DataType.Map );
|
||||||
|
node.set("id", id);
|
||||||
|
|
||||||
|
node.set("status", status.toString());
|
||||||
|
node.set("message", message.replaceAll("\"", "\\\"") );
|
||||||
|
node.set("filename", filename);
|
||||||
|
node.set("percent", getPercentComplete());
|
||||||
|
|
||||||
|
node.set("uploaded", StringUtil.formatByteSizeToString(bytes));
|
||||||
|
node.set("total", StringUtil.formatByteSizeToString(length));
|
||||||
|
node.set("speed", StringUtil.formatByteSizeToString(speed)+"/s");
|
||||||
|
return node;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,138 +36,138 @@ import java.util.logging.LogRecord;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class CompactLogFormatter extends Formatter{
|
public class CompactLogFormatter extends Formatter{
|
||||||
/** The split pattern where the **/
|
/** The split pattern where the **/
|
||||||
private static final Pattern splitter = Pattern.compile("\n");
|
private static final Pattern splitter = Pattern.compile("\n");
|
||||||
/** the stream should print time stamp **/
|
/** the stream should print time stamp **/
|
||||||
private boolean timeStamp = true;
|
private boolean timeStamp = true;
|
||||||
/** The time stamp style **/
|
/** The time stamp style **/
|
||||||
private SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
private SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||||
/** If displaying class names are enabled **/
|
/** If displaying class names are enabled **/
|
||||||
private boolean className = true;
|
private boolean className = true;
|
||||||
/** If displaying method names are enabled **/
|
/** If displaying method names are enabled **/
|
||||||
private boolean methodName = false;
|
private boolean methodName = false;
|
||||||
/** Specifies the max length of the longest class name **/
|
/** Specifies the max length of the longest class name **/
|
||||||
private int max_class_name = 0;
|
private int max_class_name = 0;
|
||||||
/** Cache for the class padding **/
|
/** Cache for the class padding **/
|
||||||
private static HashMap<String,String> padd_cache = new HashMap<String,String>();
|
private static HashMap<String,String> padd_cache = new HashMap<String,String>();
|
||||||
/** Date temp file **/
|
/** Date temp file **/
|
||||||
private Date date = new Date();
|
private Date date = new Date();
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String format(LogRecord record) {
|
public String format(LogRecord record) {
|
||||||
StringBuilder prefix = new StringBuilder();
|
StringBuilder prefix = new StringBuilder();
|
||||||
|
|
||||||
if( timeStamp ){
|
if( timeStamp ){
|
||||||
date.setTime( record.getMillis() );
|
date.setTime( record.getMillis() );
|
||||||
prefix.append(dateFormatter.format(date));
|
prefix.append(dateFormatter.format(date));
|
||||||
prefix.append(' ');
|
prefix.append(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( record.getLevel().intValue() ){
|
switch( record.getLevel().intValue() ){
|
||||||
case /* SEVERE */ 1000: prefix.append("[SEVERE] "); break;
|
case /* SEVERE */ 1000: prefix.append("[SEVERE] "); break;
|
||||||
case /* WARNING */ 900 : prefix.append("[WARNING]"); break;
|
case /* WARNING */ 900 : prefix.append("[WARNING]"); break;
|
||||||
case /* INFO */ 800 : prefix.append("[INFO] "); break;
|
case /* INFO */ 800 : prefix.append("[INFO] "); break;
|
||||||
case /* CONFIG */ 700 : prefix.append("[CONFIG] "); break;
|
case /* CONFIG */ 700 : prefix.append("[CONFIG] "); break;
|
||||||
case /* FINE */ 500 : prefix.append("[FINE] "); break;
|
case /* FINE */ 500 : prefix.append("[FINE] "); break;
|
||||||
case /* FINER */ 400 : prefix.append("[FINER] "); break;
|
case /* FINER */ 400 : prefix.append("[FINER] "); break;
|
||||||
case /* FINEST */ 300 : prefix.append("[FINEST] "); break;
|
case /* FINEST */ 300 : prefix.append("[FINEST] "); break;
|
||||||
}
|
}
|
||||||
prefix.append(' ');
|
prefix.append(' ');
|
||||||
|
|
||||||
if( className ){
|
if( className ){
|
||||||
prefix.append(paddClassName(record.getSourceClassName()));
|
prefix.append(paddClassName(record.getSourceClassName()));
|
||||||
}
|
}
|
||||||
if(methodName){
|
if(methodName){
|
||||||
prefix.append(record.getSourceMethodName());
|
prefix.append(record.getSourceMethodName());
|
||||||
}
|
}
|
||||||
prefix.append(": ");
|
prefix.append(": ");
|
||||||
|
|
||||||
StringBuilder ret = new StringBuilder();
|
StringBuilder ret = new StringBuilder();
|
||||||
if( record.getMessage() != null ){
|
if( record.getMessage() != null ){
|
||||||
String[] array = splitter.split( record.getMessage() );
|
String[] array = splitter.split( record.getMessage() );
|
||||||
for( int i=0; i<array.length ;++i ){
|
for( int i=0; i<array.length ;++i ){
|
||||||
if( i!=0 )
|
if( i!=0 )
|
||||||
ret.append( '\n' );
|
ret.append( '\n' );
|
||||||
if( prefix.length() > 0 )
|
if( prefix.length() > 0 )
|
||||||
ret.append( prefix );
|
ret.append( prefix );
|
||||||
ret.append( array[i] );
|
ret.append( array[i] );
|
||||||
}
|
}
|
||||||
ret.append( '\n' );
|
ret.append( '\n' );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( record.getThrown() != null ){
|
if( record.getThrown() != null ){
|
||||||
StringOutputStream out = new StringOutputStream();
|
StringOutputStream out = new StringOutputStream();
|
||||||
record.getThrown().printStackTrace(new PrintStream(out));
|
record.getThrown().printStackTrace(new PrintStream(out));
|
||||||
String[] array = splitter.split( out.toString() );
|
String[] array = splitter.split( out.toString() );
|
||||||
for( int i=0; i<array.length ;++i ){
|
for( int i=0; i<array.length ;++i ){
|
||||||
if( i!=0 )
|
if( i!=0 )
|
||||||
ret.append( '\n' );
|
ret.append( '\n' );
|
||||||
if( prefix.length() > 0 )
|
if( prefix.length() > 0 )
|
||||||
ret.append( prefix );
|
ret.append( prefix );
|
||||||
ret.append( array[i] );
|
ret.append( array[i] );
|
||||||
}
|
}
|
||||||
ret.append( '\n' );
|
ret.append( '\n' );
|
||||||
}
|
}
|
||||||
return ret.toString();
|
return ret.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the formatter should add a time stamp in front of the log message
|
* If the formatter should add a time stamp in front of the log message
|
||||||
*
|
*
|
||||||
* @param enable set to True to activate time stamp
|
* @param enable set to True to activate time stamp
|
||||||
*/
|
*/
|
||||||
public void enableTimeStamp(boolean enable){
|
public void enableTimeStamp(boolean enable){
|
||||||
timeStamp = enable;
|
timeStamp = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The DateFormat to print in the time stamp
|
* The DateFormat to print in the time stamp
|
||||||
*
|
*
|
||||||
* @param ts is the String to send to SimpleDateFormat
|
* @param ts is the String to send to SimpleDateFormat
|
||||||
*/
|
*/
|
||||||
public void setTimeStamp(String ts){
|
public void setTimeStamp(String ts){
|
||||||
dateFormatter = new SimpleDateFormat(ts);
|
dateFormatter = new SimpleDateFormat(ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the formatter should add the class/source name in front of the log message
|
* If the formatter should add the class/source name in front of the log message
|
||||||
*
|
*
|
||||||
* @param enable set to True to activate class/source name
|
* @param enable set to True to activate class/source name
|
||||||
*/
|
*/
|
||||||
public void enableClassName(boolean enable){
|
public void enableClassName(boolean enable){
|
||||||
className = enable;
|
className = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the formatter should add the class/source name in front of the log message
|
* If the formatter should add the class/source name in front of the log message
|
||||||
*
|
*
|
||||||
* @param enable set to True to activate class/source name
|
* @param enable set to True to activate class/source name
|
||||||
*/
|
*/
|
||||||
public void enableMethodName(boolean enable){
|
public void enableMethodName(boolean enable){
|
||||||
methodName = enable;
|
methodName = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the Class name
|
* @return the Class name
|
||||||
*/
|
*/
|
||||||
private String paddClassName(String source){
|
private String paddClassName(String source){
|
||||||
String cStr = padd_cache.get(source);
|
String cStr = padd_cache.get(source);
|
||||||
if (cStr == null || cStr.length() != max_class_name) {
|
if (cStr == null || cStr.length() != max_class_name) {
|
||||||
cStr = source.substring(source.lastIndexOf('.') + 1); // Remove packages
|
cStr = source.substring(source.lastIndexOf('.') + 1); // Remove packages
|
||||||
if (cStr.lastIndexOf('$') >= 0) { // extract subclass name
|
if (cStr.lastIndexOf('$') >= 0) { // extract subclass name
|
||||||
String subClass = cStr.substring(cStr.lastIndexOf('$') + 1);
|
String subClass = cStr.substring(cStr.lastIndexOf('$') + 1);
|
||||||
if (!Pattern.matches("\\d+", subClass)) // Don'n substring for anonymous classes
|
if (!Pattern.matches("\\d+", subClass)) // Don'n substring for anonymous classes
|
||||||
cStr = subClass;
|
cStr = subClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cStr.length() > max_class_name)
|
if (cStr.length() > max_class_name)
|
||||||
max_class_name = cStr.length();
|
max_class_name = cStr.length();
|
||||||
|
|
||||||
cStr += StringUtil.getSpaces(max_class_name - cStr.length());
|
cStr += StringUtil.getSpaces(max_class_name - cStr.length());
|
||||||
padd_cache.put(source, cStr);
|
padd_cache.put(source, cStr);
|
||||||
}
|
}
|
||||||
return cStr;
|
return cStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,95 +37,95 @@ import java.util.logging.*;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class LogUtil {
|
public class LogUtil {
|
||||||
private static final Logger logger = Logger.getLogger( LogUtil.class.getName() );
|
private static final Logger logger = Logger.getLogger( LogUtil.class.getName() );
|
||||||
|
|
||||||
|
|
||||||
private LogUtil(){}
|
private LogUtil(){}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a new Logger for the calling class
|
* @return a new Logger for the calling class
|
||||||
*/
|
*/
|
||||||
public static Logger getLogger(){
|
public static Logger getLogger(){
|
||||||
return Logger.getLogger(ClassUtil.getCallingClass(LogUtil.class));
|
return Logger.getLogger(ClassUtil.getCallingClass(LogUtil.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the log formatter to all root Handlers
|
* Sets the log formatter to all root Handlers
|
||||||
*
|
*
|
||||||
* @param f is the formatter class
|
* @param f is the formatter class
|
||||||
*/
|
*/
|
||||||
public static void setGlobalFormatter(Formatter f){
|
public static void setGlobalFormatter(Formatter f){
|
||||||
Logger root = Logger.getLogger("");
|
Logger root = Logger.getLogger("");
|
||||||
for (Handler handler : root.getHandlers()) {
|
for (Handler handler : root.getHandlers()) {
|
||||||
handler.setFormatter(f);
|
handler.setFormatter(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the log formatter to all handlers in the namespace
|
|
||||||
*
|
|
||||||
* @param f is the formatter class
|
|
||||||
*/
|
|
||||||
public static void setFormatter(String name, Formatter f){
|
|
||||||
Logger root = Logger.getLogger(name);
|
|
||||||
for (Handler handler : root.getHandlers()) {
|
|
||||||
handler.setFormatter(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the global log level
|
* Adds the log formatter to all handlers in the namespace
|
||||||
*/
|
*
|
||||||
public static void setGlobalLevel(Level level){
|
* @param f is the formatter class
|
||||||
setLevel("", level);
|
*/
|
||||||
}
|
public static void setFormatter(String name, Formatter f){
|
||||||
|
Logger root = Logger.getLogger(name);
|
||||||
|
for (Handler handler : root.getHandlers()) {
|
||||||
|
handler.setFormatter(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a Handler to the root namespace
|
* Sets the global log level
|
||||||
*/
|
*/
|
||||||
public static void addGlobalHandler(Handler handler){
|
public static void setGlobalLevel(Level level){
|
||||||
Logger root = Logger.getLogger("");
|
setLevel("", level);
|
||||||
root.addHandler(handler);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the log level for a specified class
|
|
||||||
*/
|
|
||||||
public static void setLevel(Class<?> c, Level level){
|
|
||||||
setLevel(c.getName(), level);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the log level for a specified logger
|
* Adds a Handler to the root namespace
|
||||||
*/
|
*/
|
||||||
public static void setLevel(String name, Level level){
|
public static void addGlobalHandler(Handler handler){
|
||||||
logger.fine("Changing log level of \""+name+"\" to \""+level.getLocalizedName()+"\"");
|
Logger root = Logger.getLogger("");
|
||||||
Logger newLogger = Logger.getLogger(name);
|
root.addHandler(handler);
|
||||||
newLogger.setLevel(level);
|
}
|
||||||
// Check if the logger has a handler
|
|
||||||
if( newLogger.getHandlers().length > 0 ){
|
/**
|
||||||
// Set the level on the handlers if its level is higher
|
* Sets the log level for a specified class
|
||||||
for (Handler handler : newLogger.getHandlers()) {
|
*/
|
||||||
if(handler.getLevel().intValue() > level.intValue())
|
public static void setLevel(Class<?> c, Level level){
|
||||||
|
setLevel(c.getName(), level);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the log level for a specified logger
|
||||||
|
*/
|
||||||
|
public static void setLevel(String name, Level level){
|
||||||
|
logger.fine("Changing log level of \""+name+"\" to \""+level.getLocalizedName()+"\"");
|
||||||
|
Logger newLogger = Logger.getLogger(name);
|
||||||
|
newLogger.setLevel(level);
|
||||||
|
// Check if the logger has a handler
|
||||||
|
if( newLogger.getHandlers().length > 0 ){
|
||||||
|
// Set the level on the handlers if its level is higher
|
||||||
|
for (Handler handler : newLogger.getHandlers()) {
|
||||||
|
if(handler.getLevel().intValue() > level.intValue())
|
||||||
handler.setLevel(level);
|
handler.setLevel(level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isLoggable(Class clazz, Level level){
|
public static boolean isLoggable(Class clazz, Level level){
|
||||||
return Logger.getLogger(clazz.getName()).isLoggable(level);
|
return Logger.getLogger(clazz.getName()).isLoggable(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void readConfiguration(String file){
|
public static void readConfiguration(String file){
|
||||||
try{
|
try{
|
||||||
File confFile = FileUtil.find(file);
|
File confFile = FileUtil.find(file);
|
||||||
if (confFile != null) {
|
if (confFile != null) {
|
||||||
FileInputStream in = new FileInputStream(confFile);
|
FileInputStream in = new FileInputStream(confFile);
|
||||||
LogManager.getLogManager().readConfiguration(in);
|
LogManager.getLogManager().readConfiguration(in);
|
||||||
in.close();
|
in.close();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
logger.warning("Unable to find logging configuration file: "+file);
|
logger.warning("Unable to find logging configuration file: "+file);
|
||||||
} catch (Exception e){
|
} catch (Exception e){
|
||||||
logger.log(Level.SEVERE, "Unable to load logging configuration: "+file, e);
|
logger.log(Level.SEVERE, "Unable to load logging configuration: "+file, e);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,55 +37,55 @@ import java.util.logging.Logger;
|
||||||
|
|
||||||
|
|
||||||
public class NetLogClient extends Thread{
|
public class NetLogClient extends Thread{
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
|
|
||||||
private ConcurrentLinkedQueue<NetLogListener> listeners;
|
|
||||||
private Socket s;
|
|
||||||
private ObjectOutputStream out;
|
|
||||||
|
|
||||||
public NetLogClient(String host, int port) throws UnknownHostException, IOException{
|
private ConcurrentLinkedQueue<NetLogListener> listeners;
|
||||||
s = new Socket(host, port);
|
private Socket s;
|
||||||
out = new ObjectOutputStream(s.getOutputStream());
|
private ObjectOutputStream out;
|
||||||
listeners = new ConcurrentLinkedQueue<NetLogListener>();
|
|
||||||
this.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addListener(NetLogListener listener){
|
public NetLogClient(String host, int port) throws UnknownHostException, IOException{
|
||||||
logger.info("Registring new NetLogListener: "+listener.getClass().getName());
|
s = new Socket(host, port);
|
||||||
listeners.add( listener );
|
out = new ObjectOutputStream(s.getOutputStream());
|
||||||
}
|
listeners = new ConcurrentLinkedQueue<NetLogListener>();
|
||||||
|
this.start();
|
||||||
|
}
|
||||||
|
|
||||||
public void run(){
|
public void addListener(NetLogListener listener){
|
||||||
try{
|
logger.info("Registring new NetLogListener: "+listener.getClass().getName());
|
||||||
ObjectInputStream in = new ObjectInputStream(s.getInputStream());
|
listeners.add( listener );
|
||||||
while( true ){
|
}
|
||||||
Object o = in.readObject();
|
|
||||||
|
|
||||||
for( NetLogListener listener : listeners ){
|
public void run(){
|
||||||
if( o instanceof NetLogMessage )
|
try{
|
||||||
listener.handleLogMessage((NetLogMessage)o);
|
ObjectInputStream in = new ObjectInputStream(s.getInputStream());
|
||||||
else if( o instanceof NetLogExceptionMessage )
|
while( true ){
|
||||||
listener.handleExceptionMessage((NetLogExceptionMessage)o);
|
Object o = in.readObject();
|
||||||
else if( o instanceof NetLogStatusMessage )
|
|
||||||
listener.handleStatusMessage((NetLogStatusMessage)o);
|
for( NetLogListener listener : listeners ){
|
||||||
else
|
if( o instanceof NetLogMessage )
|
||||||
logger.warning("Received unknown message: "+o.getClass().getName());
|
listener.handleLogMessage((NetLogMessage)o);
|
||||||
}
|
else if( o instanceof NetLogExceptionMessage )
|
||||||
}
|
listener.handleExceptionMessage((NetLogExceptionMessage)o);
|
||||||
} catch( Exception e ){
|
else if( o instanceof NetLogStatusMessage )
|
||||||
logger.log(Level.SEVERE, null, e);
|
listener.handleStatusMessage((NetLogStatusMessage)o);
|
||||||
close();
|
else
|
||||||
}
|
logger.warning("Received unknown message: "+o.getClass().getName());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} catch( Exception e ){
|
||||||
|
logger.log(Level.SEVERE, null, e);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void close(){
|
public void close(){
|
||||||
try{
|
try{
|
||||||
this.interrupt();
|
this.interrupt();
|
||||||
s.close();
|
s.close();
|
||||||
} catch (Exception e){
|
} catch (Exception e){
|
||||||
logger.log(Level.SEVERE, "Unable to close Client Socket.", e);
|
logger.log(Level.SEVERE, "Unable to close Client Socket.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,77 +29,77 @@ import zutil.net.nio.message.Message;
|
||||||
import java.util.logging.LogRecord;
|
import java.util.logging.LogRecord;
|
||||||
|
|
||||||
public class NetLogExceptionMessage implements Message {
|
public class NetLogExceptionMessage implements Message {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private int count;
|
|
||||||
private String name;
|
|
||||||
private String message;
|
|
||||||
private String stackTrace;
|
|
||||||
|
|
||||||
NetLogExceptionMessage(String name, String message, String stackTrace){
|
|
||||||
this.count = 1;
|
|
||||||
this.name = name;
|
|
||||||
this.message = message;
|
|
||||||
this.stackTrace = stackTrace;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NetLogExceptionMessage(LogRecord record) {
|
private int count;
|
||||||
Throwable exception = record.getThrown();
|
private String name;
|
||||||
|
private String message;
|
||||||
this.count = 1;
|
private String stackTrace;
|
||||||
this.name = exception.getClass().getName();
|
|
||||||
this.message = exception.getMessage();
|
NetLogExceptionMessage(String name, String message, String stackTrace){
|
||||||
this.stackTrace = "";
|
this.count = 1;
|
||||||
for(int i=0; i<exception.getStackTrace().length; i++){
|
this.name = name;
|
||||||
this.stackTrace += exception.getStackTrace()[i].toString();
|
this.message = message;
|
||||||
}
|
this.stackTrace = stackTrace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NetLogExceptionMessage(LogRecord record) {
|
||||||
|
Throwable exception = record.getThrown();
|
||||||
|
|
||||||
|
this.count = 1;
|
||||||
|
this.name = exception.getClass().getName();
|
||||||
|
this.message = exception.getMessage();
|
||||||
|
this.stackTrace = "";
|
||||||
|
for(int i=0; i<exception.getStackTrace().length; i++){
|
||||||
|
this.stackTrace += exception.getStackTrace()[i].toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||||
result = prime * result + ((message == null) ? 0 : message.hashCode());
|
result = prime * result + ((message == null) ? 0 : message.hashCode());
|
||||||
result = prime * result
|
result = prime * result
|
||||||
+ ((stackTrace == null) ? 0 : stackTrace.hashCode());
|
+ ((stackTrace == null) ? 0 : stackTrace.hashCode());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj)
|
|
||||||
return true;
|
|
||||||
if (obj == null || getClass() != obj.getClass())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
NetLogExceptionMessage other = (NetLogExceptionMessage) obj;
|
|
||||||
if (name.equals(other.name) && message.equals(other.message) &&
|
|
||||||
stackTrace.equals(other.stackTrace)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addCount(int add){
|
|
||||||
count += add;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCount() {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
@Override
|
||||||
return name;
|
public boolean equals(Object obj) {
|
||||||
}
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null || getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
|
||||||
public String getMessage() {
|
NetLogExceptionMessage other = (NetLogExceptionMessage) obj;
|
||||||
return message;
|
if (name.equals(other.name) && message.equals(other.message) &&
|
||||||
}
|
stackTrace.equals(other.stackTrace)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public String getStackTrace() {
|
public void addCount(int add){
|
||||||
return stackTrace;
|
count += add;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStackTrace() {
|
||||||
|
return stackTrace;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,14 +38,14 @@ import javafx.stage.Stage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class NetLogGuiClient extends Application{
|
public class NetLogGuiClient extends Application{
|
||||||
public static final String VERSION = "0.1";
|
public static final String VERSION = "0.1";
|
||||||
|
|
||||||
// UI elements
|
|
||||||
@FXML
|
|
||||||
private TabPane tabPane;
|
|
||||||
|
|
||||||
|
// UI elements
|
||||||
public static void main(String[] args) {
|
@FXML
|
||||||
|
private TabPane tabPane;
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
Application.launch(NetLogGuiClient.class, args);
|
Application.launch(NetLogGuiClient.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,40 +57,40 @@ public class NetLogGuiClient extends Application{
|
||||||
stage.setScene(new Scene(root));
|
stage.setScene(new Scene(root));
|
||||||
stage.show();
|
stage.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Menu Actions
|
// Menu Actions
|
||||||
@FXML
|
@FXML
|
||||||
protected void handleConnectAction(ActionEvent event) {
|
protected void handleConnectAction(ActionEvent event) {
|
||||||
try{
|
try{
|
||||||
tabPane.getTabs().add(new NetLoggerClientTab("koc.se", 8080));
|
tabPane.getTabs().add(new NetLoggerClientTab("koc.se", 8080));
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
protected void handleExitAction(ActionEvent event) {
|
protected void handleExitAction(ActionEvent event) {
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
protected void handleAboutAction(ActionEvent event) {
|
protected void handleAboutAction(ActionEvent event) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class NetLoggerClientTab extends Tab{
|
private class NetLoggerClientTab extends Tab{
|
||||||
public NetLoggerClientTab(String host, int port) throws IOException{
|
public NetLoggerClientTab(String host, int port) throws IOException{
|
||||||
this.setText( host+":"+port );
|
this.setText( host+":"+port );
|
||||||
|
|
||||||
FXMLLoader loader = new FXMLLoader();
|
FXMLLoader loader = new FXMLLoader();
|
||||||
Parent tabRoot = loader.load(getClass().getResource("NetLogClientInstance.fxml"));
|
Parent tabRoot = loader.load(getClass().getResource("NetLogClientInstance.fxml"));
|
||||||
this.setContent(tabRoot);
|
this.setContent(tabRoot);
|
||||||
AnchorPane.setRightAnchor(tabRoot, 0.0);
|
AnchorPane.setRightAnchor(tabRoot, 0.0);
|
||||||
//this.setOnClosed(new EventHandler<Event>() {
|
//this.setOnClosed(new EventHandler<Event>() {
|
||||||
// public void handle(Event e) {
|
// public void handle(Event e) {
|
||||||
// handleDisconnectAction(e);
|
// handleDisconnectAction(e);
|
||||||
// }
|
// }
|
||||||
//});
|
//});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -40,15 +40,15 @@ import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class NetLogGuiClientInstance implements Initializable, NetLogListener {
|
public class NetLogGuiClientInstance implements Initializable, NetLogListener {
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
private static enum Status{RUNNING, PAUSED, DISCONNECTED}
|
private static enum Status{RUNNING, PAUSED, DISCONNECTED}
|
||||||
|
|
||||||
// Logic variables
|
// Logic variables
|
||||||
private NetLogClient net;
|
private NetLogClient net;
|
||||||
private Status status;
|
private Status status;
|
||||||
|
|
||||||
// UI elements
|
// UI elements
|
||||||
@FXML private ToggleButton pauseButton;
|
@FXML private ToggleButton pauseButton;
|
||||||
@FXML private Label levelLabel;
|
@FXML private Label levelLabel;
|
||||||
@FXML private ComboBox levelComboBox;
|
@FXML private ComboBox levelComboBox;
|
||||||
@FXML private Label intervalLabel;
|
@FXML private Label intervalLabel;
|
||||||
|
|
@ -57,120 +57,120 @@ public class NetLogGuiClientInstance implements Initializable, NetLogListener {
|
||||||
@FXML private Label errorLabel;
|
@FXML private Label errorLabel;
|
||||||
@FXML private Label logCountLabel;
|
@FXML private Label logCountLabel;
|
||||||
|
|
||||||
@FXML private TableView<NetLogMessage> logTable;
|
@FXML private TableView<NetLogMessage> logTable;
|
||||||
@FXML private TableColumn<NetLogMessage, Long> logTimestampColumn;
|
@FXML private TableColumn<NetLogMessage, Long> logTimestampColumn;
|
||||||
@FXML private TableColumn<NetLogMessage, String> logLevelColumn;
|
@FXML private TableColumn<NetLogMessage, String> logLevelColumn;
|
||||||
@FXML private TableColumn<NetLogMessage, String> logColumn;
|
@FXML private TableColumn<NetLogMessage, String> logColumn;
|
||||||
|
|
||||||
@FXML private TableView<NetLogExceptionMessage> exceptionTable;
|
@FXML private TableView<NetLogExceptionMessage> exceptionTable;
|
||||||
@FXML private TableColumn<NetLogExceptionMessage, Long> exCountColumn;
|
@FXML private TableColumn<NetLogExceptionMessage, Long> exCountColumn;
|
||||||
@FXML private TableColumn<NetLogExceptionMessage, String> exNameColumn;
|
@FXML private TableColumn<NetLogExceptionMessage, String> exNameColumn;
|
||||||
@FXML private TableColumn<NetLogExceptionMessage, String> exMessageColumn;
|
@FXML private TableColumn<NetLogExceptionMessage, String> exMessageColumn;
|
||||||
@FXML private TableColumn<NetLogExceptionMessage, String> exStackTraceColumn;
|
@FXML private TableColumn<NetLogExceptionMessage, String> exStackTraceColumn;
|
||||||
|
|
||||||
|
|
||||||
public void initialize(URL arg0, ResourceBundle arg1) {
|
public void initialize(URL arg0, ResourceBundle arg1) {
|
||||||
// Connect to Server
|
// Connect to Server
|
||||||
try{
|
try{
|
||||||
net = new NetLogClient("127.0.0.1", 5050);
|
net = new NetLogClient("127.0.0.1", 5050);
|
||||||
net.addListener( this );
|
net.addListener( this );
|
||||||
status = Status.RUNNING;
|
status = Status.RUNNING;
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
logger.log(Level.SEVERE, null, e);
|
logger.log(Level.SEVERE, null, e);
|
||||||
status = Status.DISCONNECTED;
|
status = Status.DISCONNECTED;
|
||||||
errorLabel.setText(e.getMessage());
|
errorLabel.setText(e.getMessage());
|
||||||
}
|
}
|
||||||
updateStatus();
|
updateStatus();
|
||||||
|
|
||||||
// Setup Gui
|
// Setup Gui
|
||||||
logTimestampColumn.setCellValueFactory(new PropertyValueFactory<NetLogMessage, Long>("timestamp"));
|
logTimestampColumn.setCellValueFactory(new PropertyValueFactory<NetLogMessage, Long>("timestamp"));
|
||||||
logLevelColumn.setCellValueFactory(new PropertyValueFactory<NetLogMessage, String>("level"));
|
logLevelColumn.setCellValueFactory(new PropertyValueFactory<NetLogMessage, String>("level"));
|
||||||
logLevelColumn.setCellFactory(new RowCssCellFactory<NetLogMessage,String>(){
|
logLevelColumn.setCellFactory(new RowCssCellFactory<NetLogMessage,String>(){
|
||||||
public String getStyleName(String item){
|
public String getStyleName(String item){
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
logColumn.setCellValueFactory(new PropertyValueFactory<NetLogMessage, String>("log"));
|
logColumn.setCellValueFactory(new PropertyValueFactory<NetLogMessage, String>("log"));
|
||||||
|
|
||||||
exCountColumn.setCellValueFactory(new PropertyValueFactory<NetLogExceptionMessage, Long>("count"));
|
exCountColumn.setCellValueFactory(new PropertyValueFactory<NetLogExceptionMessage, Long>("count"));
|
||||||
exNameColumn.setCellValueFactory(new PropertyValueFactory<NetLogExceptionMessage, String>("name"));
|
exNameColumn.setCellValueFactory(new PropertyValueFactory<NetLogExceptionMessage, String>("name"));
|
||||||
exMessageColumn.setCellValueFactory(new PropertyValueFactory<NetLogExceptionMessage, String>("message"));
|
exMessageColumn.setCellValueFactory(new PropertyValueFactory<NetLogExceptionMessage, String>("message"));
|
||||||
exStackTraceColumn.setCellValueFactory(new PropertyValueFactory<NetLogExceptionMessage, String>("stackTrace"));
|
exStackTraceColumn.setCellValueFactory(new PropertyValueFactory<NetLogExceptionMessage, String>("stackTrace"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/************* NETWORK *****************/
|
/************* NETWORK *****************/
|
||||||
public void handleLogMessage(NetLogMessage msg) {
|
public void handleLogMessage(NetLogMessage msg) {
|
||||||
if(status == Status.RUNNING){
|
if(status == Status.RUNNING){
|
||||||
logTable.getItems().add(msg);
|
logTable.getItems().add(msg);
|
||||||
|
|
||||||
Platform.runLater(new Runnable() {
|
Platform.runLater(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
logCountLabel.setText("" + (Long.parseLong(logCountLabel.getText()) + 1));
|
logCountLabel.setText("" + (Long.parseLong(logCountLabel.getText()) + 1));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleExceptionMessage(NetLogExceptionMessage msg) {
|
public void handleExceptionMessage(NetLogExceptionMessage msg) {
|
||||||
if(status == Status.RUNNING){
|
if(status == Status.RUNNING){
|
||||||
exceptionTable.getItems().remove(msg);
|
exceptionTable.getItems().remove(msg);
|
||||||
exceptionTable.getItems().add(msg);
|
exceptionTable.getItems().add(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleStatusMessage(NetLogStatusMessage msg) {
|
public void handleStatusMessage(NetLogStatusMessage msg) {
|
||||||
if(status == Status.RUNNING){
|
if(status == Status.RUNNING){
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************** GUI *******************/
|
}
|
||||||
@FXML
|
}
|
||||||
protected void handlePauseAction(ActionEvent event) {
|
|
||||||
if(status == Status.RUNNING){
|
|
||||||
status = Status.PAUSED;
|
|
||||||
logger.info("Logging paused");
|
|
||||||
}
|
|
||||||
else if(status == Status.PAUSED){
|
|
||||||
status = Status.RUNNING;
|
|
||||||
logger.info("Logging Unpaused");
|
|
||||||
}
|
|
||||||
updateStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
@FXML
|
/*************** GUI *******************/
|
||||||
protected void handleDisconnectAction(Event event) {
|
@FXML
|
||||||
logger.info("Disconnecting from Log Server");
|
protected void handlePauseAction(ActionEvent event) {
|
||||||
net.close();
|
if(status == Status.RUNNING){
|
||||||
status = Status.DISCONNECTED;
|
status = Status.PAUSED;
|
||||||
updateStatus();
|
logger.info("Logging paused");
|
||||||
}
|
}
|
||||||
|
else if(status == Status.PAUSED){
|
||||||
|
status = Status.RUNNING;
|
||||||
|
logger.info("Logging Unpaused");
|
||||||
|
}
|
||||||
|
updateStatus();
|
||||||
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
protected void handleLevelChanged(ActionEvent event) {
|
protected void handleDisconnectAction(Event event) {
|
||||||
logger.info("Updating Log Level");
|
logger.info("Disconnecting from Log Server");
|
||||||
}
|
net.close();
|
||||||
|
status = Status.DISCONNECTED;
|
||||||
|
updateStatus();
|
||||||
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
protected void handleIntervalChanged(ActionEvent event) {
|
protected void handleLevelChanged(ActionEvent event) {
|
||||||
logger.info("Updating Log Interval");
|
logger.info("Updating Log Level");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateStatus(){
|
@FXML
|
||||||
if(progressBar == null || pauseButton == null){
|
protected void handleIntervalChanged(ActionEvent event) {
|
||||||
return;
|
logger.info("Updating Log Interval");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(status == Status.RUNNING){
|
private void updateStatus(){
|
||||||
progressBar.setProgress(-1.0);
|
if(progressBar == null || pauseButton == null){
|
||||||
pauseButton.setText("Pause");
|
return;
|
||||||
}
|
}
|
||||||
else if(status == Status.PAUSED){
|
|
||||||
progressBar.setProgress(1.0);
|
if(status == Status.RUNNING){
|
||||||
pauseButton.setText("Unpause");
|
progressBar.setProgress(-1.0);
|
||||||
}
|
pauseButton.setText("Pause");
|
||||||
else if(status == Status.DISCONNECTED){
|
}
|
||||||
pauseButton.setDisable(true);
|
else if(status == Status.PAUSED){
|
||||||
|
progressBar.setProgress(1.0);
|
||||||
|
pauseButton.setText("Unpause");
|
||||||
|
}
|
||||||
|
else if(status == Status.DISCONNECTED){
|
||||||
|
pauseButton.setDisable(true);
|
||||||
levelLabel.setDisable(true);
|
levelLabel.setDisable(true);
|
||||||
levelComboBox.setDisable(true);
|
levelComboBox.setDisable(true);
|
||||||
intervalLabel.setDisable(true);
|
intervalLabel.setDisable(true);
|
||||||
|
|
@ -181,42 +181,42 @@ public class NetLogGuiClientInstance implements Initializable, NetLogListener {
|
||||||
|
|
||||||
progressBar.setProgress(0);
|
progressBar.setProgress(0);
|
||||||
logCountLabel.setDisable(true);
|
logCountLabel.setDisable(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http://stackoverflow.com/questions/13697115/javafx-tableview-colors
|
* http://stackoverflow.com/questions/13697115/javafx-tableview-colors
|
||||||
*/
|
*/
|
||||||
public abstract class RowCssCellFactory<S,T> implements Callback<TableColumn<S,T>, TableCell<S,T>> {
|
public abstract class RowCssCellFactory<S,T> implements Callback<TableColumn<S,T>, TableCell<S,T>> {
|
||||||
|
|
||||||
public TableCell<S,T> call(TableColumn<S,T> p) {
|
public TableCell<S,T> call(TableColumn<S,T> p) {
|
||||||
TableCell<S, T> cell = new TableCell<S, T>() {
|
TableCell<S, T> cell = new TableCell<S, T>() {
|
||||||
@Override
|
@Override
|
||||||
public void updateItem(T item, boolean empty) {
|
public void updateItem(T item, boolean empty) {
|
||||||
super.updateItem(item, empty);
|
super.updateItem(item, empty);
|
||||||
setText(empty ? null : getString());
|
setText(empty ? null : getString());
|
||||||
setGraphic(null);
|
setGraphic(null);
|
||||||
|
|
||||||
String style = getStyleName(item);
|
String style = getStyleName(item);
|
||||||
if(style != null){
|
if(style != null){
|
||||||
TableRow<?> row = getTableRow();
|
TableRow<?> row = getTableRow();
|
||||||
row.getStyleClass().add(style);
|
row.getStyleClass().add(style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateSelected(boolean upd){
|
public void updateSelected(boolean upd){
|
||||||
super.updateSelected(upd);
|
super.updateSelected(upd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String getString() {
|
private String getString() {
|
||||||
return getItem() == null ? "NULL" : getItem().toString();
|
return getItem() == null ? "NULL" : getItem().toString();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract String getStyleName(T item);
|
public abstract String getStyleName(T item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -26,18 +26,18 @@ package zutil.log.net;
|
||||||
|
|
||||||
|
|
||||||
public interface NetLogListener {
|
public interface NetLogListener {
|
||||||
/**
|
/**
|
||||||
* Handle incoming log messages
|
* Handle incoming log messages
|
||||||
*/
|
*/
|
||||||
public void handleLogMessage( NetLogMessage log );
|
public void handleLogMessage( NetLogMessage log );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle incoming exception messages
|
* Handle incoming exception messages
|
||||||
*/
|
*/
|
||||||
public void handleExceptionMessage( NetLogExceptionMessage exception );
|
public void handleExceptionMessage( NetLogExceptionMessage exception );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle incoming status messages
|
* Handle incoming status messages
|
||||||
*/
|
*/
|
||||||
public void handleStatusMessage( NetLogStatusMessage status );
|
public void handleStatusMessage( NetLogStatusMessage status );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,82 +31,82 @@ import java.util.Date;
|
||||||
import java.util.logging.LogRecord;
|
import java.util.logging.LogRecord;
|
||||||
|
|
||||||
public class NetLogMessage implements Message {
|
public class NetLogMessage implements Message {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private static final SimpleDateFormat dataFormat =
|
private static final SimpleDateFormat dataFormat =
|
||||||
new SimpleDateFormat("yyyy--MM-dd HH:mm:ss");
|
new SimpleDateFormat("yyyy--MM-dd HH:mm:ss");
|
||||||
|
|
||||||
private long timestamp;
|
private long timestamp;
|
||||||
private String level;
|
private String level;
|
||||||
private int threadID;
|
private int threadID;
|
||||||
private String className;
|
private String className;
|
||||||
private String methodName;
|
private String methodName;
|
||||||
private String log;
|
private String log;
|
||||||
|
|
||||||
|
|
||||||
public NetLogMessage(String level, long timestamp, String log){
|
public NetLogMessage(String level, long timestamp, String log){
|
||||||
this.level = level;
|
this.level = level;
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
this.log = log;
|
this.log = log;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NetLogMessage( LogRecord record ){
|
public NetLogMessage( LogRecord record ){
|
||||||
timestamp = record.getMillis();
|
timestamp = record.getMillis();
|
||||||
level = record.getLevel().getName();
|
level = record.getLevel().getName();
|
||||||
threadID = record.getThreadID();
|
threadID = record.getThreadID();
|
||||||
className = record.getSourceClassName();
|
className = record.getSourceClassName();
|
||||||
methodName = record.getSourceMethodName();
|
methodName = record.getSourceMethodName();
|
||||||
log = record.getMessage();
|
log = record.getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public String getTimestamp() {
|
|
||||||
return dataFormat.format(new Date(timestamp));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTimestamp(long timestamp) {
|
|
||||||
this.timestamp = timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLevel() {
|
public String getTimestamp() {
|
||||||
return level;
|
return dataFormat.format(new Date(timestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLevel(String level) {
|
public void setTimestamp(long timestamp) {
|
||||||
this.level = level;
|
this.timestamp = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getThreadID() {
|
public String getLevel() {
|
||||||
return threadID;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setThreadID(int threadID) {
|
public void setLevel(String level) {
|
||||||
this.threadID = threadID;
|
this.level = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getClassName() {
|
public int getThreadID() {
|
||||||
return className;
|
return threadID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClassName(String className) {
|
public void setThreadID(int threadID) {
|
||||||
this.className = className;
|
this.threadID = threadID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMethodName() {
|
public String getClassName() {
|
||||||
return methodName;
|
return className;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMethodName(String methodName) {
|
public void setClassName(String className) {
|
||||||
this.methodName = methodName;
|
this.className = className;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLog() {
|
public String getMethodName() {
|
||||||
return log;
|
return methodName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMethodName(String methodName) {
|
||||||
|
this.methodName = methodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLog() {
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLog(String log) {
|
||||||
|
this.log = log;
|
||||||
|
}
|
||||||
|
|
||||||
public void setLog(String log) {
|
|
||||||
this.log = log;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,135 +42,135 @@ import java.util.logging.Logger;
|
||||||
|
|
||||||
|
|
||||||
public class NetLogServer extends Handler {
|
public class NetLogServer extends Handler {
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
|
|
||||||
private NetLogNetwork net;
|
private NetLogNetwork net;
|
||||||
private ConcurrentHashMap<NetLogExceptionMessage,NetLogExceptionMessage> exceptions;
|
private ConcurrentHashMap<NetLogExceptionMessage,NetLogExceptionMessage> exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param port the port the server will listen on
|
* @param port the port the server will listen on
|
||||||
*/
|
*/
|
||||||
public NetLogServer(int port) {
|
public NetLogServer(int port) {
|
||||||
super();
|
super();
|
||||||
exceptions = new ConcurrentHashMap<NetLogExceptionMessage,NetLogExceptionMessage>();
|
exceptions = new ConcurrentHashMap<NetLogExceptionMessage,NetLogExceptionMessage>();
|
||||||
net = new NetLogNetwork(port);
|
net = new NetLogNetwork(port);
|
||||||
net.start();
|
net.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void publish(LogRecord record) {
|
public void publish(LogRecord record) {
|
||||||
// ensure that this log record should be logged by this Handler
|
// ensure that this log record should be logged by this Handler
|
||||||
if (!isLoggable(record))
|
if (!isLoggable(record))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Output the formatted data to the file
|
// Output the formatted data to the file
|
||||||
if(record.getThrown() != null){
|
if(record.getThrown() != null){
|
||||||
NetLogExceptionMessage exception = new NetLogExceptionMessage(record);
|
NetLogExceptionMessage exception = new NetLogExceptionMessage(record);
|
||||||
if(!exceptions.containsKey(exception)){
|
if(!exceptions.containsKey(exception)){
|
||||||
logger.finest("Received new exception: "+exception);
|
logger.finest("Received new exception: "+exception);
|
||||||
exceptions.put(exception, exception);
|
exceptions.put(exception, exception);
|
||||||
net.sendMessage( exception );
|
net.sendMessage( exception );
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
exception = exceptions.get(exception);
|
exception = exceptions.get(exception);
|
||||||
exception.addCount(1);
|
exception.addCount(1);
|
||||||
logger.finest("Received known exception(Count: "+exception.getCount()+"): "+exception);
|
logger.finest("Received known exception(Count: "+exception.getCount()+"): "+exception);
|
||||||
net.sendMessage( exception );
|
net.sendMessage( exception );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
NetLogMessage log = new NetLogMessage(record);
|
NetLogMessage log = new NetLogMessage(record);
|
||||||
net.sendMessage( log );
|
net.sendMessage( log );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flush() {}
|
public void flush() {}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
net.close();
|
net.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class NetLogNetwork extends ThreadedTCPNetworkServer{
|
class NetLogNetwork extends ThreadedTCPNetworkServer{
|
||||||
private ConcurrentLinkedQueue<NetLogServerThread> threads;
|
private ConcurrentLinkedQueue<NetLogServerThread> threads;
|
||||||
|
|
||||||
public NetLogNetwork(int port) {
|
public NetLogNetwork(int port) {
|
||||||
super(port);
|
super(port);
|
||||||
threads = new ConcurrentLinkedQueue<NetLogServerThread>();
|
threads = new ConcurrentLinkedQueue<NetLogServerThread>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(Message log){
|
public void sendMessage(Message log){
|
||||||
for( NetLogServerThread thread : threads ){
|
for( NetLogServerThread thread : threads ){
|
||||||
thread.sendMessage( log );
|
thread.sendMessage( log );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ThreadedTCPNetworkServerThread getThreadInstance(Socket s) {
|
protected ThreadedTCPNetworkServerThread getThreadInstance(Socket s) {
|
||||||
try {
|
try {
|
||||||
NetLogServerThread thread = new NetLogServerThread(s);
|
NetLogServerThread thread = new NetLogServerThread(s);
|
||||||
return thread;
|
return thread;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.log(Level.SEVERE, "Unable to start Client thread", e);
|
logger.log(Level.SEVERE, "Unable to start Client thread", e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class NetLogServerThread implements ThreadedTCPNetworkServerThread{
|
class NetLogServerThread implements ThreadedTCPNetworkServerThread{
|
||||||
private ObjectOutputStream out;
|
private ObjectOutputStream out;
|
||||||
private ObjectInputStream in;
|
private ObjectInputStream in;
|
||||||
private Socket s;
|
private Socket s;
|
||||||
|
|
||||||
public NetLogServerThread(Socket s) throws IOException{
|
public NetLogServerThread(Socket s) throws IOException{
|
||||||
this.s = s;
|
this.s = s;
|
||||||
logger.info("Client connected: "+s.getInetAddress());
|
logger.info("Client connected: "+s.getInetAddress());
|
||||||
out = new ObjectOutputStream( s.getOutputStream() );
|
out = new ObjectOutputStream( s.getOutputStream() );
|
||||||
in = new ObjectInputStream( s.getInputStream() );
|
in = new ObjectInputStream( s.getInputStream() );
|
||||||
|
|
||||||
sendAllExceptions();
|
|
||||||
threads.add( this );
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendMessage(Message msg){
|
sendAllExceptions();
|
||||||
try {
|
threads.add( this );
|
||||||
out.writeObject( msg );
|
}
|
||||||
out.reset();
|
|
||||||
} catch (Exception e) {
|
|
||||||
this.close();
|
|
||||||
logger.log(Level.SEVERE, "Unable to send message to client: "+s.getInetAddress(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendAllExceptions(){
|
public void sendMessage(Message msg){
|
||||||
logger.fine("Sending all exceptions to client: "+s.getInetAddress());
|
try {
|
||||||
for(NetLogExceptionMessage e : exceptions.values())
|
out.writeObject( msg );
|
||||||
sendMessage(e);
|
out.reset();
|
||||||
}
|
} catch (Exception e) {
|
||||||
|
this.close();
|
||||||
|
logger.log(Level.SEVERE, "Unable to send message to client: "+s.getInetAddress(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void run() {
|
public void sendAllExceptions(){
|
||||||
try {
|
logger.fine("Sending all exceptions to client: "+s.getInetAddress());
|
||||||
while( true ){
|
for(NetLogExceptionMessage e : exceptions.values())
|
||||||
in.readObject();
|
sendMessage(e);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
logger.log(Level.SEVERE, null, e);
|
public void run() {
|
||||||
} finally {
|
try {
|
||||||
this.close();
|
while( true ){
|
||||||
}
|
in.readObject();
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.log(Level.SEVERE, null, e);
|
||||||
|
} finally {
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void close(){
|
public void close(){
|
||||||
try {
|
try {
|
||||||
threads.remove(this);
|
threads.remove(this);
|
||||||
logger.info("Client disconnected: "+s.getInetAddress());
|
logger.info("Client disconnected: "+s.getInetAddress());
|
||||||
out.close();
|
out.close();
|
||||||
s.close();
|
s.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.log(Level.SEVERE, "Unable to close Client Socket", e);
|
logger.log(Level.SEVERE, "Unable to close Client Socket", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@ package zutil.log.net;
|
||||||
import zutil.net.nio.message.Message;
|
import zutil.net.nio.message.Message;
|
||||||
|
|
||||||
public class NetLogStatusMessage implements Message{
|
public class NetLogStatusMessage implements Message{
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public long totalMemory;
|
public long totalMemory;
|
||||||
public long freememory;
|
public long freememory;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,100 +26,100 @@ package zutil.math;
|
||||||
|
|
||||||
public class Tick {
|
public class Tick {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ticks a given string(increments the string with one)
|
* Ticks a given string(increments the string with one)
|
||||||
*
|
*
|
||||||
* @param ts is the string to tick
|
* @param ts is the string to tick
|
||||||
* @param maxChar is the maximum number of characters in the string
|
* @param maxChar is the maximum number of characters in the string
|
||||||
* @return the ticked string
|
* @return the ticked string
|
||||||
*/
|
*/
|
||||||
public static String tick(String ts, int maxChar){
|
public static String tick(String ts, int maxChar){
|
||||||
StringBuffer ret = new StringBuffer(ts.trim());
|
StringBuffer ret = new StringBuffer(ts.trim());
|
||||||
int index = ret.length()-1;
|
int index = ret.length()-1;
|
||||||
|
|
||||||
if(ret.length() < maxChar){
|
if(ret.length() < maxChar){
|
||||||
ret.append('a');
|
ret.append('a');
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
while(index >= 0){
|
while(index >= 0){
|
||||||
char c = increment(ret.charAt(index));
|
char c = increment(ret.charAt(index));
|
||||||
if(c != 0){
|
if(c != 0){
|
||||||
if(index == 0 && ret.length() < maxChar) ret.append('a');
|
if(index == 0 && ret.length() < maxChar) ret.append('a');
|
||||||
if(index == 0) ret = new StringBuffer(""+c);
|
if(index == 0) ret = new StringBuffer(""+c);
|
||||||
else ret.setCharAt(index,c);
|
else ret.setCharAt(index,c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
//ret.setCharAt(index,'a');
|
//ret.setCharAt(index,'a');
|
||||||
ret.deleteCharAt(index);
|
ret.deleteCharAt(index);
|
||||||
index--;
|
index--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret.toString();
|
return ret.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increments the char with one after the swedish alfabet
|
* Increments the char with one after the swedish alfabet
|
||||||
*
|
*
|
||||||
* @param c is the char to increment
|
* @param c is the char to increment
|
||||||
* @return the incremented char in lowercase 0 if it reached the end
|
* @return the incremented char in lowercase 0 if it reached the end
|
||||||
*/
|
*/
|
||||||
public static char increment(char c){
|
public static char increment(char c){
|
||||||
switch(Character.toLowerCase(c)){
|
switch(Character.toLowerCase(c)){
|
||||||
case 'z': return (char)134;
|
case 'z': return (char)134;
|
||||||
case (char)134: return (char)132;
|
case (char)134: return (char)132;
|
||||||
case (char)132: return (char)148;
|
case (char)132: return (char)148;
|
||||||
}
|
}
|
||||||
c = (char)(Character.toLowerCase(c) + 1);
|
c = (char)(Character.toLowerCase(c) + 1);
|
||||||
if(isAlphabetic(c)){
|
if(isAlphabetic(c)){
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the char is a valid character in
|
* Checks if the char is a valid character in
|
||||||
* the Swedish alphabet
|
* the Swedish alphabet
|
||||||
*
|
*
|
||||||
* @param c is the char to check
|
* @param c is the char to check
|
||||||
* @return true if the char is a valid letter
|
* @return true if the char is a valid letter
|
||||||
*/
|
*/
|
||||||
public static boolean isAlphabetic(char c){
|
public static boolean isAlphabetic(char c){
|
||||||
switch(Character.toLowerCase(c)){
|
switch(Character.toLowerCase(c)){
|
||||||
case 'a':
|
case 'a':
|
||||||
case 'b':
|
case 'b':
|
||||||
case 'c':
|
case 'c':
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'e':
|
case 'e':
|
||||||
case 'f':
|
case 'f':
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'h':
|
case 'h':
|
||||||
case 'i':
|
case 'i':
|
||||||
case 'j':
|
case 'j':
|
||||||
case 'k':
|
case 'k':
|
||||||
case 'l':
|
case 'l':
|
||||||
case 'm':
|
case 'm':
|
||||||
case 'n':
|
case 'n':
|
||||||
case 'o':
|
case 'o':
|
||||||
case 'p':
|
case 'p':
|
||||||
case 'q':
|
case 'q':
|
||||||
case 'r':
|
case 'r':
|
||||||
case 's':
|
case 's':
|
||||||
case 't':
|
case 't':
|
||||||
case 'u':
|
case 'u':
|
||||||
case 'v':
|
case 'v':
|
||||||
case 'w':
|
case 'w':
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'y':
|
case 'y':
|
||||||
case 'z':
|
case 'z':
|
||||||
case (char)134:
|
case (char)134:
|
||||||
case (char)132:
|
case (char)132:
|
||||||
case (char)148:
|
case (char)148:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,285 +81,285 @@ public class FTPClient extends Thread{
|
||||||
return UNKNOWN;
|
return UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//***************************************************
|
//***************************************************
|
||||||
|
|
||||||
private FTPConnectionType connectionType;
|
private FTPConnectionType connectionType;
|
||||||
private BufferedReader in;
|
private BufferedReader in;
|
||||||
private Writer out;
|
private Writer out;
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
private long last_sent;
|
private long last_sent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a FTP connection and logs in
|
* Creates a FTP connection and logs in
|
||||||
*
|
*
|
||||||
* @param url the address to server
|
* @param url the address to server
|
||||||
* @param port port number
|
* @param port port number
|
||||||
* @param user login username
|
* @param user login username
|
||||||
* @param pass password
|
* @param pass password
|
||||||
* @param conn_type connection type
|
* @param conn_type connection type
|
||||||
*/
|
*/
|
||||||
public FTPClient(String url, int port, String user, String pass, FTPConnectionType conn_type) throws UnknownHostException, IOException, AccountException{
|
public FTPClient(String url, int port, String user, String pass, FTPConnectionType conn_type) throws UnknownHostException, IOException, AccountException{
|
||||||
socket = new Socket(url, port);
|
socket = new Socket(url, port);
|
||||||
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||||
out = new OutputStreamWriter(socket.getOutputStream());
|
out = new OutputStreamWriter(socket.getOutputStream());
|
||||||
connectionType = conn_type;
|
connectionType = conn_type;
|
||||||
|
|
||||||
readCommand();
|
readCommand();
|
||||||
sendCommand("USER "+user);
|
sendCommand("USER "+user);
|
||||||
sendNoReplyCommand("PASS "+pass);
|
sendNoReplyCommand("PASS "+pass);
|
||||||
String tmp = readCommand();
|
String tmp = readCommand();
|
||||||
if(parseReturnCode(tmp) == FTPReturnCode.LOGIN_NO){
|
if(parseReturnCode(tmp) == FTPReturnCode.LOGIN_NO){
|
||||||
close();
|
close();
|
||||||
throw new AccountException(tmp);
|
throw new AccountException(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
//**************************************************************************************
|
//**************************************************************************************
|
||||||
//********************************* Command channel ************************************
|
//********************************* Command channel ************************************
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends the given command to the server and returns a status integer
|
|
||||||
*
|
|
||||||
* @return last line received from the server
|
|
||||||
*/
|
|
||||||
private FTPReturnCode sendCommand(String cmd) throws IOException{
|
|
||||||
sendNoReplyCommand(cmd);
|
|
||||||
return parseReturnCode( readCommand( ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a command and don't cares about the reply
|
|
||||||
*/
|
|
||||||
private void sendNoReplyCommand(String cmd) throws IOException{
|
|
||||||
last_sent = System.currentTimeMillis();
|
|
||||||
out.append(cmd).append('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads from the command channel until there are nothing
|
* Sends the given command to the server and returns a status integer
|
||||||
* left to read and returns the last line
|
*
|
||||||
*
|
* @return last line received from the server
|
||||||
* @return last line received by the server
|
*/
|
||||||
*/
|
private FTPReturnCode sendCommand(String cmd) throws IOException{
|
||||||
private String readCommand() throws IOException{
|
sendNoReplyCommand(cmd);
|
||||||
String tmp = in.readLine();
|
return parseReturnCode( readCommand( ) );
|
||||||
while(!Character.isWhitespace(tmp.charAt(3))){
|
}
|
||||||
tmp = in.readLine();
|
|
||||||
|
/**
|
||||||
|
* Sends a command and don't cares about the reply
|
||||||
|
*/
|
||||||
|
private void sendNoReplyCommand(String cmd) throws IOException{
|
||||||
|
last_sent = System.currentTimeMillis();
|
||||||
|
out.append(cmd).append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads from the command channel until there are nothing
|
||||||
|
* left to read and returns the last line
|
||||||
|
*
|
||||||
|
* @return last line received by the server
|
||||||
|
*/
|
||||||
|
private String readCommand() throws IOException{
|
||||||
|
String tmp = in.readLine();
|
||||||
|
while(!Character.isWhitespace(tmp.charAt(3))){
|
||||||
|
tmp = in.readLine();
|
||||||
if(parseReturnCode(tmp).isError()) throw new IOException(tmp);
|
if(parseReturnCode(tmp).isError()) throw new IOException(tmp);
|
||||||
}
|
}
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the return line from the server and returns the status code
|
* Parses the return line from the server and returns the status code
|
||||||
*
|
*
|
||||||
* @param msg message String from the server
|
* @param msg message String from the server
|
||||||
* @return a status code response
|
* @return a status code response
|
||||||
*/
|
*/
|
||||||
private FTPReturnCode parseReturnCode(String msg){
|
private FTPReturnCode parseReturnCode(String msg){
|
||||||
return FTPReturnCode.fromCode(Integer.parseInt(msg.substring(0, 3)));
|
return FTPReturnCode.fromCode(Integer.parseInt(msg.substring(0, 3)));
|
||||||
}
|
}
|
||||||
|
|
||||||
//**************************************************************************************
|
//**************************************************************************************
|
||||||
//****************************** File system actions ************************************
|
//****************************** File system actions ************************************
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a LinkedList with names of all the files in the directory
|
* Returns a LinkedList with names of all the files in the directory
|
||||||
*
|
*
|
||||||
* @deprecated
|
* @deprecated
|
||||||
* @return List with filenames
|
* @return List with filenames
|
||||||
*/
|
*/
|
||||||
public String[] getFileList(String path) throws IOException{
|
public String[] getFileList(String path) throws IOException{
|
||||||
BufferedInputStream data_in = getDataInputStream();
|
BufferedInputStream data_in = getDataInputStream();
|
||||||
sendCommand("NLST "+path);
|
sendCommand("NLST "+path);
|
||||||
|
|
||||||
String data = new String(IOUtil.readContent(data_in));
|
|
||||||
|
|
||||||
data_in.close();
|
|
||||||
readCommand();
|
|
||||||
return data.split("[\n\r]");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns information about a file or directory
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
* @return a List of Strings with information
|
|
||||||
*/
|
|
||||||
public String getFileInfo(String path) throws IOException{
|
|
||||||
Pattern regex = Pattern.compile("\\s{1,}");
|
|
||||||
|
|
||||||
BufferedInputStream data_in = getDataInputStream();
|
|
||||||
sendCommand("LIST "+path);
|
|
||||||
|
|
||||||
String data = new String(IOUtil.readContent(data_in));
|
String data = new String(IOUtil.readContent(data_in));
|
||||||
|
|
||||||
data_in.close();
|
data_in.close();
|
||||||
readCommand();
|
readCommand();
|
||||||
return data;
|
return data.split("[\n\r]");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a file in the server with the given data
|
* Returns information about a file or directory
|
||||||
*
|
*
|
||||||
* @param path filepath
|
* @deprecated
|
||||||
* @param data data to put in the file
|
* @return a List of Strings with information
|
||||||
*/
|
*/
|
||||||
public void sendFile(String path, String data) throws IOException{
|
public String getFileInfo(String path) throws IOException{
|
||||||
BufferedOutputStream data_out = getDataOutputStream();
|
Pattern regex = Pattern.compile("\\s{1,}");
|
||||||
sendCommand("STOR "+path);
|
|
||||||
|
BufferedInputStream data_in = getDataInputStream();
|
||||||
|
sendCommand("LIST "+path);
|
||||||
|
|
||||||
|
String data = new String(IOUtil.readContent(data_in));
|
||||||
|
|
||||||
|
data_in.close();
|
||||||
|
readCommand();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a file in the server with the given data
|
||||||
|
*
|
||||||
|
* @param path filepath
|
||||||
|
* @param data data to put in the file
|
||||||
|
*/
|
||||||
|
public void sendFile(String path, String data) throws IOException{
|
||||||
|
BufferedOutputStream data_out = getDataOutputStream();
|
||||||
|
sendCommand("STOR "+path);
|
||||||
|
|
||||||
byte[] byte_data = data.getBytes();
|
byte[] byte_data = data.getBytes();
|
||||||
data_out.write(byte_data, 0, byte_data.length);
|
data_out.write(byte_data, 0, byte_data.length);
|
||||||
data_out.close();
|
data_out.close();
|
||||||
|
|
||||||
readCommand();
|
readCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a directory in the server
|
* Creates a directory in the server
|
||||||
*
|
*
|
||||||
* @param path The path to the directory
|
* @param path The path to the directory
|
||||||
*/
|
*/
|
||||||
public boolean createDir(String path) throws IOException{
|
public boolean createDir(String path) throws IOException{
|
||||||
if(sendCommand("MKD "+path) == FTPReturnCode.PATH_CREATED)
|
if(sendCommand("MKD "+path) == FTPReturnCode.PATH_CREATED)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a InputStream for a file on the server
|
* Returns a InputStream for a file on the server
|
||||||
* WARNING: you must run readCommand(); after you close the stream
|
* WARNING: you must run readCommand(); after you close the stream
|
||||||
*
|
*
|
||||||
* @return a stream with file data
|
* @return a stream with file data
|
||||||
*/
|
*/
|
||||||
private BufferedInputStream getFileInputStream(String path) throws IOException{
|
private BufferedInputStream getFileInputStream(String path) throws IOException{
|
||||||
BufferedInputStream input = getDataInputStream();
|
BufferedInputStream input = getDataInputStream();
|
||||||
sendCommand("RETR "+path);
|
sendCommand("RETR "+path);
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Download a file from the server to a local file
|
* Download a file from the server to a local file
|
||||||
*
|
*
|
||||||
* @param source source file on the server
|
* @param source source file on the server
|
||||||
* @param destination local destination file
|
* @param destination local destination file
|
||||||
*/
|
*/
|
||||||
public void getFile(String source, String destination) throws IOException{
|
public void getFile(String source, String destination) throws IOException{
|
||||||
BufferedInputStream ext_file_in = getFileInputStream(source);
|
BufferedInputStream ext_file_in = getFileInputStream(source);
|
||||||
BufferedOutputStream local_file_out = new BufferedOutputStream(new FileOutputStream(new File(destination)));
|
BufferedOutputStream local_file_out = new BufferedOutputStream(new FileOutputStream(new File(destination)));
|
||||||
|
|
||||||
IOUtil.copyStream(ext_file_in, local_file_out);
|
IOUtil.copyStream(ext_file_in, local_file_out);
|
||||||
readCommand();
|
readCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a file from the FTP server
|
* Remove a file from the FTP server
|
||||||
*
|
*
|
||||||
* @return true if the command was successful, false otherwise
|
* @return true if the command was successful, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean removeFile(String path) throws IOException{
|
public boolean removeFile(String path) throws IOException{
|
||||||
if(sendCommand("DELE "+path) == FTPReturnCode.FILE_ACTION_OK)
|
if(sendCommand("DELE "+path) == FTPReturnCode.FILE_ACTION_OK)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a directory from the FTP server
|
* Removes a directory from the FTP server
|
||||||
*
|
*
|
||||||
* @return True if the command was successful or false otherwise
|
* @return True if the command was successful or false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean removeDir(String path) throws IOException{
|
public boolean removeDir(String path) throws IOException{
|
||||||
if(sendCommand("RMD "+path) == FTPReturnCode.FILE_ACTION_OK)
|
if(sendCommand("RMD "+path) == FTPReturnCode.FILE_ACTION_OK)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//**************************************************************************************
|
//**************************************************************************************
|
||||||
//******************************** Data Connection *************************************
|
//******************************** Data Connection *************************************
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start a data connection to the server.
|
* Start a data connection to the server.
|
||||||
*
|
*
|
||||||
* @return a PrintStream for the channel
|
* @return a PrintStream for the channel
|
||||||
*/
|
*/
|
||||||
public BufferedOutputStream getDataOutputStream() throws IOException{
|
public BufferedOutputStream getDataOutputStream() throws IOException{
|
||||||
if(connectionType == FTPConnectionType.PASSIVE){ // Passive Mode
|
if(connectionType == FTPConnectionType.PASSIVE){ // Passive Mode
|
||||||
int port = setPassiveMode();
|
int port = setPassiveMode();
|
||||||
Socket data_socket = new Socket(socket.getInetAddress().getHostAddress(), port);
|
Socket data_socket = new Socket(socket.getInetAddress().getHostAddress(), port);
|
||||||
return new BufferedOutputStream(data_socket.getOutputStream());
|
return new BufferedOutputStream(data_socket.getOutputStream());
|
||||||
}
|
}
|
||||||
else{ // Active Mode
|
else{ // Active Mode
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start a data connection to the server.
|
* Start a data connection to the server.
|
||||||
*
|
*
|
||||||
* @return a BufferedReader for the data channel
|
* @return a BufferedReader for the data channel
|
||||||
*/
|
*/
|
||||||
public BufferedInputStream getDataInputStream() throws IOException{
|
public BufferedInputStream getDataInputStream() throws IOException{
|
||||||
if(connectionType == FTPConnectionType.PASSIVE){ // Passive Mode
|
if(connectionType == FTPConnectionType.PASSIVE){ // Passive Mode
|
||||||
int port = setPassiveMode();
|
int port = setPassiveMode();
|
||||||
Socket data_socket = new Socket(socket.getInetAddress().getHostAddress(), port);
|
Socket data_socket = new Socket(socket.getInetAddress().getHostAddress(), port);
|
||||||
return new BufferedInputStream(data_socket.getInputStream());
|
return new BufferedInputStream(data_socket.getInputStream());
|
||||||
}
|
}
|
||||||
else{ // Active Mode
|
else{ // Active Mode
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets Passive mode to the server
|
* Sets Passive mode to the server
|
||||||
*
|
*
|
||||||
* @return a port number for data channel
|
* @return a port number for data channel
|
||||||
*/
|
*/
|
||||||
private int setPassiveMode() throws IOException{
|
private int setPassiveMode() throws IOException{
|
||||||
sendNoReplyCommand("PASV");
|
sendNoReplyCommand("PASV");
|
||||||
String ret_msg = readCommand();
|
String ret_msg = readCommand();
|
||||||
if(parseReturnCode(ret_msg) != FTPReturnCode.ENTERING_PASSIVE){
|
if(parseReturnCode(ret_msg) != FTPReturnCode.ENTERING_PASSIVE){
|
||||||
throw new IOException("Passive mode rejected by server: "+ret_msg);
|
throw new IOException("Passive mode rejected by server: "+ret_msg);
|
||||||
}
|
}
|
||||||
ret_msg = ret_msg.substring(ret_msg.indexOf('(')+1, ret_msg.indexOf(')'));
|
ret_msg = ret_msg.substring(ret_msg.indexOf('(')+1, ret_msg.indexOf(')'));
|
||||||
String[] tmpArray = ret_msg.split("[,]");
|
String[] tmpArray = ret_msg.split("[,]");
|
||||||
|
|
||||||
if(tmpArray.length <= 1)
|
|
||||||
return Integer.parseInt(tmpArray[0]);
|
|
||||||
else
|
|
||||||
return Integer.parseInt(tmpArray[4])*256 + Integer.parseInt(tmpArray[5]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//**************************************************************************************
|
|
||||||
//**************************************************************************************
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if(tmpArray.length <= 1)
|
||||||
* Close the FTP connection
|
return Integer.parseInt(tmpArray[0]);
|
||||||
*/
|
else
|
||||||
public void close() throws IOException{
|
return Integer.parseInt(tmpArray[4])*256 + Integer.parseInt(tmpArray[5]);
|
||||||
sendCommand("QUIT");
|
}
|
||||||
in.close();
|
|
||||||
out.close();
|
//**************************************************************************************
|
||||||
socket.close();
|
//**************************************************************************************
|
||||||
this.interrupt();
|
|
||||||
}
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
public void close() throws IOException{
|
||||||
|
sendCommand("QUIT");
|
||||||
|
in.close();
|
||||||
|
out.close();
|
||||||
|
socket.close();
|
||||||
|
this.interrupt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,299 +42,299 @@ import java.net.UnknownHostException;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class POP3Client {
|
public class POP3Client {
|
||||||
public static boolean DEBUG = false;
|
public static boolean DEBUG = false;
|
||||||
public static final int POP3_PORT = 110;
|
public static final int POP3_PORT = 110;
|
||||||
public static final int POP3_SSL_PORT = 995;
|
public static final int POP3_SSL_PORT = 995;
|
||||||
|
|
||||||
private BufferedReader in;
|
private BufferedReader in;
|
||||||
private PrintStream out;
|
private PrintStream out;
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to a POP3 server without username
|
* Connect to a POP3 server without username
|
||||||
*
|
*
|
||||||
* @param host The hostname of the server
|
* @param host The hostname of the server
|
||||||
* @throws UnknownHostException
|
* @throws UnknownHostException
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public POP3Client(String host) throws UnknownHostException, IOException{
|
public POP3Client(String host) throws UnknownHostException, IOException{
|
||||||
this(host, POP3_PORT, null, null, false);
|
this(host, POP3_PORT, null, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect to a POP3 server with username and password
|
|
||||||
*
|
|
||||||
* @param host The hostname of the server
|
|
||||||
* @param user The username
|
|
||||||
* @param password the password
|
|
||||||
* @throws UnknownHostException
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public POP3Client(String host, String user, String password) throws UnknownHostException, IOException{
|
|
||||||
this(host, POP3_PORT, user, password, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connects to a POP3 server with username and password and SSL
|
|
||||||
*
|
|
||||||
* @param host The hostname of the server
|
|
||||||
* @param user The username
|
|
||||||
* @param password the password
|
|
||||||
* @param ssl If SSL should be used
|
|
||||||
* @throws UnknownHostException
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public POP3Client(String host, String user, String password, boolean ssl) throws UnknownHostException, IOException{
|
|
||||||
this(host, (ssl ? POP3_SSL_PORT : POP3_PORT), user, password, ssl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connects to a POP3 server with username and password and
|
* Connect to a POP3 server with username and password
|
||||||
* SSL and with costume port.
|
*
|
||||||
*
|
* @param host The hostname of the server
|
||||||
* @param host The hostname of the server
|
* @param user The username
|
||||||
* @param port The port number to connect to on the server
|
* @param password the password
|
||||||
* @param user The username
|
* @throws UnknownHostException
|
||||||
* @param password the password
|
* @throws IOException
|
||||||
* @param ssl If SSL should be used
|
*/
|
||||||
* @throws UnknownHostException
|
public POP3Client(String host, String user, String password) throws UnknownHostException, IOException{
|
||||||
* @throws IOException
|
this(host, POP3_PORT, user, password, false);
|
||||||
*/
|
}
|
||||||
public POP3Client(String host, int port, String user, String password, boolean ssl) throws UnknownHostException, IOException{
|
|
||||||
if(ssl) connectSSL(host, port);
|
|
||||||
else connect(host, port);
|
|
||||||
|
|
||||||
if(user != null){
|
|
||||||
login(user, password);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connects to the server
|
|
||||||
*
|
|
||||||
* @param host The hostname of the server
|
|
||||||
* @param port The port to connect to on the server
|
|
||||||
* @throws UnknownHostException
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private void connect(String host, int port) throws UnknownHostException, IOException{
|
|
||||||
socket = new Socket(host, port);
|
|
||||||
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
|
||||||
out = new PrintStream(socket.getOutputStream());
|
|
||||||
|
|
||||||
readCommand(true);
|
/**
|
||||||
}
|
* Connects to a POP3 server with username and password and SSL
|
||||||
|
*
|
||||||
/**
|
* @param host The hostname of the server
|
||||||
* Connects to the server with SSL.
|
* @param user The username
|
||||||
* http://www.exampledepot.com/egs/javax.net.ssl/Client.html
|
* @param password the password
|
||||||
*
|
* @param ssl If SSL should be used
|
||||||
* @param host The hostname of the server
|
* @throws UnknownHostException
|
||||||
* @param port The port to connect to on the server
|
* @throws IOException
|
||||||
* @throws UnknownHostException
|
*/
|
||||||
* @throws IOException
|
public POP3Client(String host, String user, String password, boolean ssl) throws UnknownHostException, IOException{
|
||||||
*/
|
this(host, (ssl ? POP3_SSL_PORT : POP3_PORT), user, password, ssl);
|
||||||
private void connectSSL(String host, int port) throws UnknownHostException, IOException{
|
}
|
||||||
SocketFactory socketFactory = SSLSocketFactory.getDefault();
|
|
||||||
socket = socketFactory.createSocket(host, port);
|
/**
|
||||||
|
* Connects to a POP3 server with username and password and
|
||||||
|
* SSL and with costume port.
|
||||||
|
*
|
||||||
|
* @param host The hostname of the server
|
||||||
|
* @param port The port number to connect to on the server
|
||||||
|
* @param user The username
|
||||||
|
* @param password the password
|
||||||
|
* @param ssl If SSL should be used
|
||||||
|
* @throws UnknownHostException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public POP3Client(String host, int port, String user, String password, boolean ssl) throws UnknownHostException, IOException{
|
||||||
|
if(ssl) connectSSL(host, port);
|
||||||
|
else connect(host, port);
|
||||||
|
|
||||||
|
if(user != null){
|
||||||
|
login(user, password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connects to the server
|
||||||
|
*
|
||||||
|
* @param host The hostname of the server
|
||||||
|
* @param port The port to connect to on the server
|
||||||
|
* @throws UnknownHostException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void connect(String host, int port) throws UnknownHostException, IOException{
|
||||||
|
socket = new Socket(host, port);
|
||||||
|
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||||
|
out = new PrintStream(socket.getOutputStream());
|
||||||
|
|
||||||
|
readCommand(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connects to the server with SSL.
|
||||||
|
* http://www.exampledepot.com/egs/javax.net.ssl/Client.html
|
||||||
|
*
|
||||||
|
* @param host The hostname of the server
|
||||||
|
* @param port The port to connect to on the server
|
||||||
|
* @throws UnknownHostException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void connectSSL(String host, int port) throws UnknownHostException, IOException{
|
||||||
|
SocketFactory socketFactory = SSLSocketFactory.getDefault();
|
||||||
|
socket = socketFactory.createSocket(host, port);
|
||||||
|
|
||||||
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||||
out = new PrintStream(socket.getOutputStream());
|
out = new PrintStream(socket.getOutputStream());
|
||||||
|
|
||||||
readCommand(DEBUG);
|
readCommand(DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs in to the POP3 server with the username and password if the password is set
|
* Logs in to the POP3 server with the username and password if the password is set
|
||||||
*
|
*
|
||||||
* @param user The user name
|
* @param user The user name
|
||||||
* @param password The password or null if no password is required
|
* @param password The password or null if no password is required
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private void login(String user, String password) throws IOException{
|
private void login(String user, String password) throws IOException{
|
||||||
sendCommand("USER "+user);
|
sendCommand("USER "+user);
|
||||||
if(password != null){
|
if(password != null){
|
||||||
sendNoReplyCommand("PASS "+password, false);
|
sendNoReplyCommand("PASS "+password, false);
|
||||||
if(DEBUG)System.out.println("PASS ***");
|
if(DEBUG)System.out.println("PASS ***");
|
||||||
readCommand(DEBUG);
|
readCommand(DEBUG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of messages that is on the server
|
* Returns the number of messages that is on the server
|
||||||
*
|
*
|
||||||
* @return Message count
|
* @return Message count
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public int getMessageCount() throws IOException{
|
public int getMessageCount() throws IOException{
|
||||||
String msg = sendCommand("STAT", DEBUG);
|
String msg = sendCommand("STAT", DEBUG);
|
||||||
return Integer.parseInt(
|
return Integer.parseInt(
|
||||||
msg.substring(
|
msg.substring(
|
||||||
msg.indexOf(' ')+1,
|
msg.indexOf(' ')+1,
|
||||||
msg.indexOf(' ', msg.indexOf(' ')+1)));
|
msg.indexOf(' ', msg.indexOf(' ')+1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the message with the given id.
|
* Retrieves the message with the given id.
|
||||||
*
|
*
|
||||||
* @param id The id of the message to get
|
* @param id The id of the message to get
|
||||||
* @return The message
|
* @return The message
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public String getMessage(int id) throws IOException{
|
public String getMessage(int id) throws IOException{
|
||||||
sendCommand("RETR "+id);
|
sendCommand("RETR "+id);
|
||||||
return readMultipleLines(DEBUG);
|
return readMultipleLines(DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the title of the message
|
* Returns the title of the message
|
||||||
*
|
*
|
||||||
* @param id The message id
|
* @param id The message id
|
||||||
* @return The title
|
* @return The title
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public String getMessageTitle(int id) throws IOException{
|
public String getMessageTitle(int id) throws IOException{
|
||||||
String tmp = getMessageHeader(id);
|
String tmp = getMessageHeader(id);
|
||||||
String tmp2 = tmp.toLowerCase();
|
String tmp2 = tmp.toLowerCase();
|
||||||
if(tmp2.contains("subject:")){
|
if(tmp2.contains("subject:")){
|
||||||
return tmp.substring(
|
return tmp.substring(
|
||||||
tmp2.indexOf("subject:")+8,
|
tmp2.indexOf("subject:")+8,
|
||||||
tmp2.indexOf('\n',
|
tmp2.indexOf('\n',
|
||||||
tmp2.indexOf("subject:")));
|
tmp2.indexOf("subject:")));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the header of the given message id.
|
* Returns the header of the given message id.
|
||||||
*
|
*
|
||||||
* @param id The id of the message to get
|
* @param id The id of the message to get
|
||||||
* @return The message
|
* @return The message
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public String getMessageHeader(int id) throws IOException{
|
public String getMessageHeader(int id) throws IOException{
|
||||||
sendCommand("TOP "+id+" 0");
|
sendCommand("TOP "+id+" 0");
|
||||||
return readMultipleLines(DEBUG);
|
return readMultipleLines(DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes the message with the given id
|
* Deletes the message with the given id
|
||||||
*
|
*
|
||||||
* @param id The id of the message to be deleted
|
* @param id The id of the message to be deleted
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public void delete(int id) throws IOException{
|
public void delete(int id) throws IOException{
|
||||||
sendCommand("DELE "+id);
|
sendCommand("DELE "+id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//*********************** IO Stuff *********************************************
|
//*********************** IO Stuff *********************************************
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 if the cmd fails
|
|
||||||
*/
|
|
||||||
private boolean sendCommand(String cmd) throws IOException{
|
|
||||||
return parseReturnCode(sendCommand(cmd, DEBUG));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends the given line to the server and returns the last line
|
* Sends the given line to the server and returns a status integer
|
||||||
*
|
*
|
||||||
* @param cmd The command to send
|
* @param cmd The command to send
|
||||||
* @param print To print out the received lines
|
* @return The return code from the server
|
||||||
* @return Last String line from the server
|
* @throws IOException if the cmd fails
|
||||||
* @throws IOException
|
*/
|
||||||
*/
|
private boolean sendCommand(String cmd) throws IOException{
|
||||||
private String sendCommand(String cmd, boolean print) throws IOException{
|
return parseReturnCode(sendCommand(cmd, DEBUG));
|
||||||
sendNoReplyCommand(cmd, print);
|
}
|
||||||
return readCommand(print);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a given command and don't cares about the reply
|
* Sends the given line to the server and returns the last line
|
||||||
*
|
*
|
||||||
* @param cmd The command
|
* @param cmd The command to send
|
||||||
* @param print If it should print to System.out
|
* @param print To print out the received lines
|
||||||
* @throws IOException
|
* @return Last String line from the server
|
||||||
*/
|
* @throws IOException
|
||||||
private void sendNoReplyCommand(String cmd, boolean print) throws IOException{
|
*/
|
||||||
out.println(cmd);
|
private String sendCommand(String cmd, boolean print) throws IOException{
|
||||||
if(print)System.out.println(cmd);
|
sendNoReplyCommand(cmd, print);
|
||||||
}
|
return readCommand(print);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads on line from the command channel
|
* Sends a given command and don't cares about the reply
|
||||||
*
|
*
|
||||||
* @param print If the method should print the input line
|
* @param cmd The command
|
||||||
* @return The input line
|
* @param print If it should print to System.out
|
||||||
* @throws IOException if the server returns a error code
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private String readCommand(boolean print) throws IOException{
|
private void sendNoReplyCommand(String cmd, boolean print) throws IOException{
|
||||||
String tmp = in.readLine();
|
out.println(cmd);
|
||||||
if(print)System.out.println(tmp);
|
if(print)System.out.println(cmd);
|
||||||
if( !parseReturnCode(tmp) ) throw new IOException(tmp);
|
}
|
||||||
|
|
||||||
return tmp;
|
/**
|
||||||
}
|
* Reads on line from the command channel
|
||||||
|
*
|
||||||
|
* @param print If the method should print the input line
|
||||||
|
* @return The input line
|
||||||
|
* @throws IOException if the server returns a error code
|
||||||
|
*/
|
||||||
|
private String readCommand(boolean print) throws IOException{
|
||||||
|
String tmp = in.readLine();
|
||||||
|
if(print)System.out.println(tmp);
|
||||||
|
if( !parseReturnCode(tmp) ) throw new IOException(tmp);
|
||||||
|
|
||||||
/**
|
return tmp;
|
||||||
* Reads from the server until there are a line with
|
}
|
||||||
* only one '.'
|
|
||||||
*
|
/**
|
||||||
* @param print To print out the received lines
|
* Reads from the server until there are a line with
|
||||||
* @return String with the text
|
* only one '.'
|
||||||
* @throws IOException
|
*
|
||||||
*/
|
* @param print To print out the received lines
|
||||||
private String readMultipleLines(boolean print) throws IOException{
|
* @return String with the text
|
||||||
StringBuffer msg = new StringBuffer();
|
* @throws IOException
|
||||||
String tmp = in.readLine();
|
*/
|
||||||
while(!tmp.equals(".")){
|
private String readMultipleLines(boolean print) throws IOException{
|
||||||
msg.append(tmp);
|
StringBuffer msg = new StringBuffer();
|
||||||
msg.append('\n');
|
String tmp = in.readLine();
|
||||||
tmp = in.readLine();
|
while(!tmp.equals(".")){
|
||||||
if(print)System.out.println(tmp);
|
msg.append(tmp);
|
||||||
}
|
msg.append('\n');
|
||||||
|
tmp = in.readLine();
|
||||||
return msg.toString();
|
if(print)System.out.println(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return msg.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the return line from the server and returns the status code
|
||||||
|
*
|
||||||
|
* @param msg The message from the server
|
||||||
|
* @return Returns true if return code is OK false if it is ERR
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private boolean parseReturnCode(String msg){
|
||||||
|
int endpos = (msg.indexOf(' ')<0 ? msg.length() : msg.indexOf(' '));
|
||||||
|
return msg.substring(0, endpos).equals("+OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the return line from the server and returns the status code
|
|
||||||
*
|
|
||||||
* @param msg The message from the server
|
|
||||||
* @return Returns true if return code is OK false if it is ERR
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private boolean parseReturnCode(String msg){
|
|
||||||
int endpos = (msg.indexOf(' ')<0 ? msg.length() : msg.indexOf(' '));
|
|
||||||
return msg.substring(0, endpos).equals("+OK");
|
|
||||||
}
|
|
||||||
|
|
||||||
//*********************************************************************************
|
//*********************************************************************************
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All the delete marked messages are unmarkt
|
* All the delete marked messages are unmarkt
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public void reset() throws IOException{
|
public void reset() throws IOException{
|
||||||
sendCommand("RSET", DEBUG);
|
sendCommand("RSET", DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All the changes(DELETE) are performed and then the connection is closed
|
* All the changes(DELETE) are performed and then the connection is closed
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public void close() throws IOException{
|
public void close() throws IOException{
|
||||||
sendCommand("QUIT", DEBUG);
|
sendCommand("QUIT", DEBUG);
|
||||||
in.close();
|
in.close();
|
||||||
out.close();
|
out.close();
|
||||||
socket.close();
|
socket.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,58 +40,58 @@ import java.net.MulticastSocket;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ServerFind extends Thread {
|
public class ServerFind extends Thread {
|
||||||
public String broadcastAddress = "230.0.0.1";
|
public String broadcastAddress = "230.0.0.1";
|
||||||
|
|
||||||
private InetAddress group;
|
|
||||||
private MulticastSocket Msocket;
|
|
||||||
|
|
||||||
private boolean avsluta;
|
private InetAddress group;
|
||||||
private int port;
|
private MulticastSocket Msocket;
|
||||||
|
|
||||||
/**
|
private boolean avsluta;
|
||||||
* Creates a ServerFind Thread an the specified port
|
private int 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();
|
/**
|
||||||
}
|
* 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);
|
||||||
|
|
||||||
public void run (){
|
start();
|
||||||
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());
|
public void run (){
|
||||||
packet = new DatagramPacket(buf, buf.length, group, port);
|
byte[] buf = new byte[256];
|
||||||
lan_socket.send(packet);
|
DatagramPacket packet;
|
||||||
lan_socket.close();
|
DatagramSocket lan_socket = null;
|
||||||
} catch (Exception e) {
|
|
||||||
MultiPrintStream.out.println("Error Establishing ServerFind Connection!!!\n" + e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
while (!avsluta){
|
||||||
* Closes the broadcast socket
|
try {
|
||||||
*/
|
packet = new DatagramPacket(buf, buf.length);
|
||||||
public void close(){
|
Msocket.receive(packet);
|
||||||
avsluta = true;
|
|
||||||
Msocket.close();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,38 +37,38 @@ import java.net.MulticastSocket;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ServerFindClient{
|
public class ServerFindClient{
|
||||||
public String broadcastAddress = "230.0.0.1";
|
public String broadcastAddress = "230.0.0.1";
|
||||||
|
|
||||||
private int port;
|
|
||||||
|
|
||||||
/**
|
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);
|
* Creates a ServerFind Client
|
||||||
lan_socket.send(packet);
|
*
|
||||||
|
* @param port The port to contact the server on
|
||||||
packet = new DatagramPacket(buf, buf.length);
|
*/
|
||||||
Msocket.receive(packet);
|
public ServerFindClient(int port){
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
return packet.getAddress();
|
/**
|
||||||
}
|
* 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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,53 +41,53 @@ import java.util.HashMap;
|
||||||
*/
|
*/
|
||||||
public class HttpClient implements AutoCloseable{
|
public class HttpClient implements AutoCloseable{
|
||||||
public static enum HttpRequestType{
|
public static enum HttpRequestType{
|
||||||
GET, POST
|
GET, POST
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request variables
|
// Request variables
|
||||||
private HttpURL url;
|
private HttpURL url;
|
||||||
private HttpRequestType type;
|
private HttpRequestType type;
|
||||||
private HashMap<String,String> headers;
|
private HashMap<String,String> headers;
|
||||||
private HashMap<String,String> cookies;
|
private HashMap<String,String> cookies;
|
||||||
private String data;
|
private String data;
|
||||||
|
|
||||||
// Response variables
|
// Response variables
|
||||||
private HttpHeaderParser rspHeader;
|
private HttpHeaderParser rspHeader;
|
||||||
private InputStream rspStream;
|
private InputStream rspStream;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public HttpClient(HttpRequestType type){
|
public HttpClient(HttpRequestType type){
|
||||||
this.type = type;
|
this.type = type;
|
||||||
headers = new HashMap<String,String>();
|
headers = new HashMap<String,String>();
|
||||||
cookies = new HashMap<String,String>();
|
cookies = new HashMap<String,String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setURL( URL url){
|
public void setURL( URL url){
|
||||||
this.url = new HttpURL( url );
|
this.url = new HttpURL( url );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a parameter to the request
|
* Adds a parameter to the request
|
||||||
*/
|
*/
|
||||||
public void setParameter( String key, String value ){
|
public void setParameter( String key, String value ){
|
||||||
url.setParameter(key, value);
|
url.setParameter(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a cookie to the request
|
* Adds a cookie to the request
|
||||||
*/
|
*/
|
||||||
public void setCookie( String key, String value ){
|
public void setCookie( String key, String value ){
|
||||||
cookies.put(key, value);
|
cookies.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a header value to the request
|
* Adds a header value to the request
|
||||||
*/
|
*/
|
||||||
public void setHeader( String key, String value ){
|
public void setHeader( String key, String value ){
|
||||||
headers.put(key, value);
|
headers.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the content data that will be included in the request.
|
* Sets the content data that will be included in the request.
|
||||||
|
|
@ -101,38 +101,38 @@ public class HttpClient implements AutoCloseable{
|
||||||
* Will send a HTTP request to the target host.
|
* Will send a HTTP request to the target host.
|
||||||
* NOTE: any previous request connections will be closed
|
* NOTE: any previous request connections will be closed
|
||||||
*/
|
*/
|
||||||
public HttpHeaderParser send() throws IOException{
|
public HttpHeaderParser send() throws IOException{
|
||||||
Socket conn = new Socket( url.getHost(), url.getPort());
|
Socket conn = new Socket( url.getHost(), url.getPort());
|
||||||
|
|
||||||
// Request
|
// Request
|
||||||
HttpPrintStream request = new HttpPrintStream( conn.getOutputStream(), HttpMessageType.REQUEST );
|
HttpPrintStream request = new HttpPrintStream( conn.getOutputStream(), HttpMessageType.REQUEST );
|
||||||
request.setRequestType( type.toString() );
|
request.setRequestType( type.toString() );
|
||||||
request.setRequestURL( url.getHttpURL() );
|
request.setRequestURL( url.getHttpURL() );
|
||||||
request.setHeaders( headers );
|
request.setHeaders( headers );
|
||||||
request.setCookies( cookies );
|
request.setCookies( cookies );
|
||||||
|
|
||||||
if( type == HttpRequestType.POST ){
|
if( type == HttpRequestType.POST ){
|
||||||
String postData = null;
|
String postData = null;
|
||||||
if(data != null)
|
if(data != null)
|
||||||
postData = data;
|
postData = data;
|
||||||
else
|
else
|
||||||
postData = url.getParameterString();
|
postData = url.getParameterString();
|
||||||
request.setHeader("Content-Length", ""+postData.length());
|
request.setHeader("Content-Length", ""+postData.length());
|
||||||
request.println();
|
request.println();
|
||||||
request.print( postData );
|
request.print( postData );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
request.println();
|
request.println();
|
||||||
request.close();
|
request.close();
|
||||||
|
|
||||||
// Response
|
// Response
|
||||||
if(rspHeader != null || rspStream != null) // Close previous request
|
if(rspHeader != null || rspStream != null) // Close previous request
|
||||||
this.close();
|
this.close();
|
||||||
rspStream = new BufferedInputStream(conn.getInputStream());
|
rspStream = new BufferedInputStream(conn.getInputStream());
|
||||||
rspHeader = new HttpHeaderParser(rspStream);
|
rspHeader = new HttpHeaderParser(rspStream);
|
||||||
|
|
||||||
return rspHeader;
|
return rspHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpHeaderParser getResponseHeader(){
|
public HttpHeaderParser getResponseHeader(){
|
||||||
return rspHeader;
|
return rspHeader;
|
||||||
|
|
|
||||||
|
|
@ -31,18 +31,18 @@ import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
public class HttpHeader {
|
public class HttpHeader {
|
||||||
// HTTP info
|
// HTTP info
|
||||||
private boolean request = true;
|
private boolean request = true;
|
||||||
private String type = "GET";
|
private String type = "GET";
|
||||||
private String url = "/";
|
private String url = "/";
|
||||||
private HashMap<String, String> urlAttributes;
|
private HashMap<String, String> urlAttributes;
|
||||||
private float version = 1.0f;
|
private float version = 1.0f;
|
||||||
private int httpCode = 200;
|
private int httpCode = 200;
|
||||||
private InputStream in;
|
private InputStream in;
|
||||||
|
|
||||||
// Parameters
|
// Parameters
|
||||||
private HashMap<String, String> headers;
|
private HashMap<String, String> headers;
|
||||||
private HashMap<String, String> cookies;
|
private HashMap<String, String> cookies;
|
||||||
|
|
||||||
|
|
||||||
public HttpHeader(){
|
public HttpHeader(){
|
||||||
|
|
@ -52,58 +52,58 @@ public class HttpHeader {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this header represents a server response
|
* @return true if this header represents a server response
|
||||||
*/
|
|
||||||
public boolean isResponse(){
|
|
||||||
return !request;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @return true if this header represents a client request
|
|
||||||
*/
|
*/
|
||||||
public boolean isRequest(){
|
public boolean isResponse(){
|
||||||
return request;
|
return !request;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @return the HTTP message type( ex. GET,POST...)
|
* @return true if this header represents a client request
|
||||||
*/
|
|
||||||
public String getRequestType(){
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @return the HTTP version of this header
|
|
||||||
*/
|
|
||||||
public float getHTTPVersion(){
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @return the HTTP Return Code from a Server
|
|
||||||
*/
|
|
||||||
public int getHTTPCode(){
|
|
||||||
return httpCode;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @return the URL that the client sent the server
|
|
||||||
*/
|
|
||||||
public String getRequestURL(){
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @return parses out the page name from the request url and returns it.
|
|
||||||
*/
|
*/
|
||||||
public String getRequestPage() {
|
public boolean isRequest(){
|
||||||
if (url != null){
|
return request;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return the HTTP message type( ex. GET,POST...)
|
||||||
|
*/
|
||||||
|
public String getRequestType(){
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return the HTTP version of this header
|
||||||
|
*/
|
||||||
|
public float getHTTPVersion(){
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return the HTTP Return Code from a Server
|
||||||
|
*/
|
||||||
|
public int getHTTPCode(){
|
||||||
|
return httpCode;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return the URL that the client sent the server
|
||||||
|
*/
|
||||||
|
public String getRequestURL(){
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return parses out the page name from the request url and returns it.
|
||||||
|
*/
|
||||||
|
public String getRequestPage() {
|
||||||
|
if (url != null){
|
||||||
int start = 0;
|
int start = 0;
|
||||||
if (url.charAt(0) == '/')
|
if (url.charAt(0) == '/')
|
||||||
start = 1;
|
start = 1;
|
||||||
int end = url.indexOf('?');
|
int end = url.indexOf('?');
|
||||||
if (end < 0)
|
if (end < 0)
|
||||||
end = url.length();
|
end = url.length();
|
||||||
|
|
||||||
return url.substring(start, end);
|
return url.substring(start, end);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @return a Iterator with all defined url keys
|
* @return a Iterator with all defined url keys
|
||||||
*/
|
*/
|
||||||
|
|
@ -111,35 +111,35 @@ public class HttpHeader {
|
||||||
return urlAttributes.keySet().iterator();
|
return urlAttributes.keySet().iterator();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @return the URL attribute value of the given name. null if there is no such attribute
|
* @return the URL attribute value of the given name. null if there is no such attribute
|
||||||
*/
|
*/
|
||||||
public String getURLAttribute(String name){
|
public String getURLAttribute(String name){
|
||||||
return urlAttributes.get( name );
|
return urlAttributes.get( name );
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @return a Iterator with all defined headers
|
* @return a Iterator with all defined headers
|
||||||
*/
|
*/
|
||||||
public Iterator<String> getHeaderKeys(){
|
public Iterator<String> getHeaderKeys(){
|
||||||
return headers.keySet().iterator();
|
return headers.keySet().iterator();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @return the HTTP attribute value of the given name. null if there is no such attribute
|
* @return the HTTP attribute value of the given name. null if there is no such attribute
|
||||||
*/
|
*/
|
||||||
public String getHeader(String name){
|
public String getHeader(String name){
|
||||||
return headers.get( name.toUpperCase() );
|
return headers.get( name.toUpperCase() );
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @return a Iterator with all defined cookies
|
* @return a Iterator with all defined cookies
|
||||||
*/
|
*/
|
||||||
public Iterator<String> getCookieKeys(){
|
public Iterator<String> getCookieKeys(){
|
||||||
return cookies.keySet().iterator();
|
return cookies.keySet().iterator();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @return the cookie value of the given name. null if there is no such attribute.
|
* @return the cookie value of the given name. null if there is no such attribute.
|
||||||
*/
|
*/
|
||||||
public String getCookie(String name){
|
public String getCookie(String name){
|
||||||
return cookies.get( name );
|
return cookies.get( name );
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @return a Reader that contains the body of the http request.
|
* @return a Reader that contains the body of the http request.
|
||||||
*/
|
*/
|
||||||
|
|
@ -148,62 +148,62 @@ public class HttpHeader {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setIsRequest(boolean request) { this.request = request; }
|
public void setIsRequest(boolean request) { this.request = request; }
|
||||||
public void setRequestType(String type){
|
public void setRequestType(String type){
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
public void setHTTPVersion(float version){
|
public void setHTTPVersion(float version){
|
||||||
this.version = version;
|
this.version = version;
|
||||||
}
|
}
|
||||||
public void setHTTPCode(int code){
|
public void setHTTPCode(int code){
|
||||||
this.httpCode = code;
|
this.httpCode = code;
|
||||||
}
|
}
|
||||||
public void setRequestURL(String url){
|
public void setRequestURL(String url){
|
||||||
this.url = url.trim().replaceAll("//", "/");
|
this.url = url.trim().replaceAll("//", "/");
|
||||||
}
|
}
|
||||||
public void setHeader(String key, String value){
|
public void setHeader(String key, String value){
|
||||||
this.headers.put(key.toUpperCase(), value);
|
this.headers.put(key.toUpperCase(), value);
|
||||||
}
|
}
|
||||||
protected void setInputStream(InputStream in){
|
protected void setInputStream(InputStream in){
|
||||||
this.in = in;
|
this.in = in;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected HashMap<String,String> getHeaderMap(){
|
protected HashMap<String,String> getHeaderMap(){
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
protected HashMap<String,String> getCookieMap(){
|
protected HashMap<String,String> getCookieMap(){
|
||||||
return cookies;
|
return cookies;
|
||||||
}
|
}
|
||||||
protected HashMap<String,String> getUrlAttributeMap(){
|
protected HashMap<String,String> getUrlAttributeMap(){
|
||||||
return urlAttributes;
|
return urlAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public String toString(){
|
public String toString(){
|
||||||
StringBuilder tmp = new StringBuilder();
|
StringBuilder tmp = new StringBuilder();
|
||||||
tmp.append("{Type: ").append(type);
|
tmp.append("{Type: ").append(type);
|
||||||
tmp.append(", HTTP_version: HTTP/").append(version);
|
tmp.append(", HTTP_version: HTTP/").append(version);
|
||||||
if(url == null)
|
if(url == null)
|
||||||
tmp.append(", URL: null");
|
tmp.append(", URL: null");
|
||||||
else
|
else
|
||||||
tmp.append(", URL: \"").append(url).append('\"');
|
tmp.append(", URL: \"").append(url).append('\"');
|
||||||
|
|
||||||
tmp.append(", URL_attr: ").append(toStringAttributes());
|
tmp.append(", URL_attr: ").append(toStringAttributes());
|
||||||
tmp.append(", Headers: ").append(toStringHeaders());
|
tmp.append(", Headers: ").append(toStringHeaders());
|
||||||
tmp.append(", Cookies: ").append(toStringCookies());
|
tmp.append(", Cookies: ").append(toStringCookies());
|
||||||
|
|
||||||
tmp.append('}');
|
tmp.append('}');
|
||||||
return tmp.toString();
|
return tmp.toString();
|
||||||
}
|
}
|
||||||
public String toStringHeaders(){
|
public String toStringHeaders(){
|
||||||
return Converter.toString(headers);
|
return Converter.toString(headers);
|
||||||
}
|
}
|
||||||
public String toStringCookies(){
|
public String toStringCookies(){
|
||||||
return Converter.toString(cookies);
|
return Converter.toString(cookies);
|
||||||
}
|
}
|
||||||
public String toStringAttributes(){
|
public String toStringAttributes(){
|
||||||
return Converter.toString(urlAttributes);
|
return Converter.toString(urlAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,33 +38,33 @@ import java.util.regex.Pattern;
|
||||||
public class HttpHeaderParser {
|
public class HttpHeaderParser {
|
||||||
private static final String HEADER_COOKIE = "COOKIE";
|
private static final String HEADER_COOKIE = "COOKIE";
|
||||||
|
|
||||||
private static final Pattern PATTERN_COLON = Pattern.compile(":");
|
private static final Pattern PATTERN_COLON = Pattern.compile(":");
|
||||||
private static final Pattern PATTERN_EQUAL = Pattern.compile("=");
|
private static final Pattern PATTERN_EQUAL = Pattern.compile("=");
|
||||||
private static final Pattern PATTERN_AND = Pattern.compile("&");
|
private static final Pattern PATTERN_AND = Pattern.compile("&");
|
||||||
|
|
||||||
|
|
||||||
private InputStream in;
|
private InputStream in;
|
||||||
private boolean skipStatusLine;
|
private boolean skipStatusLine;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the HTTP header information from a stream
|
* Parses the HTTP header information from a stream
|
||||||
*
|
*
|
||||||
* @param in is the stream
|
* @param in is the stream
|
||||||
*/
|
*/
|
||||||
public HttpHeaderParser(InputStream in){
|
public HttpHeaderParser(InputStream in){
|
||||||
this.in = in;
|
this.in = in;
|
||||||
this.skipStatusLine = false;
|
this.skipStatusLine = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the HTTP header information from a String
|
* Parses the HTTP header information from a String
|
||||||
*
|
*
|
||||||
* @param in is the String
|
* @param in is the String
|
||||||
*/
|
*/
|
||||||
public HttpHeaderParser(String in){
|
public HttpHeaderParser(String in){
|
||||||
this(new StringInputStream(in));
|
this(new StringInputStream(in));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public HttpHeader read() throws IOException {
|
public HttpHeader read() throws IOException {
|
||||||
|
|
@ -84,7 +84,7 @@ public class HttpHeaderParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Post processing
|
// Post processing
|
||||||
parseCookieValues(header.getCookieMap(), header.getHeader(HEADER_COOKIE));
|
parseCookieValues(header.getCookieMap(), header.getHeader(HEADER_COOKIE));
|
||||||
header.setInputStream(in);
|
header.setInputStream(in);
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
@ -96,38 +96,38 @@ public class HttpHeaderParser {
|
||||||
this.skipStatusLine = skipStatusLine;
|
this.skipStatusLine = skipStatusLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the first line of a http request/response and stores the values in a HttpHeader object
|
* Parses the first line of a http request/response and stores the values in a HttpHeader object
|
||||||
*
|
*
|
||||||
* @param header the header object where the cookies will be stored.
|
* @param header the header object where the cookies will be stored.
|
||||||
* @param statusLine the status line String
|
* @param statusLine the status line String
|
||||||
*/
|
*/
|
||||||
private static void parseStatusLine(HttpHeader header, String statusLine){
|
private static void parseStatusLine(HttpHeader header, String statusLine){
|
||||||
// Server Response
|
// Server Response
|
||||||
if( statusLine.startsWith("HTTP/") ){
|
if( statusLine.startsWith("HTTP/") ){
|
||||||
header.setIsRequest(false);
|
header.setIsRequest(false);
|
||||||
header.setHTTPVersion( Float.parseFloat( statusLine.substring( 5 , 8)));
|
header.setHTTPVersion( Float.parseFloat( statusLine.substring( 5 , 8)));
|
||||||
header.setHTTPCode( Integer.parseInt( statusLine.substring( 9, statusLine.indexOf(' ', 9) )));
|
header.setHTTPCode( Integer.parseInt( statusLine.substring( 9, statusLine.indexOf(' ', 9) )));
|
||||||
}
|
}
|
||||||
// Client Request
|
// Client Request
|
||||||
else if(statusLine.contains("HTTP/")){
|
else if(statusLine.contains("HTTP/")){
|
||||||
header.setIsRequest(true);
|
header.setIsRequest(true);
|
||||||
header.setRequestType( statusLine.substring(0, statusLine.indexOf(" ")).trim() );
|
header.setRequestType( statusLine.substring(0, statusLine.indexOf(" ")).trim() );
|
||||||
header.setHTTPVersion( Float.parseFloat( statusLine.substring(statusLine.lastIndexOf("HTTP/")+5 , statusLine.length()).trim()));
|
header.setHTTPVersion( Float.parseFloat( statusLine.substring(statusLine.lastIndexOf("HTTP/")+5 , statusLine.length()).trim()));
|
||||||
statusLine = (statusLine.substring(header.getRequestType().length()+1, statusLine.lastIndexOf("HTTP/")));
|
statusLine = (statusLine.substring(header.getRequestType().length()+1, statusLine.lastIndexOf("HTTP/")));
|
||||||
|
|
||||||
// parse URL and attributes
|
// parse URL and attributes
|
||||||
int index = statusLine.indexOf('?');
|
int index = statusLine.indexOf('?');
|
||||||
if(index > -1){
|
if(index > -1){
|
||||||
header.setRequestURL( statusLine.substring(0, index));
|
header.setRequestURL( statusLine.substring(0, index));
|
||||||
statusLine = statusLine.substring( index+1, statusLine.length());
|
statusLine = statusLine.substring( index+1, statusLine.length());
|
||||||
parseURLParameters(header.getUrlAttributeMap(), statusLine);
|
parseURLParameters(header.getUrlAttributeMap(), statusLine);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
header.setRequestURL(statusLine);
|
header.setRequestURL(statusLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a http key value paired header line.
|
* Parses a http key value paired header line.
|
||||||
|
|
@ -144,15 +144,15 @@ public class HttpHeaderParser {
|
||||||
(data.length>1 ? data[1] : "").trim()); //Value
|
(data.length>1 ? data[1] : "").trim()); //Value
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a raw cookie header into key and value pairs
|
* Parses a raw cookie header into key and value pairs
|
||||||
*
|
*
|
||||||
* @param map the Map where the cookies will be stored.
|
* @param map the Map where the cookies will be stored.
|
||||||
* @param cookieValue the raw cookie header value String that will be parsed
|
* @param cookieValue the raw cookie header value String that will be parsed
|
||||||
*/
|
*/
|
||||||
public static void parseCookieValues(Map<String,String> map, String cookieValue){
|
public static void parseCookieValues(Map<String,String> map, String cookieValue){
|
||||||
parseHeaderValues(map, cookieValue, ";");
|
parseHeaderValues(map, cookieValue, ";");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -173,11 +173,11 @@ public class HttpHeaderParser {
|
||||||
* Parses a header value string that contains key and value paired data and
|
* Parses a header value string that contains key and value paired data and
|
||||||
* stores them in a HashMap. If a pair only contain a key then the value
|
* stores them in a HashMap. If a pair only contain a key then the value
|
||||||
* will be set as a empty string.
|
* will be set as a empty string.
|
||||||
*
|
*
|
||||||
* TODO: method is not quote aware
|
* TODO: method is not quote aware
|
||||||
* @param map the Map where key and values will be stored.
|
* @param map the Map where key and values will be stored.
|
||||||
* @param headerValue the raw header value String that will be parsed.
|
* @param headerValue the raw header value String that will be parsed.
|
||||||
* @param delimiter the delimiter that separates key and value pairs (e.g. ';' for Cookies or ',' for Cache-Control)
|
* @param delimiter the delimiter that separates key and value pairs (e.g. ';' for Cookies or ',' for Cache-Control)
|
||||||
*/
|
*/
|
||||||
public static void parseHeaderValues(Map<String,String> map, String headerValue, String delimiter){
|
public static void parseHeaderValues(Map<String,String> map, String headerValue, String delimiter){
|
||||||
if(headerValue != null && !headerValue.isEmpty()){
|
if(headerValue != null && !headerValue.isEmpty()){
|
||||||
|
|
@ -192,31 +192,31 @@ public class HttpHeaderParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a string with variables from a get or post request that was sent from a client
|
* Parses a string with variables from a get or post request that was sent from a client
|
||||||
*
|
*
|
||||||
* @param header the header object where the url attributes key and value will be stored.
|
* @param header the header object where the url attributes key and value will be stored.
|
||||||
* @param urlAttributes is the String containing all the attributes
|
* @param urlAttributes is the String containing all the attributes
|
||||||
*/
|
*/
|
||||||
public static void parseURLParameters(HttpHeader header, String urlAttributes){
|
public static void parseURLParameters(HttpHeader header, String urlAttributes){
|
||||||
parseURLParameters(header.getUrlAttributeMap(), urlAttributes);
|
parseURLParameters(header.getUrlAttributeMap(), urlAttributes);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Parses a string with variables from a get or post request that was sent from a client
|
* Parses a string with variables from a get or post request that was sent from a client
|
||||||
*
|
*
|
||||||
* @param map a map where the url attributes key and value will be stored.
|
* @param map a map where the url attributes key and value will be stored.
|
||||||
* @param urlAttributes is the String containing all the attributes
|
* @param urlAttributes is the String containing all the attributes
|
||||||
*/
|
*/
|
||||||
public static void parseURLParameters(Map<String,String> map, String urlAttributes){
|
public static void parseURLParameters(Map<String,String> map, String urlAttributes){
|
||||||
String[] tmp;
|
String[] tmp;
|
||||||
urlAttributes = URLDecoder.decode(urlAttributes);
|
urlAttributes = URLDecoder.decode(urlAttributes);
|
||||||
// get the variables
|
// get the variables
|
||||||
String[] data = PATTERN_AND.split( urlAttributes );
|
String[] data = PATTERN_AND.split( urlAttributes );
|
||||||
for(String element : data){
|
for(String element : data){
|
||||||
tmp = PATTERN_EQUAL.split(element, 2);
|
tmp = PATTERN_EQUAL.split(element, 2);
|
||||||
map.put(
|
map.put(
|
||||||
tmp[0].trim(), // Key
|
tmp[0].trim(), // Key
|
||||||
(tmp.length>1 ? tmp[1] : "").trim()); //Value
|
(tmp.length>1 ? tmp[1] : "").trim()); //Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,20 +34,20 @@ import java.util.Map;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public interface HttpPage{
|
public interface HttpPage{
|
||||||
/**
|
/**
|
||||||
* This method has to be implemented for every page.
|
* This method has to be implemented for every page.
|
||||||
* This method is called when a client wants a response
|
* This method is called when a client wants a response
|
||||||
* from this specific page.
|
* from this specific page.
|
||||||
*
|
*
|
||||||
* @param out is a output stream to the client
|
* @param out is a output stream to the client
|
||||||
* @param headers is the header received from the client
|
* @param headers is the header received from the client
|
||||||
* @param session is the session associated with the current client
|
* @param session is the session associated with the current client
|
||||||
* @param cookie is cookie information from the client
|
* @param cookie is cookie information from the client
|
||||||
* @param request is POST and GET requests from the client
|
* @param request is POST and GET requests from the client
|
||||||
*/
|
*/
|
||||||
public abstract void respond(HttpPrintStream out,
|
public abstract void respond(HttpPrintStream out,
|
||||||
HttpHeader headers,
|
HttpHeader headers,
|
||||||
Map<String,Object> session,
|
Map<String,Object> session,
|
||||||
Map<String,String> cookie,
|
Map<String,String> cookie,
|
||||||
Map<String,String> request) throws IOException;
|
Map<String,String> request) throws IOException;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,73 +39,73 @@ import java.util.HashMap;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class HttpPrintStream extends OutputStream{
|
public class HttpPrintStream extends OutputStream{
|
||||||
// Defines the type of message
|
// Defines the type of message
|
||||||
public enum HttpMessageType{
|
public enum HttpMessageType{
|
||||||
REQUEST,
|
REQUEST,
|
||||||
RESPONSE
|
RESPONSE
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The actual output stream */
|
/** The actual output stream */
|
||||||
private PrintStream out;
|
private PrintStream out;
|
||||||
/** This defines the supported http version */
|
/** This defines the supported http version */
|
||||||
private String httpVersion;
|
private String httpVersion;
|
||||||
/** This defines the type of message that will be generated */
|
/** This defines the type of message that will be generated */
|
||||||
private HttpMessageType message_type;
|
private HttpMessageType message_type;
|
||||||
/** The status code of the message, ONLY for response */
|
/** The status code of the message, ONLY for response */
|
||||||
private Integer res_status_code;
|
private Integer res_status_code;
|
||||||
/** The request type of the message ONLY for request */
|
/** The request type of the message ONLY for request */
|
||||||
private String req_type;
|
private String req_type;
|
||||||
/** The requesting url ONLY for request */
|
/** The requesting url ONLY for request */
|
||||||
private String req_url;
|
private String req_url;
|
||||||
/** An Map of all the header values */
|
/** An Map of all the header values */
|
||||||
private HashMap<String, String> headers;
|
private HashMap<String, String> headers;
|
||||||
/** An Map of all the cookies */
|
/** An Map of all the cookies */
|
||||||
private HashMap<String, String> cookies;
|
private HashMap<String, String> cookies;
|
||||||
/** The buffered header */
|
/** The buffered header */
|
||||||
private StringBuffer buffer;
|
private StringBuffer buffer;
|
||||||
/** If the header buffering is enabled */
|
/** If the header buffering is enabled */
|
||||||
private boolean buffer_enabled;
|
private boolean buffer_enabled;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an new instance of HttpPrintStream with
|
* Creates an new instance of HttpPrintStream with
|
||||||
* message type of RESPONSE and buffering disabled.
|
* message type of RESPONSE and buffering disabled.
|
||||||
*
|
*
|
||||||
* @param out is the OutputStream where the data will be written to
|
* @param out is the OutputStream where the data will be written to
|
||||||
*/
|
*/
|
||||||
public HttpPrintStream(OutputStream out) {
|
public HttpPrintStream(OutputStream out) {
|
||||||
this( out, HttpMessageType.RESPONSE );
|
this( out, HttpMessageType.RESPONSE );
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Creates an new instance of HttpPrintStream with
|
* Creates an new instance of HttpPrintStream with
|
||||||
* message type buffering disabled.
|
* message type buffering disabled.
|
||||||
*
|
*
|
||||||
* @param out is the OutputStream where the data will be written to
|
* @param out is the OutputStream where the data will be written to
|
||||||
* @param type is the type of message
|
* @param type is the type of message
|
||||||
*/
|
*/
|
||||||
public HttpPrintStream(OutputStream out, HttpMessageType type) {
|
public HttpPrintStream(OutputStream out, HttpMessageType type) {
|
||||||
this.out = new PrintStream(out);
|
this.out = new PrintStream(out);
|
||||||
this.httpVersion = "1.0";
|
this.httpVersion = "1.0";
|
||||||
this.message_type = type;
|
this.message_type = type;
|
||||||
this.res_status_code = 200;
|
this.res_status_code = 200;
|
||||||
this.headers = new HashMap<String, String>();
|
this.headers = new HashMap<String, String>();
|
||||||
this.cookies = new HashMap<String, String>();
|
this.cookies = new HashMap<String, String>();
|
||||||
this.buffer = new StringBuffer();
|
this.buffer = new StringBuffer();
|
||||||
this.buffer_enabled = false;
|
this.buffer_enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable the buffering capability of the PrintStream.
|
* Enable the buffering capability of the PrintStream.
|
||||||
* Nothing will be sent to the client when buffering
|
* Nothing will be sent to the client when buffering
|
||||||
* is enabled until you close or flush the stream.
|
* is enabled until you close or flush the stream.
|
||||||
* This function will flush the stream if buffering is
|
* This function will flush the stream if buffering is
|
||||||
* disabled.
|
* disabled.
|
||||||
*
|
*
|
||||||
* @param b
|
* @param b
|
||||||
*/
|
*/
|
||||||
public void enableBuffering(boolean b) throws IOException {
|
public void enableBuffering(boolean b) throws IOException {
|
||||||
buffer_enabled = b;
|
buffer_enabled = b;
|
||||||
if(!buffer_enabled) flush();
|
if(!buffer_enabled) flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the http version that will be used in the http header
|
* Set the http version that will be used in the http header
|
||||||
|
|
@ -114,225 +114,225 @@ public class HttpPrintStream extends OutputStream{
|
||||||
this.httpVersion = version;
|
this.httpVersion = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a cookie that will be sent to the client
|
* Adds a cookie that will be sent to the client
|
||||||
*
|
*
|
||||||
* @param key is the name of the cookie
|
* @param key is the name of the cookie
|
||||||
* @param value is the value of the cookie
|
* @param value is the value of the cookie
|
||||||
* @throws IOException if the header has already been sent
|
* @throws IOException if the header has already been sent
|
||||||
*/
|
*/
|
||||||
public void setCookie(String key, String value) throws IOException{
|
public void setCookie(String key, String value) throws IOException{
|
||||||
if(cookies == null)
|
if(cookies == null)
|
||||||
throw new IOException("Header already sent!");
|
throw new IOException("Header already sent!");
|
||||||
cookies.put(key, value);
|
cookies.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an header value
|
* Adds an header value
|
||||||
*
|
*
|
||||||
* @param key is the header name
|
* @param key is the header name
|
||||||
* @param value is the value of the header
|
* @param value is the value of the header
|
||||||
* @throws IOException if the header has already been sent
|
* @throws IOException if the header has already been sent
|
||||||
*/
|
*/
|
||||||
public void setHeader(String key, String value) throws IOException{
|
public void setHeader(String key, String value) throws IOException{
|
||||||
if(headers == null)
|
if(headers == null)
|
||||||
throw new IOException("Header already sent!");
|
throw new IOException("Header already sent!");
|
||||||
headers.put(key, value);
|
headers.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the status code of the message, ONLY available in HTTP RESPONSE
|
* Sets the status code of the message, ONLY available in HTTP RESPONSE
|
||||||
*
|
*
|
||||||
* @param code the code from 100 up to 599
|
* @param code the code from 100 up to 599
|
||||||
* @throws IOException if the header has already been sent or the message type is wrong
|
* @throws IOException if the header has already been sent or the message type is wrong
|
||||||
*/
|
*/
|
||||||
public void setStatusCode(int code) throws IOException{
|
public void setStatusCode(int code) throws IOException{
|
||||||
if( res_status_code == null )
|
if( res_status_code == null )
|
||||||
throw new IOException("Header already sent!");
|
throw new IOException("Header already sent!");
|
||||||
if( message_type != HttpMessageType.RESPONSE )
|
if( message_type != HttpMessageType.RESPONSE )
|
||||||
throw new IOException("Status Code is only available in HTTP RESPONSE!");
|
throw new IOException("Status Code is only available in HTTP RESPONSE!");
|
||||||
res_status_code = code;
|
res_status_code = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the request type of the message, ONLY available in HTTP REQUEST
|
* Sets the request type of the message, ONLY available in HTTP REQUEST
|
||||||
*
|
*
|
||||||
* @param req_type is the type of the message, e.g. GET, POST...
|
* @param req_type is the type of the message, e.g. GET, POST...
|
||||||
* @throws IOException if the header has already been sent or the message type is wrong
|
* @throws IOException if the header has already been sent or the message type is wrong
|
||||||
*/
|
*/
|
||||||
public void setRequestType(String req_type) throws IOException{
|
public void setRequestType(String req_type) throws IOException{
|
||||||
if( req_type == null )
|
if( req_type == null )
|
||||||
throw new IOException("Header already sent!");
|
throw new IOException("Header already sent!");
|
||||||
if( message_type != HttpMessageType.REQUEST )
|
if( message_type != HttpMessageType.REQUEST )
|
||||||
throw new IOException("Request Message Type is only available in HTTP REQUEST!");
|
throw new IOException("Request Message Type is only available in HTTP REQUEST!");
|
||||||
this.req_type = req_type;
|
this.req_type = req_type;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Sets the requesting URL of the message, ONLY available in HTTP REQUEST
|
* Sets the requesting URL of the message, ONLY available in HTTP REQUEST
|
||||||
*
|
*
|
||||||
* @param req_url is the URL
|
* @param req_url is the URL
|
||||||
* @throws IOException if the header has already been sent or the message type is wrong
|
* @throws IOException if the header has already been sent or the message type is wrong
|
||||||
*/
|
*/
|
||||||
public void setRequestURL(String req_url) throws IOException{
|
public void setRequestURL(String req_url) throws IOException{
|
||||||
if( req_url == null )
|
if( req_url == null )
|
||||||
throw new IOException("Header already sent!");
|
throw new IOException("Header already sent!");
|
||||||
if( message_type != HttpMessageType.REQUEST )
|
if( message_type != HttpMessageType.REQUEST )
|
||||||
throw new IOException("Request URL is only available in HTTP REQUEST!");
|
throw new IOException("Request URL is only available in HTTP REQUEST!");
|
||||||
this.req_url = req_url;
|
this.req_url = req_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setHeaders( HashMap<String,String> map ){
|
protected void setHeaders( HashMap<String,String> map ){
|
||||||
headers = map;
|
headers = map;
|
||||||
}
|
}
|
||||||
protected void setCookies( HashMap<String,String> map ){
|
protected void setCookies( HashMap<String,String> map ){
|
||||||
cookies = map;
|
cookies = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints a new line
|
* Prints a new line
|
||||||
*/
|
*/
|
||||||
public void println() throws IOException {
|
public void println() throws IOException {
|
||||||
printOrBuffer(System.lineSeparator());
|
printOrBuffer(System.lineSeparator());
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Prints with a new line
|
* Prints with a new line
|
||||||
*/
|
*/
|
||||||
public void println(String s) throws IOException {
|
public void println(String s) throws IOException {
|
||||||
printOrBuffer(s + System.lineSeparator());
|
printOrBuffer(s + System.lineSeparator());
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Prints an string
|
* Prints an string
|
||||||
*/
|
*/
|
||||||
public void print(String s) throws IOException {
|
public void print(String s) throws IOException {
|
||||||
printOrBuffer(s);
|
printOrBuffer(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will buffer String or directly output headers if needed and then the String
|
* Will buffer String or directly output headers if needed and then the String
|
||||||
*/
|
*/
|
||||||
private void printOrBuffer(String s) throws IOException {
|
private void printOrBuffer(String s) throws IOException {
|
||||||
if(buffer_enabled){
|
if(buffer_enabled){
|
||||||
buffer.append(s);
|
buffer.append(s);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if(res_status_code != null){
|
if(res_status_code != null){
|
||||||
if( message_type==HttpMessageType.REQUEST )
|
if( message_type==HttpMessageType.REQUEST )
|
||||||
out.print(req_type + " " + req_url + " HTTP/"+httpVersion);
|
out.print(req_type + " " + req_url + " HTTP/"+httpVersion);
|
||||||
else
|
else
|
||||||
out.print("HTTP/"+httpVersion+" " + res_status_code + " " + getStatusString(res_status_code));
|
out.print("HTTP/"+httpVersion+" " + res_status_code + " " + getStatusString(res_status_code));
|
||||||
out.println();
|
out.println();
|
||||||
res_status_code = null;
|
res_status_code = null;
|
||||||
req_type = null;
|
req_type = null;
|
||||||
req_url = null;
|
req_url = null;
|
||||||
}
|
}
|
||||||
if(headers != null){
|
if(headers != null){
|
||||||
for(String key : headers.keySet()){
|
for(String key : headers.keySet()){
|
||||||
out.println(key + ": " + headers.get(key));
|
out.println(key + ": " + headers.get(key));
|
||||||
}
|
}
|
||||||
headers = null;
|
headers = null;
|
||||||
}
|
}
|
||||||
if(cookies != null){
|
if(cookies != null){
|
||||||
if( !cookies.isEmpty() ){
|
if( !cookies.isEmpty() ){
|
||||||
if( message_type==HttpMessageType.REQUEST ){
|
if( message_type==HttpMessageType.REQUEST ){
|
||||||
out.print("Cookie: ");
|
out.print("Cookie: ");
|
||||||
for(String key : cookies.keySet()){
|
for(String key : cookies.keySet()){
|
||||||
out.print(key + "=" + cookies.get(key) + "; ");
|
out.print(key + "=" + cookies.get(key) + "; ");
|
||||||
}
|
}
|
||||||
out.println();
|
out.println();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
for(String key : cookies.keySet()){
|
for(String key : cookies.keySet()){
|
||||||
out.print("Set-Cookie: " + key + "=" + cookies.get(key) + ";");
|
out.print("Set-Cookie: " + key + "=" + cookies.get(key) + ";");
|
||||||
out.println();
|
out.println();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.println();
|
out.println();
|
||||||
cookies = null;
|
cookies = null;
|
||||||
}
|
}
|
||||||
out.print(s);
|
out.print(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return if headers has been sent. The setHeader, setStatusCode, setCookie method will throw Exceptions
|
* @return if headers has been sent. The setHeader, setStatusCode, setCookie method will throw Exceptions
|
||||||
*/
|
*/
|
||||||
public boolean isHeaderSent() {
|
public boolean isHeaderSent() {
|
||||||
return res_status_code == null && headers == null && cookies == null;
|
return res_status_code == null && headers == null && cookies == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends out the buffer and clears it
|
* Sends out the buffer and clears it
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void flush() throws IOException {
|
public void flush() throws IOException {
|
||||||
flushBuffer();
|
flushBuffer();
|
||||||
out.flush();
|
out.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
flush();
|
flush();
|
||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void flushBuffer() throws IOException {
|
protected void flushBuffer() throws IOException {
|
||||||
if(buffer_enabled){
|
if(buffer_enabled){
|
||||||
buffer_enabled = false;
|
buffer_enabled = false;
|
||||||
printOrBuffer(buffer.toString());
|
printOrBuffer(buffer.toString());
|
||||||
buffer.delete(0, buffer.length());
|
buffer.delete(0, buffer.length());
|
||||||
buffer_enabled = true;
|
buffer_enabled = true;
|
||||||
}
|
}
|
||||||
else if(res_status_code != null || headers != null || cookies != null){
|
else if(res_status_code != null || headers != null || cookies != null){
|
||||||
printOrBuffer("");
|
printOrBuffer("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will flush all buffers and write binary data to stream
|
* Will flush all buffers and write binary data to stream
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(int b) throws IOException {
|
public void write(int b) throws IOException {
|
||||||
flushBuffer();
|
flushBuffer();
|
||||||
out.write(b);
|
out.write(b);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* * Will flush all buffers and write binary data to stream
|
* * Will flush all buffers and write binary data to stream
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void write(byte[] buf, int off, int len) throws IOException {
|
public void write(byte[] buf, int off, int len) throws IOException {
|
||||||
flushBuffer();
|
flushBuffer();
|
||||||
out.write(buf, off, len);
|
out.write(buf, off, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getStatusString(int type){
|
private String getStatusString(int type){
|
||||||
switch(type){
|
switch(type){
|
||||||
case 100: return "Continue";
|
case 100: return "Continue";
|
||||||
case 200: return "OK";
|
case 200: return "OK";
|
||||||
case 301: return "Moved Permanently";
|
case 301: return "Moved Permanently";
|
||||||
case 304: return "Not Modified";
|
case 304: return "Not Modified";
|
||||||
case 307: return "Temporary Redirect";
|
case 307: return "Temporary Redirect";
|
||||||
case 400: return "Bad Request";
|
case 400: return "Bad Request";
|
||||||
case 401: return "Unauthorized";
|
case 401: return "Unauthorized";
|
||||||
case 403: return "Forbidden";
|
case 403: return "Forbidden";
|
||||||
case 404: return "Not Found";
|
case 404: return "Not Found";
|
||||||
case 500: return "Internal Server Error";
|
case 500: return "Internal Server Error";
|
||||||
case 501: return "Not Implemented";
|
case 501: return "Not Implemented";
|
||||||
default: return "";
|
default: return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder str = new StringBuilder();
|
StringBuilder str = new StringBuilder();
|
||||||
str.append("{http_type: ").append(message_type);
|
str.append("{http_type: ").append(message_type);
|
||||||
if (res_status_code != null) {
|
if (res_status_code != null) {
|
||||||
if (message_type == HttpMessageType.REQUEST) {
|
if (message_type == HttpMessageType.REQUEST) {
|
||||||
str.append(", req_type: ").append(req_type);
|
str.append(", req_type: ").append(req_type);
|
||||||
if(req_url == null)
|
if(req_url == null)
|
||||||
str.append(", req_url: null");
|
str.append(", req_url: null");
|
||||||
else
|
else
|
||||||
str.append(", req_url: \"").append(req_url).append('\"');
|
str.append(", req_url: \"").append(req_url).append('\"');
|
||||||
} else if (message_type == HttpMessageType.RESPONSE){
|
} else if (message_type == HttpMessageType.RESPONSE){
|
||||||
str.append(", status_code: ").append(res_status_code);
|
str.append(", status_code: ").append(res_status_code);
|
||||||
|
|
|
||||||
|
|
@ -50,122 +50,122 @@ import java.util.logging.Logger;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class HttpServer extends ThreadedTCPNetworkServer{
|
public class HttpServer extends ThreadedTCPNetworkServer{
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
|
|
||||||
public static final String SESSION_KEY_ID = "session_id";
|
public static final String SESSION_KEY_ID = "session_id";
|
||||||
public static final String SESSION_KEY_TTL = "session_ttl";
|
public static final String SESSION_KEY_TTL = "session_ttl";
|
||||||
public static final String SERVER_NAME = "Zutil HttpServer";
|
public static final String SERVER_NAME = "Zutil HttpServer";
|
||||||
public static final int SESSION_TTL = 10*60*1000; // in milliseconds
|
public static final int SESSION_TTL = 10*60*1000; // in milliseconds
|
||||||
|
|
||||||
|
|
||||||
private Map<String,HttpPage> pages;
|
private Map<String,HttpPage> pages;
|
||||||
private HttpPage defaultPage;
|
private HttpPage defaultPage;
|
||||||
private Map<String,Map<String,Object>> sessions;
|
private Map<String,Map<String,Object>> sessions;
|
||||||
private int nextSessionId;
|
private int nextSessionId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of the sever
|
* Creates a new instance of the sever
|
||||||
*
|
*
|
||||||
* @param port The port that the server should listen to
|
* @param port The port that the server should listen to
|
||||||
*/
|
*/
|
||||||
public HttpServer(int port){
|
public HttpServer(int port){
|
||||||
this(port, null, null);
|
this(port, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of the sever
|
* Creates a new instance of the sever
|
||||||
*
|
*
|
||||||
* @param port The port that the server should listen to
|
* @param port The port that the server should listen to
|
||||||
* @param keyStore If this is not null then the server will use SSL connection with this keyStore file path
|
* @param keyStore If this is not null then the server will use SSL connection with this keyStore file path
|
||||||
* @param keyStorePass If this is not null then the server will use a SSL connection with the given certificate
|
* @param keyStorePass If this is not null then the server will use a SSL connection with the given certificate
|
||||||
*/
|
*/
|
||||||
public HttpServer(int port, File keyStore, String keyStorePass){
|
public HttpServer(int port, File keyStore, String keyStorePass){
|
||||||
super( port, keyStore, keyStorePass );
|
super( port, keyStore, keyStorePass );
|
||||||
|
|
||||||
pages = new ConcurrentHashMap<>();
|
pages = new ConcurrentHashMap<>();
|
||||||
sessions = new ConcurrentHashMap<>();
|
sessions = new ConcurrentHashMap<>();
|
||||||
nextSessionId = 0;
|
nextSessionId = 0;
|
||||||
|
|
||||||
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
|
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
|
||||||
exec.scheduleWithFixedDelay(new SessionGarbageCollector(), 10000, SESSION_TTL / 2, TimeUnit.MILLISECONDS);
|
exec.scheduleWithFixedDelay(new SessionGarbageCollector(), 10000, SESSION_TTL / 2, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
logger.info("HTTP"+(keyStore==null?"":"S")+" Server ready!");
|
logger.info("HTTP"+(keyStore==null?"":"S")+" Server ready!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class acts as an garbage collector that
|
* This class acts as an garbage collector that
|
||||||
* removes old sessions from the session HashMap
|
* removes old sessions from the session HashMap
|
||||||
*/
|
*/
|
||||||
private class SessionGarbageCollector implements Runnable {
|
private class SessionGarbageCollector implements Runnable {
|
||||||
public void run(){
|
public void run(){
|
||||||
Object[] keys = sessions.keySet().toArray();
|
Object[] keys = sessions.keySet().toArray();
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for(Object key : keys){
|
for(Object key : keys){
|
||||||
Map<String,Object> session = sessions.get(key);
|
Map<String,Object> session = sessions.get(key);
|
||||||
|
|
||||||
// Check if session is still valid
|
// Check if session is still valid
|
||||||
if(((Timer) session.get(SESSION_KEY_TTL)).hasTimedOut()){
|
if(((Timer) session.get(SESSION_KEY_TTL)).hasTimedOut()){
|
||||||
sessions.remove(key);
|
sessions.remove(key);
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
logger.fine("Removed "+count+" old sessions");
|
logger.fine("Removed "+count+" old sessions");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a HttpPage to a specific URL
|
* Add a HttpPage to a specific URL
|
||||||
*
|
*
|
||||||
* @param name The URL or name of the page
|
* @param name The URL or name of the page
|
||||||
* @param page The page itself
|
* @param page The page itself
|
||||||
*/
|
*/
|
||||||
public void setPage(String name, HttpPage page){
|
public void setPage(String name, HttpPage page){
|
||||||
if(name.charAt(0) != '/')
|
if(name.charAt(0) != '/')
|
||||||
name = "/"+name;
|
name = "/"+name;
|
||||||
pages.put(name, page);
|
pages.put(name, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a default page that will be shown
|
* This is a default page that will be shown
|
||||||
* if there is no other matching page,
|
* if there is no other matching page,
|
||||||
*
|
*
|
||||||
* @param page The HttpPage that will be shown
|
* @param page The HttpPage that will be shown
|
||||||
*/
|
*/
|
||||||
public void setDefaultPage(HttpPage page){
|
public void setDefaultPage(HttpPage page){
|
||||||
defaultPage = page;
|
defaultPage = page;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ThreadedTCPNetworkServerThread getThreadInstance( Socket s ){
|
protected ThreadedTCPNetworkServerThread getThreadInstance( Socket s ){
|
||||||
try {
|
try {
|
||||||
return new HttpServerThread( s );
|
return new HttpServerThread( s );
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.log(Level.SEVERE, "Could not start new Thread", e);
|
logger.log(Level.SEVERE, "Could not start new Thread", e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal class that handles all the requests
|
* Internal class that handles all the requests
|
||||||
*/
|
*/
|
||||||
protected class HttpServerThread implements ThreadedTCPNetworkServerThread{
|
protected class HttpServerThread implements ThreadedTCPNetworkServerThread{
|
||||||
private HttpPrintStream out;
|
private HttpPrintStream out;
|
||||||
private BufferedInputStream in;
|
private BufferedInputStream in;
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
|
|
||||||
public HttpServerThread(Socket socket) throws IOException{
|
public HttpServerThread(Socket socket) throws IOException{
|
||||||
out = new HttpPrintStream(socket.getOutputStream());
|
out = new HttpPrintStream(socket.getOutputStream());
|
||||||
in = new BufferedInputStream(socket.getInputStream());
|
in = new BufferedInputStream(socket.getInputStream());
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run(){
|
public void run(){
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
HttpHeaderParser headerParser;
|
HttpHeaderParser headerParser;
|
||||||
HttpHeader header = null;
|
HttpHeader header = null;
|
||||||
Map<String, Object> session = null;
|
Map<String, Object> session = null;
|
||||||
try {
|
try {
|
||||||
//**************************** PARSE REQUEST *********************************
|
//**************************** PARSE REQUEST *********************************
|
||||||
headerParser = new HttpHeaderParser(in);
|
headerParser = new HttpHeaderParser(in);
|
||||||
header = headerParser.read();
|
header = headerParser.read();
|
||||||
|
|
@ -176,8 +176,8 @@ public class HttpServer extends ThreadedTCPNetworkServer{
|
||||||
|
|
||||||
//******* Read in the post data if available
|
//******* Read in the post data if available
|
||||||
if (header.getHeader("Content-Length") != null &&
|
if (header.getHeader("Content-Length") != null &&
|
||||||
header.getHeader("Content-Type") != null &&
|
header.getHeader("Content-Type") != null &&
|
||||||
header.getHeader("Content-Type").contains("application/x-www-form-urlencoded")) {
|
header.getHeader("Content-Type").contains("application/x-www-form-urlencoded")) {
|
||||||
// Reads the post data size
|
// Reads the post data size
|
||||||
int postDataLength = Integer.parseInt(header.getHeader("Content-Length"));
|
int postDataLength = Integer.parseInt(header.getHeader("Content-Length"));
|
||||||
// read the data
|
// read the data
|
||||||
|
|
@ -186,8 +186,8 @@ public class HttpServer extends ThreadedTCPNetworkServer{
|
||||||
for (int i = 0; i < postDataLength; i++) {
|
for (int i = 0; i < postDataLength; i++) {
|
||||||
tmpBuff.append((char) in.read());
|
tmpBuff.append((char) in.read());
|
||||||
}
|
}
|
||||||
// get the variables
|
// get the variables
|
||||||
HttpHeaderParser.parseURLParameters(header, tmpBuff.toString());
|
HttpHeaderParser.parseURLParameters(header, tmpBuff.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
//**************************** HANDLE REQUEST *********************************
|
//**************************** HANDLE REQUEST *********************************
|
||||||
|
|
@ -228,25 +228,25 @@ public class HttpServer extends ThreadedTCPNetworkServer{
|
||||||
out.setStatusCode(404);
|
out.setStatusCode(404);
|
||||||
out.println("404 Page Not Found: " + header.getRequestURL());
|
out.println("404 Page Not Found: " + header.getRequestURL());
|
||||||
logger.warning("Page not defined: " + header.getRequestURL());
|
logger.warning("Page not defined: " + header.getRequestURL());
|
||||||
}
|
}
|
||||||
//********************************************************************************
|
//********************************************************************************
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logRequest(header, session, time);
|
logRequest(header, session, time);
|
||||||
logger.log(Level.SEVERE, "500 Internal Server Error", e);
|
logger.log(Level.SEVERE, "500 Internal Server Error", e);
|
||||||
try {
|
try {
|
||||||
if (!out.isHeaderSent())
|
if (!out.isHeaderSent())
|
||||||
out.setStatusCode(500);
|
out.setStatusCode(500);
|
||||||
if (e.getMessage() != null)
|
if (e.getMessage() != null)
|
||||||
out.println("500 Internal Server Error: " + e.getMessage());
|
out.println("500 Internal Server Error: " + e.getMessage());
|
||||||
else if (e.getCause() != null) {
|
else if (e.getCause() != null) {
|
||||||
out.println("500 Internal Server Error: " + e.getCause().getMessage());
|
out.println("500 Internal Server Error: " + e.getCause().getMessage());
|
||||||
} else {
|
} else {
|
||||||
out.println("500 Internal Server Error: " + e);
|
out.println("500 Internal Server Error: " + e);
|
||||||
}
|
}
|
||||||
}catch(IOException ioe){
|
}catch(IOException ioe){
|
||||||
logger.log(Level.SEVERE, null, ioe);
|
logger.log(Level.SEVERE, null, ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
try{
|
try{
|
||||||
out.close();
|
out.close();
|
||||||
|
|
@ -256,8 +256,8 @@ public class HttpServer extends ThreadedTCPNetworkServer{
|
||||||
logger.log(Level.WARNING, "Could not close connection", e);
|
logger.log(Level.WARNING, "Could not close connection", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected static void logRequest(HttpHeader header,
|
protected static void logRequest(HttpHeader header,
|
||||||
|
|
|
||||||
|
|
@ -33,130 +33,130 @@ import java.util.HashMap;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public class HttpURL {
|
public class HttpURL {
|
||||||
public static final String PROTOCOL_SEPARATOR = "://";
|
public static final String PROTOCOL_SEPARATOR = "://";
|
||||||
public static final String PORT_SEPARATOR = ":";
|
public static final String PORT_SEPARATOR = ":";
|
||||||
public static final String PATH_SEPARATOR = "/";
|
public static final String PATH_SEPARATOR = "/";
|
||||||
public static final String PARAMETER_SEPARATOR = "?";
|
public static final String PARAMETER_SEPARATOR = "?";
|
||||||
public static final String ANCHOR_SEPARATOR = "#";
|
public static final String ANCHOR_SEPARATOR = "#";
|
||||||
|
|
||||||
private String protocol = "";
|
private String protocol = "";
|
||||||
private String host = "127.0.0.1";
|
private String host = "127.0.0.1";
|
||||||
private int port = -1;
|
private int port = -1;
|
||||||
private String path;
|
private String path;
|
||||||
private String anchor;
|
private String anchor;
|
||||||
|
|
||||||
private HashMap<String,String> parameters = new HashMap<String,String>();
|
|
||||||
|
|
||||||
|
private HashMap<String,String> parameters = new HashMap<String,String>();
|
||||||
public HttpURL(){}
|
|
||||||
|
|
||||||
public HttpURL( URL url ){
|
|
||||||
this.setProtocol( url.getProtocol() );
|
|
||||||
this.setHost( url.getHost() );
|
|
||||||
this.setPort( url.getPort() );
|
|
||||||
this.setPath( url.getPath() );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String getProtocol( ){
|
|
||||||
return protocol;
|
|
||||||
}
|
|
||||||
public String getHost( ){
|
|
||||||
return host;
|
|
||||||
}
|
|
||||||
public int getPort( ){
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
public String getPath( ){
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
public String getAnchor( ){
|
|
||||||
return anchor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setProtocol( String prot ){
|
|
||||||
this.protocol = prot;
|
|
||||||
}
|
|
||||||
public void setHost( String host ){
|
|
||||||
this.host = host;
|
|
||||||
}
|
|
||||||
public void setPort( int port ){
|
|
||||||
this.port = port;
|
|
||||||
}
|
|
||||||
public void setPath( String path ){
|
|
||||||
if( path.length() >= 1 && !path.startsWith(PATH_SEPARATOR))
|
|
||||||
path = PATH_SEPARATOR + path;
|
|
||||||
this.path = path;
|
|
||||||
}
|
|
||||||
public void setAnchor( String anch ){
|
|
||||||
this.anchor = anch;
|
|
||||||
}
|
|
||||||
public void setParameter( String key, String value ){
|
|
||||||
this.parameters.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setParameters( HashMap<String,String> pars ){
|
|
||||||
this.parameters = pars;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates the parameter string in a URL.
|
|
||||||
*
|
|
||||||
* e.g.
|
|
||||||
* "key=value&key2=value&..."
|
|
||||||
*/
|
|
||||||
public String getParameterString(){
|
|
||||||
StringBuilder param = new StringBuilder();
|
|
||||||
for(String key : parameters.keySet()){
|
|
||||||
if (param.length() > 0)
|
|
||||||
param.append('&');
|
|
||||||
param.append(key);
|
|
||||||
param.append('=');
|
|
||||||
param.append( parameters.get(key) );
|
|
||||||
}
|
|
||||||
return param.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a path that are used in the HTTP header
|
public HttpURL(){}
|
||||||
*/
|
|
||||||
public String getHttpURL(){
|
public HttpURL( URL url ){
|
||||||
StringBuilder url = new StringBuilder();
|
this.setProtocol( url.getProtocol() );
|
||||||
url.append( path );
|
this.setHost( url.getHost() );
|
||||||
if( !parameters.isEmpty() )
|
this.setPort( url.getPort() );
|
||||||
url.append( PARAMETER_SEPARATOR ).append( getParameterString() );
|
this.setPath( url.getPath() );
|
||||||
|
}
|
||||||
return url.toString();
|
|
||||||
}
|
|
||||||
|
public String getProtocol( ){
|
||||||
/**
|
return protocol;
|
||||||
* Generates a full URL
|
}
|
||||||
*/
|
public String getHost( ){
|
||||||
public String getURL(){
|
return host;
|
||||||
return toString();
|
}
|
||||||
}
|
public int getPort( ){
|
||||||
|
return port;
|
||||||
/**
|
}
|
||||||
* Generates the whole URL
|
public String getPath( ){
|
||||||
*/
|
return path;
|
||||||
public String toString(){
|
}
|
||||||
StringBuilder url = new StringBuilder();
|
public String getAnchor( ){
|
||||||
url.append( protocol );
|
return anchor;
|
||||||
url.append( PROTOCOL_SEPARATOR );
|
}
|
||||||
url.append( host );
|
|
||||||
if( port > 0 )
|
public void setProtocol( String prot ){
|
||||||
url.append( PORT_SEPARATOR ).append( port );
|
this.protocol = prot;
|
||||||
|
}
|
||||||
if( path != null )
|
public void setHost( String host ){
|
||||||
url.append( path );
|
this.host = host;
|
||||||
else
|
}
|
||||||
url.append( PATH_SEPARATOR );
|
public void setPort( int port ){
|
||||||
|
this.port = port;
|
||||||
if( !parameters.isEmpty() )
|
}
|
||||||
url.append( PARAMETER_SEPARATOR ).append( getParameterString() );
|
public void setPath( String path ){
|
||||||
if( anchor != null )
|
if( path.length() >= 1 && !path.startsWith(PATH_SEPARATOR))
|
||||||
url.append( ANCHOR_SEPARATOR ).append( anchor );
|
path = PATH_SEPARATOR + path;
|
||||||
|
this.path = path;
|
||||||
return url.toString();
|
}
|
||||||
}
|
public void setAnchor( String anch ){
|
||||||
|
this.anchor = anch;
|
||||||
|
}
|
||||||
|
public void setParameter( String key, String value ){
|
||||||
|
this.parameters.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setParameters( HashMap<String,String> pars ){
|
||||||
|
this.parameters = pars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the parameter string in a URL.
|
||||||
|
*
|
||||||
|
* e.g.
|
||||||
|
* "key=value&key2=value&..."
|
||||||
|
*/
|
||||||
|
public String getParameterString(){
|
||||||
|
StringBuilder param = new StringBuilder();
|
||||||
|
for(String key : parameters.keySet()){
|
||||||
|
if (param.length() > 0)
|
||||||
|
param.append('&');
|
||||||
|
param.append(key);
|
||||||
|
param.append('=');
|
||||||
|
param.append( parameters.get(key) );
|
||||||
|
}
|
||||||
|
return param.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a path that are used in the HTTP header
|
||||||
|
*/
|
||||||
|
public String getHttpURL(){
|
||||||
|
StringBuilder url = new StringBuilder();
|
||||||
|
url.append( path );
|
||||||
|
if( !parameters.isEmpty() )
|
||||||
|
url.append( PARAMETER_SEPARATOR ).append( getParameterString() );
|
||||||
|
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a full URL
|
||||||
|
*/
|
||||||
|
public String getURL(){
|
||||||
|
return toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the whole URL
|
||||||
|
*/
|
||||||
|
public String toString(){
|
||||||
|
StringBuilder url = new StringBuilder();
|
||||||
|
url.append( protocol );
|
||||||
|
url.append( PROTOCOL_SEPARATOR );
|
||||||
|
url.append( host );
|
||||||
|
if( port > 0 )
|
||||||
|
url.append( PORT_SEPARATOR ).append( port );
|
||||||
|
|
||||||
|
if( path != null )
|
||||||
|
url.append( path );
|
||||||
|
else
|
||||||
|
url.append( PATH_SEPARATOR );
|
||||||
|
|
||||||
|
if( !parameters.isEmpty() )
|
||||||
|
url.append( PARAMETER_SEPARATOR ).append( getParameterString() );
|
||||||
|
if( anchor != null )
|
||||||
|
url.append( ANCHOR_SEPARATOR ).append( anchor );
|
||||||
|
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,14 +31,14 @@ package zutil.net.http.multipart;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public interface MultipartField{
|
public interface MultipartField{
|
||||||
/**
|
/**
|
||||||
* @return the amount of data received for this field. Might only be available when all data has been processed
|
* @return the amount of data received for this field. Might only be available when all data has been processed
|
||||||
*/
|
*/
|
||||||
public long getLength();
|
public long getLength();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the name of the field.
|
* @return the name of the field.
|
||||||
*/
|
*/
|
||||||
public String getName();
|
public String getName();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,26 +42,26 @@ import static zutil.net.http.multipart.MultipartParser.HEADER_CONTENT_TYPE;
|
||||||
public class MultipartFileField implements MultipartField{
|
public class MultipartFileField implements MultipartField{
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
|
|
||||||
private String fieldname;
|
private String fieldname;
|
||||||
private String filename;
|
private String filename;
|
||||||
private String contentType;
|
private String contentType;
|
||||||
private byte[] content;
|
private byte[] content;
|
||||||
private InputStream in;
|
private InputStream in;
|
||||||
|
|
||||||
|
|
||||||
protected MultipartFileField(Map<String,String> headers, InputStream in) throws IOException {
|
protected MultipartFileField(Map<String,String> headers, InputStream in) throws IOException {
|
||||||
this.fieldname = headers.get("name");
|
this.fieldname = headers.get("name");
|
||||||
this.filename = headers.get("filename");
|
this.filename = headers.get("filename");
|
||||||
this.contentType = headers.get(HEADER_CONTENT_TYPE);
|
this.contentType = headers.get(HEADER_CONTENT_TYPE);
|
||||||
this.in = in;
|
this.in = in;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the amount of data received for this field
|
* @return the amount of data received for this field
|
||||||
*/
|
*/
|
||||||
public long getLength(){
|
public long getLength(){
|
||||||
return 0; //TODO:
|
return 0; //TODO:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the field name
|
* @return the field name
|
||||||
|
|
@ -70,13 +70,13 @@ public class MultipartFileField implements MultipartField{
|
||||||
return fieldname;
|
return fieldname;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFilename(){
|
public String getFilename(){
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getContentType() {
|
public String getContentType() {
|
||||||
return contentType;
|
return contentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -100,20 +100,20 @@ public class MultipartFileField implements MultipartField{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads in all data and save it into the specified file.
|
* Reads in all data and save it into the specified file.
|
||||||
*
|
*
|
||||||
* Note: Only one of the methods {@link #getContent()} or
|
* Note: Only one of the methods {@link #getContent()} or
|
||||||
* {@link #saveToFile(File)} can be used as they will consume the data in the stream.
|
* {@link #saveToFile(File)} can be used as they will consume the data in the stream.
|
||||||
*
|
*
|
||||||
* @param file is the new file where the data will be stored
|
* @param file is the new file where the data will be stored
|
||||||
*/
|
*/
|
||||||
public void saveToFile(File file) throws IOException {
|
public void saveToFile(File file) throws IOException {
|
||||||
if (in == null)
|
if (in == null)
|
||||||
throw new IOException("Stream already consumed.");
|
throw new IOException("Stream already consumed.");
|
||||||
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
|
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
|
||||||
IOUtil.copyStream(in, out);
|
IOUtil.copyStream(in, out);
|
||||||
out.close();
|
out.close();
|
||||||
in = null; // reset InputStream
|
in = null; // reset InputStream
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,12 +51,12 @@ public class MultipartParser implements Iterable<MultipartField>{
|
||||||
protected static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition".toUpperCase();
|
protected static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition".toUpperCase();
|
||||||
protected static final String HEADER_CONTENT_TYPE = "Content-Type".toUpperCase();
|
protected static final String HEADER_CONTENT_TYPE = "Content-Type".toUpperCase();
|
||||||
|
|
||||||
/** This is the delimiter that will separate the fields */
|
/** This is the delimiter that will separate the fields */
|
||||||
private String delimiter;
|
private String delimiter;
|
||||||
/** The length of the HTTP Body */
|
/** The length of the HTTP Body */
|
||||||
private long contentLength;
|
private long contentLength;
|
||||||
/** This is the input stream */
|
/** This is the input stream */
|
||||||
private InputStream in;
|
private InputStream in;
|
||||||
|
|
||||||
private MultiPartIterator iterator;
|
private MultiPartIterator iterator;
|
||||||
|
|
||||||
|
|
@ -66,11 +66,11 @@ public class MultipartParser implements Iterable<MultipartField>{
|
||||||
this.delimiter = delimiter;
|
this.delimiter = delimiter;
|
||||||
this.contentLength = length;
|
this.contentLength = length;
|
||||||
}
|
}
|
||||||
public MultipartParser(HttpHeader header){
|
public MultipartParser(HttpHeader header){
|
||||||
this(header.getInputStream(),
|
this(header.getInputStream(),
|
||||||
parseDelimiter(header.getHeader("Content-type")),
|
parseDelimiter(header.getHeader("Content-type")),
|
||||||
Long.parseLong(header.getHeader("Content-Length")));
|
Long.parseLong(header.getHeader("Content-Length")));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String parseDelimiter(String contentTypeHeader){
|
private static String parseDelimiter(String contentTypeHeader){
|
||||||
String delimiter = contentTypeHeader.split(" *; *")[1];
|
String delimiter = contentTypeHeader.split(" *; *")[1];
|
||||||
|
|
@ -78,18 +78,18 @@ public class MultipartParser implements Iterable<MultipartField>{
|
||||||
return delimiter;
|
return delimiter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getContentLength(){
|
public long getContentLength(){
|
||||||
return contentLength;
|
return contentLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<MultipartField> iterator() {
|
public Iterator<MultipartField> iterator() {
|
||||||
if (iterator == null)
|
if (iterator == null)
|
||||||
iterator = new MultiPartIterator();
|
iterator = new MultiPartIterator();
|
||||||
return iterator;
|
return iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected class MultiPartIterator implements Iterator<MultipartField>{
|
protected class MultiPartIterator implements Iterator<MultipartField>{
|
||||||
|
|
|
||||||
|
|
@ -35,43 +35,43 @@ import java.nio.channels.spi.SelectorProvider;
|
||||||
|
|
||||||
|
|
||||||
public class NioClient extends NioNetwork{
|
public class NioClient extends NioNetwork{
|
||||||
private InetSocketAddress remoteAddress;
|
private InetSocketAddress remoteAddress;
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a NioClient that connects to a server
|
|
||||||
*
|
|
||||||
* @param remoteAddress the server address
|
|
||||||
* @param remotePort the port to listen on
|
|
||||||
*/
|
|
||||||
public NioClient(InetAddress remoteAddress, int remotePort) throws IOException {
|
|
||||||
this.remoteAddress = new InetSocketAddress(remoteAddress, remotePort);
|
|
||||||
connect(this.remoteAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Selector initSelector() throws IOException {
|
/**
|
||||||
// Create a new selector
|
* Creates a NioClient that connects to a server
|
||||||
return SelectorProvider.provider().openSelector();
|
*
|
||||||
}
|
* @param remoteAddress the server address
|
||||||
|
* @param remotePort the port to listen on
|
||||||
/**
|
*/
|
||||||
* Sends a Message to the connected server
|
public NioClient(InetAddress remoteAddress, int remotePort) throws IOException {
|
||||||
*
|
this.remoteAddress = new InetSocketAddress(remoteAddress, remotePort);
|
||||||
* @param data the data to be sent
|
connect(this.remoteAddress);
|
||||||
*/
|
}
|
||||||
public void send(Message data) throws IOException {
|
|
||||||
send(remoteAddress, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
protected Selector initSelector() throws IOException {
|
||||||
* Sends a Message to the connected server
|
// Create a new selector
|
||||||
*
|
return SelectorProvider.provider().openSelector();
|
||||||
* @param data the data to be sent
|
}
|
||||||
*/
|
|
||||||
public void send(byte[] data) throws IOException {
|
|
||||||
send(remoteAddress, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SocketAddress getRemoteAddress(){
|
/**
|
||||||
return remoteAddress;
|
* Sends a Message to the connected server
|
||||||
|
*
|
||||||
|
* @param data the data to be sent
|
||||||
|
*/
|
||||||
|
public void send(Message data) throws IOException {
|
||||||
|
send(remoteAddress, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a Message to the connected server
|
||||||
|
*
|
||||||
|
* @param data the data to be sent
|
||||||
|
*/
|
||||||
|
public void send(byte[] data) throws IOException {
|
||||||
|
send(remoteAddress, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SocketAddress getRemoteAddress(){
|
||||||
|
return remoteAddress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,33 +43,33 @@ import java.util.logging.Logger;
|
||||||
|
|
||||||
|
|
||||||
public abstract class NioNetwork implements Runnable {
|
public abstract class NioNetwork implements Runnable {
|
||||||
private static Logger logger = LogUtil.getLogger();
|
private static Logger logger = LogUtil.getLogger();
|
||||||
|
|
||||||
protected SocketAddress localAddress;
|
protected SocketAddress localAddress;
|
||||||
// The channel on which we'll accept connections
|
// The channel on which we'll accept connections
|
||||||
protected ServerSocketChannel serverChannel;
|
protected ServerSocketChannel serverChannel;
|
||||||
// The selector we will be monitoring
|
// The selector we will be monitoring
|
||||||
private Selector selector;
|
private Selector selector;
|
||||||
// The buffer into which we'll read data when it's available
|
// The buffer into which we'll read data when it's available
|
||||||
private ByteBuffer readBuffer = ByteBuffer.allocate(8192);
|
private ByteBuffer readBuffer = ByteBuffer.allocate(8192);
|
||||||
protected Worker worker;
|
protected Worker worker;
|
||||||
|
|
||||||
// This map contains all the clients that are connected
|
// This map contains all the clients that are connected
|
||||||
protected Map<InetSocketAddress, ClientData> clients = new HashMap<InetSocketAddress, ClientData>();
|
protected Map<InetSocketAddress, ClientData> clients = new HashMap<InetSocketAddress, ClientData>();
|
||||||
|
|
||||||
// A list of PendingChange instances
|
// A list of PendingChange instances
|
||||||
private List<ChangeRequest> pendingChanges = new LinkedList<ChangeRequest>();
|
private List<ChangeRequest> pendingChanges = new LinkedList<ChangeRequest>();
|
||||||
// Maps a SocketChannel to a list of ByteBuffer instances
|
// Maps a SocketChannel to a list of ByteBuffer instances
|
||||||
private Map<SocketChannel, List<ByteBuffer>> pendingWriteData = new HashMap<SocketChannel, List<ByteBuffer>>();
|
private Map<SocketChannel, List<ByteBuffer>> pendingWriteData = new HashMap<SocketChannel, List<ByteBuffer>>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a client based Network object
|
* Create a client based Network object
|
||||||
*/
|
*/
|
||||||
public NioNetwork() throws IOException {
|
public NioNetwork() throws IOException {
|
||||||
this(null);
|
this(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a server based Network object
|
* Create a server based Network object
|
||||||
|
|
@ -77,25 +77,25 @@ public abstract class NioNetwork implements Runnable {
|
||||||
* @param localAddress the address the server will listen on
|
* @param localAddress the address the server will listen on
|
||||||
*/
|
*/
|
||||||
public NioNetwork(SocketAddress localAddress) throws IOException {
|
public NioNetwork(SocketAddress localAddress) throws IOException {
|
||||||
this.localAddress = localAddress;
|
this.localAddress = localAddress;
|
||||||
// init selector
|
// init selector
|
||||||
this.selector = initSelector();
|
this.selector = initSelector();
|
||||||
// init traffic thread
|
// init traffic thread
|
||||||
new Thread(this).start();
|
new Thread(this).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract Selector initSelector() throws IOException;
|
protected abstract Selector initSelector() throws IOException;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the default worker for non System messages.
|
* Sets the default worker for non System messages.
|
||||||
*
|
*
|
||||||
* @param worker the worker that should handle incoming messages
|
* @param worker the worker that should handle incoming messages
|
||||||
*/
|
*/
|
||||||
public void setDefaultWorker(Worker worker){
|
public void setDefaultWorker(Worker worker){
|
||||||
this.worker = worker;
|
this.worker = worker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -118,9 +118,9 @@ public abstract class NioNetwork implements Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void send(SocketAddress address, Object data) throws IOException{
|
public void send(SocketAddress address, Object data) throws IOException{
|
||||||
send(address, Converter.toBytes(data));
|
send(address, Converter.toBytes(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queues a message to be sent
|
* Queues a message to be sent
|
||||||
|
|
@ -128,61 +128,61 @@ public abstract class NioNetwork implements Runnable {
|
||||||
* @param address the target address where the message should be sent
|
* @param address the target address where the message should be sent
|
||||||
* @param data the data to send
|
* @param data the data to send
|
||||||
*/
|
*/
|
||||||
public void send(SocketAddress address, byte[] data){
|
public void send(SocketAddress address, byte[] data){
|
||||||
logger.finest("Sending Queue...");
|
logger.finest("Sending Queue...");
|
||||||
SocketChannel socket = getSocketChannel(address);
|
SocketChannel socket = getSocketChannel(address);
|
||||||
|
|
||||||
// And queue the data we want written
|
// And queue the data we want written
|
||||||
synchronized (pendingWriteData) {
|
synchronized (pendingWriteData) {
|
||||||
List<ByteBuffer> queue = pendingWriteData.get(socket);
|
List<ByteBuffer> queue = pendingWriteData.get(socket);
|
||||||
if (queue == null) {
|
if (queue == null) {
|
||||||
queue = new ArrayList<>();
|
queue = new ArrayList<>();
|
||||||
pendingWriteData.put(socket, queue);
|
pendingWriteData.put(socket, queue);
|
||||||
}
|
}
|
||||||
queue.add(ByteBuffer.wrap(data));
|
queue.add(ByteBuffer.wrap(data));
|
||||||
}
|
}
|
||||||
// Changing the key state to write
|
// Changing the key state to write
|
||||||
synchronized (pendingChanges) {
|
synchronized (pendingChanges) {
|
||||||
// Indicate we want the interest ops set changed
|
// Indicate we want the interest ops set changed
|
||||||
pendingChanges.add(new ChangeRequest(socket, ChangeRequest.CHANGEOPS, SelectionKey.OP_WRITE));
|
pendingChanges.add(new ChangeRequest(socket, ChangeRequest.CHANGEOPS, SelectionKey.OP_WRITE));
|
||||||
}
|
}
|
||||||
// Finally, wake up our selecting thread so it can make the required changes
|
// Finally, wake up our selecting thread so it can make the required changes
|
||||||
selector.wakeup();
|
selector.wakeup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
logger.info("NioNetwork Started.");
|
logger.info("NioNetwork Started.");
|
||||||
while (selector.isOpen()) {
|
while (selector.isOpen()) {
|
||||||
try {
|
try {
|
||||||
// Handle any pending changes
|
// Handle any pending changes
|
||||||
synchronized (pendingChanges) {
|
synchronized (pendingChanges) {
|
||||||
Iterator<ChangeRequest> changes = pendingChanges.iterator();
|
Iterator<ChangeRequest> changes = pendingChanges.iterator();
|
||||||
while (changes.hasNext()) {
|
while (changes.hasNext()) {
|
||||||
ChangeRequest change = changes.next();
|
ChangeRequest change = changes.next();
|
||||||
switch (change.type) {
|
switch (change.type) {
|
||||||
case ChangeRequest.CHANGEOPS:
|
case ChangeRequest.CHANGEOPS:
|
||||||
SelectionKey key = change.socket.keyFor(selector);
|
SelectionKey key = change.socket.keyFor(selector);
|
||||||
key.interestOps(change.ops);
|
key.interestOps(change.ops);
|
||||||
logger.finest("change.ops "+change.ops);
|
logger.finest("change.ops "+change.ops);
|
||||||
break;
|
break;
|
||||||
case ChangeRequest.REGISTER:
|
case ChangeRequest.REGISTER:
|
||||||
change.socket.register(selector, change.ops);
|
change.socket.register(selector, change.ops);
|
||||||
logger.finest("register socket ");
|
logger.finest("register socket ");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pendingChanges.clear();
|
pendingChanges.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for an event from one of the channels
|
// Wait for an event from one of the channels
|
||||||
selector.select();
|
selector.select();
|
||||||
logger.finest("selector is awake");
|
logger.finest("selector is awake");
|
||||||
|
|
||||||
// Iterate over the set of keys for which events are available
|
// Iterate over the set of keys for which events are available
|
||||||
if (selector.isOpen()) {
|
if (selector.isOpen()) {
|
||||||
Iterator<SelectionKey> selectedKeys = selector.selectedKeys().iterator();
|
Iterator<SelectionKey> selectedKeys = selector.selectedKeys().iterator();
|
||||||
while (selectedKeys.hasNext()) {
|
while (selectedKeys.hasNext()) {
|
||||||
|
|
@ -208,33 +208,33 @@ public abstract class NioNetwork implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.info("Shutting down NioNetwork");
|
logger.info("Shutting down NioNetwork");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle an accept event from a remote host. Channel can only be a server socket.
|
* Handle an accept event from a remote host. Channel can only be a server socket.
|
||||||
*/
|
*/
|
||||||
private void accept(SelectionKey key) throws IOException {
|
private void accept(SelectionKey key) throws IOException {
|
||||||
// For an accept to be pending the channel must be a server socket channel.
|
// For an accept to be pending the channel must be a server socket channel.
|
||||||
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
|
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
|
||||||
|
|
||||||
// Accept the connection and make it non-blocking
|
// Accept the connection and make it non-blocking
|
||||||
SocketChannel socketChannel = serverSocketChannel.accept();
|
SocketChannel socketChannel = serverSocketChannel.accept();
|
||||||
socketChannel.socket().setReuseAddress(true);
|
socketChannel.socket().setReuseAddress(true);
|
||||||
socketChannel.configureBlocking(false);
|
socketChannel.configureBlocking(false);
|
||||||
|
|
||||||
// Register the new SocketChannel with our Selector, indicating
|
// Register the new SocketChannel with our Selector, indicating
|
||||||
// we'd like to be notified when there's data waiting to be read
|
// we'd like to be notified when there's data waiting to be read
|
||||||
socketChannel.register(selector, SelectionKey.OP_READ);
|
socketChannel.register(selector, SelectionKey.OP_READ);
|
||||||
|
|
||||||
// adds the client to the clients list
|
// adds the client to the clients list
|
||||||
registerSocketChannel(socketChannel);
|
registerSocketChannel(socketChannel);
|
||||||
logger.fine("New Connection("+socketChannel.getRemoteAddress()+")!!! Count: "+clients.size());
|
logger.fine("New Connection("+socketChannel.getRemoteAddress()+")!!! Count: "+clients.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finnish an ongoing remote connection establishment procedure
|
* Finnish an ongoing remote connection establishment procedure
|
||||||
|
|
@ -291,47 +291,47 @@ public abstract class NioNetwork implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a read event from a socket specified by the key.
|
* Handle a read event from a socket specified by the key.
|
||||||
*/
|
*/
|
||||||
private void read(SelectionKey key) throws IOException {
|
private void read(SelectionKey key) throws IOException {
|
||||||
SocketChannel socketChannel = (SocketChannel) key.channel();
|
SocketChannel socketChannel = (SocketChannel) key.channel();
|
||||||
SocketAddress remoteAdr = socketChannel.socket().getRemoteSocketAddress();
|
SocketAddress remoteAdr = socketChannel.socket().getRemoteSocketAddress();
|
||||||
|
|
||||||
// Clear out our read buffer so it's ready for new data
|
// Clear out our read buffer so it's ready for new data
|
||||||
readBuffer.clear();
|
readBuffer.clear();
|
||||||
|
|
||||||
// Attempt to read off the channel
|
// Attempt to read off the channel
|
||||||
int numRead;
|
int numRead;
|
||||||
try {
|
try {
|
||||||
numRead = socketChannel.read(readBuffer);
|
numRead = socketChannel.read(readBuffer);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// The remote forcibly closed the connection, cancel
|
// The remote forcibly closed the connection, cancel
|
||||||
// the selection key and close the channel.
|
// the selection key and close the channel.
|
||||||
key.cancel();
|
key.cancel();
|
||||||
socketChannel.close();
|
socketChannel.close();
|
||||||
clients.remove(remoteAdr);
|
clients.remove(remoteAdr);
|
||||||
pendingWriteData.remove(socketChannel);
|
pendingWriteData.remove(socketChannel);
|
||||||
logger.fine("Connection forcibly closed("+remoteAdr+")! Remaining connections: "+clients.size());
|
logger.fine("Connection forcibly closed("+remoteAdr+")! Remaining connections: "+clients.size());
|
||||||
throw new IOException("Remote forcibly closed the connection");
|
throw new IOException("Remote forcibly closed the connection");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numRead == -1) {
|
if (numRead == -1) {
|
||||||
// Remote entity shut the socket down cleanly. Do the
|
// Remote entity shut the socket down cleanly. Do the
|
||||||
// same from our end and cancel the channel.
|
// same from our end and cancel the channel.
|
||||||
key.channel().close();
|
key.channel().close();
|
||||||
key.cancel();
|
key.cancel();
|
||||||
clients.remove(remoteAdr);
|
clients.remove(remoteAdr);
|
||||||
pendingWriteData.remove(socketChannel);
|
pendingWriteData.remove(socketChannel);
|
||||||
logger.fine("Connection Closed("+remoteAdr+")! Remaining connections: "+clients.size());
|
logger.fine("Connection Closed("+remoteAdr+")! Remaining connections: "+clients.size());
|
||||||
throw new IOException("Remote closed the connection");
|
throw new IOException("Remote closed the connection");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a correctly sized copy of the data before handing it to the client
|
// Make a correctly sized copy of the data before handing it to the client
|
||||||
//byte[] rspByteData = new byte[numRead];
|
//byte[] rspByteData = new byte[numRead];
|
||||||
//System.arraycopy(readBuffer.array(), 0, rspByteData, 0, numRead);
|
//System.arraycopy(readBuffer.array(), 0, rspByteData, 0, numRead);
|
||||||
|
|
||||||
try{
|
try{
|
||||||
Object rspData = Converter.toObject(readBuffer.array());
|
Object rspData = Converter.toObject(readBuffer.array());
|
||||||
|
|
||||||
// Hand the data off to our worker thread
|
// Hand the data off to our worker thread
|
||||||
|
|
@ -341,10 +341,10 @@ public abstract class NioNetwork implements Runnable {
|
||||||
} else {
|
} else {
|
||||||
logger.fine("No worker set, message unhandled!");
|
logger.fine("No worker set, message unhandled!");
|
||||||
}
|
}
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -370,22 +370,22 @@ public abstract class NioNetwork implements Runnable {
|
||||||
closeConnection(getSocketChannel(address));
|
closeConnection(getSocketChannel(address));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closeConnection(SocketChannel socketChannel) throws IOException{
|
private void closeConnection(SocketChannel socketChannel) throws IOException{
|
||||||
socketChannel.close();
|
socketChannel.close();
|
||||||
socketChannel.keyFor(selector).cancel();
|
socketChannel.keyFor(selector).cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close all connections
|
* Close all connections
|
||||||
*/
|
*/
|
||||||
public void close() throws IOException{
|
public void close() throws IOException{
|
||||||
if(serverChannel != null){
|
if(serverChannel != null){
|
||||||
serverChannel.close();
|
serverChannel.close();
|
||||||
serverChannel.keyFor(selector).cancel();
|
serverChannel.keyFor(selector).cancel();
|
||||||
}
|
}
|
||||||
clients.clear();
|
clients.clear();
|
||||||
pendingChanges.clear();
|
pendingChanges.clear();
|
||||||
pendingWriteData.clear();
|
pendingWriteData.clear();
|
||||||
selector.close();
|
selector.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,56 +35,56 @@ import java.util.Iterator;
|
||||||
|
|
||||||
public class NioServer extends NioNetwork{
|
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(new InetSocketAddress(address, port));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Selector initSelector() throws IOException {
|
/**
|
||||||
// Create a new selector
|
* Creates a NioServer object which listens on localhost
|
||||||
Selector socketSelector = SelectorProvider.provider().openSelector();
|
*
|
||||||
|
* @param port the port to listen to
|
||||||
|
*/
|
||||||
|
public NioServer(int port) throws IOException {
|
||||||
|
this(null, port);
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new non-blocking server socket channel
|
/**
|
||||||
serverChannel = ServerSocketChannel.open();
|
* Creates a NioServer object which listens to a specific address
|
||||||
serverChannel.socket().setReuseAddress(true);
|
*
|
||||||
serverChannel.configureBlocking(false);
|
* @param address the address to listen to
|
||||||
|
* @param port the port to listen to
|
||||||
|
*/
|
||||||
|
public NioServer(InetAddress address, int port) throws IOException {
|
||||||
|
super(new InetSocketAddress(address, port));
|
||||||
|
}
|
||||||
|
|
||||||
// Bind the server socket to the specified address and port
|
protected Selector initSelector() throws IOException {
|
||||||
serverChannel.socket().bind(localAddress);
|
// Create a new selector
|
||||||
|
Selector socketSelector = SelectorProvider.provider().openSelector();
|
||||||
|
|
||||||
// Register the server socket channel, indicating an interest in
|
// Create a new non-blocking server socket channel
|
||||||
// accepting new connections
|
serverChannel = ServerSocketChannel.open();
|
||||||
serverChannel.register(socketSelector, SelectionKey.OP_ACCEPT);
|
serverChannel.socket().setReuseAddress(true);
|
||||||
|
serverChannel.configureBlocking(false);
|
||||||
|
|
||||||
return socketSelector;
|
// Bind the server socket to the specified address and port
|
||||||
}
|
serverChannel.socket().bind(localAddress);
|
||||||
|
|
||||||
|
// 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){
|
||||||
|
for(InetSocketAddress target : clients.keySet()){
|
||||||
|
send(target, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Broadcasts the message to all the connected clients
|
|
||||||
*
|
|
||||||
* @param data the data to broadcast
|
|
||||||
*/
|
|
||||||
public void broadcast(byte[] data){
|
|
||||||
synchronized(clients){
|
|
||||||
for(InetSocketAddress target : clients.keySet()){
|
|
||||||
send(target, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,22 +30,22 @@ package zutil.net.nio.message;
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*/
|
*/
|
||||||
public abstract class EchoMessage implements Message{
|
public abstract class EchoMessage implements Message{
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private boolean echo = false;
|
private boolean echo = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this message is an echo/copy of an original message
|
* @return true if this message is an echo/copy of an original message
|
||||||
*/
|
*/
|
||||||
public boolean echo() {
|
public boolean echo() {
|
||||||
return echo;
|
return echo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the receiver to mark this message as an echo copy
|
* Called by the receiver to mark this message as an echo copy
|
||||||
*/
|
*/
|
||||||
public void received() {
|
public void received() {
|
||||||
echo = true;
|
echo = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,9 @@ package zutil.net.nio.response;
|
||||||
|
|
||||||
public class PrintResponseHandler extends ResponseHandler {
|
public class PrintResponseHandler extends ResponseHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void responseEvent(Object rsp) {
|
protected void responseEvent(Object rsp) {
|
||||||
System.out.println(rsp);
|
System.out.println(rsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,9 @@ package zutil.net.nio.response;
|
||||||
*/
|
*/
|
||||||
public interface RequestResponseMessage {
|
public interface RequestResponseMessage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a unique id for this message
|
* @return a unique id for this message
|
||||||
*/
|
*/
|
||||||
long getResponseId();
|
long getResponseId();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,33 +26,33 @@ package zutil.net.nio.response;
|
||||||
|
|
||||||
// TODO: this class has a strange structure, should be refactored
|
// TODO: this class has a strange structure, should be refactored
|
||||||
public abstract class ResponseHandler {
|
public abstract class ResponseHandler {
|
||||||
private Object rsp = null;
|
private Object rsp = null;
|
||||||
|
|
||||||
public synchronized void handleResponse(Object rsp) {
|
public synchronized void handleResponse(Object rsp) {
|
||||||
this.rsp = rsp;
|
this.rsp = rsp;
|
||||||
responseEvent(rsp);
|
responseEvent(rsp);
|
||||||
notify();
|
notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Blocks the calling thread until there is a response
|
* Blocks the calling thread until there is a response
|
||||||
*/
|
*/
|
||||||
public void waitForResponse() {
|
public void waitForResponse() {
|
||||||
while(!gotResponse()) {
|
while(!gotResponse()) {
|
||||||
try {
|
try {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
this.wait();
|
this.wait();
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {}
|
} catch (InterruptedException e) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if a response has been received
|
* @return true if a response has been received
|
||||||
*/
|
*/
|
||||||
public boolean gotResponse(){
|
public boolean gotResponse(){
|
||||||
return (rsp != null);
|
return (rsp != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void responseEvent(Object rsp);
|
protected abstract void responseEvent(Object rsp);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,27 +28,27 @@ package zutil.net.nio.response;
|
||||||
import zutil.net.nio.message.EchoMessage;
|
import zutil.net.nio.message.EchoMessage;
|
||||||
|
|
||||||
public class StringResponseMessage extends EchoMessage implements RequestResponseMessage {
|
public class StringResponseMessage extends EchoMessage implements RequestResponseMessage {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private long responseId;
|
private long responseId;
|
||||||
private String msg;
|
private String msg;
|
||||||
|
|
||||||
|
|
||||||
public StringResponseMessage(String msg){
|
public StringResponseMessage(String msg){
|
||||||
this.msg = msg;
|
this.msg = msg;
|
||||||
responseId = (long)(Math.random()*Long.MAX_VALUE);
|
responseId = (long)(Math.random()*Long.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public long getResponseId() {
|
public long getResponseId() {
|
||||||
return responseId;
|
return responseId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setString(String msg){
|
public void setString(String msg){
|
||||||
this.msg = msg;
|
this.msg = msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -28,17 +28,17 @@ import java.nio.channels.SocketChannel;
|
||||||
|
|
||||||
|
|
||||||
public class ChangeRequest {
|
public class ChangeRequest {
|
||||||
public static final int REGISTER = 1;
|
public static final int REGISTER = 1;
|
||||||
public static final int CHANGEOPS = 2;
|
public static final int CHANGEOPS = 2;
|
||||||
|
|
||||||
public SocketChannel socket;
|
public SocketChannel socket;
|
||||||
public int type;
|
public int type;
|
||||||
public int ops;
|
public int ops;
|
||||||
|
|
||||||
|
|
||||||
public ChangeRequest(SocketChannel socket, int type, int ops) {
|
public ChangeRequest(SocketChannel socket, int type, int ops) {
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.ops = ops;
|
this.ops = ops;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,28 +28,28 @@ import java.net.InetSocketAddress;
|
||||||
import java.nio.channels.SocketChannel;
|
import java.nio.channels.SocketChannel;
|
||||||
|
|
||||||
public class ClientData {
|
public class ClientData {
|
||||||
private SocketChannel socketChannel;
|
private SocketChannel socketChannel;
|
||||||
private long lastMessageReceived;
|
private long lastMessageReceived;
|
||||||
|
|
||||||
|
|
||||||
public ClientData(SocketChannel socketChannel){
|
public ClientData(SocketChannel socketChannel){
|
||||||
this.socketChannel = socketChannel;
|
this.socketChannel = socketChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public SocketChannel getSocketChannel(){
|
public SocketChannel getSocketChannel(){
|
||||||
return socketChannel;
|
return socketChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InetSocketAddress getAddress(){
|
public InetSocketAddress getAddress(){
|
||||||
return (InetSocketAddress) socketChannel.socket().getRemoteSocketAddress();
|
return (InetSocketAddress) socketChannel.socket().getRemoteSocketAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLastMessageReceived(long time){
|
public void setLastMessageReceived(long time){
|
||||||
lastMessageReceived = time;
|
lastMessageReceived = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLastMessageReceived(){
|
public long getLastMessageReceived(){
|
||||||
return lastMessageReceived;
|
return lastMessageReceived;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,29 +40,29 @@ import java.util.logging.Logger;
|
||||||
|
|
||||||
|
|
||||||
public class StandardWorker extends ThreadedEventWorker {
|
public class StandardWorker extends ThreadedEventWorker {
|
||||||
private static Logger logger = LogUtil.getLogger();
|
private static Logger logger = LogUtil.getLogger();
|
||||||
|
|
||||||
private NioNetwork nio;
|
private NioNetwork nio;
|
||||||
// Maps a responseId to a RspHandler
|
// Maps a responseId to a RspHandler
|
||||||
private Map<Long, ResponseHandler> rspEvents = new HashMap<>();
|
private Map<Long, ResponseHandler> rspEvents = new HashMap<>();
|
||||||
// Different services listening on specific messages
|
// Different services listening on specific messages
|
||||||
private Map<Class<?>, ThreadedEventWorker> services = new HashMap<>();
|
private Map<Class<?>, ThreadedEventWorker> services = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new StandardWorker
|
* Creates a new StandardWorker
|
||||||
*/
|
*/
|
||||||
public StandardWorker(NioNetwork nio){
|
public StandardWorker(NioNetwork nio){
|
||||||
this.nio = nio;
|
this.nio = nio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageEvent(WorkerEventData event) {
|
public void messageEvent(WorkerEventData event) {
|
||||||
try {
|
try {
|
||||||
logger.finer("Message: "+event.data.getClass().getName());
|
logger.finer("Message: "+event.data.getClass().getName());
|
||||||
|
|
||||||
if(event.data instanceof EchoMessage && !((EchoMessage)event.data).echo()){
|
if(event.data instanceof EchoMessage && !((EchoMessage)event.data).echo()){
|
||||||
// Echo back the received message
|
// Echo back the received message
|
||||||
|
|
@ -86,29 +86,29 @@ public class StandardWorker extends ThreadedEventWorker {
|
||||||
services.get(event.data.getClass()).messageEvent(event);
|
services.get(event.data.getClass()).messageEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a Worker to a specific message
|
* Maps a Worker to a specific message
|
||||||
*
|
*
|
||||||
* @param messageClass the received message class
|
|
||||||
* @param worker the worker that should handle the specified message type
|
|
||||||
*/
|
|
||||||
public void registerWorker(Class<?> messageClass, ThreadedEventWorker worker){
|
|
||||||
services.put(messageClass, worker);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Un-maps a message class to a worker
|
|
||||||
*
|
|
||||||
* @param messageClass the received message class
|
* @param messageClass the received message class
|
||||||
*/
|
* @param worker the worker that should handle the specified message type
|
||||||
public void unregisterWorker(Class<?> messageClass){
|
*/
|
||||||
services.remove(messageClass);
|
public void registerWorker(Class<?> messageClass, ThreadedEventWorker worker){
|
||||||
}
|
services.put(messageClass, worker);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Un-maps a message class to a worker
|
||||||
|
*
|
||||||
|
* @param messageClass the received message class
|
||||||
|
*/
|
||||||
|
public void unregisterWorker(Class<?> messageClass){
|
||||||
|
services.remove(messageClass);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a message with a defined response handler
|
* Send a message with a defined response handler
|
||||||
|
|
@ -117,10 +117,10 @@ public class StandardWorker extends ThreadedEventWorker {
|
||||||
* @param message the message object
|
* @param message the message object
|
||||||
* @param handler the handler that should be called when a response is received
|
* @param handler the handler that should be called when a response is received
|
||||||
*/
|
*/
|
||||||
public void send(SocketAddress address, RequestResponseMessage message, ResponseHandler handler) throws IOException {
|
public void send(SocketAddress address, RequestResponseMessage message, ResponseHandler handler) throws IOException {
|
||||||
// Register the response handler
|
// Register the response handler
|
||||||
rspEvents.put(message.getResponseId(), handler);
|
rspEvents.put(message.getResponseId(), handler);
|
||||||
|
|
||||||
nio.send(address, Converter.toBytes(message));
|
nio.send(address, Converter.toBytes(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,24 +25,24 @@
|
||||||
package zutil.net.nio.worker;
|
package zutil.net.nio.worker;
|
||||||
|
|
||||||
public abstract class ThreadedEventWorker extends Worker implements Runnable{
|
public abstract class ThreadedEventWorker extends Worker implements Runnable{
|
||||||
private Thread thread;
|
private Thread thread;
|
||||||
|
|
||||||
public ThreadedEventWorker(){
|
public ThreadedEventWorker(){
|
||||||
thread = new Thread(this);
|
thread = new Thread(this);
|
||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
while(true) {
|
while(true) {
|
||||||
try{
|
try{
|
||||||
// Wait for data to become available
|
// Wait for data to become available
|
||||||
messageEvent(pollEvent());
|
messageEvent(pollEvent());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public abstract void messageEvent(WorkerEventData e);
|
public abstract void messageEvent(WorkerEventData e);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,37 +32,37 @@ import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
public abstract class Worker {
|
public abstract class Worker {
|
||||||
private LinkedList<WorkerEventData> queue = new LinkedList<>();
|
private LinkedList<WorkerEventData> queue = new LinkedList<>();
|
||||||
|
|
||||||
|
|
||||||
public void processData(NioNetwork server, SocketAddress remote, Object data) {
|
public void processData(NioNetwork server, SocketAddress remote, Object data) {
|
||||||
synchronized(queue) {
|
synchronized(queue) {
|
||||||
queue.add(new WorkerEventData(server, remote, data));
|
queue.add(new WorkerEventData(server, remote, data));
|
||||||
queue.notify();
|
queue.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if there is a event in the queue
|
/**
|
||||||
*/
|
* @return true if there is a event in the queue
|
||||||
protected boolean hasEvent(){
|
*/
|
||||||
return !queue.isEmpty();
|
protected boolean hasEvent(){
|
||||||
}
|
return !queue.isEmpty();
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Polls a event from the list or blocks until there is a event available
|
/**
|
||||||
|
* Polls a event from the list or blocks until there is a event available
|
||||||
*
|
*
|
||||||
* @return the next event
|
* @return the next event
|
||||||
*/
|
*/
|
||||||
protected WorkerEventData pollEvent(){
|
protected WorkerEventData pollEvent(){
|
||||||
synchronized(queue) {
|
synchronized(queue) {
|
||||||
while (queue.isEmpty()) {
|
while (queue.isEmpty()) {
|
||||||
try {
|
try {
|
||||||
queue.wait();
|
queue.wait();
|
||||||
} catch (InterruptedException e) {}
|
} catch (InterruptedException e) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return queue.poll();
|
return queue.poll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,14 +31,14 @@ import java.nio.channels.SocketChannel;
|
||||||
|
|
||||||
|
|
||||||
public class WorkerEventData {
|
public class WorkerEventData {
|
||||||
public NioNetwork network;
|
public NioNetwork network;
|
||||||
public SocketAddress remoteAddress;
|
public SocketAddress remoteAddress;
|
||||||
public Object data;
|
public Object data;
|
||||||
|
|
||||||
|
|
||||||
public WorkerEventData(NioNetwork server, SocketAddress remoteAddress, Object data) {
|
public WorkerEventData(NioNetwork server, SocketAddress remoteAddress, Object data) {
|
||||||
this.network = server;
|
this.network = server;
|
||||||
this.remoteAddress = remoteAddress;
|
this.remoteAddress = remoteAddress;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
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