Академический Документы
Профессиональный Документы
Культура Документы
ACKNOWLEDGEMENT i
DECLARATION ii
ABSTRACT iii
CHAPTER 1. INTRODUCTION
5.1 MODULES
5.2 MODULE DESCRIPTION
5.3 SAMPLE CODING
CHAPTER 6. TESTING
CHAPTER 7. CONCLUSION
7.1 SUMMARY
7.2 FUTURE ENHANCEMENTS
7.3 BIBLIOGRAPHY
ACKNOWLEDGEMENT
DECLARATION
ABSTRACT
IMPLEMENTATION OF BPCS-STEGANOGRAPHY
This technique makes use of the characteristics of the human vision system whereby a
human cannot perceive any shape information in a very complicated binary pattern. We
can replace all of the “noise-like” regions in the bit-planes of the vessel image with secret
data without deteriorating the image quality. We termed our Steganography “BPCS-
Steganography,” which stands for Bit-Plane Complexity Segmentation Steganography.
CHAPTER 1. INTRODUCTION
1.2 TECHNOLOGIES
This project has been developed to work all in SUN platforms for the client side
and it needs APPLET as the server side platform. We have used JAVA coding AWT and
Swing components and we have implemented these components in JAVA. The windows
API calls are mainly used in all objects to get required systems files.
Both sender and receiver must know the value of n.The sender knows the value of e and
only the receiver knows the value of d.Thus, this is a public key encryption algorithm
with a public key of KU = {d,n}.
For this algorithm to be satisfactory for public key encryption, the following
requirements to be met :
1. It is possible to find the values of e, d, n such that Med = M mod n for all M < n.
2. It is relatively easy to calculate Me and Cd for all values of M < n.
3. It is infeasible to determine d given e and n.
For now,we focus on the first requirement and consider the other questions
later.We need to find a relationship of the form
Med = M mod n
Given two prime numbers and q, and two integers and m, such that n=pq
and 0<m<n, and arbitrary integer k, the following relationships holds:
Where φ(n) is the euler’s totient function, which is the number of positive
integers less than n and relatively prime to n. it is shown that for p,q prime,
φ(p,q)=(p-1)(q-1). Thus we can achieve the desired relationship if
ed = kφ(n)+1
This is equivalent to saying:
ed = 1 mod φ(n)
d = e-1 mod φ(n)
That is, e and d are multiplicative inverses mod φ (n). Note that, according to the
rules of modular arithmetic, this is true only if d (and therefore e) is relatively prime to φ
(n). Equivalently, gcd (φ(n),d) = 1.
We are now ready to state the rsa scheme.the ingredients are the following:
The private key consist of {d,n} and the public key consists of {e,n}.suppose that
user a has published its public key and that user b wishes to send the message M to A.
then b calculates C = Me (mod n) and transmits C. on receipt of this cipher text, user a
decrypts by calculating M = Cd (mod n).
It is worthwhile to summarize the justification for this algorithm. We have chosen
e and d such that
Therefore,
Ed = 1 mod ø (n)
Therefore,ed is of the form kø(n)+1
So M ed = mod n .Now
C = Me mod n
M = Cd mod n = (Me)d mod n = M mod n
The keys were generated as follows:
1. Select two prime numbers p and q
2. Calculate n = pq
3. Calculate ø (n) = (p-1) (q-1)
4. Select e such that e is relatively prime to ø (n) and less than ø(n)
5. Determine d such that de = 1 mod ø (n)
KEY GENERATION
Before the application of the public key cryptosystem, each participant must generate
a pair of keys. This involves the following tasks:
1. Determining two prime numbers, p and q
2. Selecting either e or d and calculating the other
The compressed data size is 505,502 bytes, which is 54% of the vessel size. Even with
this much information embedded in the image, the embedded and original images look
nearly identical when viewed on the monitor.
(A) Original vessel image (B) Embedded vessel image
Fig.4 Example of a vessel image
Through our embedding experiments, we found that most color images
taken by a digital camera can be used as vessel images. In almost all cases, the
information hiding capacity was nearly 50% of the size of each vessel image. This
capacity is 4 to 5 times as large as currently known steganographic techniques. For a
given image, embedding capacity can be traded with image quality by altering the
complexity threshold. The image of Fig. 4 used a threshold of 24 border pixels per 8
8 region; therefore regions having more border pixels than this were eligible for
embedding. Fig. 7 shows how the capacity changes with threshold for this image. For this
image a threshold of 24 seemed optimal, while lower thresholds introduced some “noise”
to the image.
2. USING GRAY CODED BIT-PLANES FOR COMPLEXITY
SEGMENTATION
The advantage to using Gray Coded bit planes for complexity segmentation. Parts
A through C of this figure show the PBC red bit planes numbered 3 through 5 for the
image of Fig. 5a, while parts D through F show the CGC version of these same planes.
From looking at such bit planes, one can get a pretty good idea of which regions of the bit
plane are complex enough to be replaced with information during BPCS embedding.
Recall that the goal with BPCS Steganography is to use as much of the image as possible
for hiding information without appreciably altering the visual appearance of the image. In
comparing these two sets of bit planes, it is evident that the PBC bit planes provide a
much greater region for embedding.
However, substantial portions of the regions on the higher bit planes deemed
embeddable using PBC are actually relatively flat in color. For example, note the wall in
the background. This is because of the “Hamming Cliffs” which occur with PBC wherein
a small change in color affects many bits of the color value. If embedding were to replace
the bits in such complex looking but actually relative flat regions, then substantial color
changes would occur. As a simple example, consider a region where the blue value
hovers nearly randomly between the binary values of 01111111 and 10000000. In this
region, every bit plane would look complex and would thus appear to be embeddable,
while in practice, it would be prudent to only embed in the lower one or two planes.
Although occurrences such as this where all bits change in a relatively flat region are
rare, the frequency of occurrence doubles on each lower bit plane.
It is very easy for a single BPCS Steganography program to allow the user to
customize parameters such as these, producing a very large number of possible
customized programs. In this way, each user or group of users can have their own
program that embeds data in an image in a way that is unreadable by others.
CHAPTER 2. SYSTEM STUDY
•This Technique uses an image as the vessel data, and we embed secret information in the
bit-planes of the vessel.
•We can replace all of the “noise-like” regions in the bit-planes of the vessel
image with secret data without deteriorating the image quality
•We termed our Steganography “BPCS-Steganography,” which stands for Bit-
Plane Complexity Segmentation Steganography
2.4 PROPOSED SYSTEM MODULES
Hider
File Segmentation (8 X 8)
Noise Level Identifier
Complexity Identifier
Gray Converter
Noisy level Revalidator
Secret File Segmentor
Text & Image bits replacer
Image Reproducer
Retriever
Image Scanner
Image Segmentor (8 x 8)
Complex Plan Identifier
Information Retriever
Process State Identifier
2.5 JUSTIFICATION
•In Encryption, Message can be hacked, because some one can easily detect the
encrypted file.
•This technique makes use of the characteristics of the human vision system
whereby a human cannot perceive any shape information in a very complicated binary
pattern.
CHAPTER 3. REQUIREMENTS ANALYSIS AND
SPECIFICATION
3.1 HARDWARE REQUIREMENTS
3.3 JAVA
JAVA is an object oriented language, it is basically supports all concepts of
c and c++ with some additional features. Other attractive feature JAVA is a platform
independent language. The genesis of java is complete without a look at the java
buzzwords.
simple
secure
portable
object-oriented
robust
multithreaded
architecture-neutral
interpreted
high performance
distributed
dynamic
Java can be used to create two types of programs: applications and applets.
An application is a program that runs on your computer under the operating system
of your computer. An applet is a application designed to transmitted over the internet and
executed by the java compatible web server. An applet is a tiny java program,
dynamically downloaded across the network, just like an image, sound file or video clip.
The important difference is that an applet is an intelligent program, not just an animation
or media file.
AWT
The AWT classes contained by the java.awt package. It is one of the largest
packages. Because it is logically organized in a top-down, hierarchical fashion, it is easier
to understand and use than you might at first believe. AWT contains numerous classes
and methods that allow you to create and manage windows. It also explains further
aspects of of java’s event handling mechanism. The main purpose of the AWT is to
support applet windows, it can be used to create stand –alone windows that run in a GUI
environment such as windows.
APPLET
UTIL
NET
Now that you have learned the theory behind the delegation event model
and have had an over view of its various components,it is time to see it in
practice.appletprogramming using the delegation event model is actually
quite easy.just follow these two steps:
1.implement the appropriate interface in the listener so that it will receive the
type of event desired.
2.implement code to register and unregister(if necessary)the listener as a
recipient for the event notifications.
Remember that a source may generate several types of events.each event
must be registered separately.also,an object may register to receive several
types of events,but it must implement all of the interfaces that are required to
receive these events.
To see how the delegation model works in practice,we will look at
examples that handle the two most commonly used event generators:the
mouse and keyboard.
Applet
Applet provides all necessary support for execution, such as starting
and stoping.it also provides methods that load and display images and
methods that load and play audio clips. Applet extends the AWT class
panel. In turn panel extends container, which extends component. These
classes provide support java’s window based, graphical interface. Thus
applet provides all of the necessary support for window-based activities.
image
This class provides support foe imaging. Images are objects of the
Image class, which is a part of the java.awt package. There are a large
number of imaging classes and interfaces defined by java.awt.image and its
not possible to examine them all.
event
The classes that represent events are at the core of java’s events
handling mechanisms. They provide a consistent, easy-to-use means of
encapsulating events. At the root of the java event class hierarchy is
EventObject, which is in java.util. it is the super class for all events. Its one
constructor is shown
EventObject(Object src)
CHAPTER 4. SYSTEM DESIGN
SERVER SIDE
Encryption key,
Other keys
(Images.
Audio files,
Network packets, (Stego
Circuitry/software Information
media)
Text) to hide
CLIENT SIDE
Decryption key,
Other keys
FLOW DIAGRAM
(Client Side)
HOME
PAGE
HOME User
PAGE Exist
User Interaction
Stego-image
Encryption
Decompression
decryption
Original Message
FLOW DIAGRAM
(Server Side)
HOME
PAGE
HOME User
PAGE Exist
User Interaction
Encryption
Compression
Sign Out
CHAPER 5. IMPLEMENTATION
5.1 MODULES
Bit-Plane Complexity Segmentation Steganography is our new
steganographic technique, which has a large information hiding capacity. As was shown
in the previous section, the replacement of the complex regions in each bit-plane of a
color image with random binary patterns is invisible to the human eye. We can use this
property for our information hiding (embedding) strategy. Our practical method is as
follows.
In our method we call a carrier image a “vessel” or“dummy” image. It is a color image in
BMP file format, which hides (or,embeds) the secret information (files in any format). We
segment each secretfile to be embedded into a series of blocks having 8 bytes of data
each.
These blocks are regarded as 8 8 image patterns. We call such blocks the secret
blocks. We embed these secret blocks into the vessel image using the following steps.
1.Transform the dummy image from PBC to CGC system.
2. Segment each bit-plane of the dummy image into informative and noise-like regions by
using a threshold value (a0). A
typical value is a0 = 0.3.
3. Group the bytes of the secret file into a series of secret blocks.
4. If a block (S) is less complex than the threshold (0), then Conjugate it to make it a
more complex block (S*). The conjugated block Must be more complex than 0 as
shown by equation .
5. Embedded each secret block into the noise-like regions of the bit-
planes (or, replace all the noise-like regions with a series of secret blocks). If the block
is conjugated, then record this fact in a “conjugation map.”
6. Also embed the conjugation map as was done with the secret blocks
7. Convert the embedded dummy image from CGC back to PBC.
The Decoding algorithm (i.e., the extracting operation of the secret
information from an embedded dummy image) is just the reverse procedure of the
embedding steps.
The novelty in BPCS-Steganography is itemized in the following.
Modules Names
Hider
Retriver
5.2 MODULE DESCRIPTION
HIDER
1. Load Image
2. Load Source
3. Choose Encryption
Keys
4. File Compressor
5. Image Analyzer
6.File Hider
RETRIEVER
1. Choose Embedded
Image
3. File Extractor
4. Content Displayer
BPCS
2. Load Source
2. Choose Text File /
Directory
3. Choose Encryption
Keys 3. File Extractor
4. File Compressor
4. Content Displayer
6.File Hider
MODULES SPECIFICATIONS
HIDER
File Segmentation (8 X 8)
Noise Level Identifier
Complexity Identifier
Gray Converter
Noisy level Revalidator
Secret File Segmentor
Text & Image bits replacer
Image Reproducer
RETRIEVER
Image Scanner
Image Segmentor (8 x 8)
Complex Plan Identifier
Information Retriever
Process State Identifier
SUB MODULES
ENCRYPTOR
Public key Exponent Finder
Private Key Exponent Finder
File Reader
File Text Encryption
Encrypted File Storage
FILE COMPRESSOR
Get Encrypted file from Encryptor
File compression
Store compressed File
IMAGE ANALYSER
Identifier
File size
IMAGE LIST VIEWER
Database Connector
Image List Displayer
File Name Container
5.3 SAMPLING CODING
DynamicFilterInputStream cDynamicFilterInputStream;
EndsWithFilter cEndsWithFilter;
EzStegoEncoder cEzStegoEncoder;
RGBPaletteSorter cRGBPaletteSorter;
StegoCanvas canvas;
else {
f.add("Center",stego);
f.show(); }
*/ if (!NOGUI) {
foreColor = Color.black;
setLayout(new BorderLayout(0,0));
setBackground(backColor);
setForeground(foreColor);
topBox.setBackground(backColor);
topBox.setForeground(foreColor);
add( "North",topBox);
topBox.setLayout(new BorderLayout());
urlBox.setLayout( urlBoxLayout );
urlBox.setBackground(backColor);
urlBox.setForeground(foreColor);
urlLabel.setBackground(backColor);
urlLabel.setForeground(foreColor);
urlLabel.setAlignment(Label.LEFT);
urlLabel.setFont(font);
gbc.gridheight = 1;
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.WEST;
gbc.weightx = 0;
urlBoxLayout.setConstraints(urlLabel,gbc);
urlTextField.setEditable(true);
urlTextField.minimumSize(50);
urlTextField.preferredSize(50);
urlTextField.setFont(new
Font(dfltFont,Font.PLAIN,12));
gbc.gridx = GridBagConstraints.RELATIVE; //
gbc.gridwidth = 4;
gbc.gridheight = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.EAST;
gbc.weightx = 0.80;
urlBox.add(urlTextField);
urlBoxLayout.setConstraints(urlTextField,gbc);
urlBox.add(urlButton);
gbc.gridx = GridBagConstraints.RELATIVE; //
gbc.gridwidth = 4;
gbc.gridheight = 1;
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.EAST;
gbc.weightx = 0.20;
urlBox.add(urlButton);
gbl.setConstraints(openGIFButton,gbc);
stegButton.setBackground(buttonColor);
stegButton.setFont(font);
gbl.setConstraints(stegButton,gbc);
c.gridy = 0;
gridBag.setConstraints(verticalSB, c);
canvasBox.add(verticalSB);
add("Center",canvasBox);
statusPanel.setBackground(backColor);
statusPanel.setForeground(foreColor);
statusPanel.setLayout(gbl);
statusLabel.setBackground(backColor);
statusLabel.setForeground(foreColor);
gbl.setConstraints(statusLabel,gbc);
statusPanel.add(statusLabel);
add("South", statusPanel);
f.show(); }
}
topBox.setLayout(new BorderLayout());
urlBox.setLayout( urlBoxLayout );
urlBox.setBackground(backColor);
urlBox.setForeground(foreColor);
urlLabel.setForeground(foreColor);
urlLabel.setAlignment(Label.LEFT);
urlLabel.setFont(font);
gbc.gridheight = 1;
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.WEST;
gbc.weightx = 0;
urlBox.add(urlLabel);
urlBoxLayout.setConstraints(urlLabel,gbc);
urlTextField.setEditable(true);
urlTextField.minimumSize(50);
urlTextField.preferredSize(50);
urlTextField.setFont(new
Font(dfltFont,Font.PLAIN,12));
gbc.gridx = GridBagConstraints.RELATIVE; //
gbc.gridwidth = 4;
gbc.gridheight = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.EAST;
gbc.weightx = 0.80;
urlBox.add(urlTextField);
urlBoxLayout.setConstraints(urlTextField,gbc);
urlBox.add(urlButton);
gbc.gridx = GridBagConstraints.RELATIVE; //
gbc.gridwidth = 4;
gbc.gridheight = 1;
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.EAST;
gbc.weightx = 0.20;
urlBox.add(urlButton);
urlBoxLayout.setConstraints(urlButton,gbc);
urlButton.setForeground(Color.black);
urlButton.setBackground(buttonColor);
urlButton.setFont(font);
topBox.add("South",urlBox);
buttonBox.setLayout(gbl);
//
GridBagConstraints
gbc.weightx = 1.0;
canvasBox.setLayout(gridBag); //
first the canvas
c.weightx = 1.0;
c.weighty = 1.0;
c.fill = GridBagConstraints.BOTH;
gridBag.setConstraints(canvas, c);
canvasBox.add(canvas); //
then the horizontal Scrollbar
c.weightx = 0.0;
c.weighty = 0.0;
c.gridx = 0; c.gridy = 1;
gridBag.setConstraints(horizontalSB, c);
canvasBox.add(horizontalSB); //
finally, the vertical Scrollbar
c.gridx = 1;
c.gridy = 0;
gridBag.setConstraints(verticalSB, c);
canvasBox.add(verticalSB); add("Center",canvasBox);
statusPanel.setForeground(foreColor);
statusPanel.setLayout(gbl);
statusLabel.setFont(msgfont);
statusLabel.setBackground(backColor);
statusLabel.setForeground(foreColor);
gbl.setConstraints(statusLabel,gbc);
stego.start();
if
(NOGUI)
stego.init_nogui(); }
else {
f.add("Center",stego);
f.show(); }
}
String arg;
arg = args[i++];
//S
ystem.out.println(arg); //
use this type of check for "wordy" arguments if
(arg.equals("-verbose")) {
VERBOSE = true; }
if (arg.equals("-nogui")) { if (VERBOSE) {System.out.println("Batch
mode on");} NOGUI = true; } if (arg.equals("-unsteg")) { if
(VERBOSE) {System.out.println("Unsteg mode on");} UNSTEG =
true; } // use this type of check for arguments that require
parseCmdLine(argv);
stego.start();
if
(NOGUI) {
stego.init_nogui(); }
else {
f.add("Center",stego);
f.resize( 400, 400);
f.show(); }
}
super.start();
//p
reload all classes to avoid Win95 FileDialog bug
openImageFile(); if
(UNSTEG) unSteg();
else doSteg(); }
return image; }
catch (Exception e)
return; }
try
{
return; }
waitForImage(this,image);
}
catch (Exception e)
return; }
bytes",false); if
(!NOGUI) {
canvas.setImage(image);
invalidate();
getParent().layout();
canvas.repaint();
repaint(); }
} public void openImageFile() { if (!NOGUI) {
setStatus( "Select a GIF image file.",false); Container f = getParent();
while (f != null && !(f instanceof Frame)) f = f.getParent();
setStatus("Enter a name for the new GIF file.",false); repaint();
Container f = getParent(); myfileDialog.setFile("output.gif");
myfileDialog.show(); repaint(); //Workaround Win95 FileDialog
bug // If user cancels from dialog, return if (myfileDialog.getFile()
== null) return; InputStream myFileInputStream = getFiletoHide();
if (myFileInputStream == null) return; // Create output file & try to
open a stream to it setStatus("Opening output file stream. ",false);
File destination_file = null; if (outputfile != null)
{ destination_file = new File(outputfile); try { destination =
new FileOutputStream(destination_file); } catch (Exception e)
return; } } } OutputStream destination = System.out; if (outputfile
!= null) { File destination_file = new File(outputfile); try
{ destination = new FileOutputStream(destination_file); catch
(IOException e) { SetStatus("Error while saving file.
"+e.getMessage(),true); return; } } try { ie = new
EzStegoEncoder( image, destination, null, rgbPalette); } Catch
(Exception e) { setStatus( "Could not initialize image
encoder."+e.getMessage(),true);
return; }
/**
Try to encode the .gif */
ie.encode(); }
catch (IOException e) {
setStatus( "Stego recovery failed: "+e.getMessage(),true);
return; };
}
void setHorizontalScrollbar(int value, int visible, int
min, int max) {
Functional Tests are used to exercise the code with nominal inputs (input values)
for which the expected values are available. We also know the boundary conditions for
these inputs. For instance, functional testing of matrix multiplication can involve some
data (matrices) for which the results are known in advance.
Stress Tests are designed to break a software module. This type of testing
determines the strengths and limitations of the software.
Structure Tests are aimed at exercising the internal logic of a software system.
TEST ACTIVITIES
Test plans
Test design
Test cases
Test procedure
Test execution
Test report
A test plan indicates the scope, approach, resources and the schedule of testing
activity. At this stage, one indicates what is to be or not to be tested and which tasks to
perform. In addition, it is necessary to identify the sources and levels of risk in testing.
Software testers are also identified. Test planning may begin as soon as the requirements
are completed. The key features in a test plan are
Transitioning
Estimates
Completion
Risk analysis allocation
Test case
Implementation Generation
Test
Test procedure
Generation
Test
execution
6.2 PHASES OF TESTING
Testing can be divided into a number of phases as shown below:
Program Testing
System Testing
User Acceptance Testing
Program Testing:
The purpose of program testing is to check out whether the program is working
accordingly to the specification given. This phase ensures that the program or modules
function ass expected. In this phase, all parts of the program are checked thoroughly
System Testing:
System testing should prove that the computer system work as intended and are
acceptable to user operations and audit. It would also show that the system would
interface correctly with other existing computer systems. The running of system test
should be under the control of operations, it can also prove that all the operations, so that
operating procedures can prove to be correct. There should be sufficient volume of data
to demonstrate that the system meets the performance constraints.
Unit Testing:
Unit testing focuses verification effort on the smallest unit of software design. Unit
testing is simplified when a module with high cohesion is designed. In unit testing
various programs, which comprises the system are tested separately. So unit testing is
sometimes called as “Program Testing”. This reduces the error produced by the larger
program.
The system testing is used to find the integration of each module in the system. It is
also tested to find discrepancies between the system and its original objectives, current
specification and system documentation. System testing is a series of different test
whose primary purpose is to fully exercise the computer-based system. Testing is used
to find the compatibility between the various programs units available in the system.
Testing Strategies:
Testing of the software ids done in the aim of finding errors. Test cases are devised to
bring out errors in the system. The test data are created with the intention of
determining whether the system will program will handle them appropriately. There are
two general testing strategies for testing software namely:
Code Testing
Specification Testing
Code Testing:
The code testing strategy examines the logic of the program. Test cases are devised
such that they result in executing every instruction in the program (i.e.) every path of
the program is tested. Specification testing handles all these problems.
Specification Testing:
Specification Testing involve stating what the program should and how it should
perform under various conditions. The test are developed for each condition or
combination of condition and submitted for processing. By examining the results we can
determine where the program performs according to its specified requirements.
Validation Testing:
Validation can be defined in many ways, but a simple definitions is that validation
succeeds when software functions in a manner that can be reasonable expected by the
customer. Software validation is achieved through a series of black box tests that
demonstrate conformity with requirements.
6.3 SCREEN SHOTS
CHAPTER 7. CONCLUSION
7.1 SUMMARY
The objective of this paper was to demonstrate our BPCS-Steganography, which is based
on a property of the human visual system. The most important point for this technique is
that humans cannot see any information in the bit-planes of a color image if it is very
complex. We have discussed the following points and showed our experiments.
(1) We can categorize the bit-planes of a natural image as informative areas and noise-
like areas by the complexity thresholding.
(2) Humans see informative information only in a very simple binary pattern.
(3) We can replace complex regions with secret information in the bit-planes of a natural
image without changing the image quality. This leads to our BPCS-Steganography.
(4) Gray coding provides a better means of identifying which regions of the higher bit
planes can be embedded.
(5) A BPCS-Steganography program can be customized for each user. Thus it guarantees
secret Internet communication. We are very convinced that this steganography is a very
strong information security technique, especially when combined with encrypted
embedded data.
.
Furthermore, it can be applied to areas other than secret communication. Future research
will include the application to vessels other than 24-bit images, identifying and
formalizing the customization parameters, and developing new applications.
7.3 BIBLIOGRAPHY
2. Unleashed JAVA 2 By
Jamie jaworski
Budi kurniawan