If you want to pass a policy file to the appletviewer, then use a “-J-Djava.security.policy” argument as follows:
appletviewer -J-Djava.security.policy=someURL myApplet
If you want to pass a policy file to the appletviewer, then use a “-J-Djava.security.policy” argument as follows:
appletviewer -J-Djava.security.policy=someURL myApplet
Ciphers process data in blocks, for example 8 byte blocks. If the length of the data that you want to encrypt is not evenly divisible by the blocksize that your encryption algorithm uses, the data needs to be padded. PKCS#5 is one way of padding. It appends to every message a block of data varying from 1 to 8 bytes where each bytes contain the number of bytes that are padded.
For instance, if the length of the data is 10, then 6 bytes need to be padded. The last block of 8 bytes will look like this:
+---+---+---+---+---+---+---+---+ | D | D | 6 | 6 | 6 | 6 | 6 | 6 | +---+---+---+---+---+---+---+---+
If the length of your data happens to be evenly divisible by 8, an extra 8 bytes will be added looking like this:
+---+---+---+---+---+---+---+---+ | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | +---+---+---+---+---+---+---+---+
This is because PKCS5Padding always assumes there is a pad.
Triple-DES or DESede is an improvement over DES (Data Encryption Standard). It uses three DES keys k1, k2 and k3. A message is encrypted with k1 first, then decrypted with k2 and encrypted again with k3 (DESencryptiondecryptionencryption). This increases security as the key length effectively increases from 56 to 112 or 168 (two or three keys may be used in DESede). As a programmer you don’t have to worry about managing several keys, they are all encoded into one key.
The DESede key size is 128 or 192 bit and block size 64 bit.
Eventually, DES and Triple-DES will be replaced by the Advanced Encryption Standard (AES).
Main.java:
import javax.crypto.spec.*; import java.security.*; import javax.crypto.*; public class Main { public static void main(String []args) throws Exception { String toEncrypt = "The shorter you live, the longer you're dead!"; System.out.println("Encrypting..."); byte[] encrypted = encrypt(toEncrypt, "password"); System.out.println("Decrypting..."); String decrypted = decrypt(encrypted, "password"); System.out.println("Decrypted text: " + decrypted); } public static byte[] encrypt(String toEncrypt, String key) throws Exception { // create a binary key from the argument key (seed) SecureRandom sr = new SecureRandom(key.getBytes()); KeyGenerator kg = KeyGenerator.getInstance("DESede"); kg.init(sr); SecretKey sk = kg.generateKey(); // create an instance of cipher Cipher cipher = Cipher.getInstance("DESede"); // initialize the cipher with the key cipher.init(Cipher.ENCRYPT_MODE, sk); // enctypt! byte[] encrypted = cipher.doFinal(toEncrypt.getBytes()); return encrypted; } public static String decrypt(byte[] toDecrypt, String key) throws Exception { // create a binary key from the argument key (seed) SecureRandom sr = new SecureRandom(key.getBytes()); KeyGenerator kg = KeyGenerator.getInstance("DESede"); kg.init(sr); SecretKey sk = kg.generateKey(); // do the decryption with that key Cipher cipher = Cipher.getInstance("DESede"); cipher.init(Cipher.DECRYPT_MODE, sk); byte[] decrypted = cipher.doFinal(toDecrypt); return new String(decrypted); } }
(tested with the BouncyCastle JCE provider, http://www.bouncycastle.org)
To create a client and a server that exchange encrypted messages, you can use the JSSE package that can be downloaded as an optional package or comes standard with JDK1.4. I’ll assume your have correctly downloaded and installed the package or are using JDK1.4.
SSL stands for Secure Socket Layer. It contains a handshake protocol where two parties exchange a series of messages to agree on a symmetric key that will be used to encrypt the rest of the messages that are exchanged throughout the session. The problem is how to let the other party know what key to use. There can always be someone spying on the messages that are sent over the network.
The solution is to use public/private key cryptography. A message encrypted with a private key can be decrypted with the associated public key and vice versa. Only one party holds his own private key and can distribute his public key to anyone, even the spy. The other party encrypts the message with the public key and sends it to the other party, which is the only one that can decrypt the message as he, and only he, holds the private key.
Party A could encrypt the symmetric key information using the public key of party B and sends him this info. Party B decrypts it and obtaines that symmetric key which they both will use during the session.
To ensure that the public key of the Party B actually belongs to him, and is not something made up of a spy claiming he is party B, he can use a public-key certificate. A public-key certificate is issued by a certification authority (CA) which you typically have to pay a couple hundred dollars and provide proof of identity in order to obtain it.
In short, the whole process goes like this.
Assume Party B is the server and party A the client.
One more thing: even though messages are send encrypted, a spy may still tamper with the data that flows between A and B. To ensure data integrity, messages are appended with an HMAC before being encrypted. The result of an HMAC (Message Authentication Code) is a small series of bytes that can be used to detect the slightest change in data, even if it’s only one bit. The whole shebang (message + HMAC) are encrypted with the secret symmetric key and is send over. The receiver then decrypts the message, calculates the HMAC again, and compares it with the one that was send to him.
Writing the server
Instead of creating a ServerSocket using ServerSocket ss = new ServerSocket(port), we would use the SSLServerSocketFactory that creates a ServerSocket that supports SSL. This SSL ServerSocket takes care of all the gory details
For more information, check out the excellent JSSE Sun’s User’s Guide here.
Start of by creating a self-signed certificate that is needed by the server to send back
to the client during the SSL handshake.
C:securityssl>keytool -v -genkey -keyalg RSA -keystore .keystore Enter keystore password: esuspass What is your first and last name? [Unknown]: Joris Van den Bogaert What is the name of your organizational unit? [Unknown]: Esus Team What is the name of your organization? [Unknown]: Esus, Inc What is the name of your City or Locality? [Unknown]: Meerbeek What is the name of your State or Province? [Unknown]: What is the two-letter country code for this unit? [Unknown]: BE Is <CN=Joris Van den Bogaert, OU=Esus Team, O="Esus, Inc", L=Meerbeek, ST=Unkno n, C=BE> correct? [no]: yes Generating 1024 bit RSA key pair and self-signed certificate (MD5WithRSA) for: CN=Joris Van den Bogaert, OU=Esus Team, O="Esus, Inc", L=Meerbeek, ST=Unknown, C=BE Enter key password for <mykey> (RETURN if same as keystore password): [Saving .keystore] C:securityssl>dir .keystore Volume in drive C has no label Volume Serial Number is 1380-0FE3 Directory of C:securityssl KEYSTO~1 1,379 07-24-01 3:53p .keystore 1 file(s) 1,379 bytes 0 dir(s) 146,989,056 bytes free
Here’s the code for SecureServer.java and SecureClient.java:
SecureServer.java:
import javax.net.ssl.*; import java.net.*; import java.io.*; public class SecureServer { private static final int port = 4321; public static void main(String []args) throws Exception { SSLServerSocketFactory ssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); ServerSocket ss = ssf.createServerSocket(port); System.out.println("Ready to accept messages!"); Socket s = ss.accept(); System.out.println("A client has connected!"); DataInputStream dis = new DataInputStream(s.getInputStream()); DataOutputStream dos = new DataOutputStream(s.getOutputStream()); String line = null; try { while (true) { line = dis.readUTF(); System.out.println("Client sent: " + line); dos.writeUTF("You send: " + line); } } finally { dis.close(); dos.close(); s.close(); } } }
SecureClient.java:
import javax.net.ssl.*; import java.net.*; import java.io.*; public class SecureClient { private static final String host = "127.0.0.1"; private static int port = 4321; public static void main(String []args) throws Exception { SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault(); Socket s = sf.createSocket(host, port); DataInputStream dis = new DataInputStream(s.getInputStream()); DataOutputStream dos = new DataOutputStream(s.getOutputStream()); System.out.println("Connected.n"); System.out.println("Type messages to send to server, exit to end!"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line; while ((line = br.readLine()) != null) { if (line.equals("exit")) break; dos.writeUTF(line); dos.flush(); String reply = dis.readUTF(); System.out.println("Server reply: " + reply); } dis.close(); dos.close(); s.close(); } }
Note: change the IP address (127.0.0.1) in SecureClient.java to the IP address where your server is deployed. To test it, we’ll run it all on the same machine.
The file .keystore containing the self-signed certificate should be located on the server’s machine. Put both the files SecureServer.class and .keystore in the directory c:\security\ssl\server and SecureClient.class in c:\securitysslclient.
The server should know where it can find its private key. The keystore can be specified at runtime along with the password in order to access it.
The client needs to have access to the certificate in order to check it. Certain certificates, issued by a Certificate Authority (CA) are automatically trusted (they are saved in the file
1) a trustStore specified in the javax.net.ssl.trustStore property 2) <i><JRE_HOME>/lib/security/jssecacerts</i> 3) <i><JRE_HOME>/lib/security/cacerst</i>
I’ll show you how to run the example by specifying the trustStore at command line, and by adding the certificate to the cacerts file.
First we need to export the certificate:
C:\security\ssl\server> keytool -export -keystore .keystore -file ssltest.cer Enter keystore password: esuspass Certificate stored in file <ssltest.cer>
Running SecureServer and SecureClient by specifying the trustStore
On the client side, create a truststore .trustStore and import certificate contained in the file ssltest.cer:
C:\security\ssl\client>copy ..\server ssltest.cer 1 file(s) copied C:\security\ssl\client>keytool -import -keystore .trustStore -file ssltest.cer Enter keystore password: esuspass Owner: CN=Joris Van den Bogaert, OU=Esus Team, O="Esus, Inc", L=Meerbeek, ST=Unk nown, C=BE Issuer: CN=Joris Van den Bogaert, OU=Esus Team, O="Esus, Inc", L=Meerbeek, ST=Un known, C=BE Serial number: 3b5d7dd7 Valid from: Tue Jul 24 15:53:27 CEST 2001 until: Mon Oct 22 15:53:27 CEST 2001 Certificate fingerprints: MD5: 07:DE:52:94:15:1D:53:88:C5:C5:51:48:0F:AF:83:76 SHA1: A7:92:CF:29:EF:B9:74:05:6F:05:E5:75:4B:78:42:D1:35:8B:D7:55 Trust this certificate? [no]: yes Certificate was added to keystore
Open another terminal to start running the server:
C:\security\ssl\server> c:\jdk1.4\bin\java -Djavax.net.ssl.keyStore=.keystore -Dj avax.net.ssl.keyStorePassword=esuspass SecureServer
Now wait a couple seconds until the server shows up Ready to accept messages!.
Run the client by specifying the trustStore:
C:\security\ssl\client>c:\jdk1.4\bin\java -Djavax.net.ssl.trustStore=.trustStore SecureClient
This is the result at the server’s side:
C:\security\ssl\server> c:\jdk1.4\bin\java -Djavax.net.ssl.keyStore=.keystore -Djavax.net.ssl.keyStorePassword=esuspass SecureServer Ready to accept messages! A client has connected! Client sent: whoever spies on this connection Client sent: can't see crap Client sent: or should i say... only crap EOF!
and the result at the client’s side:
C:\security\ssl\client> c:\jdk1.4\bin\java -Djavax.net.ssl.trustStore=.trustStore SecureClient Connected. Type messages to send to server, exit to end! whoever spies on this connection Server reply: You send: whoever spies on this connection can't see crap Server reply: You send: can't see crap or should i say... only crap Server reply: You send: or should i say... only crap exit
To include our self-signed certificate in the default cacerts file:
C:\jdk1.4\jre\lib\security> copy c:\securitysslserver ssltest.cer 1 file(s) copied C:\jdk1.4\jre\lib\security> keytool -import -keystore cacerts -file ssltest.cer Enter keystore password: changeit Owner: CN=Joris Van den Bogaert, OU=Esus Team, O="Esus, Inc", L=Meerbeek, ST=Unk nown, C=BE Issuer: CN=Joris Van den Bogaert, OU=Esus Team, O="Esus, Inc", L=Meerbeek, ST=Un known, C=BE Serial number: 3b5d7dd7 Valid from: Tue Jul 24 15:53:27 CEST 2001 until: Mon Oct 22 15:53:27 CEST 2001 Certificate fingerprints: MD5: 07:DE:52:94:15:1D:53:88:C5:C5:51:48:0F:AF:83:76 SHA1: A7:92:CF:29:EF:B9:74:05:6F:05:E5:75:4B:78:42:D1:35:8B:D7:55 Trust this certificate? [no]: yes
Run the server again. Now run the client without specifying the trustStore and see what happens!
The BitSet allows you to work with bits (0 and 1). You can not only get and set bits individually but also perform bitwise operations like and and or. The size of the BitSet may vary. For example, if you initialy set the first bit to 1, 64 bits will be used. Then if you set the bit 100 to 1, the BitSet will grow to 128. The 64 alignment may be different in future implementations.
Operations:
and: result of (a and b) is 1 if only a and b have the value of 1 or: result of (a or b) is 1 if at least a or b has the value of 1 xor: result of (a xor b) is 1 if a or b has the value of 1, but not both
Main.java:
import java.util.*; public class Main { public static void main(String args[]) { BitSet bs1 = new BitSet(); bs1.set(7); // sets the 7th bit 00000001000... (64) System.out.println(bs1); // outputs {7} bs1.set(5); // sets the 5th bit 00000101000... (64) System.out.println(bs1); // outputs {5, 7} bs1.clear(7); // 00000100000... (64) System.out.println(bs1); // outputs {5} BitSet bs2 = new BitSet(); bs2.set(1); // 01000000000... (64) bs2.set(5); // 01000100000... (64) bs1.and(bs2); // 00000100000... (64) System.out.println(bs1); // outputs {5} bs1.xor(bs2); // 01000000000... (64) System.out.println(bs1); // outputs {1} bs1.or(bs2); // 01000100000... (64) System.out.println(bs1); // outputs {1, 5} } }
outputs:
{7} {5, 7} {5} {5} {1} {1, 5}
This small example looks only at the days of february of the last 20 years.
Main.java:
import java.util.*; public class Main { public static void main(String []args) { for (int i=1980; i<2010; i++) { Calendar calendar = new GregorianCalendar(i, Calendar.FEBRUARY, 1); int numberOfDays = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); System.out.println("February " + i + ": " + numberOfDays + " days"); } } }
outputs:
February 1980: 29 days February 1981: 28 days February 1982: 28 days February 1983: 28 days February 1984: 29 days February 1985: 28 days February 1986: 28 days February 1987: 28 days February 1988: 29 days February 1989: 28 days February 1990: 28 days February 1991: 28 days February 1992: 29 days February 1993: 28 days February 1994: 28 days February 1995: 28 days February 1996: 29 days February 1997: 28 days February 1998: 28 days February 1999: 28 days February 2000: 29 days February 2001: 28 days February 2002: 28 days February 2003: 28 days February 2004: 29 days February 2005: 28 days February 2006: 28 days February 2007: 28 days February 2008: 29 days February 2009: 28 days
import java.util.Locale; public class Main { public static void main(String[] args) { Locale[] locales = Locale.getAvailableLocales(); printInColumn("DisplayName", 20); printInColumn("DisplayCountry", 15); printInColumn("DispLang", 11); printInColumn("ISO3L", 6); printInColumn("Lang", 5); printInColumn("ISO3C", 6); printInColumn("Variant", 6); printInColumn("DispVariant", 10); System.out.println(); System.out.println(); for (int i=0; i<locales.length; i++) { printInColumn(locales[i].getDisplayName(), 20); printInColumn(locales[i].getDisplayCountry(), 15); printInColumn(locales[i].getDisplayLanguage(), 11); printInColumn(locales[i].getISO3Language(), 6); printInColumn(locales[i].getLanguage(), 5); printInColumn(locales[i].getISO3Country(), 6); printInColumn(locales[i].getVariant(), 6); printInColumn(locales[i].getDisplayVariant(), 10); System.out.println(); } } public static void printInColumn(String s, int col) { if (s.length() > col-2) s = s.substring(0, col-2); System.out.print(s); for (int i=s.length(); i<col; ++i) System.out.print(" "); } }
outputs:
DisplayName DisplayCountr DispLang ISO3 Lan ISO3 Vari DispVari English English eng en English (United St United States English eng en USA Arabic Arabic ara ar Arabic (United Ara United Arab E Arabic ara ar ARE Arabic (Bahrain) Bahrain Arabic ara ar BHR Arabic (Algeria) Algeria Arabic ara ar DZA Arabic (Egypt) Egypt Arabic ara ar EGY Arabic (Iraq) Iraq Arabic ara ar IRQ Arabic (Jordan) Jordan Arabic ara ar JOR Arabic (Kuwait) Kuwait Arabic ara ar KWT Arabic (Lebanon) Lebanon Arabic ara ar LBN Arabic (Libya) Libya Arabic ara ar LBY Arabic (Morocco) Morocco Arabic ara ar MAR Arabic (Oman) Oman Arabic ara ar OMN Arabic (Qatar) Qatar Arabic ara ar QAT Arabic (Saudi Arab Saudi Arabia Arabic ara ar SAU Arabic (Sudan) Sudan Arabic ara ar SDN Arabic (Syria) Syria Arabic ara ar SYR Arabic (Tunisia) Tunisia Arabic ara ar TUN Arabic (Yemen) Yemen Arabic ara ar YEM Byelorussian Byeloruss bel be Byelorussian (Bela Belarus Byeloruss bel be BLR Bulgarian Bulgarian bul bg Bulgarian (Bulgari Bulgaria Bulgarian bul bg BGR Catalan Catalan cat ca Catalan (Spain) Spain Catalan cat ca ESP Czech Czech ces cs Czech (Czech Repub Czech Republi Czech ces cs CZE Danish Danish dan da Danish (Denmark) Denmark Danish dan da DNK German German deu de German (Austria) Austria German deu de AUT German (Austria,Eu Austria German deu de AUT EURO Euro German (Switzerlan Switzerland German deu de CHE German (Germany) Germany German deu de DEU German (Germany,Eu Germany German deu de DEU EURO Euro German (Luxembourg Luxembourg German deu de LUX German (Luxembourg Luxembourg German deu de LUX EURO Euro Greek Greek ell el Greek (Greece) Greece Greek ell el GRC English (Australia Australia English eng en AUS English (Canada) Canada English eng en CAN English (United Ki United Kingdo English eng en GBR English (Ireland) Ireland English eng en IRL English (Ireland,E Ireland English eng en IRL EURO Euro English (New Zeala New Zealand English eng en NZL English (South Afr South Africa English eng en ZAF Spanish Spanish spa es Spanish (Bolivia) Bolivia Spanish spa es BOL Spanish (Argentina Argentina Spanish spa es ARG Spanish (Chile) Chile Spanish spa es CHL Spanish (Colombia) Colombia Spanish spa es COL Spanish (Costa Ric Costa Rica Spanish spa es CRI Spanish (Dominican Dominican Rep Spanish spa es DOM Spanish (Ecuador) Ecuador Spanish spa es ECU Spanish (Spain) Spain Spanish spa es ESP Spanish (Spain,Eur Spain Spanish spa es ESP EURO Euro Spanish (Guatemala Guatemala Spanish spa es GTM Spanish (Honduras) Honduras Spanish spa es HND Spanish (Mexico) Mexico Spanish spa es MEX Spanish (Nicaragua Nicaragua Spanish spa es NIC Spanish (Panama) Panama Spanish spa es PAN Spanish (Peru) Peru Spanish spa es PER Spanish (Puerto Ri Puerto Rico Spanish spa es PRI Spanish (Paraguay) Paraguay Spanish spa es PRY Spanish (El Salvad El Salvador Spanish spa es SLV Spanish (Uruguay) Uruguay Spanish spa es URY Spanish (Venezuela Venezuela Spanish spa es VEN Estonian Estonian est et Estonian (Estonia) Estonia Estonian est et EST Finnish Finnish fin fi Finnish (Finland) Finland Finnish fin fi FIN Finnish (Finland,E Finland Finnish fin fi FIN EURO Euro French French fra fr French (Belgium) Belgium French fra fr BEL French (Belgium,Eu Belgium French fra fr BEL EURO Euro French (Canada) Canada French fra fr CAN French (Switzerlan Switzerland French fra fr CHE French (France) France French fra fr FRA French (France,Eur France French fra fr FRA EURO Euro French (Luxembourg Luxembourg French fra fr LUX French (Luxembourg Luxembourg French fra fr LUX EURO Euro Croatian Croatian hrv hr Croatian (Croatia) Croatia Croatian hrv hr HRV Hungarian Hungarian hun hu Hungarian (Hungary Hungary Hungarian hun hu HUN Icelandic Icelandic isl is Icelandic (Iceland Iceland Icelandic isl is ISL Italian Italian ita it Italian (Switzerla Switzerland Italian ita it CHE Italian (Italy) Italy Italian ita it ITA Italian (Italy,Eur Italy Italian ita it ITA EURO Euro Hebrew Hebrew heb iw Hebrew (Israel) Israel Hebrew heb iw ISR Japanese Japanese jpn ja Japanese (Japan) Japan Japanese jpn ja JPN Korean Korean kor ko Korean (South Kore South Korea Korean kor ko KOR Lithuanian Lithuania lit lt Lithuanian (Lithua Lithuania Lithuania lit lt LTU Latvian (Lettish) Latvian ( lav lv Latvian (Lettish) Latvia Latvian ( lav lv LVA Macedonian Macedonia mkd mk Macedonian (Macedo Macedonia Macedonia mkd mk MKD Dutch Dutch nld nl Dutch (Belgium) Belgium Dutch nld nl BEL Dutch (Belgium,Eur Belgium Dutch nld nl BEL EURO Euro Dutch (Netherlands Netherlands Dutch nld nl NLD Dutch (Netherlands Netherlands Dutch nld nl NLD EURO Euro Norwegian Norwegian nor no Norwegian (Norway) Norway Norwegian nor no NOR Norwegian (Norway, Norway Norwegian nor no NOR NY Nynorsk Polish Polish pol pl Polish (Poland) Poland Polish pol pl POL Portuguese Portugues por pt Portuguese (Brazil Brazil Portugues por pt BRA Portuguese (Portug Portugal Portugues por pt PRT Portuguese (Portug Portugal Portugues por pt PRT EURO Euro Romanian Romanian ron ro Romanian (Romania) Romania Romanian ron ro ROM Russian Russian rus ru Russian (Russia) Russia Russian rus ru RUS Serbo-Croatian Serbo-Cro srp sh Serbo-Croatian (Yu Yugoslavia Serbo-Cro srp sh YUG Slovak Slovak slk sk Slovak (Slovakia) Slovakia Slovak slk sk SVK Slovenian Slovenian slv sl Slovenian (Sloveni Slovenia Slovenian slv sl SVN Albanian Albanian sqi sq Albanian (Albania) Albania Albanian sqi sq ALB Serbian Serbian srp sr Swedish Swedish swe sv Serbian (Yugoslavi Yugoslavia Serbian srp sr YUG Swedish (Sweden) Sweden Swedish swe sv SWE Thai Thai tha th Thai (Thailand) Thailand Thai tha th THA Turkish Turkish tur tr Turkish (Turkey) Turkey Turkish tur tr TUR Ukrainian Ukrainian ukr uk Ukrainian (Ukraine Ukraine Ukrainian ukr uk UKR Chinese Chinese zho zh Chinese (China) China Chinese zho zh CHN Chinese (Hong Kong Hong Kong Chinese zho zh HKG Chinese (Taiwan) Taiwan Chinese zho zh TWN
The Properties class is able to contain key/value pairs, just like a Hashtable (in fact, Properties extends from Hashtable). An example of where the Properties class is used is in the System class, that uses this class to store its system properties (like java.version, …). Properties allows its key/value pairs to be loaded and stored and through the methods load and store.
This following example stores the system properties in a file. The store method allows you to save an extra header comment for identification purposes.
Main.java:
import java.util.*; import java.io.*; public class Main { public static void main(String[] args) throws Exception { if (args.length != 1) { System.out.println("Usage: java Main <filename>"); System.exit(1); } BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(args[0])); Properties p = System.getProperties(); p.store(bos, "Our stored System properties"); } }
stores in a specified file:
#Our stored System properties #Wed Jun 27 17:21:15 CEST 2001 java.specification.name=Java Platform API Specification awt.toolkit=sun.awt.windows.WToolkit java.version=1.2.2 java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment user.timezone=Europe/Paris java.specification.version=1.2 java.vm.vendor=Sun Microsystems Inc. java.vm.specification.version=1.0 user.home=C:\WINDOWS os.arch=x86 java.awt.fonts= java.vendor.url=http://java.sun.com/ file.encoding.pkg=sun.io user.region=US java.home=C:\JDK1.2.2\JRE java.class.path=c:\jdk1.2.2\jre\lib\rt.jar;C:\PRO GRA~1\JMF2.1\LIB\SOUND.JAR;C:\PROGRA~1\JMF2.1\LIB\ JMF.JAR;c:\jakarta-log4j-1.0.4\log4j-core.jar; line.separator=rn java.ext.dirs=C:\JDK1.2.2\JRE\lib\ext java.io.tmpdir=c:\windows\TEMP\ os.name=Windows 95 java.vendor=Sun Microsystems Inc. java.awt.printerjob=sun.awt.windows.WPrinterJob java.library.path=C:\JDK1.2.2\BIN;.;C:\WINDOWS\SYSTEM;C:\WINDOWS;C:\JIKES\BIN ;C:\ANT\BIN\;C:\JDK1.2.2\BIN;C:\WINDOWS;C:\WIN DOWS;C:\WINDOWS\COMMAND;;C:\WN16\BIN;C:\PROGRA~1 NETWOR~1\PGP;C:\VIM\VIM55 java.vm.specification.vendor=Sun Microsystems Inc. sun.io.unicode.encoding=UnicodeLittle file.encoding=Cp1252 java.specification.vendor=Sun Microsystems Inc. user.name=esus user.language=en java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport.cgi java.vm.name=Classic VM java.vm.specification.name=Java Virtual Machine Specification java.class.version=46.0 sun.boot.library.path=C:\JDK1.2.2\JRE\bin os.version=4.10 java.vm.info=build JDK-1.2.2_005, native threads, symcjit java.vm.version=1.2.2 java.compiler=symcjit path.separator=; user.dir=C:\ file.separator=\ sun.boot.class.path=C:\JDK1.2.2\JRE\lib\rt.jar;C:\ JDK1.2.2\JRE\lib\i18n.jar;C:\JDK1.2.2\JRE\classes
You can create your own properties object as follows:
import java.util.*; import java.io.*; public class Main { public static void main(String[] args) throws Exception { // creating a properties object Properties p = new Properties(); p.put("lastlogin", "crazycow"); p.put("lastpassword", "j23js09zz"); // storing our properties in the file test.prop BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("test.prop")); p.store(bos, "Our own properties"); // loading our properties in another Properties object and // printing its values out. Properties p2 = new Properties(); p2.load(new BufferedInputStream(new FileInputStream("test.prop"))); p2.list(System.out); } }
Notice that Properties extends from Hashtable, so you can put elements in there that are not Strings. In this case, the load and save methods won’t work properly. A better way of implementating Properties is to have it contain a Hashtable instead of extending from it.
First determine what characters delimit your text tokens, for example if you’re parsing a comma-separated values file (csv), your delimiter character would probably be the comma. Then create an instance of StringTokenizer with the String you want to split up into tokens and pass it your set of delimiter characters. You can also use the default set of delimiter characters which is ” tnrf”, the space character, the tab character, the newline character, the carriage-return character and the form-feed character.
Then continually call the method hasMoreTokens and nextToken until there are no more tokens. The StringTokenizer will keep track of the current position and nextToken will return the set of characters that appear before the next delimiter character. You can change the delimiter character(s) anytime by calling nextToken(String delim).
Here’s an example that reads in a csv and prints out its tokens.
csv.txt:
"Mike",1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,9,8,7,6,5,4 "George",3,6,4,2,3,5,2,3,4 "Anne",7,4,3,2,8,5,4,1,,3,4,5
Main.java:
import java.util.*; import java.io.*; public class Main { public static void main(String []args) throws IOException { if (args.length != 1) { System.out.println("Usage: java Main <textfile>"); System.exit(1); } String text = readFile(args[0]); String lineSep = System.getProperty("line.separator"); StringTokenizer st = new StringTokenizer(text, " ," + lineSep); while (st.hasMoreTokens()) { String token = st.nextToken(); if (token.charAt(0) == '"') { System.out.println(); } System.out.print(token + "/"); } } public static String readFile(String filename) throws IOException { BufferedReader br = new BufferedReader(new FileReader(filename)); StringBuffer total = new StringBuffer(); String lineSep = System.getProperty("line.separator"); String line; while ((line = br.readLine()) != null) { total.append(line + lineSep); } br.close(); return total.toString(); } }
outputs:
"Mike"/1/2/3/4/5/6/7/8/9/1/2/3/4/5/6/9/8/7/6/5/4/ "George"/3/6/4/2/3/5/2/3/4/ "Anne"/7/4/3/2/8/5/4/1/3/4/5/
Courtesy of Nobuo Tamemasa (http://www2.gol.com/users/tame/swing/examples/JTableExamples5.html)
CompTitledPaneExample1.java:
import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; /** * @version 1.0 08/12/99 */ public class CompTitledPaneExample1 extends JFrame { String title = "<html>Title (" + "<font color="#ffffff"><i>JLabel</i></font>" + ")"; public CompTitledPaneExample1() { super("CompTitledPaneExample1"); JLabel titleLabel = new JLabel(title); CompTitledPane p1 = new CompTitledPane(titleLabel); JPanel p = p1.getContentPane(); p.setLayout(new BorderLayout()); p.add(new SwitchPanel(p1), BorderLayout.CENTER); getContentPane().add(p1, BorderLayout.CENTER); } class SwitchPanel extends JPanel implements ActionListener { String[] posStr = {"", "ABOVE_TOP" , "TOP" , "BELOW_TOP" , "ABOVE_BOTTOM", "BOTTOM", "BELOW_BOTTOM"}; String[] jusStr = {"", "LEFT" , "CENTER", "RIGHT"}; TitledBorder border; CompTitledPane panel; SwitchPanel(CompTitledPane panel) { this.panel = panel; this.border = (TitledBorder)panel.getBorder(); add(createPanel("Position" ,posStr, 2)); add(createPanel("Justification",jusStr, 1)); } JPanel createPanel(String str, String[] strs, int selectPos) { JPanel p = new JPanel(); p.setLayout(new GridLayout(strs.length, 1)); p.add(new JLabel(str)); ButtonGroup g = new ButtonGroup(); for (int i=1;i<strs.length;i++) { JRadioButton b = new JRadioButton(strs[i]); if (i == selectPos) { b.setSelected(true); } p.add( b ); g.add( b ); b.addActionListener(this); } return p; } public void actionPerformed(ActionEvent e) { JRadioButton b = (JRadioButton)e.getSource(); String label = b.getText(); for (int i=1; i<posStr.length; i++) { if (label.equals(posStr[i])) { border.setTitlePosition(i); panel.revalidate(); panel.repaint(); return; } } for (int i=1; i<jusStr.length; i++) { if (label.equals(jusStr[i])) { border.setTitleJustification(i); panel.revalidate(); panel.repaint(); return; } } } } public static void main (String args[]) { CompTitledPaneExample1 frame = new CompTitledPaneExample1(); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); frame.setSize(280, 230); frame.setVisible(true); } }
CompTitledPane.java:
import java.awt.*; import javax.swing.*; import javax.swing.border.*; /** * @version 1.0 08/12/99 */ public class CompTitledPane extends JPanel { protected CompTitledBorder border; protected JComponent component; protected JPanel panel; protected boolean transmittingAllowed; protected StateTransmitter transmitter; public CompTitledPane() { this(new JLabel("Title")); // debug // JLabel label = (JLabel)getTitleComponent(); // label.setOpaque(true); // label.setBackground(Color.yellow); } public CompTitledPane(JComponent component) { this.component = component; border = new CompTitledBorder(component); setBorder(border); panel = new JPanel(); setLayout(null); add(component); add(panel); transmittingAllowed = false; transmitter = null; } public JComponent getTitleComponent() { return component; } public void setTitleComponent(JComponent newComponent) { remove(component); add(newComponent); border.setTitleComponent(newComponent); component = newComponent; } public JPanel getContentPane() { return panel; } public void doLayout() { Insets insets = getInsets(); Rectangle rect = getBounds(); rect.x = 0; rect.y = 0; Rectangle compR = border.getComponentRect(rect,insets); component.setBounds(compR); rect.x += insets.left; rect.y += insets.top; rect.width -= insets.left + insets.right; rect.height -= insets.top + insets.bottom; panel.setBounds(rect); } public void setTransmittingAllowed(boolean enable) { transmittingAllowed = enable; } public boolean getTransmittingAllowed() { return transmittingAllowed; } public void setTransmitter(StateTransmitter transmitter) { this.transmitter = transmitter; } public StateTransmitter getTransmitter() { return transmitter; } public void setEnabled(boolean enable) { super.setEnabled(enable); if (transmittingAllowed && transmitter != null) { transmitter.setChildrenEnabled(enable); } } }
StateTransmitter.java:
/** * @version 1.0 08/12/99 */ public interface StateTransmitter { public void setChildrenEnabled(boolean enable); } // sample // // public void setChildrenEnabled(boolean enable) { // // Component[] children = panel.getComponents(); // for(int i=0; i<children.length; i++) { // System.out.println(" " + i + // " " + children[i].getClass().getName() + // " " + enable); // children[i].setEnabled(enable); // } // } //
CompTitledBorder.java:
import java.awt.*; import javax.swing.*; import javax.swing.border.*; /** * @version 1.0 08/12/99 */ public class CompTitledBorder extends TitledBorder { protected JComponent component; public CompTitledBorder(JComponent component) { this(null, component, LEFT, TOP); } public CompTitledBorder(Border border) { this(border, null, LEFT, TOP); } public CompTitledBorder(Border border, JComponent component) { this(border, component, LEFT, TOP); } public CompTitledBorder(Border border, JComponent component, int titleJustification, int titlePosition) { super(border, null, titleJustification, titlePosition, null, null); this.component = component; if (border == null) { this.border = super.getBorder(); } } public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { Rectangle borderR = new Rectangle(x + EDGE_SPACING, y + EDGE_SPACING, width - (EDGE_SPACING * 2), height - (EDGE_SPACING * 2)); Insets borderInsets; if (border != null) { borderInsets = border.getBorderInsets(c); } else { borderInsets = new Insets(0, 0, 0, 0); } Rectangle rect = new Rectangle(x,y,width,height); Insets insets = getBorderInsets(c); Rectangle compR = getComponentRect(rect, insets); int diff; switch (titlePosition) { case ABOVE_TOP: diff = compR.height + TEXT_SPACING; borderR.y += diff; borderR.height -= diff; break; case TOP: case DEFAULT_POSITION: diff = insets.top/2 - borderInsets.top - EDGE_SPACING; borderR.y += diff; borderR.height -= diff; break; case BELOW_TOP: case ABOVE_BOTTOM: break; case BOTTOM: diff = insets.bottom/2 - borderInsets.bottom - EDGE_SPACING; borderR.height -= diff; break; case BELOW_BOTTOM: diff = compR.height + TEXT_SPACING; borderR.height -= diff; break; } border.paintBorder(c, g, borderR.x, borderR.y, borderR.width, borderR.height); Color col = g.getColor(); g.setColor(c.getBackground()); g.fillRect(compR.x, compR.y, compR.width, compR.height); g.setColor(col); component.repaint(); } public Insets getBorderInsets(Component c, Insets insets) { Insets borderInsets; if (border != null) { borderInsets = border.getBorderInsets(c); } else { borderInsets = new Insets(0,0,0,0); } insets.top = EDGE_SPACING + TEXT_SPACING + borderInsets.top; insets.right = EDGE_SPACING + TEXT_SPACING + borderInsets.right; insets.bottom = EDGE_SPACING + TEXT_SPACING + borderInsets.bottom; insets.left = EDGE_SPACING + TEXT_SPACING + borderInsets.left; if (c == null || component == null) { return insets; } int compHeight = 0; if (component != null) { compHeight = component.getPreferredSize().height; } switch (titlePosition) { case ABOVE_TOP: insets.top += compHeight + TEXT_SPACING; break; case TOP: case DEFAULT_POSITION: insets.top += Math.max(compHeight,borderInsets.top) - borderInsets.top; break; case BELOW_TOP: insets.top += compHeight + TEXT_SPACING; break; case ABOVE_BOTTOM: insets.bottom += compHeight + TEXT_SPACING; break; case BOTTOM: insets.bottom += Math.max(compHeight,borderInsets.bottom) - borderInsets.bottom; break; case BELOW_BOTTOM: insets.bottom += compHeight + TEXT_SPACING; break; } return insets; } public JComponent getTitleComponent() { return component; } public void setTitleComponent(JComponent component) { this.component = component; } public Rectangle getComponentRect(Rectangle rect,Insets borderInsets) { Dimension compD = component.getPreferredSize(); Rectangle compR = new Rectangle(0,0,compD.width,compD.height); switch (titlePosition) { case ABOVE_TOP: compR.y = EDGE_SPACING; break; case TOP: case DEFAULT_POSITION: compR.y = EDGE_SPACING + (borderInsets.top -EDGE_SPACING -TEXT_SPACING -compD.height)/2; break; case BELOW_TOP: compR.y = borderInsets.top - compD.height - TEXT_SPACING; break; case ABOVE_BOTTOM: compR.y = rect.height - borderInsets.bottom + TEXT_SPACING; break; case BOTTOM: compR.y = rect.height - borderInsets.bottom + TEXT_SPACING + (borderInsets.bottom -EDGE_SPACING -TEXT_SPACING -compD.height)/2; break; case BELOW_BOTTOM: compR.y = rect.height - compD.height - EDGE_SPACING; break; } switch (titleJustification) { case LEFT: case DEFAULT_JUSTIFICATION: compR.x = TEXT_INSET_H + borderInsets.left; break; case RIGHT: compR.x = rect.width - borderInsets.right -TEXT_INSET_H -compR.width; break; case CENTER: compR.x = (rect.width - compR.width) / 2; break; } return compR; } }