0% found this document useful (0 votes)
73 views593 pages

Advanced Java Programming Workbook

Uploaded by

Emir Güleryüz
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
73 views593 pages

Advanced Java Programming Workbook

Uploaded by

Emir Güleryüz
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Advanced Java

Programming
Advanced Java
Programming
Student Workbook
Advanced Java Programming

Page ii Rev 5.1.4


Advanced Java Programming

Contents
Chapter 1 - Course Introduction ............................................................................................................. 11
Course Objectives ............................................................................................................................ 12
Course Overview .............................................................................................................................. 14
Using the Workbook ......................................................................................................................... 15
Suggested References ....................................................................................................................... 16

Chapter 2 - Advanced I/O — Object Serialization .................................................................................. 19


What is Serialization? ........................................................................................................................ 20
Serializable Objects........................................................................................................................... 22
Writing an Object .............................................................................................................................. 24
Reading an Object ............................................................................................................................ 26
Handling Exceptions .......................................................................................................................... 28
Customizing Serialization ................................................................................................................... 30
Controlling Serialization ..................................................................................................................... 32
Versioning ......................................................................................................................................... 34
Labs ................................................................................................................................................. 36

Chapter 3 - Advanced I/O — New I/O .................................................................................................. 39


The [Link] Package ........................................................................................................................ 40
Buffers and Channels......................................................................................................................... 42
Buffer Implementations ...................................................................................................................... 44
Buffer Methods ................................................................................................................................. 46
ByteBuffer Methods .......................................................................................................................... 48
FileChannel ....................................................................................................................................... 50
File Locking ...................................................................................................................................... 52
MappedByteBuffer ........................................................................................................................... 54
Transferring Data Between Channels ................................................................................................. 56
Character Sets .................................................................................................................................. 58
Labs ................................................................................................................................................. 60

Chapter 4 - Reflection ............................................................................................................................. 63


Introduction to Reflection .................................................................................................................. 64
The Class Class ................................................................................................................................ 66
The reflect Package........................................................................................................................... 68
© 2011 ITCourseware, LLC Rev 5.1.4 Page iii
Advanced Java Programming

Constructors ..................................................................................................................................... 70
Fields ................................................................................................................................................ 72
Methods ........................................................................................................................................... 74
Exception Handling and Reflection .................................................................................................... 76
JavaBeans ......................................................................................................................................... 78
Dynamic Programming ...................................................................................................................... 80
Labs ................................................................................................................................................. 82

Chapter 5 - Advanced JDBC .................................................................................................................. 85


JDBC SQL Escape Syntax ............................................................................................................... 86
The execute() Method ....................................................................................................................... 88
Batch Updates .................................................................................................................................. 90
Updatable Result Sets ....................................................................................................................... 92
Large Objects ................................................................................................................................... 94
Working with Savepoints ................................................................................................................... 96
RowSets ........................................................................................................................................... 98
CachedRowSet ............................................................................................................................... 100
DataSources ................................................................................................................................... 102
Labs ............................................................................................................................................... 104

Chapter 6 - Networking with Sockets ................................................................................................... 107


Clients and Servers ......................................................................................................................... 108
Ports, Addresses, and Protocols ..................................................................................................... 110
The Socket Class ............................................................................................................................ 112
Communication Using I/O ............................................................................................................... 114
Servers ........................................................................................................................................... 116
The ServerSocket Class .................................................................................................................. 118
Concurrent Servers ......................................................................................................................... 120
The URL Class ............................................................................................................................... 122
The URLConnection Class .............................................................................................................. 124
Labs ............................................................................................................................................... 126

Chapter 7 - Remote Method Invocation ................................................................................................ 129


Distributed Applications .................................................................................................................. 130
Stubs .............................................................................................................................................. 132
Steps to Create a Remote Object ................................................................................................... 134
An RMI Client ................................................................................................................................ 136
An RMI Server ............................................................................................................................... 138
RMI Classes and Interfaces ............................................................................................................ 140
Class Distribution ............................................................................................................................ 142
Page iv Rev 5.1.4
Advanced Java Programming

RMI Utilities ................................................................................................................................... 144


Parameter Passing and Serialization ................................................................................................. 146
Labs ............................................................................................................................................... 148

Chapter 8 - Advanced RMI .................................................................................................................. 151


Client Callbacks .............................................................................................................................. 152
Dynamic Class Loading ................................................................................................................... 154
Activation........................................................................................................................................ 156
Activatable Objects......................................................................................................................... 158
Registering Activatable Objects ....................................................................................................... 160
Security and Activation .................................................................................................................... 162
JNDI and RMI Registry .................................................................................................................. 164
RMI-IIOP ...................................................................................................................................... 166
Labs ............................................................................................................................................... 168

Chapter 9 - Managing Security Policies ................................................................................................. 171


Untrusted Code .............................................................................................................................. 172
Security Managers .......................................................................................................................... 174
The Java Security Model ................................................................................................................. 176
Policy Entries .................................................................................................................................. 178
Policy Files...................................................................................................................................... 180
Using the Policy Tool....................................................................................................................... 182
Securing Applets ............................................................................................................................. 184
Securing Applications ...................................................................................................................... 186
Labs ............................................................................................................................................... 188

Chapter 10 - Keys, Signatures, and Certificates .................................................................................... 191


Jar Files .......................................................................................................................................... 192
Data Security Concerns .................................................................................................................. 194
Message Digests ............................................................................................................................. 196
Digital Signatures ............................................................................................................................. 198
Using keytool .................................................................................................................................. 200
Using jarsigner ................................................................................................................................ 202
Certificates ...................................................................................................................................... 204
Certificate Chains ............................................................................................................................ 206
Managing Keys and Certificates ...................................................................................................... 208
Security Policies for Signed Code ................................................................................................... 210
Java Cryptography Architecture ...................................................................................................... 212
Labs ............................................................................................................................................... 214

Rev 5.1.4 Page v


Advanced Java Programming

Chapter 11 - Encryption with the [Link] Package ........................................................................ 217


Cryptography Concepts .................................................................................................................. 218
Encryption Keys ............................................................................................................................. 220
Cipher Algorithms ........................................................................................................................... 222
Modes and Padding Schemes ......................................................................................................... 224
The Cipher Class ............................................................................................................................ 226
Encrypting and Decrypting Data ...................................................................................................... 228
Cipher Output Streams ................................................................................................................... 230
Cipher Input Stream ........................................................................................................................ 232
Encryption Using Password Ciphers ................................................................................................ 234
Exchanging Encrypted Keys ............................................................................................................ 236
Sealed Objects ............................................................................................................................... 238
Labs ............................................................................................................................................... 240

Chapter 12 - Java Authentication and Authorization Service (JAAS) ..................................................... 243


Authentication and Authorization ..................................................................................................... 244
JAAS Overview .............................................................................................................................. 246
LoginContext .................................................................................................................................. 248
Subjects, Principals, and PrivilegedActions ...................................................................................... 250
Authentication with the NTLoginModule ......................................................................................... 252
Defining Permissions in Policy Files ................................................................................................. 254
KeyStoreLoginModule ................................................................................................................... 256
Callbacks ........................................................................................................................................ 258
NameCallback and PasswordCallback ........................................................................................... 260
The Policy Class ............................................................................................................................. 262
Labs ............................................................................................................................................... 264

Chapter 13 - Java Naming and Directory Interface (JNDI) ................................................................... 267


Naming and Directory Services ....................................................................................................... 268
Namespaces and Contexts .............................................................................................................. 270
Naming Operations ......................................................................................................................... 272
Bindings .......................................................................................................................................... 274
Attributes ........................................................................................................................................ 276
Directory Operations....................................................................................................................... 278
DNS Lookups with JNDI ............................................................................................................... 280
JNDI in J2EE .................................................................................................................................. 282
Labs ............................................................................................................................................... 284

Page vi Rev 5.1.4


Advanced Java Programming

Chapter 14 - Processing XML with Java — JAXP ............................................................................... 287


The Java API for XML Processing .................................................................................................. 288
Introduction to SAX Parsing ........................................................................................................... 290
SAXParser and JAXP .................................................................................................................... 292
SAX Event Methods ....................................................................................................................... 294
Introduction to DOM ...................................................................................................................... 296
Parsing DOM with JAXP ................................................................................................................ 298
The DOM API ................................................................................................................................ 300
Validation ........................................................................................................................................ 302
Transformation ................................................................................................................................ 304
Labs ............................................................................................................................................... 306

Chapter 15 - Native Methods ............................................................................................................... 309


Overview of Java Native Methods and JNI ..................................................................................... 310
How to Create and Use Native Methods ........................................................................................ 312
Native Method Declaration ............................................................................................................. 314
Using javah ..................................................................................................................................... 316
Creating the Implementation Code .................................................................................................. 318
Compilation .................................................................................................................................... 320
Distribution...................................................................................................................................... 322
Using the Native Methods ............................................................................................................... 324
JNI ................................................................................................................................................. 326
Passing Arguments .......................................................................................................................... 328
Calling Java Methods in Native Code .............................................................................................. 330
JNI Signatures ................................................................................................................................ 332
Labs ............................................................................................................................................... 334

Chapter 16 - Java Design Patterns — Creational Patterns ..................................................................... 337


What Are Design Patterns? ............................................................................................................. 338
What Are Creational Patterns? ........................................................................................................ 340
Singleton — Introduction ................................................................................................................ 342
Singleton — Implementation ............................................................................................................ 344
Singleton — When to Use? ............................................................................................................. 346
Factory Method — Introduction ..................................................................................................... 348
Factory Method — Implementation ................................................................................................ 350
Factory Method — When to Use? .................................................................................................. 352
Builder — Introduction ................................................................................................................... 354
Builder — Implementation ............................................................................................................... 356
Builder — When to Use? ................................................................................................................ 358
Labs ............................................................................................................................................... 360
© 2011 ITCourseware, LLC Rev 5.1.4 Page vii
Advanced Java Programming

Chapter 17 - Java Design Patterns — Structural Patterns ...................................................................... 363


What Are Structural Patterns? ......................................................................................................... 364
Façade — Introduction ................................................................................................................... 366
Façade — Implementation .............................................................................................................. 368
Façade — When to Use? ............................................................................................................... 370
Adapter — Introduction .................................................................................................................. 372
Adapter — Implementation ............................................................................................................. 374
Adapter — When to Use? .............................................................................................................. 376
Composite — Introduction .............................................................................................................. 378
Composite — Implementation ......................................................................................................... 380
Composite — When to Use? .......................................................................................................... 382
Labs ............................................................................................................................................... 384

Chapter 18 - Java Design Patterns — Behavioral Patterns .................................................................... 387


What Are Behavioral Patterns?........................................................................................................ 388
Template — Introduction ................................................................................................................ 390
Template — Implementation ............................................................................................................ 392
Template — When to Use? ............................................................................................................. 394
State — Introduction....................................................................................................................... 396
State — Implementation .................................................................................................................. 398
State — When to Use? ................................................................................................................... 400
Observer — Introduction ................................................................................................................ 402
Observer — Implementation ........................................................................................................... 404
Observer — When to Use? ............................................................................................................ 406
Labs ............................................................................................................................................... 408

Appendix A - JDBC SQL Programming ................................................................................................ 411


Error Checking and the SQLException Class .................................................................................. 412
The SQLWarning Class ................................................................................................................... 414
JDBC Types ................................................................................................................................... 416
Executing SQL Queries ................................................................................................................... 418
ResultSetMetaData ......................................................................................................................... 420
Executing SQL Updates .................................................................................................................. 422
Using a PreparedStatement ............................................................................................................. 424
Parameterized Statements ............................................................................................................... 426
Stored Procedures .......................................................................................................................... 428
Transaction Management ................................................................................................................. 430
Labs ............................................................................................................................................... 432

Page viii Rev 5.1.4 © 2011 ITCourseware, LLC


Advanced Java Programming

Appendix B - Eclipse ............................................................................................................................ 435


Introduction to Eclipse .................................................................................................................... 436
Installing Eclipse ............................................................................................................................. 438
Running Eclipse for the First Time .................................................................................................... 440
Editors, Views, and Perspectives ..................................................................................................... 442
Setting up a Project ......................................................................................................................... 444
Creating a New Java Application .................................................................................................... 446
Running a Java Application .............................................................................................................. 448
Debugging a Java Application .......................................................................................................... 450
Shortcut Key Sequences ................................................................................................................. 452
More Shortcut Key Sequences ....................................................................................................... 454
Setting the Classpath ....................................................................................................................... 456
Importing Existing Java Code into Eclipse ....................................................................................... 458

Solutions ............................................................................................................................................... 461

Index..................................................................................................................................................... 583

© 2011 ITCourseware, LLC Rev 5.1.4 Page ix


Advanced Java Programming

Page x Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 1 Course Introduction

Chapter 1 - Course Introduction

© 2011 ITCourseware, LLC Rev 5.1.4 Page 11


Advanced Java Programming

Course Objectives

” Store and retrieve a serialized Java object.

” Use buffers and channels from Java's New I/O packages.

” Use reflection classes to examine objects and classes at runtime.

” Write Java programs that use advanced features of JDBC to interact with a
relational database.

” Create client/server Java applications using Remote Method Invocation


(RMI).

” Use activation and dynamic class loading within your RMI applications.

” Use Java's security features and utilities.

” Encrypt data with the [Link] package.

” Authenticate and authorize clients with the Java Authentication and


Authorization Service (JAAS).

” Bind and lookup objects in a naming service using the Java Naming and
Directory Interface (JNDI).

” Access XML content with the Java API for XML Processing (JAXP).

” Integrate legacy C/C++ code into your Java programs using the Java Native
Interface (JNI).

” Implement common creational, structural, and behavioral design patterns in


Java.

Page 12 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 1 Course Introduction

© 2011 ITCourseware, LLC Rev 5.1.4 Page 13


Advanced Java Programming

Course Overview

” Audience: This course is designed for Java programmers who wish to


develop applications taking advantage of advanced packages and features of
the Java language.

” Prerequisites: Java Programming. Experience writing applications in Java.

” Classroom Environment:

¾ One Java development environment per student.

¾ DBMS Server.

Page 14 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 1 Course Introduction

Using the Workbook

This workbook design is based on a page-pair, consisting of a Topic page and a Support page. When you
lay the workbook open flat, the Topic page is on the left and the Support page is on the right. The Topic
page contains the points to be discussed in class. The Support page has code examples, diagrams, screen
shots and additional information. Hands On sections provide opportunities for practical application of key
concepts. Try It and Investigate sections help direct individual discovery.

In addition, there is an index for quick look-up. Printed lab solutions are in the back of the book as well as
on-line if you need a little help.

The Topic page provides The Support page has


the main topics for additional information,
classroom discussion. examples and suggestions.

Java Servlets Chapter 2 Servlet Basics

Code examples are in a


The Servlet Life Cycle Hands On:
fixed font and shaded. The
 The servlet container controls the life cycle of the servlet. Add an init() method to your Today servlet that initializes a on-line file
bornOn date, then name
print the bornOn dateis listed
along with the current date:
 When the first request is received, the container loads the servlet class above the shaded area.
[Link]
and calls the init() method.
Topics are organized

into
For every request, the container uses a separate thread to call
...

first (”), secondthe(¾) andmethod.


service() public class Today extends GenericServlet {
private Date bornOn;

third (ƒ)level
Whenpoints.
the servlet is unloaded, the container calls the destroy()
public void service(ServletRequest request,
ServletResponse response) throws ServletException, IOException
method. {
...
// Write the document
 As with Java’s finalize() method, don’t count on this being
called.
Callout boxes point out
[Link]("This servlet was born on " + [Link]());
[Link]("It is now " + [Link]());

 Override one of the init() methods for one-time initializations, instead of


important parts of the
}
public void init() {

using a constructor. example code.


}
bornOn = new Date();
The init() method is
called when the servlet is
}
loaded into the container.
 The simplest form takes no parameters.

public void init() {...}

 If you need to know container-specific configuration information, use


the other version.

public void init(ServletConfig config) {...

 Whenever you use the ServletConfig approach, always call the


superclass method, which performs additional initializations.

[Link](config);

Screen shots show


examples of what you
Page 16 Rev 2.0.0 © 2002 ITCourseware, LLC © 2002 ITCourseware, LLC Rev 2.0.0 Page 17

Pages are numbered should see in class.


sequentially throughout
the book, making lookup
easy.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 15


Advanced Java Programming

Suggested References

Fisher, Maydene, Jonathan Bruce, and Jon Ellis. 2003. JDBC API Tutorial and Reference: Universal
Data Access for the Java2 Platform, Third Edition. Addison-Wesley, Reading, MA.
ISBN 0321173848.

Flanagan, David. 2005. Java in a Nutshell, Fifth Edition. O'Reilly & Associates, Sebastopol, CA.
ISBN 0596007736.

Freeman, Elizabeth, et al. 2004. Head First Design Patterns. O'Reilly & Associates, Sebastopol, CA.
ISBN 0596007124.

Gamma, Erich, et al. 1995. Design Patterns. Addison-Wesley, Reading, MA. ISBN 0201633612.

Gordon, Rob. 1998. Essential JNI: Java Native Interface. Prentice Hall, Upper Saddle River, NJ.
ISBN 0136798950.

Harold, Elliotte Rusty. 2004. Java Network Programming, Third Edition. O'Reilly & Associates,
Sebastopol, CA. ISBN 0596007213.

Hitchens, Ron. 2002. Java NIO. O'Reilly & Associates, Sebastopol, CA. ISBN 0596002882.

Horstmann, Cay S. and Gary Cornell. 2004. Core Java 2, Volume II: Advanced Features, Seventh
Edition. Prentice Hall, Upper Saddle River, NJ. ISBN 0131118269.

Oaks, Scott. 2001. Java Security, Second Edition. O'Reilly & Associates, Sebastopol, CA.
ISBN 0596001576.

[Link]

Page 16 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 1 Course Introduction

© 2011 ITCourseware, LLC Rev 5.1.4 Page 17


Advanced Java Programming

Page 18 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 2 Advanced I/O — Object Serialization

Chapter 2 - Advanced I/O — Object


Serialization

Objectives

” Save and retrieve objects.

” Send an object across a network


connection.

” Customize the serialization process.

” Handle exceptions thrown during the


serialization process.

” Support compatibility between


versions of a Serializable class.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 19


Advanced Java Programming

What is Serialization?

” Serializing, or marshalling, an object converts it to a "stream of data."

¾ A serialized object contains the information necessary to deserialize, or


unmarshal, the object.

” The ObjectOutputStream and ObjectInputStream classes are used to write


and read objects on any type of existing I/O stream.

¾ To write a serialized object to a file, create an ObjectOutputStream from


a FileOutputStream.

ƒ The data in the file is in a proprietary Java format, so it will be


difficult for you to read it.

¾ To write a serialized object to another Java program, retrieve the


OutputStream from a Socket and create the ObjectOutputStream
from that.

ƒ The other Java program will re-create the object when reading it.

¾ To write a serialized object to a byte array, create a


ByteArrayOutputStream from a byte[] and wrap an
ObjectOutputStream around it.

ƒ This array could then be stored in a DBMS.

Page 20 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 2 Advanced I/O — Object Serialization

birthDate:Date title:String name:String

value = 08/05/1930 value = "astronaut" value = "Neil Armstrong"

astronaut:Person

id = 1

Serialization

¬ í \0 005 s r \0 006 P e r s o n E ý
b ÿ T 235 ê h 002 \0 004 I \0 002 i d L \0
\t b i r t h D a t e t \0 020 L j a
v a / u t i l / D a t e ; L \0 004
n a m e t \0 022 L j a v a / l a n
g / S t r i n g ; L \0 005 t i t l
e q \0 ~ \0 002 x p \0 \0 \0 001 s r \0 016
j a v a . u t i l . D a t e h j
201 001 K Y t 031 003 \0 \0 x p w \b ÿ ÿ þ
Þ r ¯ - 200 x t \0 016 N e i l A r
m s t r o n g t \0 \t A s t r o n
a u t

© 2011 ITCourseware, LLC Rev 5.1.4 Page 21


Advanced Java Programming

Serializable Objects

” A serializable object must be an instance of a class that implements


[Link] (or [Link]).

” [Link] defines an interface with no methods.

package [Link];
public interface Serializable {}

¾ Implementing the interface simply marks your class for special treatment
by the Virtual Machine.

” The serialization mechanism uses reflection to construct the Serializable objects.

¾ If the superclass of a Serializable class is not Serializable, it must have


a no-argument constructor.

ƒ The serialization mechanism uses this constructor to initialize the


fields of the non-serializable superclass(es) of the object.

ƒ If the superclass does not have a no-argument constructor, you can


use the Externalizable interface to work around this constraint.

Page 22 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 2 Advanced I/O — Object Serialization

This Person class is an example of a Serializable class. The toString() and equals() methods are included
to compare original objects with restored objects.

[Link]
...
public class Person implements Serializable {
private String name;
private String title;
private Date birthDate;
private int id;

public Person() {
}
public Person(String nm, String ti, String shortBirthDate, int i) {
name = nm;
title = ti;
id = i;
try {
SimpleDateFormat df = new SimpleDateFormat("M/d/yyyy");
birthDate = [Link](shortBirthDate);
}
catch (ParseException e) {
[Link]("Parsing error: " + shortBirthDate);
birthDate = new Date();
}
}
public boolean equals(Object obj) {
if (! (obj instanceof Person)) {
return false;
}

Person p = (Person) obj;

return [Link]([Link]) &&


[Link]([Link]) &&
[Link]([Link]) &&
id == [Link];
}
public String toString() {
SimpleDateFormat df = new SimpleDateFormat("MMM d, yyyy");
return title + " " + name + " born " + [Link](birthDate) +
" id " + id;
}
...
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 23


Advanced Java Programming

Writing an Object

” ObjectOutputStream's writeObject() method serializes (marshals) an object.

¾ The marshalled object contains structural information necessary to


reconstruct the object.

” Build an ObjectOutputStream from any OutputStream.

” Marshalling an object involves dissecting the object into its component elements.

¾ If the object has already been written to this ObjectOutputStream, only


a handle is written.

ƒ This protects against recursive relationships and preserves shared


references.

¾ An ObjectStreamClass identifying the class of the object is written first.

ƒ This includes the name and serialVersionUID of the class.

¾ Primitive fields are written to the stream.

¾ Reference fields are serialized recursively.

¾ static fields will not be serialized.

ƒ Only data specific to the instance is written.

¾ transient fields will not be serialized.

” Since reference data (object members) must also be sent, they must implement
Serializable.

” Transmitting an object will expose private data members.

Page 24 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 2 Advanced I/O — Object Serialization

The writeObject() method takes an Object, not a Serializable. This means that attempting to write a non-
serializable object will not result in a compiler error, but in a NotSerializableException, which will
be caught in the IOException catch, but will not be very descriptive.

[Link]
import [Link];
import [Link];
import [Link];

public class WriteObj {


public static void main(String args[]) {
Person armstrong = new Person("Neil Armstrong", "Astronaut",
"08/05/1930", 1);

ObjectOutputStream out = null;


try {
out = new ObjectOutputStream(
new FileOutputStream("[Link]"));
[Link](armstrong);
[Link]("Wrote \"" + armstrong + "\" to file");
}
catch (IOException e) {
[Link]("Error writing object: " + [Link]());
}
finally {
try {
[Link]();
}
catch (IOException e) {
[Link]([Link]());
}
}
}
}

Try It:
Compile and run [Link]. You can look at the resulting [Link] file and see if you recognize
any of the data.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 25


Advanced Java Programming

Reading an Object

” ObjectInputStream's readObject() method deserializes (unmarshals) an


object.

” Build an ObjectInputStream from any InputStream.

¾ Creating an ObjectInputStream from a stream which does not contain a


serialized object will result in a StreamCorruptedException.

” The readObject() method returns a [Link].

¾ Downcast the object to the appropriate class, making sure to catch the
ClassCastException which may result.

” Unmarshalling an object involves assembling the object from its component


elements.

¾ If the object has been read from the stream already, then a reference to the
existing object is returned.

¾ First, the ObjectStreamClass is read.

ƒ This is then used to load the class and verify the version.

¾ The no-argument constructor of the first non-serializable superclass is


called.

¾ Primitive data members are set directly from the stream.

ƒ No Serializable class constructor is called and field initializers are


also ignored.

¾ Reference data members are deserialized recursively.

Page 26 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 2 Advanced I/O — Object Serialization

[Link]
import [Link];
import [Link];
import [Link];

public class ReadObj {


public static void main(String args[]) {

ObjectInputStream in = null;
try {
in = new ObjectInputStream(
new FileInputStream("[Link]"));
Person p = (Person) [Link]();
[Link](p);
}
catch (ClassCastException e) {
[Link]("Error casting object to a Person");
}
catch (ClassNotFoundException e) {
[Link]("Class not found"); StreamCorruptedException
} extends IOException.
catch (IOException e) {
[Link]("Error reading object: " + [Link]());
}
finally {
try {
[Link]();
}
catch (IOException e) {
[Link]([Link]());
}
}
}
}

Try It:
Compile and run [Link] to load the person.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 27


Advanced Java Programming

Handling Exceptions

” Attempting to serialize an object containing data that is not Serializable will


result in a NotSerializableException.

” Any IOException generated during an attempt to write an object to an


ObjectOutputStream will be copied to the OutputStream in addition to being
thrown.

” The application reading serialized objects is responsible for handling any


exceptions discovered in the InputStream.

” The readObject() method throws a ClassNotFoundException if the VM can't


find the object's .class file.

¾ This happens even if you don't downcast the object.

Page 28 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 2 Advanced I/O — Object Serialization

[Link]
...
public class BadBatchProcessor implements Runnable, Serializable {
private ArrayList<Runnable> jobs;
private ListIterator<Runnable> iterator;

public BadBatchProcessor(ArrayList<Runnable> jobs) {


[Link] = jobs;
The ListIterator implementation
iterator = [Link](); returned is not Serializable.
}
...
public static void main(String args[]) {
BadBatchProcessor processor = null;
File serialFile = new File("batch_processor_bad.ser");
if ([Link]()) {
ObjectInputStream in = null;
try {
in = new ObjectInputStream(new FileInputStream(serialFile));
processor = (BadBatchProcessor)[Link]();
[Link]("Found previous batch processor : " +
processor); This will catch the exception thrown
} when reading the bad serialized object.
catch (IOException ioex) {
[Link]("Error occurred reading "
+ serialFile + ": " + ioex);
[Link](1);
}
catch (ClassNotFoundException cnfex) {
[Link]("Class " + [Link]()
+ " not found while unmarshalling " + serialFile);
[Link](2);
}
...
}
}

While serializing the BadBatchProcessor, an Exception will be thrown due to the non-serializable
ListIterator.

Try It:
Run BadBatchProcessor once to create the serialized object with the Exception. Then run it again to see
what happens when the object is read.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 29


Advanced Java Programming

Customizing Serialization

” Serializing an object also serializes the data members of the object.

” Use the transient modifier to specify that a data member should not be
serialized.

¾ The transient data will not be initialized when the object is read.

” Serialization behavior can be altered by defining the readObject() and


writeObject() methods in the class to be serialized.

private void readObject(ObjectInputStream in)


throws IOException, ClassNotFoundException

private void writeObject(ObjectOutputStream out)


throws IOException

¾ Implementing writeObject() and readObject() allows the class to pre-


and post-process the serialization process, usually handling static or
transient data members.

¾ ObjectOutputStream provides defaultWriteObject() to serialize the


object.

ƒ This method can only be called from writeObject() to write the


Serializable portion of the object.

¾ ObjectInputStream provides defaultReadObject() to deserialize the


object.

ƒ This method can only be called from readObject() to read the


Serializable portion of the object.

Page 30 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 2 Advanced I/O — Object Serialization

Use the transient modifier either for data which is temporary, such as mouse coordinates, or for data
which cannot be successfully serialized. While the Serializable interface does not require any
implementation, it is the developer's responsibility to ensure that the class and all of its data members
are, in fact, Serializable. Failure will result in a runtime exception.

[Link]
...
public class BatchProcessor implements Runnable, Serializable {
private ArrayList<Runnable> jobs;
private transient ListIterator<Runnable> iterator; Since the ListIterator
is not Serializable,
public BatchProcessor(ArrayList<Runnable> jobs) { declare it transient.
[Link] = jobs;
iterator = [Link]();
}

public void run() {


while ([Link]() && ! [Link]()) {
Runnable job = [Link]();
[Link](); Deserialize the non-
} transient fields first.
}
...
private void readObject(ObjectInputStream in)
Read the index stored
throws IOException, ClassNotFoundException { at serialization and get
[Link](); an Iterator to continue
// get a list iterator to start at the next job where we left off.
int firstJob = [Link]();
iterator = [Link](firstJob);
}
Serialize the non-
private void writeObject(ObjectOutputStream out)
transient fields first.
throws IOException {
[Link]();
// store the index of the next job for use at deserialization
[Link]([Link]());
}
Store the index of the next
... job for use at deserialization.
}

Try It:
BatchProcessor has a main() method. The first time you run it, it creates a new batch of test jobs and runs
for a couple of seconds. Each time you run it after that it will continue where it left off.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 31


Advanced Java Programming

Controlling Serialization

” Classes that need to completely control the serialization process can implement
[Link], which extends Serializable.

” Externalizable declares two methods, readExternal() and writeExternal().

” This interface completely replaces the default serialization behavior for


assembling and disassembling the component elements.

¾ An Externalizable class must provide a no-argument constructor which


is invoked before readExternal().

¾ The readExternal() and writeExternal() methods must explicitly read


and write any data necessary to reconstruct the object.

ƒ This includes fields from the class and all its superclasses.

¾ readObject() and writeObject() will not be called on the class or any


superclass, and defaultReadObject() and defaultWriteObject() are not
available.

¾ The ObjectStreamClass and internal handle are used in the same way as
they are for Serializable classes.

” Use Externalizable when you need more control than readObject() and
writeObject() provide.

¾ Coordinating with the default serialization may be tedious; it might be


easier to use Externalizable.

¾ An Externalizable object can override the serialization behavior of its


superclass.

Page 32 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 2 Advanced I/O — Object Serialization

Customer is a subclass of Person, so it inherits Person's serialization behavior. For privacy, we want to
leave the personal information out of the serialized objects. The easiest way to do this without changing
Person is to use Externalizable.

[Link]
...
public class Customer extends Person implements Externalizable {
private int accountNumber;

// required no-argument constructor for Externalizable mechanism


public Customer() {
Here we must define appropriate
// provide a dummy birth date defaults for the fields we will not be
// Person can't handle null serializing. For most, null will suffice.
setBirthDate(new Date());
}

public Customer(int accountNumber, String name, String title,


String birthDate, int id) {
super(name, title, birthDate, id);
[Link] = accountNumber;
}

// read [Link] and [Link]


public void readExternal(ObjectInput in) throws IOException {
setId([Link]());
All other fields for Person have
accountNumber = [Link](); been defaulted by Customer's
} no-argument constructor.

// write [Link] and [Link], we don't want to


// expose the other fields of Person on the output stream.
public void writeExternal(ObjectOutput out) throws IOException {
[Link](getId());
The only data we write
[Link](accountNumber);
from Person is the id.
}
...
}

Try It:
Test Customer with WriteCust and ReadCust.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 33


Advanced Java Programming

Versioning

” Every Serializable class contains a serialVersionUID.

¾ By default, this long value is calculated from the name and signature of
the class and its fields and methods using the Secure Hash Algorithm.

¾ You can provide your own public static final long serialVersionUID
for backward compatibility.

ƒ Use the serialver utility (before you change the class) to find out
the old version ID: serialver Person.

” You must ensure that the changes are both forwards and backwards compatible.

¾ Adding, removing, or modifying methods is compatible, though you must


consider your business logic.

¾ Adding fields is compatible.

ƒ The new class must handle default values for fields missing from
old objects.

ƒ The old class will ignore the unknown fields in new objects.

¾ Removing fields is incompatible.

ƒ The old class might rely on non-default values from the fields
missing in new objects.

¾ You may need to use readObject() and writeObject() to ensure


compatibility.

Page 34 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 2 Advanced I/O — Object Serialization

[Link]
...
public class Person implements Serializable {
public static final long serialVersionUID = 5043296006500641384L;

private String name;


private String title;
private Date birthDate;
private int id;
private String quote =
"Be respectful to your superiors, if you have any. - Mark Twain";

...
public String toString() {
SimpleDateFormat df = new SimpleDateFormat("MMM d, yyyy");
StringBuilder result = new StringBuilder();
[Link](title).append(" ").append(name);
[Link](" born ").append([Link](birthDate));
[Link](" id ").append(id);
if (quote == null) {
[Link](" old class version: no quote specified");
} Here we handle objects serialized
else { under the old version of the class.
[Link](" quote ");
[Link]('"').append(quote).append('"');
}
return [Link]();
}
...
}

Try It:
Make sure you have already run WriteObj with the original version of Person.

Make a backup copy of [Link], then copy [Link] to [Link]. Compile


[Link], then run ReadObj to view the old serialized object with the new class.

Now run WriteObj to create a new serialized object. Restore [Link] from the backup, then compile
it and run ReadObj to view the new object with the old class.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 35


Advanced Java Programming

Labs

Write an Employee class with appropriate fields, including a hireDate. Write a Department class
which has an Employee for the manager. Write an application which creates a Department object
and writes it to a file. (Hint: Use SimpleDateFormat to create a hire date.)
(Solution: [Link], [Link], [Link])

Write an application that reads a Department object from a file and displays it.
(Solution: [Link])

Modify the solution to to read from a file that doesn't contain a serialized object.
(Solution: [Link], [Link])

In the next set of exercises you will modify your Employee class to create a new version. You should save a
copy of [Link] and [Link] before continuing.

Run serialver on the Employee class and copy the value into a new serialVersionUID field in
your Employee class. Then, add a new Date field, departmentStartDate, to Employee. Do not
modify toString() to include this field yet. In your constructor(s), default the departmentStartDate
to the hireDate. Make sure your new class works with the serialized objects you created in ;
you should still be able to display the object using ReadDept.
(Solution: [Link].4)

Use SimpleDateFormat to include the departmentStartDate in the toString() method. What


happens when you run ReadDept?
(Solution: [Link].5, [Link])

Fix your Employee class using readObject so that if the departmentStartDate was missing in the
serialized object, it would default to hireDate. Verify that this works with ReadDept.
(Solution: [Link].6)

Modify your application that writes the department so that it uses the new Employee class with a
non-default departmentStartDate. After creating the new serialized object, restore the original
version of Employee and verify that you can read the new serialized object with the old class.
(Solution: [Link])

Page 36 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 2 Advanced I/O — Object Serialization

© 2011 ITCourseware, LLC Rev 5.1.4 Page 37


Advanced Java Programming

Page 38 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 3 Advanced I/O — New I/O

Chapter 3 - Advanced I/O — New I/O

Objectives
” Describe the classes and interfaces in the
[Link] package.

” Store data within a Buffer.

” Map a file onto memory with a


MappedByteBuffer.

” Connect I/O objects together with


Channels.

” Use the FileChannel object to lock files.

” Translate characters to byte sequences


using Charset implementations.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 39


Advanced Java Programming

The [Link] Package

” The traditional I/O classes in the [Link] package are easy to use, but they are not
very efficient and do not take advantage of services that most operating systems
provide.

¾ Sun introduced the New I/O library (NIO) with JDK version 1.4 to
address those concerns.

¾ The old [Link] library was rewritten to take advantage of some of the
new features.

” The new I/O library reads and writes data in blocks, instead of the byte or
character streams of the [Link] package.

¾ Blocks of data are managed in buffers.

¾ Developers read and write data to the buffer, instead of directly to the
stream.

¾ The [Link] package contains a buffer class for each of the primitive
Java types.

” Channels handle reading and writing to the output device.

¾ The [Link] package contains channel classes and interfaces.

¾ It also contains selector classes, which are used to multiplex channels.

” Charsets encode and decode data from an I/O device to Java unicode
characters.

¾ The [Link] package contains charset, decoder, and encoder


classes.

Page 40 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 3 Advanced I/O — New I/O

© 2011 ITCourseware, LLC Rev 5.1.4 Page 41


Advanced Java Programming

Buffers and Channels

” In the NIO model, buffers and channels work together to read and write to I/O
devices.

¾ You read and write data to a buffer, instead of directly to the channel.

¾ You then pass the buffer to the channel, which reads or writes it to the
device.

” To read from a file, first get a [Link] object from a


RandomAccessFile, FileInputStream, or FileOutputStream.

RandomAccessFile raf = new RandomAccessFile(fname, "rw");


FileChannel fc = [Link]();

” Then allocate a buffer to handle the data from the channel:

ByteBuffer buf = [Link](1024);

¾ Allocate buffers in integer multiples of the device's default page size,


usually 512 bytes.

” If you want to read from the file, call the read() method on the channel, passing
the buffer:

int count = [Link](buf);

¾ To get the data from buffer, flip it, then use the get() method:

byte[] bytes = new byte[count];


[Link]();
[Link](bytes);

” If you want to write to the file, fill the buffer, flip it, and then call the channel's
write() method.

Page 42 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 3 Advanced I/O — New I/O

[Link]
import [Link];
import [Link];
import [Link];

public class NIORead {


public static void main(String[] args) {
try {
String fileName = "access_log";
RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
FileChannel fc = [Link]();
ByteBuffer buf = [Link](1024);
byte[] bytes = null;
Read from the channel
int count=-1;
into the buffer until the end
of file is indicated by a -1
while ((count = [Link](buf)) != -1) { return value.
bytes = new byte[count];
[Link](); Get the data
[Link](bytes); from the buffer.
for (byte b: bytes) {
[Link]((char) b);
}
[Link]();
}

// write to file
[Link]("Hello".getBytes());
[Link]();
[Link](buf);
[Link]("Wrote string \"Hello\" to access_log.");
[Link]();
}
catch (Exception e) {
[Link]();
}
}
}

Try It:
Compile and run [Link] to use buffers and channels to read a file.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 43


Advanced Java Programming

Buffer Implementations

” The [Link] package contains several buffer classes.

¾ All of the buffer classes in [Link] are abstract, and must be


implemented by a service provider.

” The basic class, Buffer, is the superclass for implementations for various types
of data.

¾ It defines the way a buffer keeps track of its internal positioning.

” The most commonly-used subclass is ByteBuffer, which stores its data as a


byte[].

¾ It provides methods for getting or putting each of the primitive Java types
except boolean.

” There are six other buffer classes, one for each of the primitive Java types
(except boolean).

¾ Each TypeBuffer class provides get() and put() methods that work with
its type.

¾ The CharBuffer class also has a put() method that takes a String
parameter.

” Because most I/O devices work with bytes, channels can only read or write a
ByteBuffer.

¾ To use a buffer of another type, get a view into the ByteBuffer:

ByteBuffer bbuf = [Link](16);


DoubleBuffer dbuf = [Link]();

¾ Both buffers are sharing the same storage, so be careful.


Page 44 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 3 Advanced I/O — New I/O

[Link]

Buffer

ByteBuffer CharBuffer DoubleBuffer FloatBuffer IntBuffer LongBuffer ShortBuffer

[Link]
...
public class DoubleWrite {
public static void main(String[] args) {
try {
String fileName = "constants";
FileOutputStream fout = new FileOutputStream(fileName);
FileChannel fc = [Link]();
ByteBuffer bbuf = [Link](16);
DoubleBuffer dbuf = [Link]();

[Link]([Link]); Write pi and e to file.


[Link](Math.E);
[Link]();
[Link](bbuf);
[Link]("Wrote math constants to constants file.");
[Link]();

[Link]();
FileInputStream fin = new FileInputStream(fileName);
fc = [Link]();
[Link](bbuf);
[Link](); Read pi and e from file.
double pi = [Link]();
double e = [Link]();
[Link]();
[Link]("pi = " + pi + " e = " + e);
}
catch (Exception e) {
[Link]();
}
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 45


Advanced Java Programming

Buffer Methods

” [Link] defines methods that are related to the position, limit, and
capacity of the buffer.

¾ The capacity is defined when the buffer is allocated and is the amount of
data the buffer can hold.

¾ The position is where any reading or writing operations will occur.

¾ The limit is one more than maximum position that contains valid data or
to which you can write data.

¾ 0 <= position <= limit <= capacity.

” In a read operation, after the channel fills the buffer, the position specifies how
much data has been read from the device into the buffer.

¾ If you want to pull data out of the buffer, you must reset the position to
define where you are getting from and the limit to define how much you
can get.

¾ Use the flip() method to set limit = position and position = 0 so that calls
to get() will retrieve the correct data from the buffer.

” In a write operation, after you put() data into the buffer, the position specifies
the last place you put data.

¾ Before you write() to the channel, call flip() to set the limit = position and
position = 0 so that the channel knows what data to write to the device.

” Use clear() to reset position = 0 and limit = capacity if you want to do any more
read or write operations on the buffer.

” Channel operations, and get and put calls on the buffer, set the position and limit
properly; however, you can retrieve the values or set them with methods in the
Buffer class.
Page 46 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 3 Advanced I/O — New I/O

When you allocate a buffer, an array is allocated to hold the data. The capacity is defined to be the
allocation size of the buffer. The position is initialized to 0 and the limit is initialized to the capacity.
ByteBuffer buf = [Link](8);
0 1 2 3 4 5 6 7 8

position limit, capacity


When we read from the channel into the buffer, the channel starts at position and continues until either the
entire file is read or the buffer is full (position = limit). Let's read from a file that contains six bytes of data:
[Link](buf);
0 1 2 3 4 5 6 7 8
a b c d e f
position limit, capacity
Now position = 6 and limit hasn't changed. Call flip() to ready the buffer for a get:
[Link]();
0 1 2 3 4 5 6 7 8
a b c d e f
position limit capacity
Now position = 0 and limit = 6. Call get() to read the buffer into a byte array:
[Link](data);
0 1 2 3 4 5 6 7 8
a b c d e f
position, limit capacity
After the get, position = limit. Prepare the buffer for a new operation by calling clear(), which resets
position and limit to their initial values so that we can put new data into the buffer:
[Link]();
[Link]("Hello".getBytes());
0 1 2 3 4 5 6 7 8
H e l l o f

position limit, capacity


Position = 5 and limit = capacity, telling us we still have room if we want to put more in the buffer. Instead,
let's get ready to write:
[Link]();
0 1 2 3 4 5 6 7 8
H e l l o f

position limit capacity


Now when we call [Link](), it will write our new data to the file.
Try It:
Compile and run [Link] to see the position, limit, and capacity in action.
© 2011 ITCourseware, LLC Rev 5.1.4 Page 47
Advanced Java Programming

ByteBuffer Methods

” [Link] defines methods that help get data from and put data in the
buffer.

¾ There are get and put methods for each primitive type except boolean.

¾ There are overloaded get and put methods that allow you to specify an
absolute position within the buffer.

ƒ These methods do not use or effect the position or limit.

¾ There are also get and put methods to read from or write to a byte array.

ƒ Since the file channel's read() method returns the number of bytes
read, it is convenient to allocate a byte array and use this version of
the get method.

” You can work directly with the buffer's array by calling the array() method.

¾ This returns a reference to the underlying byte array.

¾ Any manipulation of the array bypasses the buffer's internal bookkeeping,


so you will have to fix the position and limit yourself.

” You can also supply your own array to a buffer with the static wrap() method.

” Most of the Buffer and ByteBuffer methods that do not need to return
something else (eg. get methods), return a reference to the buffer itself.

¾ This is so you can chain several method calls together:

[Link]().get(bytes);

Page 48 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 3 Advanced I/O — New I/O

© 2011 ITCourseware, LLC Rev 5.1.4 Page 49


Advanced Java Programming

FileChannel

” The [Link] class provides mechanisms for reading,


writing, locking, and mapping files.

¾ As with Buffer, the class is abstract and you actually get an instance of a
class defined by a service provider.

¾ The [Link] package provides classes that make it easier


to write service provider implementations.

” The read() and write() methods require one or more ByteBuffers.

¾ An overloaded read() method accepts a ByteBuffer array, allowing you


to do a scattered read.

¾ An overloaded write() method also accepts a ByteBuffer array, allowing


you to do a gathered write.

¾ Scatter and gather are useful for data that has different sections.

ƒ For example, you may have a header section that contains binary
data and a body section that contains UTF-16 encoded text.

” FileChannel provides some useful methods for manipulating files:

¾ size() returns the size of the file in bytes.

¾ truncate(size) cuts off the file at the specified size.

¾ force() causes any updates to the channel to be written to the device.

Page 50 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 3 Advanced I/O — New I/O

[Link]
...
public class Scatter {
public static void main(String[] args) {
try {
String fileName = "mixed";

FileInputStream fin = new FileInputStream(fileName);


FileChannel fc = [Link]();
ByteBuffer[] bufs = new ByteBuffer[2];

// set up the temps buffer


bufs[0] = [Link](16);
FloatBuffer fbuf = bufs[0].asFloatBuffer();

// set up the cities buffer


bufs[1] = [Link](100);
CharBuffer cbuf = bufs[1].asCharBuffer();

int bytes = (int) [Link](bufs);

// read the temps


float[] temps = new float[4];
bufs[0].flip();
[Link](temps);

// read the cities


char[] cCities = new char[(bytes - 16)/2];
bufs[1].flip();
[Link](cCities);
String sCities = new String(cCities);
String[] cities = [Link]("\\s");

for (int i = 0; i < [Link]; i++) {


[Link](cities[i] + ": " + temps[i]);
}
[Link]();
}
catch (Exception e) {
[Link]();
}
}
}

Try It:
Compile and run [Link] to write an array of float temperatures and an array of String cities to
the mixed file. Use the [Link] program to read the file.
© 2011 ITCourseware, LLC Rev 5.1.4 Page 51
Advanced Java Programming

File Locking

” Obtain a file lock by calling the FileChannel's lock() method.

public FileLock lock(long start, long size, boolean shared)

¾ The third argument should be true if you want a shared (read) lock, false
if you want an exclusive (write) lock.

¾ An overloaded version of lock() with no parameters places an exclusive


lock on the entire file.

” lock() returns a FileLock object, which provides a release() method to call


when you are done with the lock.

¾ The FileLock also knows about the channel that created it, its start
position, size, and whether it is shared.

” The lock() methods block until the requested lock can be obtained.

¾ Use FileChannel's tryLock() method to avoid blocking.

¾ tryLock() returns null if the lock could not be obtained.

” File locking in Java relies on the operating system implementation, so it will work
differently on different systems.

¾ On some systems a file lock is advisory, while on others it is mandatory.

¾ Some systems do not provide shared locks, if you request one it will be
silently promoted to exclusive.

” Locks are implemented within the operating system on a per file, per process
basis.

¾ Use file locking to coordinate processes, not threads within a process, or


different FileChannel objects on the same file.
Page 52 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 3 Advanced I/O — New I/O

[Link]
...
public class LockTest {
public static void main(String[] args) {
try {
String fileName = "access_log";

RandomAccessFile raf = new RandomAccessFile(fileName, "rw");


FileChannel fc = [Link]();

[Link]("Press <Enter> to obtain the exclusive lock");


[Link]();
if ([Link]() == 1)
[Link](); //for Windows

FileLock lock = [Link]();


[Link]("\nObtained an exclusive lock on " + fileName);
[Link](3000);
[Link]();
[Link]("Released exclusive lock");

[Link]("Press <Enter> to obtain the shared lock");


[Link]();

lock = [Link](0, Long.MAX_VALUE, true);


[Link]("\nObtained a shared lock on " + fileName);
[Link](3000);
[Link]();
[Link]("Released shared lock");

[Link]();
}
catch (Exception e) {
[Link]();
}
}
}

Try It:
Run this program in two separate JVMs to test file locking. Start both programs before pressing <Enter> to
get the lock. The program sleeps three seconds between obtaining and releasing the lock, so you have time
to go to the other instance and press <Enter>.

Note: In the example, we pass Long.MAX_VALUE as the second argument to the shared lock call. This
does not affect the size of the file, and any expansions to the size will still be covered by our lock.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 53


Advanced Java Programming

MappedByteBuffer

” Until now, we have been transferring data to and from Java buffers, which
encapsulate byte arrays, to the kernel's paging memory so that the OS can write
or read the data to the physical file.

¾ You can avoid the buffer copy by mapping your buffer directly to the
paging memory.

” Get a MappedByteBuffer by calling the map() method on the FileChannel


object.

¾ The first argument to map() is the map mode, which is defined by


constants in the [Link] class: READ_ONLY,
READ_WRITE, and PRIVATE.

¾ The second and third arguments specify the map's position and size
within the physical file.

” A MappedByteBuffer is a ByteBuffer, so you can put data in it or get data


from it with the same put() and get() methods.

¾ When you put() into a MappedByteBuffer, the data is directly written to


the file, no write() is required.

¾ When you get() from the buffer, you are retrieving the data as it is in the
file, including any changes made by other processes since you opened the
channel.

” MappedByteBuffer defines additional methods for working with the file.

¾ force() is like the force() in FileChannel; use this for mapped buffers.

¾ load() causes the entire file to be read into paging memory, and
isLoaded() checks if it is.

ƒ Because paging memory is dynamic, use these methods with care.


Page 54 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 3 Advanced I/O — New I/O

Note:
The third argument to the FileChannel map() method is the size of the mapped buffer that you want to
create. If you specify a size larger than the size of the file, the physical file size will increase to the size you
specify. Do not pass Long.MAX_VALUE, as we did with file locking, unless you really want (and have
disks that will hold) seven exabytes (7 x 1018).

© 2011 ITCourseware, LLC Rev 5.1.4 Page 55


Advanced Java Programming

Transferring Data Between Channels

” FileChannel provides two methods to facilitate transferring data between


channels.

¾ These methods do not use buffers; they copy data directly to and from
the kernel's paging area.

” At least one of the channels must be a FileChannel, because the methods are
defined in the FileChannel class.

¾ The transferTo() method allows you to send data from this channel to a
WritableByteChannel.

long transferTo(long position, long size,


WritableByteChannel target)

¾ The transferFrom() method allows you to get data from a


ReadableByteChannel and put it in this channel.

long transferFrom(ReadableByteChannel src,


long position, long size)

¾ SocketChannel implements WritableByteChannel and


ReadableByteChannel, so you can send data to or get data from a
SocketChannel.

” When you call transferTo() or transferFrom(), you specify the start position
and size of the data you want to transfer.

¾ If position + size is greater than the size of the file to which you are
transferring, your transfer will be truncated.

¾ Both methods return the actual number of bytes transferred.

Page 56 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 3 Advanced I/O — New I/O

© 2011 ITCourseware, LLC Rev 5.1.4 Page 57


Advanced Java Programming

Character Sets

” A charset is a combination of a coded character set (a set of characters with a


numeric value assigned to each) and an encoding scheme for representing those
values in a binary computer.

¾ The [Link] class represents charsets in Java.

¾ From the Charset, you can obtain a CharsetEncoder to encode a


CharBuffer as a sequence of bytes.

¾ You can also obtain a CharsetDecoder to convert a sequence of bytes as


a CharBuffer.

” The Charset class provides methods for finding out what charsets are available
in the JVM, and for getting a Charset object for a specific charset.

¾ The static forName(String name) method returns the Charset object for
the specified charset.

ƒ The name can be either the canonical name or an alias.

” The Charset provides two encode() methods for encoding a CharBuffer or a


String to a ByteBuffer, and a decode() method for decoding a ByteBuffer to a
CharBuffer.

¾ For more control, call newEncoder() to get a CharsetEncoder or


newDecoder() to get a CharsetDecoder.

” CharsetEncoder allows you to do multiple encode() calls, in case you need to


encode more data, or your result buffer fills up, or there is an error.

¾ Call reset() before you start, and flush() when you are finished.

” CharsetDecoder allows the same control with the decode() method.

Page 58 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 3 Advanced I/O — New I/O

[Link]
...
public class ReadLog1 {
public static void main(String[] args) {
try {
String fileName = "access_log";
RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
FileChannel channel = [Link]();

ByteBuffer bbuf = [Link](1024);


CharBuffer cbuf = [Link]();
int count = [Link](bbuf);
[Link]();
char[] chars = new char[count / 2];
[Link](chars);
for (char c : chars) {
[Link](c);
...
}
}

Try It:
When you compile and run [Link], you will notice that the output is garbage. That is because the
data in the access_log file is encoded with the US-ASCII charset, but we are reading it as UTF-16.
[Link] decodes and displays the information correctly.

[Link]
...
public class ReadLog2 {
public static void main(String[] args) {
try {
...
ByteBuffer bbuf = [Link](1024);
int count = [Link](bbuf);
[Link]();
Charset ascii = [Link]("US-ASCII");
CharBuffer cbuf = [Link](bbuf);
char[] chars = new char[[Link]()];
[Link](chars);
for (char c : chars) {
[Link](c);
}
...
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 59


Advanced Java Programming

Labs

Write a program that reads [Link] and writes it to a filed called JavaSource.
(Solution: [Link])

Bonus: Can you do it without a buffer?


(Solution: [Link])

† Write a program that uses a Charset, ByteBuffer, and FileChannel to write the names of
each of the installed charsets to a file. Use ByteBuffer's put() method that takes a byte array
for a parameter. Get the byte array from String's getBytes() method.

Hint: [Link]() returns a SortedMap<String, Charset>. You can get a


Set of the names of the charsets from the Map's keySet() method.

Hint: [Link]() throws a BufferOverflowException if the buffer does not have room
for what you are trying to put on it. You can avoid that by checking the position and limit before
you put.
(Solution: [Link])

‡ Change your program from † to use a CharBuffer. What is the difference in the output?
(Solutions: [Link], [Link])

Page 60 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 3 Advanced I/O — New I/O

© 2011 ITCourseware, LLC Rev 5.1.4 Page 61


Advanced Java Programming

Page 62 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 4 Reflection

Chapter 4 - Reflection

Objectives

” Obtain the fields and methods of a


class.

” Dynamically invoke a method on an


object.

” Catch an exception thrown from a


dynamically-invoked method.

” Create a JavaBean.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 63


Advanced Java Programming

Introduction to Reflection

” The Java Reflection API allows programs to find out everything about an object
at runtime.

¾ Since Java is a dynamic language, classes can be loaded, instantiated, and


methods invoked on the objects after a program has started.

¾ The Reflection API gives developers a window into what the JVM knows
about an object.

” The Reflection API is defined by the [Link] class, and the classes and
interfaces of the [Link] package.

¾ With reflection, you can identify the type of an object, which class it
extends, which interfaces it implements, and which modifiers, such as
public or final, apply to the class.

¾ You can query for the constructors, methods and fields of a class, and
their modifiers.

¾ You can instantiate a class without knowing its name at build time.

¾ You can invoke methods or access fields of an object dynamically.

ƒ Unlike pointers in C++, you can not use reflection to bypass the
visibility modifiers.

” Reflection is primarily used by developers of tools, such as GUI design tools or


debuggers.

¾ You can use a Method object like a type-safe function pointer, but it may
be better to design your calls to work with interfaces.

Page 64 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 4 Reflection

© 2011 ITCourseware, LLC Rev 5.1.4 Page 65


Advanced Java Programming

The Class Class

” For any Java class, there is a corresponding [Link] object.

” There are three ways to obtain the Class object:

1. Use the class literal.

Class personClass = [Link];

2. Call the forName() static method of [Link].

Class personClass = [Link]("Person");

3. Call the getClass() method of an object.

Person p = new Person("Sam","Java Programmer",


"03/20/92", 1);
Class personClass = [Link]();

” The Class object provides information about the class.

¾ The name of the class.

¾ The class' constructors.

¾ The class' methods.

¾ The class' fields.

Page 66 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 4 Reflection

[Link]
...
public class Person {
private String name;
private String title;
private Date birthDate;
private int id;

public Person(String nm, String ti, String bDate, int i) {


name = nm;
title = ti;
id = i;
try {
SimpleDateFormat df = new SimpleDateFormat("M/d/yyyy");
birthDate = [Link](bDate);
}
catch (ParseException e) {
[Link]("Error parsing Birth Date: " + bDate);
birthDate = new Date();
}
}

public String getName(){


return name;
}
public String getTitle(){
return title;
}
public Date getBirthDate(){
return birthDate;
}
public int getId(){
return id;
}
public String toString() {
SimpleDateFormat df = new SimpleDateFormat("MMM d, yyyy");
return title + " " + name + " born " + [Link](birthDate);
}
public boolean equals(Object o) {
if (o instanceof Person) {
Person pTest = (Person) o;
return [Link]([Link]) && [Link]([Link])
&& [Link]([Link]) && id == [Link];
}
return false;
}
}
© 2011 ITCourseware, LLC Rev 5.1.4 Page 67
Advanced Java Programming

The reflect Package

” The [Link] package contains classes that encapsulate the parts of a


class.

” The Member interface declares three methods of interest:

public Class getDeclaringClass()

public int getModifiers()

public String getName()

” The Member interface is implemented by the Field, Constructor, and Method


classes.

¾ The Field class encapsulates information about a field, including a way to


access the data.

¾ The Constructor class encapsulates information about an available


constructor, including a way to invoke it.

¾ The Method class encapsulates information about a method, including a


way to invoke it.

Page 68 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 4 Reflection

The Member interface also defines constants used when calling SecurityManager's
checkMemberAccess().

[Link] identifies the set of members declared within a class or interface, not including
inherited members.

[Link] identifies the set of public members of a class or interface including inherited members.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 69


Advanced Java Programming

Constructors

” The newInstance() method of Class requires a default constructor.

Class personClass = [Link];


Person p = (Person) [Link]();

” To instantiate an object with a different constructor, use a Constructor object.

¾ The Constructor class provides a newInstance() method which takes an


array of Objects for the parameter values.

¾ For primitive parameter values, create an instance of the corresponding


wrapper class.

ƒ Java 5 boxing works here, as well.

Page 70 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 4 Reflection

[Link]
import [Link];
import [Link];

public class CreateObject {


public static void main(String[] args) {
Class personClass = [Link];

Class[] parmTypes = {[Link], [Link],


[Link], [Link]};
The class literal
works on primitives.
Constructor pCreate = null;

try {
pCreate = [Link](parmTypes);
}
catch (NoSuchMethodException nsme) {
[Link](nsme);
[Link](1);
}

Object[] parms = new Object[4];


parms[0] = "Sam";
parms[1] = "Java Programmer";
parms[2] = "03/20/1992";
parms[3] = new Integer(1);

try {
Person p = (Person) [Link](parms);
[Link](p);
}
catch (InstantiationException ie) {
[Link]("Instantiation Exception " + ie);
}
catch (InvocationTargetException ie) {
[Link]("Invocation Target Exception " + ie);
}
catch (IllegalAccessException ie) {
[Link]("Illegal Access Exception " + ie);
}
}
}

Try It:
Compile and run [Link] to create a Person object, using Constructor's newInstance()
method.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 71


Advanced Java Programming

Fields

” To find the public fields of a class, invoke the getFields() method on the Class
object.

¾ The getDeclaredFields() method ignores inherited fields, but shows


public, protected, and private members.

” Get a specific field with the getField() or getDeclaredField() methods.

Field nameField = [Link]("name");

¾ getField() throws a NoSuchFieldException, which must be caught or


declared.

” Query or modify the value of the field with the set() and get() methods.

Person p1 = new Person("Sam");


String nm = (String) [Link](p1);

¾ get() and set() throw an IllegalAccessException if you don't have


access to the field.

” The getModifiers() method returns an int, which defines the modifiers for a
member.

¾ The Modifier class defines several static final fields and methods for
decoding the modifier value.

Page 72 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 4 Reflection

The ReadFields application uses reflection to display the names and values of its public fields.

[Link]
import [Link];

public class ReadFields {


public String name;
private String title;

public static void main(String[] args) {


ReadFields[] test = new ReadFields[5];
for (int i=0; i < [Link]; i++) {
test[i] = new ReadFields();
test[i].name = "Object" + i; The getFields() method
test[i].title = "Title" + i; will return all public
} fields of this class.

Class rfClass = [Link];


Field[] fields = [Link]();

[Link]("number of fields: " + [Link]);

// display the name of the field and the value


for (int i=0; i < [Link]; i++) {
[Link]("ReadFields #" + i);

for (int j=0; j<[Link]; j++) {


try {
[Link]("\t" + fields[j].getName() + ": " +
fields[j].get(test[i]));
}
catch (IllegalAccessException e) {
[Link](e);
}
}
}
}
}

An IllegalAccessException will be thrown from the get() method if the underlying field is
inaccessible.

Try It:
Compile this program to display the public fields of an object. Modify the code to call
getDeclaredFields() instead of getFields() to see all of the fields declared in the object.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 73


Advanced Java Programming

Methods

” To find the public methods of a class, invoke the getMethods() method on the
Class object.

¾ The getDeclaredMethods() method ignores inherited methods, but


shows public, protected, and private members.

” Get a specific method with getMethod() or getDeclaredMethod().

Class[] parms = new Class[0];


Method method = [Link]("getName", parms);

¾ getMethod() throws a NoSuchMethodException, which must be


caught or declared.

¾ If there are no parameters, you can substitute null for the empty array.

Method method = [Link]("getName", null);

” Invoke the method by providing an object and parameter array to the invoke()
method:

Person p = new Person("Sam");


Object[] parms = new Object[0];
String nm = (String) [Link](p, parms);

¾ invoke() throws IllegalAccessException and


InvocationTargetException, which must be caught or declared.

Page 74 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 4 Reflection

[Link]
import [Link];
import [Link];

public class ReadMethods {


private String name;
private String title;

public String getName() {


return name;
}
protected String getTitle() {
return title;
}
private void setTitle( String ti ) {
title = ti;
}
public static void main(String[] args) {
ReadMethods obj = new ReadMethods();
Class clazz = [Link]();
Method[] methods = [Link]();

[Link]("Number of methods: " + [Link]);


[Link]([Link]() + " methods:");

for (int i = 0; i < [Link]; i++) {


int mods = methods[i].getModifiers(); Loop through all methods.
if ([Link](mods))
[Link]("static "); Print static modifier.

[Link](methods[i].getReturnType().getName() + " ");

Class dcl = methods[i].getDeclaringClass(); Print return type.


if (! [Link]().equals([Link]())) {
[Link]([Link]() + ".");
} Optionally print
declaring class.
[Link](methods[i].getName() + "(");
Class[] parms = methods[i].getParameterTypes(); Print method name.
for (int j = 0; j < [Link]; j++) {
[Link]( (j > 0 ? ", " : "") + parms[j].getName());
}
[Link](")");
} Print parameters.
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 75


Advanced Java Programming

Exception Handling and Reflection

” A dynamically-invoked method can throw an exception.

” Use the getExceptionTypes() method to find which exceptions can be thrown


from a method.

Class[] exceptions = [Link]();

” If an exception is thrown by the invoked method, invoke() itself will throw an


InvocationTargetException.

” The InvocationTargetException will contain information about the originally-


thrown exception.

¾ Call getCause() to get the originally-thrown exception object.

Page 76 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 4 Reflection

This example creates a Person2 object using a Constructor. The corresponding Person2 constructor has
been edited to throw a ParseException.

[Link]
...
public class Person2 {
...
public Person2(String nm, String ti, String bDate, int i)
throws ParseException {
...
}
}

[Link]
...
public class CreatePerson {
public static void main(String[] args) {
Class clazz = [Link];
Class[] parmTypes = {[Link], [Link],
[Link], [Link]};

try {
Constructor constructor = [Link](parmTypes);

Object[] parms = {"Jane Doe", "CEO", "3/20/1964", 1};


Person2 person = (Person2) [Link](parms);
[Link](person);

parms = new Object[] {"John Doe", "CIO", "xx/02/1968", 2};


person = (Person2) [Link](parms);
[Link](person); Pass in an invalid
} birthdate.
catch (InvocationTargetException ite) {
[Link]("The invoked method threw an exception: " +
[Link]().getClass());
[Link]();
}
catch (Exception e) {
[Link]();
}
}
}

Try It:
Compile and run [Link] to test exception handling with reflection.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 77


Advanced Java Programming

JavaBeans

” A JavaBean is a reusable Java component.

¾ In component-based development, the idea is that you have solid, robust


components that you can plug into an application to perform some
functionality.

¾ Application development then becomes more wiring together of


components and less writing code from scratch.

¾ An integrated development environment (IDE) allows developers to


visually place and configure components.

” The concept of component-driven development actually sounds a lot like


Object-Oriented Development (OOD), and, in fact, JavaBeans are implemented
as Java classes.

¾ There are some special requirements of JavaBean classes to make it easier


for IDEs to work with them.

ƒ A JavaBean class must implement [Link] and provide


a no-argument constructor.

ƒ Properties are defined by getPropertyName() and


setPropertyName() methods.

ƒ The JavaBean class should be packaged in a .jar and identified as a


JavaBean.

” If you follow the rules for JavaBeans, you can load your JavaBean into your
IDE's toolbox, drag and drop it onto your window, set its properties, and even
handle events.

¾ The IDE performs all of those tasks by quering the bean class with
reflection.
Page 78 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 4 Reflection

The Person class from earlier in the chapter almost fulfills all of the requirements of a JavaBean
class. It already implements Serializable, but we need to add a no-argument constructor. We should also
provide set methods to match the get methods.

[Link]
...
public class PersonBean implements Serializable {
private String name;
private String title;
private Date birthDate;
private int id;

public PersonBean() {
name = "";
title = "";
birthDate = new Date();
}
...
public String getName() {
return name;
}
public void setName(String nm) {
name = nm;
}
public String getTitle() {
return title;
}
public void setTitle(String t) {
title = t;
}
public int getId() {
return id;
}
public void setId(int i) {
id = i;
}
public String getBirthDate() {
SimpleDateFormat df = new SimpleDateFormat("M/d/yyyy");
return [Link](birthDate);
}
public void setBirthDate(String shortDate)
throws ParseException {
SimpleDateFormat df = new SimpleDateFormat("M/d/yyyy");
birthDate = [Link](shortDate);
}
...
}
© 2011 ITCourseware, LLC Rev 5.1.4 Page 79
Advanced Java Programming

Dynamic Programming

” While the loading and execution of code in the JVM is dynamic, the actual
programs themselves are static.

¾ We have seen that it is possible to use reflection to dynamically create


objects and invoke their methods, but the syntax is cumbersome;
reflection really was not designed for that.

” Tool developers can use reflection when developing IDEs.

¾ IDE views that present your code as a tree structure made up of fields,
constructors and methods are most likely using reflection to generate the
tree.

¾ Editors can use reflection to generate code completion drop-downs.

¾ Debuggers can use reflection to show you the current state of fields in a
running program.

” Reflection is also used heavily in Java Enterprise Edition packages.

¾ JavaServer Pages (JSP) use reflection to instantiate and access properties


on server-side JavaBeans.

ƒ The JSP container calls the newInstance() method on the bean


class to instantiate the bean, using its no-argument constructor.

ƒ The container converts property names into the appropriate get() or


set() method call.

” Enterprise Java Beans (EJB) use reflection in a similar way to create instances
and identify properties.

” JavaServer Faces (JSF) use reflection to dynamically populate beans with data
that has been declared in an XML file.
Page 80 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 4 Reflection

The Java Community Process (JCP) has identified a need for a dynamic scripting language, where you
can type commands into an interpreter and have them evaluated immediately. You can even define new
types and methods on the fly. Java Specification Request (JSR) 223 defines an API for scripting languages,
and will be included in a future version of Java.

Two other JSRs, 241 and 274, define scripting languages which may be included with a future release
of Java. Both scripting languages use Java-like syntax and provide access to the full power of Java. JSR
241 is Groovy, an agile language, suitable for rapid prototyping and similar in usage to Python and Smalltalk.
Groovy can replace Java in small-to-medium size applications. For more information, see
[Link]

JSR 274 is the BeanShell language, also intended for rapid prototyping and to work with existing Java
applications. For more information, see [Link]

© 2011 ITCourseware, LLC Rev 5.1.4 Page 81


Advanced Java Programming

Labs

The chapter directory contains a GUI program called Reflect that is a reflection test bed. All of the
GUI part has been created ([Link], [Link]), however the GUI calls
methods in the Reflect class to find information about classes and objects. Currently the Reflect
class contains stubs for the methods, but you need to fill in those stubs. In the Reflect class, fill in
the code for the getCtors() method to get a Vector of Constructor objects for the given class:

public Vector<Constructor> getCtors(String className)

You can test your program at any time by compiling it and running java Reflect.
(Solution: [Link])

† Write the code for the instantiate() method. Because we want to be able to create objects with
overloaded constructors, use the newInstance() method in Constructor, not the one in Class.

public Object instantiate(Constructor ctor, Object[] args)

(Solution: [Link])

‡ Write the code for the getMethods() method, which returns a Vector of Method objects:

public Vector<Method> getMethods(Object obj)

(Solution: [Link])

ˆ Write the code for the invoke() method to invoke the selected method on the selected object. The
return value should be the return from the invoked method.

public Object invoke(Method method, Object target, Object[] args)

(Solution: [Link])

Page 82 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 4 Reflection

© 2011 ITCourseware, LLC Rev 5.1.4 Page 83


Advanced Java Programming

Page 84 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 5 Advanced JDBC

Chapter 5 - Advanced JDBC

Objectives

” Create portable SQL statements using JDBC


escape syntax.

” Use the execute() method to execute arbitrary


SQL statements.

” Execute several updates at once using batch


updates.

” Store and retrieve DBMS Large Objects (LOBs).

” Make your transactions more granular with


Savepoints.

” Use RowSets and DataSources from the


[Link] package.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 85


Advanced Java Programming

JDBC SQL Escape Syntax

” When you call executeQuery() or executeUpdate(), the driver actually parses


the SQL statement before passing it to the DBMS.

” The JDBC driver will scan the SQL string for escape clauses.

{keyword parameters}

[Link]("UPDATE employee" +
"SET hire_date = {d '1998-01-05'}");

¾ The driver can then turn the generic JDBC escape sequence into the
appropriate vendor-specific SQL syntax.

ƒ Date and time formatting


ƒ SQL function execution
ƒ Stored procedure calls
ƒ Set the escape metacharacter for a SQL LIKE clause
ƒ Generic outer join syntax

¾ Or the driver may itself implement the feature indicated by the escape
sequence, even if the DBMS doesn't.

¾ Escape sequences allow you to use extensions of the SQL language in a


DBMS-independent way.

¾ JDBC's escape syntax is compatible with ODBC's.

Page 86 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 5 Advanced JDBC

{keyword parameters}

Keyword Parameter(s)

d Date in ISO standard format (yyyy-mm-dd).

t Time in ISO standard format (hh:mm:ss.f).

ts Timestamp in ISO standard format (yyyy-mm-dd hh:mm:ss.f).

escape Escape character for LIKE clause in this statement.

fn SQL scalar function call with any paramaters.

call Stored procedure call with any parameters.

oj Outer join criteria in SQL2 standard format.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 87


Advanced Java Programming

The execute() Method

” Statement's execute() method is the most general way to execute SQL.

” execute() executes any arbitrary SQL string.

¾ It may generate either a result set, an update count, a combination of any


number of either, or even no results at all; for example:

ƒ A statement built dynamically at runtime, which you can't restrict to


either a query or an update.

ƒ A stored procedure yielding multiple result sets or update counts (if


the DBMS supports this).

” execute() returns a boolean.

¾ true if the statement generated an initial result set.

¾ false if the statement generated either an initial update count or no results


at all.

” Use getResultSet() and getUpdateCount() to retrieve the actual results of the


statement.

¾ getResultSet() returns a ResultSet object if one is available, otherwise


null.

¾ getUpdateCount() returns an int: 0 or greater for DML or DDL, -1 if no


update count is available.

Page 88 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 5 Advanced JDBC

After an execute(), your Statement object has either a ResultSet, an update count, or neither. In addition,
after you are finished with that result (either the ResultSet or the update count), there may be another result
to retrieve and process. If you have no idea what to expect, you can still process all of your results:

[Link]
...
public class ExecuteExample {
public static void main(String args[]) {
...
Statement stmt = [Link]();
boolean haveResultSet = [Link](sqlstring);

if (haveResultSet) {
ResultSet rs = [Link]();
ResultSetMetaData rsmd = [Link]();
int cols = [Link]();
for (int col = 1; col <= cols; col++)
[Link]([Link](col) + "\t");
[Link]("");
while ([Link]()) {
for (int col = 1; col <= cols; col++) {
[Link]([Link](col) + "\t");
}
[Link]("");
}
[Link]();
}
else { // No result set.
int uc = [Link]();
[Link](uc + " row(s) updated.");
}
[Link]();
[Link]();
...
}
}

Try It:
Compile and run [Link]. Enter an INSERT, UPDATE, or DELETE SQL statements
when prompted.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 89


Advanced Java Programming

Batch Updates

” Batch updating allows you to execute several UPDATEs in a batch, saving


processing time.

¾ Batch updates can be used for anything except SELECT statements.

” Create a Statement, then add SQL commands to it with the addBatch()


method.

¾ You can delete the commands from a batch with the clearBatch()
method.

” Call executeBatch() to execute the commands that you added to the batch.

¾ executeBatch() returns an int[] containing an update count from each


command.

¾ The order of the array corresponds to the order in which the commands
were added to the batch.

” It is up to the driver whether it supports batches, and if so, how they are
handled.

¾ If an error is encountered while executing the batch, the method will


throw a BatchUpdateException.

¾ Set autoCommit to false to handle errors correctly.

ƒ You then have the option of calling commit() or rollback() if a


BatchUpdateException is thrown.

Page 90 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 5 Advanced JDBC

[Link]
...
public class Batch {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
[Link]("[Link]");
String url = "jdbc:derby://localhost:1527/j2se";
conn = [Link](url);
[Link](false);

stmt = [Link]();
[Link]("UPDATE department SET manager_id = 7223 " +
" WHERE department_code = 'AC'");
[Link]("UPDATE department SET manager_id = 6881 " +
" WHERE department_code = 'AD'");
[Link]("UPDATE department SET manager_id = 8339 " +
" WHERE department_code = 'CS'");
[Link]("UPDATE department SET manager_id = 8053 " +
" WHERE department_code = 'HR'");
int[] uc = [Link]();

[Link]();
}
catch (BatchUpdateException bue) {
try {
[Link]();
}
catch (SQLException e) {
[Link](e);
}
[Link](bue);
}
...
}
}

Try It:
You can compile and run this program to update the department managers.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 91


Advanced Java Programming

Updatable Result Sets

” While iterating through a ResultSet, you can update or delete the current result
set row from the database if:

¾ The DBMS and JDBC driver support updatable result sets.

[Link](int type)
[Link](int type,
int concurrency)

¾ The SQL statement meets the requirements for updatable result sets:

ƒ The statement was created with the


ResultSet.CONCUR_UPDATABLE flag.

ƒ A general rule is that the query should include the primary key, and
reference only one table.

ƒ The ResultSet's getType() and getConcurrency() methods return


the types of the result set actually produced.

” Use the ResultSet's updateXXX() methods to update the current row.

[Link]("manager_id", newMgrId);

” When you are finished updating, call updateRow() or cancelRowUpdates().

” Call deleteRow() to delete the current row.

” Inserting a row requires more steps:

1. Call moveToInsertRow() to move cursor to insert row.


2. Call updateXXX() to add column values to insert row.
3. Call insertRow() to add data to result set and database.
4. Call moveToCurrentRow() to return to the former position in result set.

Page 92 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 5 Advanced JDBC

[Link]
...
public class RowIdExample {
public static void main(String args[]) {
...
Statement empStatement = [Link]();
Statement deptStatment = [Link](
ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);

ResultSet empResultSet;
ResultSet deptResultSet = [Link](
"SELECT department_code, department_name, manager_id " +
"FROM department" );
Loop through
departments.
while ([Link]()) {
String currentDeptCode =
[Link]("department_code");
empResultSet = [Link](
"SELECT id, department_code " +
"FROM employee " +
"WHERE title = 'Department Manager'");
Loop through
while ([Link]()) { department managers.
String employeeDeptCode =
[Link]("department_code");
if ([Link](currentDeptCode)) {
// determine if current department has a manager_id
// don't update a row that already has a manager_id
[Link]("manager_id");
if (![Link]())
continue;
[Link]("Updating dept " + currentDeptCode);
int mgrId = [Link]("id");
[Link](", setting manager_id to " + mgrId);
[Link]("manager_id", mgrId);
[Link]();

}
}
[Link]();
...
}
}

Try It:
Compile and run [Link] to update manager fields.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 93


Advanced Java Programming

Large Objects

” Most DBMSs support some form of LOB (Large OBject) datatypes, like LONG,
LONG RAW, BYTE, BINARY, LONG BINARY, IMAGE, etc.

ƒ Photo, video, or audio data


ƒ Large documents
ƒ Application or other program code
ƒ Serialized Java objects

¾ You may also know these as BLOBs (Binary Large OBjects) or CLOBs
(Character Large OBjects).

” JDBC 2.0 provides datatypes for these values; see your driver's documentation
for DBMS type equivalencies.

¾ BLOB, CLOB

” JDBC defines interfaces to make it easier to work with LOB values.

¾ Retrieve the value with the ResultSet's getBlob() or getClob() methods.

¾ A Blob can be converted to a byte[] or read as an InputStream.

¾ A Clob can be converted to a String, read as a Reader or as an


InputStream.

¾ Call length() to find out how many bytes or characters are in the LOB.

” You can use a PreparedStatement and setBytes() or setString() to insert or


update LOB values.

¾ If you are copying from another data element, you can use setBlob() or
setClob().

Page 94 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 5 Advanced JDBC

Blob and Clob are available since JDBC 2.0. If you have a JDBC 1.1 driver, you need to use getBytes(),
getString(), or a getxxxStream() method.

[Link]
...
class ImageFromFile {
public static void main(String args[]) {
try {
[Link]("[Link]");
String url = "jdbc:derby://localhost:1527/j2se";
Connection conn = [Link](url);

String sqltxt = "UPDATE employee SET mugshot = ? WHERE id = ?";


PreparedStatement pstmt = [Link](sqltxt);

String filepath[] = {"[Link]","[Link]","[Link]"};


int idArray[] = {9883, 6881, 6644};

for (int i = 0; i < [Link]; i++) {


FileInputStream istream = new FileInputStream(filepath[i]);
int length = (int) (new File(filepath[i])).length();
byte[] image = new byte[length];
[Link](image, 0, length);

[Link](1, image);
[Link](2, idArray[i]);
int uc = [Link]();

[Link]();
}
[Link]();
[Link]();
}
catch (Exception e) {
[Link]();
}
}
}

Try It:
[Link] will populate the Employee table with three images.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 95


Advanced Java Programming

Working with Savepoints

” Savepoints allow you to rollback updates to a specific point in a database


transaction.

” Savepoint objects are created from the setSavepoint() method of the


Connection object.

Savepoint s = [Link]();

¾ Savepoints can be named by passing a String to the setSavepoint()


method.

Savepoint sp = [Link]("SaveA");

¾ You can retrieve the Savepoint name by calling getSavepointName().

String name = [Link]();

” Pass the Savepoint object to the Connection rollback() method to establish


where to stop the rollback.

[Link](sp);

” You can call releaseSavepoint() to remove the Savepoint from the current
transaction.

[Link](sp);

Page 96 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 5 Advanced JDBC

JDBCSavepoint creates two update statements, executes the first and then creates a savepoint before
executing the second. Before the commit is performed, a rollback to the savepoint is performed, eliminating
the second update from the transaction.

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link]; Be sure to set
AutoCommit to false in
public class JDBCSavepoint { order to use Savepoints.
public static void main(String args[]) {
try {
[Link]("[Link]");
String url = "jdbc:derby://localhost:1527/j2se";
Connection conn = [Link](url);

[Link](false);
String s1 = "UPDATE employee SET salary = salary * 1.1253";
String s2 = "UPDATE employee SET title = 'CEO' WHERE id = 9683";
Statement stmt = [Link]();

[Link](s1);
Savepoint sp = [Link]("SVP1");
[Link](s2);

[Link](sp);
[Link]();
[Link]();
[Link]();
}
catch (ClassNotFoundException cnfe) {
[Link](cnfe);
}
catch (SQLException sqle) {
[Link](sqle);
}
}
}

Try It:
Compile and run [Link]. To view the changes to the database, ask your instructor how to
list the Employee table.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 97


Advanced Java Programming

RowSets

” A RowSet is a JavaBean that can be used to work with tabular data.

¾ RowSets can easily send data over a network.

¾ RowSet extends the ResultSet interface.

¾ RowSets can provide scrollable resultsets if your database and driver


doesn't support them.

” RowSet is an interface in the [Link] package.

¾ [Link] is included with Java 1.4.

¾ The interface needs to be implemented by a class.

ƒ You can implement your own RowSet class.

ƒ You can get a RowSet class from a vendor.

” A RowSet can be either connected or disconnected, depending on


implementation.

¾ A connected RowSet gets a connection to the database when it is created


and keeps it until it is destroyed.

¾ A disconnected RowSet gets a connection to initialize the data or


propagate changes, but then closes the connection.

ƒ The RowSet maintains the data in memory.

ƒ This makes it good for sending across a network to a thin client.

” RowSet uses a DataSource or a URL to make a connection to a database.

Page 98 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 5 Advanced JDBC

[Link]
import [Link];
import [Link];

public class JDBCRowSetList {


public static void main(String args[]) {
try {
[Link]("[Link]");
String url = "jdbc:derby://localhost:1527/j2se";
String sqlStmt = "SELECT id, lastname, salary, title " +
"FROM employee " +
"ORDER BY lastname";

RowSet rs = new CachedRowSetImpl();


[Link](url);
[Link](sqlStmt);
[Link]();

while ([Link]()) {
[Link]([Link]("id") + " " +
[Link]("lastname") + " " + [Link]("salary")
+ " " + [Link]("title"));
}
}
catch (Exception e){
[Link]();
}
}
}

Try It:
Compile and run [Link]. This should list all of the employees currently in the Employee
table.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 99


Advanced Java Programming

CachedRowSet

” CachedRowSet (extends RowSet) is an interface that represents a disconnected


RowSet used for storing all rows obtained from a query into local memory.

¾ CachedRowSetImpl is an implementation of CachedRowSet.

” There are two ways you can populate a CachedRowSet:

¾ CachedRowSets can be populated from a ResultSet object using the


populate() method.

CachedRowSet crs = new CachedRowSetImpl();


[Link](rs);

¾ CachedRowSets can be populated by calling the execute() method.

[Link](url);
[Link]("SELECT id, lastname FROM employee");
[Link]();

” CachedRowSet inherits from ResultSet, allowing you to use the set and update
methods from ResultSet to retrieve and modify the RowSet columns.

¾ Once a column has been updated, call updateRow() to make the change
to the row.

” You call acceptChanges() with an active connection to propagate the changes


back to the database.

Connection conn = [Link](url);


[Link](conn);

Page 100 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 5 Advanced JDBC

The CachedRowSetImpl comes with JDK, Standard Edition and implements the CachedRowSet
interface. It is part of the [Link] package. In general, it is not a good idea to rely on this package
because the sun.* packages are not part of the supported, public interface. A Java program that directly
calls into a sun.* packages is not guaranteed to work on every Java platform. Such a program is not even
guaranteed to work with future versions of the same platform.

[Link]
import [Link].*;
import [Link];
import [Link];

public class JDBCRowSetUpdate {


public static void main(String args[]) {
try {
[Link]("[Link]");
String url = "jdbc:derby://localhost:1527/j2se";
Connection conn = [Link](url);
String sqlStmt = "SELECT id, salary, title " +
"FROM employee " +
"ORDER BY lastname";
Statement stmt = [Link]();
ResultSet rs = [Link](sqlStmt);

CachedRowSet crs = new CachedRowSetImpl();


[Link](rs);
Move the data from the
[Link](); DBMS into the
CachedRowSet.
while ([Link]()) {
if (! [Link]("title").equals("Manager")) {
float oldSal = [Link]("salary");
[Link]("salary", oldSal * 1.1f);
}
[Link]();
}
[Link]("employee"); The RowSet is
[Link](conn); updated, but not the
} database table.
catch (Exception e){
[Link]();
}
}
Updates to the RowSet
}
are propagated back to
the physical database.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 101


Advanced Java Programming

DataSources

” A DataSource is an alternative to the DriverManager class for establishing a


connection to a data source.

¾ The DataSource interface is defined in the [Link] package.

¾ A driver vendor supplies the implementation for the DataSource


interface.

¾ A DataSource may be a complex database or a simple file with rows and


columns.

” A DataSource is deployed separately from an application.

¾ The DataSource is given a name and is deployed using the Java Naming
and Directory Interface (JNDI).

¾ All the properties that describe the data source are kept separate from, and
can be changed independently of, an application.

” Use a JNDI name to retrieve the DataSource object.

” Retrieve a Connection object from the DataSource object.

¾ Implementations of Connections can include advanced features, such as


connection pooling and distributed transactions.

ƒ Connection pooling can dramatically increase performance by


reusing connections rather than opening a new connection for each
request.

ƒ A distributed transaction can access two or more DBMS servers.

Page 102 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 5 Advanced JDBC

Deployment Application

ƒ Instantiate a DataSource class and populate properties.


ƒ Deploy the DataSource object with a JNDI name.

Client Application

ƒ Retrieve the DataSource object using JNDI.


ƒ Obtain a Connection object from the DataSource object.
ƒ Use the Connection object to interact with the database.

1. lookup(JNDIname)
Naming Service

Connection Pool

Client
Application Database
Connection
2. getConnection()
DataSource Database
Database Connection DBMS
Connection Reference
Database
Connection

© 2011 ITCourseware, LLC Rev 5.1.4 Page 103


Advanced Java Programming

Labs

Write a program that will find all of the Employee records that do not contain null in the mugshot
field. Extract each mugshot into a file using the lastname of the Employee as the filename.
(Solution: [Link])

† Write a program to list the lastname, hire_date, and salary of all employees who started
before January 1, 1995. Put all of the records into RowSet and display the information from
the RowSet.
(Solution: [Link])

‡ Modify the previous program so all long-term employees make at least $50,000 a year. Be sure to
populate your changes back to the database.
(Solution: [Link])

ˆ Modify the program one more time to insert yourself into the RowSet. The steps for insertion will
be the same as ResultSet's steps, since RowSet inherits from ResultSet.
(Solution: [Link])

Page 104 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 5 Advanced JDBC

The following SQL statement will find all employees that have mugshots:

SELECT lastname, mugshot


FROM employee
WHERE mugshot IS NOT NULL

© 2011 ITCourseware, LLC Rev 5.1.4 Page 105


Advanced Java Programming

Page 106 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 6 Networking with Sockets

Chapter 6 - Networking with Sockets

Objectives

” Write Java programs that act as


clients.

” Use the Socket class to specify a


host and port for a server.

” Send and retrieve data over a socket.

” Create an iterative server program.

” Communicate between a client and


server.

” Access Web content through URLs.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 107


Advanced Java Programming

Clients and Servers

” A client is any program that initiates communication with a server.

¾ A Java client can be either an applet or an application.

” A client typically contains the user interface, but uses a server to interact with a
database or some other resource.

¾ The client may be unable to interact directly with the resource, or it may
just be more efficient to have a single server program accessing the
resource.

” A server program provides a service and waits for clients to "call."

¾ Servers in Java are typically applications or servlets (Java applications


attached to a web server).

” A server can even act as a client, requesting services from another server.

” Clients and servers communicate using many different mechanisms:

¾ Remote Method Invocation (RMI) — networking is made to look like


normal method calls.

¾ Applet/Servlet communication — networking is handled by the web


server.

¾ Common Object Request Broker Architecture (CORBA) — networking is


handled by an ORB (usually a separate process) and calls look like
normal method calls.

¾ Sockets — data is transmitted directly between two separate processes.

Page 108 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 6 Networking with Sockets

In this chapter you will create a client-side socket communications class that communicates through sockets
with a server program (which you will also create). Provided is a GUI-based client program that will use
your socket communications class. The name of the provided client program is ClientGUI. The class you
create will be called SocketHandler, with one static method named echo().

© 2011 ITCourseware, LLC Rev 5.1.4 Page 109


Advanced Java Programming

Ports, Addresses, and Protocols

” A client needs to know what host the server is on.

¾ A host is a computer that can be identified by either an IP address or a


hostname (which is converted to an address).

” A client also needs to know which process on the host is the actual server
program.

¾ Process IDs change every time a program starts, so each host has a set of
numbers called ports which identify servers.

¾ We say that a server "listens" on a specific port.

” A client needs to know how to communicate with the server.

¾ A protocol defines the format of the communication (how much data is


being sent, what comes first, etc.).

¾ Two types of protocol in common use are stream and datagram.

ƒ The most common stream protocol, TCP, is the default


because it does a lot of automatic error checking.

ƒ The most common datagram protocol, UDP, is used when speed is


very important and errors do not matter.

” A client must know the host, port, and protocol of the server in order to find
and communicate with it properly.

Page 110 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 6 Networking with Sockets

Try It:

Compile and run [Link]. When the send button is pressed, ClientGUI passes the data from the
sendArea to SocketHandler, which currently just returns the data to ClientGUI, who displays it in the
receiveArea. Look at the source code for both [Link] and [Link]. We will
develop SocketHandler to send the data through sockets to a server, which will simply echo the data
back, and then SocketHandler will return the echoed data to ClientGUI. We will not modify
[Link].

[Link]
...
public class ClientGUI extends JFrame {
...
JButton send = new JButton("Send");
[Link](new ActionListener() {
public void actionPerformed(ActionEvent e) {
String host = [Link]();
int port = [Link]([Link]());
String textToSend = [Link]();

String result = [Link](host, port, textToSend);


[Link](result);
}
});
...
}

[Link]
public class SocketHandler {
public static String echo(String host, int port, String input) {
return input;
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 111


Advanced Java Programming

The Socket Class

” Use a [Link] object to connect to a server.

¾ Various constructors are available to allow you to pass the server's


hostname or IP address and the server's port number.

Socket s = new Socket(host, port);

ƒ Pass a host as either an InetAddress object or as a String.

ƒ Pass the port as an int.

” The Socket constructor locates the host on the network and connects to the
server listening on the given port.

¾ UnknownHostException means that the constructor cannot convert a


hostname to an IP address.

¾ IOException means there is a problem finding the host or port.

” The Socket constructors assume TCP protocol is being used.

¾ Additional methods and classes exist for using UDP and other protocols.

Page 112 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 6 Networking with Sockets

Hands On:

Let’s begin building [Link].

[Link]
import [Link].*;
import [Link].*;

public class SocketHandler {


public static String echo(String host, int port, String input) {
String receive = "";
try {
Socket s = new Socket(host, port);

}
catch (UnknownHostException e) {
[Link]("UnknownHost" + [Link]());
[Link](1);
}
catch (IOException e) {
[Link]([Link]());
[Link](2);
}
return receive;
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 113


Advanced Java Programming

Communication Using I/O

” Once a client has constructed a Socket object, all communication between the
client and server is done using the Java input and output classes.

” The getOutputStream() method returns the OutputStream object that you use
to send data to the server.

” The getInputStream() method returns the InputStream object that you use to
read data from the server.

¾ You can convert these streams to any I/O class that you would like.

” Any type of data can be sent across these streams: String objects, Java
primitives, or even Serializable objects.

¾ You need to pick an I/O class that is appropriate for your data.

” Calling close() on the Socket will send an end-of-file to the server; do not forget
this!

Page 114 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 6 Networking with Sockets

Hands On:

Add the I/O code to SocketHandler. The query string from the ClientGUI sendArea may have
embedded newline characters, and each line will come back from the server individually, so we will send a
"\u0004" and when it comes back we will know that everything sent has been echoed.

[Link]
...
Socket s = new Socket(host, port);

BufferedReader in = new BufferedReader(


new InputStreamReader([Link]()));
Force the PrintWriter
PrintWriter out = to flush the buffer.
new PrintWriter([Link](), true);

[Link](input);
We'll use this to
[Link]("\u0004"); end messages.

String line = [Link]();


while (![Link]("\u0004") ) {
receive += line + "\n"; Stop when server
[Link]("Client DEBUG: " + line); replies "\u0004".
line = [Link]();
}
[Link]();
[Link]();
[Link]();
}
catch (UnknownHostException e) {
...

Try It:
Compile your client. If you are on a host or network with INET services (UNIX or Linux hosts will have
these available) you can run your client against port 7, the standard echo server. Otherwise you will have to
wait until you have built your server . . .

© 2011 ITCourseware, LLC Rev 5.1.4 Page 115


Advanced Java Programming

Servers

” Server programs are typically daemons: they stay running in the background all
the time.

” Your server will loop infinitely, waiting for clients to try to connect it.

” When requests start coming in, you have two ways to handle the requests:
iteratively or concurrently.

¾ An iterative server simply handles each client completely before it goes


on to listen for other clients.

¾ A concurrent server handles multiple clients at once by using a separate


thread or process to handle each one.

” You would use an iterative server when the service provided is quick, or the
service is based on scarce resources.

¾ An iterative server may be able to handle the client request quicker than it
could handle the separate thread or process.

¾ A scarce resource could be a database that only allows a few connections


at once.

¾ If more requests come in while the server is busy serving the previous
one, they are queued by the underlying network software layer.

Page 116 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 6 Networking with Sockets

Hands On:

Let's begin building the server side. Create a class named EchoServer with a main() method. We will leave
the try and finally blocks empty for now.

[Link]
import [Link].*;
import [Link].*;

public class EchoServer {


public static void main(String[] args) {
Socket clientSocket = null;
BufferedReader sockin = null;
PrintWriter sockout = null;
try {

}
catch (IOException e) {
[Link]([Link]());
}
finally {

}
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 117


Advanced Java Programming

The ServerSocket Class

” Use a ServerSocket to listen for clients.

¾ The port to be listened on is passed to the constructor.

ServerSocket ss = new ServerSocket(7777);

” The accept() method is a blocking call that returns a Socket object when a
client connects with a Socket.

Socket s = [Link]();

¾ The Socket object returned by accept() has the client address, port, and
protocol.

¾ All client communication is done through this Socket object.

” Retrieve the input and output stream objects to send and receive data.

” Use the following steps for a basic iterative server:

1. Create a ServerSocket on a specific port.

2. Start an infinite loop.

2a. Call accept(), which blocks and returns a Socket object.

2b. Retrieve I/O stream objects from the Socket and communicate
with the client.

2c. Call close() to free up the temporary Socket.

3. Go back to the top of the loop.

Page 118 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 6 Networking with Sockets

Hands On:

Construct a ServerSocket on your own port. Ask the instructor for the appropriate port number. Create a
Socket object when a client connects. Read each line from the client and echo it back through the socket.

[Link]
...
public class EchoServer {
public static void main(String[] args) {
Socket clientSocket = null;
BufferedReader sockin = null;
PrintWriter sockout = null;
try {
ServerSocket listenSocket = new ServerSocket(7777);

while(true) {
clientSocket = [Link]();

sockin = new BufferedReader(


new InputStreamReader([Link]()));
sockout =
new PrintWriter([Link](), true);

String linein;
// Read from socket until client closes its end
while ((linein = [Link]()) != null) {
[Link](linein);
[Link]("Server DEBUG: " + linein);
}
[Link]("Server DEBUG: Connection closed");
[Link]();
[Link]();
[Link]();
}
}
catch (IOException e) {
[Link]([Link]());
}
finally {
try {
if (clientSocket != null)
[Link]();
}
catch (IOException e) {}
}
}
}
© 2011 ITCourseware, LLC Rev 5.1.4 Page 119
Advanced Java Programming

Concurrent Servers

” Concurrent servers are more complex to design, build, and maintain than
iterative servers.

” Concurrent servers can handle multiple, simultaneous client requests.

¾ They do this by executing multiple processes or threads, one for each


client request.

” Concurrent servers can be faster than iterative servers if each client will take a
long time to process, and if there are enough threads in the operating system for
each client.

” The algorithm for a concurrent TCP server is:

¾ Primary server (always running)

1. Create a ServerSocket on the port for the service being offered.

2. Block on an accept() message to the ServerSocket.

3. Create an object (multi-threaded) or spawn a child process (multi-


process) to handle the client request.

¾ Secondary server (either an object or a separate process)

1. Provide the service to the client via the Socket returned from the
accept().

2. close() the Socket and clean up (a threaded object releases


resources and is garbage collected, a process releases resources and
dies).

Page 120 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 6 Networking with Sockets

[Link]
...
public class ConcurrentServer implements Runnable {
private Socket client;
private Thread theThread;
private static int count;
private static ThreadGroup threadGroup; Create a new thread.

public ConcurrentServer(Socket s) {
client = s;
theThread = new Thread(threadGroup, this, "Socket" + count);
[Link]("Client connected to server: " + count +
", Current active threads: " + [Link]());
count++;
[Link]();
}
public void run(){ Start the thread.
BufferedReader sockin = null;
PrintWriter sockout = null;
Get the input stream
try {
from the client socket.
sockin = new BufferedReader(
new InputStreamReader([Link]()) );
sockout = new PrintWriter( [Link](), true);

// loop, reading input from the socket and writing


// the data to the client socket till client closes socket
String linein = null;
while( (linein = [Link]()) != null ) {
[Link]( linein );
}
...
}
public static void main(String[] args) {
threadGroup = new ThreadGroup("Sockets");
try {
ServerSocket ss = new ServerSocket(7777);

while(true) {
// wait for the connection
Socket s = [Link]();
// create a threaded object to handle the client
new ConcurrentServer(s);
}
}
...
}
}
© 2011 ITCourseware, LLC Rev 5.1.4 Page 121
Advanced Java Programming

The URL Class

” A Uniform Resource Locator (URL) allows a Java program to easily retrieve


data (typically a file) from a host, using well-known protocols.

¾ The Java program is acting as a client.

¾ The server you connect to depends on the protocol you specify.

ƒ Typical protocols for a URL include HTTP, FTP, file, and mailto.

” A URL can be constructed in much the same way you would type a URL into a
web browser:

URL myPage = new URL("[Link]

¾ The URL protocol, host, port, and file can also be specified individually:

URL myPage = new URL("http", "[Link]", 80,


"[Link]");

” Data can be retrieved from the URL object using one of three methods:

¾ getContent() — requires a ContentHandler to convert the data.

¾ openStream() — returns an InputStream that can be read.

¾ openConnection() — returns a URLConnection object.

Page 122 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 6 Networking with Sockets

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class GetFile {


public static void main(String[] args) {
String contents = null;
BufferedReader buf = null;
try {
URL myPage = new URL("[Link]

buf = new BufferedReader(new InputStreamReader(


[Link]()));

while ((contents = [Link]()) != null) {


[Link](contents);
}
}
catch (MalformedURLException e) {
[Link]([Link]());
}
catch (IOException e) {
[Link]([Link]());
}
}
}

Note:
This program may fail to connect if you are inside a firewall without a configured proxy server. To specify
proxy information, add the following two lines of code:

[Link]().put("proxyHost", "Host_IP");
[Link]().put("proxyPort", "Port_Number");

Replace Host_IP and Port_Number with the appropriate values for your proxy server.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 123


Advanced Java Programming

The URLConnection Class

” The URLConnection class allows a program to obtain details of a resource


prior to using it.

” A URLConnection object is retrieved from a URL object by calling


openConnection().

URLConnection conn = [Link]();

” Methods such as getContentLength() and getContentType() can be used to


help determine what type of data the URL represents.

¾ For instance, if the data is very long, you may want to create an input
stream to read it, or if it is an image, you may not want to retrieve it into a
String.

” getInputStream() and getOutputStream() can be used to read from and write


to a URLConnection.

¾ Writing to a URLConnection will only work if the protocol supports


output (such as HTTP) and if setDoOutput(true) has been called.

ƒ This method is often used with applet-servlet communication.

Page 124 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 6 Networking with Sockets

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class GetConn {


public static void main(String[] args) {
String contents = null;
URLConnection conn = null;
BufferedReader buf = null;
try {
URL myPage = new URL("[Link]

conn = [Link]();

[Link]("File type: " + [Link]());

int len = [Link]();


if (len == -1)
[Link]("File length unknown");
else
[Link]("File length: " + len);

[Link]("Hit RETURN to continue");


[Link]();

buf = new BufferedReader(new InputStreamReader(


[Link]()));

while ((contents = [Link]()) != null) {


[Link](contents);
}
}
catch (MalformedURLException e) {
[Link]([Link]());
}
catch (IOException e) {
[Link]([Link]());
}
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 125


Advanced Java Programming

Labs

Create an application that takes the URL for an image on the command line and writes a local copy
of the image. The program should verify that the URL actually points to an image using
[Link](). You can test your program with an arbitrary image from the
internet using HTTP or FTP protocol, or with a file on the local machine using file protocol.
(Hint: The content-type header for most image types starts with image/.)
(Solution: [Link])

† Create a server that waits for a connection and sends an arbitrary text file to any client that
connects to it. (Hint: The server writes to the socket, but does not read from it.)
(Solutions: [Link], [Link])

‡ Write a client to access the server in †. (Hint: The client reads from the socket, but does not write
to it.)
(Solution: [Link])

ˆ Modify the server from † so that it stores usage statistics, such as the total number of connections,
in an object. Have the server listen on a separate administrative port and send the statistics object to
the client. (Hint: The server must listen concurrently to both ServerSocket objects.)
(Solutions: [Link], [Link])

‰ Write an administrative client to read the statistics object from the server in ˆ.
(Solution: [Link])

Page 126 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 6 Networking with Sockets

© 2011 ITCourseware, LLC Rev 5.1.4 Page 127


Advanced Java Programming

Page 128 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 7 Remote Method Invocation

Chapter 7 - Remote Method Invocation

Objectives

” Explain what a distributed


application is.

” Write distributed applications using


RMI.

” Use RMI utilities such as the


rmiregistry and the rmic compiler.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 129


Advanced Java Programming

Distributed Applications

” In a distributed application, part of the work is done on one host and part is
done on another.

¾ Several hosts can be utilized for a distributed application.

” Communication among the various parts of the application typically happens at a


low level, using sockets for example.

¾ For large amounts of communication between the parts of the application,


sockets can be very tedious to program.

” Remote Method Invocation (RMI) provides a way to communicate across the


network in a way that looks like there is no network involved.

¾ RMI takes care of the socket work and allows you to invoke methods of
an object that is running in another Virtual Machine, on the same or a
different host.

” The parts of a distributed application are clients, servers, or both.

¾ Servers have objects that are declared remote; these objects can be
accessed from clients.

¾ Clients access the remote objects in a server.

¾ A particular part of the system may be both a client and a server, serving
some remote objects and accessing those from other servers.

Page 130 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 7 Remote Method Invocation

There are three ways that a client can access a remote object:

1. By looking up the object using an RMI URL.

2. By having the object returned to the client from a different remote object.

3. By having the object sent to it as a parameter to one of its own remote methods.

Only option 1 allows a client that has no remote objects the opportunity to get one. The other two options
require that a remote object is already being referenced by either the client or the server.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 131


Advanced Java Programming

Stubs

” Stubs are produced by the RMI compiler, rmic.

¾ The server's code is compiled with rmic, which creates the stub .class
files.

” The stub performs marshalling, turning the client's arguments into a marshal
stream (datastream) to be sent over the network.

” On the server side, the stub unmarshals the arguments and calls the method, then
marshals the return value or exception.

” The client stub then unmarshals the return value and returns it to the calling
applet or application.

” The client code simply locates the remote object and calls its methods as though
it were a local object.

¾ Remote objects may have other methods which are not available to the
client.

Page 132 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 7 Remote Method Invocation

RMI Application Flow

Client's Java VM
Stub marshalled
arguments
Application datastream
methodA()
methodB()
return value

Server's Java VM
Remote Stub marshalled
return value datastream
methodA() methodA()
methodB() methodB()
arguments
methodC()
...

© 2011 ITCourseware, LLC Rev 5.1.4 Page 133


Advanced Java Programming

Steps to Create a Remote Object

1. Create a remote interface.

¾ Any interface that extends the [Link] interface is a remote


interface.

interface MyInterface extends [Link] {...}

¾ The methods in the remote interface are the methods available to clients.

¾ All remote methods must declare that they throw


[Link].

2. Create a class that implements the remote interface.

¾ It must extend [Link], or else call


[Link]().

¾ This class implements all of your remote methods.

3. Compile the .java files with javac to create the .class files.

javac [Link]
javac [Link]

4. Compile the remote class with rmic to create the stub .class files.

rmic MyRemoteClass

¾ This creates MyRemoteClass_Stub.class.

5. Distribute the .class files for the interface and the stub (and any inner classes
they use) to the client.

Page 134 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 7 Remote Method Invocation

One of the enhancements to RMI in Java 5 is automatic stub generation. If the VM cannot locate the
stub class in its classpath when you export an object, it will automatically generate a stub class. You
must still use rmic, however, if you are supporting clients that run on a pre-Java 5 VM.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 135


Advanced Java Programming

An RMI Client

” RMI makes working with remote objects very similar to working with local
objects.

” To access a remote object, locate it with the [Link]() method.

¾ Each object has a unique URL to identify it on the Internet.

//hostname:1099/objectname

¾ The lookup() method can throw several types of exceptions.

ƒ [Link] if the calling code does not have


permission to use RMI.

ƒ [Link] if it is not a valid URL.

ƒ [Link] if the host is not available.

ƒ [Link] if the server registry is not available.

ƒ [Link] if there is no object with that name


in the specified registry.

” Once you have a reference to the object, call its methods as you would with a
local object.

¾ Because of the network transmission, each remote method can throw a


RemoteException.

” In order to compile, the client code must have access to the remote interface.

¾ To run, the client needs to have access to the stub.

Page 136 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 7 Remote Method Invocation

client/[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class ShowTimeClient {


public static void main(String args[]) {
new ShowTimeClient();
}

public ShowTimeClient() {
Time t;
try {
t = (Time) [Link]("///Time");
[Link]("The time is: " + [Link]());
}
catch (NotBoundException e) {
[Link](e);
}
catch (MalformedURLException e) {
[Link](e);
}
catch (UnknownHostException e) {
[Link](e);
}
catch (RemoteException e) {
[Link](e);
}
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 137


Advanced Java Programming

An RMI Server

” The remote code consists of two parts, which may be in one class or separated
into two:

¾ The actual remote class.

¾ Server code that instantiates and registers the remote class.

” The remote class implements the previously-written remote interface.

¾ All methods from the interface must be implemented.

ƒ Additional methods will not be available to clients.

¾ All constructors must throw RemoteException.

ƒ The compiler-supplied no-arg constructor will not work, because it


does not throw RemoteException.

” The server portion creates an instance of the remote class and registers it with
the RMI Registry through [Link]() or [Link]().

” The RMI Registry is a process that keeps track of the objects on a particular host
that are available remotely.

¾ Several servers can register objects with the RMI Registry, or a single
server can register multiple objects.

” When the object is exported (via a UnicastRemoteObject constructor or


exportObject() method) an RMI thread is created in the server.

¾ Every remote method call will run its own separate thread.

Page 138 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 7 Remote Method Invocation

server/[Link]
import [Link];
import [Link];

public interface Time extends Remote {


public String getSystemTime() throws RemoteException;
}

server/[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class TimeServer extends UnicastRemoteObject implements Time {


public TimeServer() throws RemoteException {
Your method does not
}
throw RemoteException
public String getSystemTime() { — the stub does.
DateFormat df = [Link]();
[Link]([Link]());
return [Link](new Date());
}
public static void main(String args[]) {
try {
TimeServer ts = new TimeServer();
[Link]("///Time", ts);
}
catch (MalformedURLException e) {
[Link](e);
}
catch (RemoteException e) {
[Link](e);
}
}
}

Try It:
From within the server directory, compile the remote interface and server class by running
javac Time*.java. Then generate the stub class by running rmic TimeServer.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 139


Advanced Java Programming

RMI Classes and Interfaces

” The [Link] interface contains no methods, but must be directly or


indirectly implemented by all remote objects.

” The [Link] class is used by servers to register remote objects, and by


clients to look up remote classes based on a URL of the following format:

protocol://host:port/name

¾ The protocol defaults to rmi, host defaults to the local machine, and port
defaults to 1099.

¾ The most commonly-used methods are:

ƒ bind() associates a name with a remote object; the RMI Registry


keeps a reference to the object stub for delivery to clients.

ƒ rebind() does the same thing, but replaces an existing object with
the same name.

ƒ lookup() returns the remote object associated with a name.

” The [Link] class allows the remote object to


behave properly by keeping track of remote references (references from clients).

¾ A remote class should subclass this class if possible; otherwise, it must


override some of the methods from [Link] (such as the
hashCode() method) to work with remote references, and call
exportObject() in its constructor.

Page 140 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 7 Remote Method Invocation

The Naming class:


// package [Link]
public final class Naming {
public static void bind(String name, Remote obj);
public static String[] list(String name);
public static Remote lookup(String name);
public static void rebind(String name, Remote obj);
public static void unbind(String name);
}

The UnicastRemoteObject class:


// package [Link]
public class UnicastRemoteObject extends RemoteServer {
protected UnicastRemoteObject() throws RemoteException;
protected UnicastRemoteObject(int port) throws RemoteException;
protected UnicastRemoteObject(int port, RMIClientSocketFactory csf,
RMIServerSocketFactory ssf) throws RemoteException;
public Object clone() throws CloneNotSupportedException;
public static RemoteStub exportObject(Remote obj)
throws RemoteException;
public static Remote exportObject(Remote obj, int port)
throws RemoteException;
public static Remote exportObject(Remote obj, int port,
RMIClientSocketFactory csf, RMIServerSocketFactory ssf)
throws RemoteException;
public static boolean unexportObject(Remote obj, boolean force)
throws NoSuchObjectException;
}

Other classes and interfaces are rarely used by the programmer to implement RMI. Some are used to
create customized registries and servers.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 141


Advanced Java Programming

Class Distribution

” An RMI client needs access to the server's interface and stub class files.

¾ Access to the interface is required at build time so the compiler can verify
the method calls.

¾ Access to both the interface and stub is required at runtime.

” Often, the interface and stub class files are distributed along with the client
application.

¾ This ties the client to a specific server.

” It is possible to dynamically download the stub class file (and any other
necessary class files) at runtime.

¾ To use this feature, you must install a security manager in the client and
provide an appropriate policy.

” The RMI Registry must also have access to the stub class file.

¾ The stub class file can be in the registry's classpath.

¾ You can also specify the codebase for the class file when you start your
server:

java -[Link]=URL ServerClass

ƒ The codebase URL can reference a local (file), FTP, or HTTP


resource pointing to either a directory or a .jar file.

ƒ If the registry does not find the stub class file in the classpath, it
will load it from this location.

ƒ A directory URL must end with a /.


Page 142 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 7 Remote Method Invocation

Try It:

1. cd into the client directory in this chapter directory.

2. Copy the interface class file from the server: copy ..\server\[Link]

3. Compile the client program: javac [Link]

4. Copy the stub class file from the server: copy ..\server\TimeServer_Stub.class

© 2011 ITCourseware, LLC Rev 5.1.4 Page 143


Advanced Java Programming

RMI Utilities

” rmic generates the stub class file for classes implementing the [Link]
interface.

rmic [options] RemoteClassName

¾ options include: verbose compiling, alternative classpath, producing


source code for stubs, etc.

” rmiregistry starts an RMI Registry on a specified port.

rmiregistry [port]

¾ This is usually run as a background process.

¾ The default port is 1099.

Page 144 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 7 Remote Method Invocation

Steps to Create an Application using RMI:

1. Create an interface that extends the Remote interface.


a. Add the desired method signatures.

2. Create a class that implements the new interface.


a. Write the required methods.

3. Create a client application that uses the remote class.

4. Compile the client and remote .java files with javac.

5. Compile the remote class with rmic.

6. Start the RMI Registry with rmiregistry.

7. Register the remote class by running the server code with java.

8. Run the client with java.

Try It:
1. Start the RMI Registry:
a. Open a new command prompt window and cd into the root directory.
b. Run: rmiregistry

2. Start the server:


a. Open another command prompt window and cd into the server directory in this chapter
directory.
b. Run: java -[Link]=[Link] TimeServer

Note: Your codebase URL may be different, depending on where your class files are installed.

3. Run the client program in your original command prompt window: java ShowTimeClient

© 2011 ITCourseware, LLC Rev 5.1.4 Page 145


Advanced Java Programming

Parameter Passing and Serialization

” Remember, for local methods:

¾ Objects are always passed by reference.

¾ Primitive datatypes are always passed by value.

” For remote methods:

¾ Objects that implement the Remote interface are passed by reference.

ƒ You must export a remote object before you pass it as a parameter


or return it from a method, but you do not need to bind it to the
registry.

ƒ The stub and interface class files must be available to the client.

¾ Objects that implement the Serializable interface are serialized and passed
by value.

ƒ The class file must be available to both the client and server.

¾ Primitive datatypes are passed by value.

¾ No other objects can be used as arguments or return types of remote


methods.

” If you return a remote object from a remote method, that object will be available
to the client remotely.

¾ RMI developers can use the factory design pattern to give each client a
unique server object.

¾ This is useful for situations where there are many related transactions or
where the transaction may take some time.
Page 146 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 7 Remote Method Invocation

server/[Link]
package server;

import [Link];
import [Link];
import [Link];
import [Link];

public class CountServerFactory extends UnicastRemoteObject


implements CounterFactory {
public CountServerFactory() throws RemoteException {
}
public Counter getCounter() throws RemoteException {
return new CountServer();
}
public static void main(String args[]) {
CountServerFactory factory;
try {
factory = new CountServerFactory();
[Link]("///CountFactory", factory);
}
catch(MalformedURLException mue) {
[Link](mue);
}
catch(RemoteException re) {
[Link](re);
}
}
}

server/[Link]
package server;

import [Link];
import [Link];

public class CountServer implements Counter {


private int count=0;

public CountServer() throws RemoteException {


[Link](this);
}
public int getCount() {
return ++count;
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 147


Advanced Java Programming

Labs

In this chapter directory there are two remote interfaces, Store and Attendant. There is also a
server implementation for each interface. The StoreServer binds a server object to the "///Store"
URL. Write a client program that locates the store object, gets an attendant, and places an order.
Release the attendant when you have finished placing your order. Compile and test your application.
(Solution: [Link])

† Create a Serializable Order class that contains information about an order. The order can include
several itemcode/quantity pairs. Change the submitOrder() method in the Attendant interface so
that it accepts an Order object as a parameter. Make the appropriate changes in the
AttendantServer. Remember to change the Store interface and StoreServer to use the new
Attendant. Compile and test your application.
(Solutions: [Link], [Link], [Link], [Link],
[Link], [Link])

‡ The store has an inventory, which is an array of Item objects. Add methods to the Attendant that
allow a customer to retrieve a list of the item codes as a String[], and an individual Item by
itemcode. Since Item includes a quantityOnHand field, you should make it remote so that your
customer knows about any changes. Change your customer to use the new methods. Compile and
test your application.
(Solutions: [Link], [Link], [Link], [Link],
[Link], [Link])

Page 148 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 7 Remote Method Invocation

[Link]
import [Link];
import [Link];

public interface Store extends Remote {


public Attendant getAttendant() throws RemoteException;
}

[Link]
import [Link];
import [Link];

public interface Attendant extends Remote {


public int submitOrder(String itemCode, int quantity)
throws RemoteException;
public boolean release() throws RemoteException;
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 149


Advanced Java Programming

Page 150 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 8 Advanced RMI

Chapter 8 - Advanced RMI

Objectives
” Make an RMI client act as a server through
client callbacks.

” Use dynamic class loading to load class


definitions remotely.

” Make remote objects activatable on demand.

” Use JNDI to bind and lookup objects in the


RMI Registry.

” Allow RMI applications to communicate with


CORBA using the IIOP protocol.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 151


Advanced Java Programming

Client Callbacks

” A remote server might need to send messages asynchronously back to a client.

¾ A client callback lets the remote server call methods on the client.

¾ The roles of "client" and "server" are now temporarily reversed — the
remote server now invokes a remote method on the client.

” A typical scenario for implementing a client callback involves these steps:

¾ Create an interface which extends Remote and declares the client callback
method.

¾ In the server, define a remote method that takes the interface as a


parameter and stores the object in a list of registered clients.

¾ In the client, create an object that implements the remote interface, and
register the object by passing it to the remote method on the server.

¾ When the server event occurs, the server calls the client callback method
for each registered client.

¾ A separate thread in the client will execute the client callback method.

ƒ The client's callback method must be thread safe.

Page 152 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 8 Advanced RMI

[Link]
import [Link];
import [Link];
import [Link];

public class StockClient extends UnicastRemoteObject


implements StockListener {
private String[] stocks = {"OATS", "MSFT", "AUO"};
Pass the client
public StockClient() throws RemoteException { object to the server.
try {
Stock s = (Stock) [Link]("//localhost:1099/stock");
for (int i = 0; i < [Link]; i++) {
[Link](stocks[i], this);
[Link](stocks[i] + "=" + [Link](stocks[i]));
}
}
catch (Exception e) {
[Link](e); This method implements
} the remote callback
interface.
}

public void stockEvent(String ticker, float value) {


[Link]();
[Link](ticker + " has changed value to " + value);
}
public static void main(String[] args) throws Exception {
new StockClient();
}
}

[Link]
import [Link];
import [Link];

public interface Stock extends Remote {


public float getQuote(String ticker) throws RemoteException;
public void registerForStockEvents(String ticker, StockListener n)
throws RemoteException;
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 153


Advanced Java Programming

Dynamic Class Loading

” At runtime, RMI clients need class files for interfaces, stub classes, classes
returned by remote methods, and any classes that are used by those classes.

¾ It may be impractical to provide local copies of those classes to the end


user.

¾ Dynamic class loading allows clients to load classes from a remote


location.

” A codebase is a location from which a Java program can load class files.

¾ It is specified as a space-delimited list of URLs which specify .jar files or


directories using file, FTP, or HTTP protocol.

ƒ Directory URLs must have a trailing slash.

¾ You specify the codebase property in the server using the


[Link] system property.

ƒ A remote object carries its codebase with it over the network.

¾ If the client cannot find the class file in its classpath, it will attempt to load
the class file from the codebase.

” In order to use dynamic loading, you must install a security manager in your
client.

¾ You need a policy file for your client that grants permissions for
connecting to the RMI Registry and remote objects.

” If a client passes objects to a server, it may also need the codebase property.

Page 154 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 8 Advanced RMI

bank/[Link]
package bank;

import [Link];

public class BankClient {


public static void main(String args[]) {
[Link](new SecurityManager());
try {
String loc = "rmi://localhost/BankAccountImpl";
BankAccount bank = (BankAccount)[Link](loc);
double result = [Link]("156");
[Link]("Balance: " + result);
}
catch (Exception e) {
[Link](e);
}
}
}

bank/[Link]
grant {
permission [Link] "*:1024-", "connect,resolve";
};

This policy file allows the client to connect to services on any non-priviledged port. This includes the
rmiregistry (port 1098), as well as any Remote objects. If the server's codebase specifies an HTTP
service, we need to add an entry to allow connection to port 80.

Now that we have installed a security manager, any task the client performs that has security
restrictions must be permitted in the policy file, even if it has nothing to do with RMI.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 155


Advanced Java Programming

Activation

” Activation is a mechanism that provides references to remote objects which can


be instantiated when needed.

¾ Activatable remote objects are only created when a client needs to call a
method, saving resources in systems with many remote objects.

¾ Activation provides persistence in the event that a server object crashes or


is otherwise garbage collected.

” The process of instantiating passive objects to make them active is called


activation and is the responsibility of the activator.

¾ The activator maintains a registry of activatable objects, acting as a proxy


for remote method calls sent to those objects.

¾ Sun provides rmid as the standard activator that comes with the JRE.

” Since activatable remote objects need not be instantiated until accessed, they do
not run in a virtual machine until activated.

¾ An activation group is a collection of activatable objects that can share the


same VM.

ƒ Each activation group runs in its own separate VM.

¾ The activator monitors and manages the VM for each activation group,
starting it when needed.

” Activation is invisible to the client, which uses activatable objects in exactly the
same way it uses standard remote objects.

Page 156 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 8 Advanced RMI

© 2011 ITCourseware, LLC Rev 5.1.4 Page 157


Advanced Java Programming

Activatable Objects

” Create activatable objects in the same way you create other remote objects with
the following exceptions:

¾ You must extend [Link] or call one of the


[Link]() methods in place of UnicastRemoteObject.

ƒ Activatable provides the same functionality as


UnicastRemoteObject with the addition of activation capabilities.

¾ You must provide a constructor which takes two arguments, an


ActivationID and a MarshalledObject.

ƒ This constructor is called by the activator to activate the object.

¾ The rest of the steps and requirements are the same as for standard
remote objects.

” You allow for activation by providing a constructor which takes an


ActivationID and a MarshalledObject.

¾ Pass the ActivationID to the Activatable super-constructor or


exportObject() method.

¾ A MarshalledObject contains a serialized object which should contain


information for loading the state of the activatable object.

ƒ You specify the MarshalledObject when you register the


activatable object.

ƒ For example, you could provide a primary key for use in a JDBC
query.

Page 158 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 8 Advanced RMI

bank/[Link]
package bank;
The interface has nothing
import [Link]; in it specific to activation.
import [Link];

public interface BankAccount extends Remote {


public double getBalance(String id) throws RemoteException;
}

bank/[Link]
... This is the constructor
public class BankAccountImpl extends Activatable used by the activator
implements BankAccount { to activate the object.
private File accountFile = null;

public BankAccountImpl(ActivationID id, MarshalledObject data)


throws RemoteException {
0 for port means "use
super(id, 0);
an anonymous port."
try {
accountFile = (File)[Link]();
} data should contain a
catch (Exception e) { File object from the
throw new RemoteException( ActivationDesc.
"Failed unmarshalling File object", e);
} Any Exception that occurs due to
} unmarshalling will be deferred to the client.

// scan a tab delimited file for the balance for the given id
public double getBalance(String id) throws RemoteException {
double result = 0;
Scanner scanner = null;
...
return result;
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 159


Advanced Java Programming

Registering Activatable Objects

” Register activatable objects with the activator by calling [Link]().

¾ This method returns a Remote stub which you could use to pass a
reference to the activatable object to clients.

ƒ Pass this stub to [Link]() or [Link]() to allow


clients to locate the object through the RMI Registry.

” The register() method requires an ActivationDesc object containing the


information the activator needs to construct the object:

¾ groupID identifies the ActivationGroup to which the object belongs.

¾ classname is the name of the class that implements the remote interface.

¾ location is the codebase for the object's class files.

¾ data is the MarshalledObject that will be passed to the object on


activation.

” Each activatable object must belong to an activation group.

” Call [Link]().registerGroup() to register a new


activation group.

¾ Use the return value when you register your activatable objects.

” Since the activator starts the VM for the activation group, you must use an
ActivatonGroupDesc to specify properties and arguments to the VM.

¾ You can specify properties for the activation group VM by passing a


Properties object in the ActivationGroupDesc constructor.

Page 160 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 8 Advanced RMI

bank/[Link]
...
public class BankSetup {
public static void main(String[] args) throws Exception {
...
String policy = args[0]; Provide a MarshalledObject
Properties props = new Properties(); containing the file from which the
[Link]("[Link]", policy); BankAccount reads balances.

ActivationGroupDesc group = new ActivationGroupDesc(props, null);

ActivationGroupID groupId =
[Link]().registerGroup(group);

[Link]("registered group: security policy: "+ policy);

// copy the activation group's codebase from the system property


String codebase = [Link]("[Link]");

File accountFile = new File("bank/[Link]").getCanonicalFile();


MarshalledObject mo = new MarshalledObject(accountFile);

ActivationDesc desc = new ActivationDesc (


groupId, "[Link]", codebase, mo);

// Register the interface with the activation system (rmid)


BankAccount stub = (BankAccount) [Link](desc);
[Link]("Got stub for the BankAccount");
Bind the stub from
// Bind it in the registry (rmiregistry) [Link]()
in the registry.
[Link]("BankAccountImpl", stub);
[Link]("Bound stub to \"BankAccountImpl\"");
}
}

When you run this code (we will give you directions at the end of the activation discussion) you should
notice that, unlike standard RMI servers, it returns right away.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 161


Advanced Java Programming

Security and Activation

” The standard ActivationGroup implementation installs an


RMISecurityManager.

¾ You must provide a policy file if the default policy is too restrictive.

ƒ Since the default policy does not usually allow your activatable
objects to accept connections you will most likely need a policy
file.

ƒ The activation group must also have permission to access the


resources specified in the codebases of its activatable objects.

” rmid also uses a security manager.

¾ Specify the policy file using -[Link]=/path/to/


policyfile on the rmid command line.

¾ If you wish to specify properties for an activation group you must


specifically allow those properties in the policy file for rmid.

ƒ Use [Link] to allow a specific


property

” There are a few differences in how you use dynamic class loading with
activatable classes:

¾ Since you do not have direct control of the VM in which your object runs,
you pass the codebase to the ActivationDesc constructor.

¾ Your client's policy file must allow connections to the activator's port (the
default for rmid is 1098).

Page 162 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 8 Advanced RMI

bank/[Link]
grant {
permission [Link] "*:1024-", "accept,resolve";
permission [Link] "[Link]", "read";
};

This policy file will allow remote objects in the activation group to accept connections on any non-
privileged port. It will also allow the remote objects to read the [Link] file in the current
directory.

This policy file should be assigned to the [Link] property in the Properties passed to
the ActivationGroupDesc constructor.

bank/[Link]
grant {
permission [Link]
"-[Link]=*";
};

This policy file will allow rmid to assign a value to the [Link] property when starting a
VM for an activation group.

bank/[Link]
grant {
permission [Link] "*:1024-", "connect,resolve";
};

This policy file will allow the BankClient to connect to non-privileged ports so that it can connect to
remote objects, as well as rmid on port 1098 and rmiregistry on port 1099.

Try It:
The steps for compiling and running the bank example are listed in the file [Link] in the
online files for this chapter.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 163


Advanced Java Programming

JNDI and RMI Registry

” The Java Naming and Directory Interface (JNDI) is an API that allows you to
access various directory services in a standardized way.

” Sun's virtual machine includes a JNDI service provider for accessing the RMI
Registry.

” To access the registry using JNDI you first create an InitialContext.

¾ Specify the initial context factory and provider URL as entries in a


Hashtable.

Hashtable<String, String> env =


new Hashtable<String, String>();
[Link](Context.INITIAL_CONTEXT_FACTORY,
"[Link]");
[Link](Context.PROVIDER_URL, "rmi://localhost:1099/");
Context ctx = new InitialContext(env);

” Use rebind(String name, Object obj) to initially bind an object to a logical


name or rebind an existing name to a different object:

[Link]("stock", server);

” Use the lookup(String name) method to get a stub reference.

¾ lookup() returns an Object, so you must downcast it to the appropriate


class:

Stock s = (Stock)[Link]("stock");

Page 164 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 8 Advanced RMI

JNDI also allows you to configure the InitialContext through system properties or a [Link] file.

java -[Link]=[Link]
-[Link]=rmi:/// StockClient

If you want to allow the use of properties, you can use the no-argument constructor for InitialContext.

Context ctx = new InitialContext();

Several JNDI service providers allow you to bind remote objects in the service. Examples included with
Sun's virtual machine are the COSNaming service provider for CORBA naming services, and the LDAP
service provider which allows you to specify remote object references as attributes of an entry in an LDAP
directory.

If you use JNDI instead of accessing the registry directly via the RMI classes, then it may be possible to
migrate to a different kind of naming service without modifying any code. Using the standard JNDI
properties, and perhaps a bit of extra code, you can easily allow the end user to determine which naming or
directory service to use.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 165


Advanced Java Programming

RMI-IIOP

” RMI, by default, uses the Java Remote Method Protocol (JRMP) to


communicate over the network. This is only useful for communication between
Java components.

” Common Object Request Broker Architecture (CORBA) is a distributed-object


programming model that uses the IIOP protocol for communication between
components which may be programmed in many different languages.

” RMI-IIOP uses IIOP as the networking protocol for RMI components, allowing
developers to implement CORBA components in Java using RMI.

” RMI-IIOP requires some changes to the way you develop RMI components.

¾ Components use JNDI to lookup and bind objects in a CORBA Naming


service in place of the RMI Registry.

¾ Remote objects must use PortableRemoteObject in place of Activatable


or UnicastRemoteObject.

¾ You must not downcast any Remote object passed as a parameter or


returned from a method using IIOP.

ƒ Call [Link]() on the object and


downcast the return value.

¾ You must run rmic with the -iiop option to generate IIOP compliant stubs
and ties.

” To access an RMI component from CORBA code, you will need to generate the
IDL interfaces for the RMI component by running rmic with the -idl option.

Page 166 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 8 Advanced RMI

[Link]
...
public class TimeImpl extends PortableRemoteObject implements Time {
public TimeImpl() throws RemoteException {
}
public String getTime() {
Date d = new Date();
return [Link]();
}
}

[Link]
...
public class TimeServer {
public static void main(String[] args) {
try {
TimeImpl time = new TimeImpl();
Context initialNamingContext = new InitialContext();
[Link]("TimeService", time );
[Link]("Time Server is ready...");
}
catch (Exception e) {
[Link]("Trouble contacting TimeService: " + e);
}
}
}
The InitialContext
[Link] must be configured
... using system properties
public class TimeClient { or a [Link] file.
public static void main(String args[]) {
try {
Context ctx = new InitialContext();
Object objref = [Link]("TimeService");
Time time =
(Time) [Link](objref, [Link]);
[Link]([Link]());
}
catch(Exception e) {
[Link]();
}
}
}

TryIt:
Instructions for building and running the Time example are in [Link].
© 2011 ITCourseware, LLC Rev 5.1.4 Page 167
Advanced Java Programming

Labs

Create a command-line chatroom that uses client callbacks. The chatroom will allow for
multiple clients. The chat interface should have a postChat(String msg, String sender)
method, and the client callback should then print the message whenever other clients send a
message.
(Solutions: [Link], [Link], [Link], [Link])

† Create an activatable remote object that returns book titles from ISBN numbers. For this
exercise, just hard code the ISBN numbers in a HashMap. The file [Link] contains some
data you can use to fill in the HashMap.
(Solutions: ISBN_IF.java, ISBN_Impl.java, [Link], [Link], [Link],
[Link])

‡ Write a client that uses the ISBN server.


(Solution: [Link])

ˆ (Optional) Convert the stock remote server and client from the chapter code to use the IIOP
protocol.
(Solutions: [Link], [Link])

Page 168 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 8 Advanced RMI

© 2011 ITCourseware, LLC Rev 5.1.4 Page 169


Advanced Java Programming

Page 170 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 9 Managing Security Policies

Chapter 9 - Managing Security Policies

Objectives

” Describe Java’s security model.

” Define security policies for Java


programs you run, based on where
the program code was loaded.

” Correctly format a policy entry.

” Manage policy files using policytool.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 171


Advanced Java Programming

Untrusted Code

” Ask software developers about security, and they will likely talk about any
number of topics.

¾ One possible topic is security of data, or encryption.

¾ They might also discuss securing access to an application, or


authentication and authorization.

¾ A third topic is protecting the system from misbehaving or malicious


programs, also known as code access security.

ƒ This third topic is the only one that has been addressed by Java
since version 1.0.

” From the beginning, Java was intended to be a dynamic, distributed, networked


language.

¾ One of the first types of Java programs, the applet, is downloaded from a
web server and executed in a browser's JVM.

¾ RMI stubs can also be downloaded dynamically from a web server to


execute remote code.

¾ Java Web Start is a mechanism for easing client-side installation of


programs by automatically downloading them from a server.

” When code is dynamically downloaded and executed, often without the


knowledge of the user, there is potential for worms or Trojan horses.

¾ By default, untrusted code, or code that was dynamically downloaded


from a server, is very restricted in what it can do.

¾ The rest of this chapter discusses how you can define policies by which
your JVM grants permissions to applications.
Page 172 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 9 Managing Security Policies

Whenever you design an application that is intended to dynamically download code, you are in effect
bypassing some of your network's security mechanisms. This code distribution via HTTP can tunnel through
firewalls, which often do not allow binary downloads on non-standard ports. Usually this is not an issue
within an intranet, but if your application is designed to serve clients on the internet, make sure that
administrators on both the client and server sides are on board with your plans.

Try It:
There is an RMI application in this chapter directory that gets the server's time. To run it, first go to the root
directory and run rmiregistry.

Open another command prompt window, cd into the server directory in this chapter directory and
compile [Link]: javac [Link]. Generate the stubs for TimeServer: rmic
TimeServer. Run the server program: java -[Link]=[Link]
server/ TimeServer (your codebase may be different).

Open another command prompt window, cd into the client directory in this chapter directory and copy
[Link] from the server directory. We are going to dynamically download the stub, so do not copy it
into the client directory. Compile [Link]: javac [Link].

When you try to run the client program (java ShowTimeClient) you will get an error message:

error unmarshalling return; nested exception is:


[Link]: TimeServer_Stub (no security
manager: RMI class loader disabled)

Investigate:
When you are tracking down security problems, pay attention to the exception messages; they usually give
you very good information about what needs to be fixed. What do you need to do to ShowTimeClient to
enable the RMI class loader?

© 2011 ITCourseware, LLC Rev 5.1.4 Page 173


Advanced Java Programming

Security Managers

” Java VM system code calls SecurityManager methods at runtime to check if a


running applet has permission to call "dangerous" methods: file I/O, network
access, defining new classes, etc.

¾ The SecurityManager invokes methods of the AccessController class to


determine if the security policy currently in effect allows the activity.

” Java applications (that is, those run with the java command) do not install a
SecurityManager automatically.

¾ That is why most Java applications have access to all system resources by
default.

” Because dynamically downloading an RMI stub would grant total access to


untrusted code, it is not allowed without an installed SecurityManager.

¾ Most browsers install a SecurityManager when they start their VM for


running applets.

” To subject a Java program to the same SecurityManager restrictions as an


applet, either:

¾ Use a command-line option to install a SecurityManager when you run


the program.

java -[Link] MyApp

¾ Write the program so that it installs a SecurityManager itself.

[Link](new SecurityManager());

Page 174 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 9 Managing Security Policies

Hands On:
Edit the ShowTimeClient program to install a security manager:

client/[Link]
...
public class ShowTimeClient {
public static void main(String args[]) {
[Link](new SecurityManager());
new ShowTimeClient();
}
...
}

Now, when you compile and run your program again, you will get a different exception:

Exception in thread "main" [Link]: access


denied ([Link] [Link]:1099 connect,resolve)

This is because socket (RMI) connections are a protected resource, and we have not granted any
permission.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 175


Advanced Java Programming

The Java Security Model

” Java's "Write Once, Run Anywhere" motto does not mean you have to allow
code from anywhere to run unchecked on your machine.

” You can specify security policies for your VM that are applied according to the
code base (that is, the location) of programs you run.

¾ Policies can also be applied based on the signer of a .jar containing the
code.

” Various methods in the Java API libraries will throw a SecurityException


unless your security policy permits their activity.

” A few of the more obvious examples of permissions you will want to control
include:

¾ The ability of a Java program to read, write, execute, or delete files on


your machine.

¾ The ability of a Java program to shut down the VM.

¾ The ability of a Java program to connect to a remote server, or to listen


for and accept connections from a remote client.

¾ The ability of a Java program to modify your security policies.

Page 176 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 9 Managing Security Policies

Pe rmission Package Risk


AudioPe rmission [Link] d Interfere with mixer or eavesdrop on
user.
AuthPe rmission [Link] [Link] Change credentials, execute code
with different credentials.
AWTPe rmission [Link] Interfere with events, clipboard,
screen.
De le gationPe rmission [Link] [Link]. Substitute malicious ticket granting
ke rbe ros s e r vi c e s .
File Pe rmission [Link] Snoop or corrupt data, execute
malicious programs.
LoggingPe rmission [Link] Snoop application logs.
Ne tPe rmission [Link] t Steal authentication data, redirect to a
malicous server.
Private Cre de ntialPe rmission [Link] [Link] Snoop credentials of a subject.
Prope rtyPe rmission [Link] Snoop or modify system properties.
Re fle ctPe rmission [Link] fle ct Snoop or modify private fields.
Runtime Pe rmission [Link] Bypass security.
Se curityPe rmission [Link] curity Bypass security.
Se rializ able Pe rmission [Link] Substitute serialized objects.
Se rvice Pe rmission [Link] [Link]. Initiate or accept unauthorized
ke rbe ros principal.
Socke tPe rmission [Link] t Connect to or from unauthorized
server.
SQLPe rmission [Link] Snoop SQL log data.
SSLPe rmission [Link] [Link] Monitor HTTPS sessions.
AllPe rmission [Link] curity All of the above.

Most of the permissions listed above have multiple targets or actions. The Java documentation contains
excellent information about the possible targets and actions and the associated risks. The API
documentation for each permission class is a good place to look, as well as the docs/guide/security/
[Link] page.
© 2011 ITCourseware, LLC Rev 5.1.4 Page 177
Advanced Java Programming

Policy Entries

” Policy files contain entries that grant permissions to code, based on where the
code is loaded from at runtime.

grant codeBase "[Link] {


permission [Link] "<<ALL FILES>>",
"read";
permission [Link] "C:\\TEMP\\*",
"read,write";
permission [Link] "exitVM";
}

” The codeBase URL can reference either a local or remote location.

¾ If the URL ends in a slash, /, then it matches all .class files in that
directory.

¾ If it ends in /*, then it matches all .class files and .jar files in that
directory.

¾ If it ends in /-, then it matches all .class files and .jar files in and under
that directory.

” Policy entries without a codeBase URL will apply to all URLs.

grant {
permission [Link]
"[Link]", "connect";
}

Page 178 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 9 Managing Security Policies

A list and description of all the various permissions, when they are checked, and possible values can
be found in the JDK documentation. See docs/guide/security/[Link] for more information on
each permission.

For file permissions, you must specify the file or files over which the permission is granted. The special
token "<<ALL FILES>>" means (surprise) the permission applies to any file on your machine.

permission [Link] "<<ALL FILES>>", "read";

You can specify individual files or directories, using either relative or absolute paths (note the double
backslashes necessary for Windows filepaths). For directory paths, the convention is similar to that for
codebase URLs. For a specific file:

permission [Link] "[Link]", "read,write";


permission [Link] "C:\\TEMP\\[Link]", "write";

Read the names of the files in the directory /tmp:

permission [Link] "/tmp/", "read";


permission [Link] "/tmp", "read"; //Same thing

Read the contents of all files in the directory /tmp:

permission [Link] "/tmp/*", "read";

Read the contents of all files in the directory /tmp and its subdirectories:

permission [Link] "/tmp/-", "read";

You can even use the values of Java properties in permission targets:

permission [Link] "${[Link]}\\pub", "read";

Finally, you can use the special token ${/} instead of a platform-specific file separator:

permission [Link] "${[Link]}${/}pub", "read";

When specifying socket permissions, you must specify the host and the port for which the permission
is granted. The host can consist of a hostname (wild cards are allowed) or an IP address. The port can
consist of a single port, or a closed or open range of ports. The special token localhost (or an empty
hostname) refers to the local machine.

permission [Link] ":8088", "listen,accept";


permission [Link] "*.[Link]", "connect";
permission [Link] "appsrv:4075-4085", "connect";

© 2011 ITCourseware, LLC Rev 5.1.4 Page 179


Advanced Java Programming

Policy Files

” When the VM starts, it will read two policy files by default: a system policy file
and one for the individual user.

¾ This allows each user to define customized policies.

” The system policy file is named [Link] and is located under the JRE's
lib/security/ directory.

¾ On multi-user systems, the System Administrator should manage and


protect this file.

” The user-specific policy file is named .[Link] and is located under a user-
specific directory.

¾ On UNIX, this file will be $HOME/.[Link].

¾ On Windows, it is C:\Documents and Settings\%USER%\.[Link].

” If you create additional security policy files, you will need to specify them on the
command-line when you run Java programs.

¾ This adds [Link] to the list of policy files applied for this execution
of MyApp:

java -[Link]=[Link] MyApp

¾ Use == to cause [Link] to be the only policy file used for this
execution of MyApp, ignoring the default policy files:

java -[Link]==[Link] MyApp

Page 180 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 9 Managing Security Policies

The System Administrator can list additional default policy files by adding them in the JRE's
lib/security/[Link] file. This file starts out with:

[Link].1=${[Link]}/lib/security/[Link]
[Link].2=${[Link]}/.[Link]

To add more default policy files, the administrator just adds them to the list, giving each a new number:

[Link].3=/usr/local/BizApp/admin/[Link]
[Link].4=${[Link]}/.[Link]
[Link].5=[Link]

Note that if a [Link] number is left out, no [Link] with higher numbers will be used:

[Link].7=/java/will/not/use/this/[Link]
[Link].8=/this/[Link]

© 2011 ITCourseware, LLC Rev 5.1.4 Page 181


Advanced Java Programming

Using the Policy Tool

” Policy files are text files you can maintain with any text editor.

¾ Policy entry syntax is not especially complicated.

” For convenience, though, the JDK provides a GUI program, policytool, for
creating and maintaining entries in policy files.

” policytool validates the syntax of your entries, provides a list of the standard
permissions, and can edit any policy file.

¾ It will open your user-specific policy file by default.

Page 182 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 9 Managing Security Policies

Hands On:

Start the policytool. The first time you run it, policytool may complain that it cannot find your personal
policy file (because, of course, you have not created it yet). Note the name of the default policy file the
policytool expected to find (you will use it in a moment), and otherwise ignore the error message for now.
Click Add Policy Entry. Enter [Link] (your codebase location may be different) in the
CodeBase textbox, then click Add Permission. Select SocketPermission from the Permission list. In
the text field next to the Target Name list, enter the host and port: *:*. From the Actions list, choose
connect, then choose resolve. Click OK when you are finished.

Because the server codebase uses a file URL instead of an HTTP URL, we also need to grant a
FilePermission to our client. Click Add Permission again. Select FilePermission from the Permission
list. In the text field next to the Target Name list, enter the stub location: C:\\advj2se\\ch09\\server\\- (your
stub location may be different). From the Actions list, choose read. Click OK when you are finished and
click Done on the Policy Entry window. You have granted permission to access the server and download
the stub.

Now save your policy entry, creating your default policy file. To do this, choose Save As in the File menu.
Use the file dialog to specify the correct path and filename for your default policy file. This is the path the
policytool mentioned in the message dialog when it started up the first time. On Windows, if your account
name is student, the full path should be something like C:\Documents and Settings\student\.[Link].
On UNIX, it should be something like /home/s1/.[Link]. Note the leading '.' in the filename! Close
policytool and try running the ShowTimeClient again. If you specified the paths and permissions correctly,
the client should be able to connect to the TimeServer.
© 2011 ITCourseware, LLC Rev 5.1.4 Page 183
Advanced Java Programming

Securing Applets

” Java classes are loaded by a [Link] or one of its subclasses.

¾ The class loader is responsible for calling the SecurityManager to see if


the program has permission to load the class, and for setting up the
protection for the class based on the policy.

” Applets use a [Link] (or a subclass) to download the applet


class files from the web server.

¾ Because classes downloaded from a web server are inherently untrusted,


URLClassLoader requires a SecurityManager to be installed.

¾ The SecurityManager subjects the code to the locally-defined security


policies.

” In Java 1.0, all applets were locked in a security sandbox and were not allowed
to make "dangerous" method calls.

” In Java 1.1, an applet was locked in the sandbox unless it was loaded from a .jar
file that included a recognized digital signature, in which case it was trusted and
granted full access.

” Neither the Java 1.0 nor Java 1.1 approach is very effective, so both Netscape
and IE came up with their own, proprietary security mechanism and API.

” To use the Java 2 security model, you must use the Java Plug-In.

¾ If the applet is loaded via an <APPLET> tag, the browser might use its
built-in 1.1 VM.

ƒ Instead of the simple <APPLET> tag, Internet Explorer uses an


<OBJECT> tag while Netscape Navigator uses an <EMBED>
tag.

<EMBED TYPE=application/x-java-applet;version=1.2 CODE=... >


Page 184 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 9 Managing Security Policies

Try It:
The WriteFile program can be run as an applet, loaded from the [Link] file. Compile and load
[Link] into the appletviewer that comes with the JDK:

appletviewer [Link]

When you click the Write button, the applet attempts to write the file specified in the text box. Our security
policy has not granted file write permission, so the applet fails.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 185


Advanced Java Programming

Securing Applications

” RMI uses a [Link] to dynamically load remote class


files.

¾ As with a URLClassLoader, the RMIClassLoader requires a


SecurityManager to be installed.

” To have policy entries apply to a Java application run with the java command,
you must install a SecurityManager.

¾ The program can install the SecurityManager itself:

[Link](new SecurityManager());

¾ You can also install a SecurityManager with the [Link]


property:

java -[Link] MyApp

Page 186 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 9 Managing Security Policies

Try It:
The WriteFile program can also be run as an application: java WriteFile. Try running it with a security
manager to see if your policies are applied: java -[Link] WriteFile.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 187


Advanced Java Programming

Labs

Edit your policy entry to include a FilePermission with a write action. Try running the WriteFile
applet in appletviewer and see if you can save the file.
(Solution: [Link])

† Run the WriteFile applet in appletviewer. Is an exception thrown when you click the Close
button? Why?
(Solution: [Link])

‡ Use the policytool to grant the RuntimePermission target exitVM for this codebase. Be sure to
save your policy before going on.

What happens when you restart appletviewer and click the Close button of the WriteFile applet?
Does your applet have the necessary permission now?
(Solution: [Link])

ˆ Add code to the TimeServer program to install a SecurityManager when the program starts.
Now run the server (do not forget to start the rmiregistry). Run the ShowTimeClient. Add the
correct permission to your policy to allow the server to accept connections.
(Solutions: [Link], [Link])

‰ Currently, your policy file grants all the permissions needed by any application that we've worked
with to all applications in this chapter directory. This could open security holes. For example, the
WriteFile applet could accept socket connections. A better approach is to only grant permissions
that are required for a program to do its job.

Create a new policy file that contains the permissions that TimeServer requires, and remove them
from your .[Link] file. Run TimeServer with just the policy file that you created.
(Solution: [Link])

Page 188 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 9 Managing Security Policies

© 2011 ITCourseware, LLC Rev 5.1.4 Page 189


Advanced Java Programming

Page 190 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 10 Keys, Signatures, and Certificates

Chapter 10 - Keys, Signatures, and


Certificates

Objectives

” Describe the purpose of signed


JARs.

” Create a keypair and use your private


key to sign JARs.

” Maintain a database of trusted


certificates.

” Define security policies for code


signed by trusted signers.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 191


Advanced Java Programming

Jar Files

” A Java Archive (JAR) is a file used for storing and distributing Java programs
and components.

¾ A JAR usually contains Java .class files, supporting files, and sometimes a
manifest describing what is in the JAR.

” Create a JAR with the jar utility that comes with the JDK:

jar cvf [Link] *.class

¾ You can create or look at a JAR with any zip utility because JARs use zip
compression.

ƒ However, only Java's jar utility will add the manifest file for you.

” You don't need to extract the JAR to use it — Java can extract what it needs at
runtime.

¾ To use classes from a JAR, include the JAR file (not just the directory
that contains the JAR file) in your classpath.

¾ To run an application that is in a JAR, type java -jar [Link].

¾ To access an applet that is in a JAR, use a modified applet tag:

<APPLET ARCHIVE="[Link]" CODE="[Link]" WIDTH="600"


HEIGHT="100">
</APPLET>

Page 192 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 10 Keys, Signatures, and Certificates

Hands On:
Compile the [Link] program that's in the working directory for this chapter:

javac [Link]

Create a new JAR containing the resulting .class files:

jar cvfm [Link] [Link] WriteFile*.class

Look at what is in the JAR file. Notice the jar utility created a META-INF/[Link] file:

jar tvf [Link]

Run the WriteFile application from the JAR:

java -jar [Link]

Run the WriteFile applet in appletviewer:

appletviewer [Link]

© 2011 ITCourseware, LLC Rev 5.1.4 Page 193


Advanced Java Programming

Data Security Concerns

” Some concerns when you are using electronically-transmitted data include:

¾ Am I receiving the data exactly as it was sent?

¾ Is the data's sender who I think it is?

¾ Is the data's sender someone I trust?

¾ Was anyone else able to intercept and read the data's content?

” And, if the sender is someone I trust, just how far do I trust him — specifically,
if he sends me a Java program, will I allow his program to:

¾ Read, write, execute, and delete files on my machine?

¾ Cause the VM to exit?

¾ Open network connections with other machines?

¾ Modify my local security policies?

” Java addresses all these concerns — integrity, authentication, trust,


confidentiality, and security policy in a provider-independent way with Java
Cryptography Architecture (JCA) defined in the [Link] packages.

” Using the JCA, you can write applications that generate message digests and
digital signatures, interact directly with keystores, generate keys, create
certificates, define and check permissions, and more.

Page 194 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 10 Keys, Signatures, and Certificates

Insecure Data Transmission

Any electronic message can potentially be intercepted and modified, without the recipient's knowledge.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 195


Advanced Java Programming

Message Digests

” From any digital message of any length, a digital digest can be computed.

¾ A digest verifies a message's integrity.

” A digest is a compact, fixed-sized number which is calculated arithmetically


from the contents of the message.

¾ There's no way, given the digest, to reproduce any part of the message;
digest algorithms are completely one-way.

¾ A very small change in the message content yields a significantly different


digest value.

” Commonly-used algorithms for computing digests include MD5 and SHA.

¾ MD5 produces a 128-bit digest, SHA a 160-bit digest.

” If a sender calculates and tells you the digest of a transmitted message, and the
digest you calculate from the message you receive matches it, then you can be
confident the message was not altered during transmission.

¾ However, the sender must somehow communicate the digest value to you.

¾ If someone were to intercept both the message and the correct digest, he
could substitute a falsified message, plus a new digest of the falsified
message.

Try It:
Compile and run the [Link] program, including the string you want
to create a digest for as a command-line argument: java MessageDigestTest "Four
score and seven years ago . . ."

Page 196 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 10 Keys, Signatures, and Certificates

Assuring Integrity with Message Digests

A digest comparison assures recipients that they received the message exactly as it was sent. The sender
could tell the recipient the digest in a separate message, by telephone or by some other means.

If the digest actually accompanies the message, though, someone who wants to tamper with a message
can simply delete the original digest, alter the message, recalculate the new digest using the same algorithm,
and attach it to the altered message:

© 2011 ITCourseware, LLC Rev 5.1.4 Page 197


Advanced Java Programming

Digital Signatures

” The digest of a digitally signed message is encrypted using the sender's private
key.

¾ The recipient decrypts the digest using the sender's public key.

” Digital signatures are specific to each message.

” Nobody can alter the message and add a forged signature.

¾ They don't have access to the sender's private key, which is necessary to
create a signature the public key can decrypt.

¾ This assures message integrity.

” Nobody can send a signed message pretending to be someone else.

¾ Only the private key of the authentic sender works with his public key.

¾ This assures authenticity.

¾ By the way, the sender of a signed message can't claim later that he didn't
send it.

” Java's jarsigner utility digitally signs a JAR file.

¾ The signed JAR can contain code, documents, or whatever.

¾ We will see how to use jarsigner shortly.

” To sign a JAR, you must first have a public/private keypair.

Page 198 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 10 Keys, Signatures, and Certificates

The digest of a digitally signed message is encrypted with the sender's private key. The recipient uses the
sender's previously-published public key to decrypt the digest.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 199


Advanced Java Programming

Using keytool

” Java's keytool allows you to generate your own keypairs.

” keytool stores your keypairs (you can have more than one) in a keystore.

¾ By default, this will be a file, named .keystore, in your home directory.

¾ The keystore file is protected by its own internal password (passphrase,


actually) which you enter when you first create it.

” Each key in a keystore has a unique alias — just a short, convenient name for
that key.

¾ Unless you specify an alias with the -alias option, keytool uses mykey as
the default.

” To generate a key, use keytool -genkey:

keytool -genkey -alias keyname

¾ keytool prompts you for certain information about the entity (person or
organization) to whom the key belongs.

¾ Each key is individually protected by a password, which by default is the


same as the keystore's password.

” The keystore can also be accessed programmatically using a


[Link] object.

Page 200 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 10 Keys, Signatures, and Certificates

Generating a Keypair

keytool -genkey -alias firefly


Enter keystore password: Hello, I must be going
What is your first and last name?
[Unknown]: Rufus T. Firefly
What is the name of your organizational unit?
[Unknown]: African Exploration
What is the name of your organization?
[Unknown]: Animal Crackers, Inc.
What is the name of your City or Locality?
[Unknown]: New York
What is the name of your State or Province?
[Unknown]: New York
What is the two-letter country code for this unit?
[Unknown]: US
Is <CN=Rufus T. Firefly, OU=African Exploration, O=Animal Crackers,
Inc., L=New York, ST=New York, C=US> correct?
[no]: yes

Enter key password for <firefly>


(RETURN if same as keystore password):

Hands On:

Use keytool to generate a keypair for yourself. Use your lastname (or your unique login ID, if you prefer)
as the alias. You will be prompted for a keystore password, so choose something easy to remember (you
must enter this every time you run keytool). Enter appropriate values for the entity information. Note
carefully what happens when you enter yes to confirm your entry — generating a keypair is computationally
expensive, hence there may be a delay. After your key is generated, use keytool to view the contents of
your keystore:

keytool -list

Try the -v (for verbose) option:

keytool -v -list

© 2011 ITCourseware, LLC Rev 5.1.4 Page 201


Advanced Java Programming

Using jarsigner

” jarsigner uses your private key to create a digital signature for a JAR's contents.

jarsigner [Link] keyname

¾ Several entities can sign the same JAR.

” If any of the JAR's contents are changed, the JAR will fail verification unless the
signature is regenerated.

¾ jarsigner -verify will tell you if any file in a JAR doesn't match the
signature.

¾ When the Java VM loads classes from a JAR, it will throw a


SecurityException on modified class files.

” The manifest (META-INF/[Link]) of a signed JAR includes a digest


of each file in the JAR.

” For each signature, a signed JAR's META-INF/ directory additionally contains a


signature file and a signature block file.

¾ The signature file contains digests, not of the JAR's contents, but of the
JAR's manifest entries.

¾ The signature block file contains the signature (digitally signed digest) of
the signature file.

ƒ The signature block file also contains a certificate for the signer's
public key.

” That is it — your signed code is ready to distribute!

Page 202 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 10 Keys, Signatures, and Certificates

Hands On:

Using the key you generated earlier, sign [Link]:

jarsigner [Link] keyname

. . . where keyname is the alias you used when you generated your key. You will have to enter the password
for your keystore. Go ahead and use jarsigner to verify your signed JAR:

jarsigner -verify [Link]

Try the -verbose option (keytool uses -v, jarsigner uses -verbose):

jarsigner -verbose -verify [Link]

Use appletviewer to make sure you can load the classes from the JAR:

appletviewer [Link]

Now, make a modification to [Link], recompile, and update the JAR. For the modification, simply
change the value of the filename variable from [Link] to [Link]. Be sure to use jar's u (update)
option, not c:

javac [Link]
jar uvf [Link] WriteFile*.class

Use jarsigner -verify again to verify the modified JAR. Try loading the JAR's classes in appletviewer.

Re-sign [Link]:

jarsigner [Link] keyname

© 2011 ITCourseware, LLC Rev 5.1.4 Page 203


Advanced Java Programming

Certificates

” Signed code is trustworthy only if the public key the recipient uses to verify it
actually belongs to the entity they think it belongs to.

¾ An intruder could publish a public key, claiming to be someone the


recipient trusts.

” A public key certificate is a statement, digitally signed using a trusted entity's


private key, that the enclosed public key actually belongs to a certain entity.

¾ If you trust the issuer of the certificate, then you can trust the public key it
contains.

¾ A Certificate Authority (CA) will issue certificates based on


documentation (company letterhead, incorporation document, driver's
license, notarized document, etc.).

” When you sign a JAR, the JAR will include a certificate for your public key.

¾ If the recipient trusts the issuer of the certificate, then they can trust that
the JAR was, in fact, signed by you.

” To export a certificate with your public key, use keytool -export:

keytool -export -alias keyname -file pubkeyfile

” If recipients of your data trust you, they import your certificate into their
keystores.

keytool -import -alias keyname -file pubkeyfile

Page 204 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 10 Keys, Signatures, and Certificates

The base [Link] class does not give you a lot of information about a certificate,
because it is generic, and does not represent any specific format. By default, keytool creates an X509
certificate, which is an ANSI standard and the dominant format.

[Link]
...
public class ShowCert {
public static void main(String[] args) {
try {
String keyStoreLocation = [Link]("[Link]");
String keyStoreFile = ".keystore";
String password = "Hello, I must be going";
String alias = "firefly";

KeyStore keyStore = [Link]("jks");


FileInputStream fis = new FileInputStream(
keyStoreLocation + [Link] + keyStoreFile);
[Link](fis, [Link]());

Certificate cert = [Link](alias);


if (cert instanceof X509Certificate) {
X509Certificate x509cert = (X509Certificate) cert;
[Link]("Certificate subject: " +
x509cert.getSubjectX500Principal());
[Link]("Certificate issuer: " +
x509cert.getIssuerX500Principal());
}
}
catch (KeyStoreException e) {
[Link](e);
}
catch (IOException e) {
[Link](e);
}
catch (NoSuchAlgorithmException e) {
[Link](e);
}
catch (CertificateException e) {
[Link](e);
}
}
}

Try It:
Change the keyStoreFile, password, and alias values to match the values for your certificate. Then
compile and run [Link].
© 2011 ITCourseware, LLC Rev 5.1.4 Page 205
Advanced Java Programming

Certificate Chains

” One entity might issue a certificate of another entity, who, in turn, might issue a
certificate for another, and so on.

¾ The resulting certificate chain validates all its entities based on the
original issuer's authority.

” When you generate a keypair, keytool creates a self-certified certificate for your
public key.

¾ That is, your own private key is used to sign a statement that your public
key belongs to you.

” A more convincing certificate is one from a CA.

” To request an authoritative certificate of your key:

1. Use keytool -certreq to export your public key into a Certificate Signing
Request file:

keytool -certreq -alias firefly -file [Link]

2. Send your Certificate Signing Request file to a CA and follow their


procedures to establish your identity.

3. From the CA, you'll receive a certificate file, signed by them, containing
your public key.

4. Import the certificate into your keystore.

” Recipients of your signed code can import your certificate into their keystores,
and grant permissions to your code based on how much they trust you . . .

Page 206 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 10 Keys, Signatures, and Certificates

© 2011 ITCourseware, LLC Rev 5.1.4 Page 207


Advanced Java Programming

Managing Keys and Certificates

” Java manages keys and certificates in a keystore.

¾ The default keystore is in the .keystore file in your home directory, but
you can have many keystores, with different file names, in different
directories.

¾ You can even use some other I/O device.

” Java provides three different algorithms for storing keys, and you can specify
which a given keystore uses whenever you create or alter a keystore.

¾ The default, JKS, provides the weakest encryption and can not store
secret keys (used for encryption).

¾ JCEKS, provided with the Java Cryptography Extension, has better


encryption and can store secret keys.

¾ PKCS12 is used for importing certificates from Netscape Navigator.

” You can manage keys and certificates with the keytool utility or through the key
management API.

¾ The API allows you to manage the keystore through the


[Link] class.

¾ Call the static getInstance() method to initialize a KeyStore object,


passing it the algorithm used for the keystore.

¾ Call load(), passing an InputStream to read the keystore file.

¾ Call store() when you are done, passing an OutputStream.

Page 208 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 10 Keys, Signatures, and Certificates

[Link]
import [Link].*;
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class ShowAliases {


public static void main(String[] args) {
try {
String keyStoreLocation = [Link]("[Link]");
String keyStoreFile = ".keystore";
String password = "Hello, I must be going";

KeyStore keyStore = [Link]("jks");


FileInputStream fis = new FileInputStream(
keyStoreLocation + [Link] + keyStoreFile);
[Link](fis, [Link]());

Enumeration aliases = [Link]();


while ([Link]()) {
[Link]([Link]());
}
}
catch (KeyStoreException e) {
[Link](e);
}
catch (IOException e) {
[Link](e);
}
catch (NoSuchAlgorithmException e) {
[Link](e);
}
catch (CertificateException e) {
[Link](e);
}
}
}

Try It:
Change [Link] to use your keystore file and password. Compile and run it to see all of the
aliases associated with your keystore/password combination.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 209


Advanced Java Programming

Security Policies for Signed Code

” You can specify security policies for your VM that are applied according to the
signer of the JAR containing programs you run.

” In policytool, use Change Keystore under the Edit menu to specify the path to
your keystore file.

¾ To add policy entries for JAR signers, enter their aliases (as listed in your
keystore) in the Signed By field.

Page 210 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 10 Keys, Signatures, and Certificates

Hands On:

Use appletviewer to run the WriteFile applet from your signed JAR: appletviewer [Link].
Try writing a file. You should get a security exception, because, by default, the applet does not have the
appropriate FilePermission.

To fix this you will need to set up the keystore first. Start policytool, select EditÆChange KeyStore and
enter the location of your .keystore file and jks for the type. Use [Link] and Settings/
student/.keystore for the keystore URL on Windows.(Use your login, rather than "student.")

Now, grant write permission to all files in the working directory for this chapter, to code signed by you (that
is, use the alias you used earlier to sign your JAR in the SignedBy field in the policy entry). For the Target
Name, list the chapter directory, followed by an *.

After saving your policy file, run appletviewer again and try writing a file.
© 2011 ITCourseware, LLC Rev 5.1.4 Page 211
Advanced Java Programming

Java Cryptography Architecture

” The Java Cryptography Architecture (JCA) defines the structure of


cryptographic APIs in Java.

¾ The parts of the [Link] package, and its sub packages, that deal
with key management, certificates, digital signatures, message digests, and
ciphers are part of the JCA.

¾ The [Link] package includes other classes that deal with policies,
authentication and authorization.

” The JCA specifies a provider architecture, where different providers can


implement part or all of the API.

¾ You can have multiple providers installed, and select which you want to
use at runtime.

” The JCA was first released with JDK 1.1, when it included support for digital
signatures and message digests.

” A Java Cryptography Extension (JCE) implements the JCA, providing classes


for key generation, data encryption, key exchange and message authentication
codes.

¾ The SunJCE is now bundled with the JDK, but older versions required a
separate download.

¾ You can buy third-party JCA implementations from other vendors.

Page 212 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 10 Keys, Signatures, and Certificates

© 2011 ITCourseware, LLC Rev 5.1.4 Page 213


Advanced Java Programming

Labs

Extract the META-INF/ directory from the signed .jar file you created in this chapter, and
examine the contents.
(Solution: [Link])

† Create another keypair, giving it a unique alias, using keytool. List the contents of your keystore.
(Solution: [Link])

‡ Sign the same .jar file you signed earlier, but this time use your new keypair. Afterwards,
extract the META-INF/ directory again. What files are there? Compare the contents of the
signature (.SF) files.
(Solution: [Link])

ˆ Using the -keystore keystorefile option to keytool, create a new keypair in a temporary keystore
file in the current directory. List the contents of the new keystore. Now use keytool's -export
option to export the public key from your new keypair — be sure to use the -file option as well, or
the key will be exported in binary form to your terminal screen.

Now, import the key you just exported, into your default keystore. List the contents of your default
keystore.

‰ Write a program to iterate through the aliases in your keystore, displaying whether each is a private
key entry or a certificate entry. If it is a key, display the private key. Display the beginning and
ending validity period dates for each entry.
(Solution: [Link])

Page 214 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 10 Keys, Signatures, and Certificates

© 2011 ITCourseware, LLC Rev 5.1.4 Page 215


Advanced Java Programming

Page 216 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 11 Encryption with the [Link] Package

Chapter 11 - Encryption with the [Link]


Package

Objectives
” Encrypt data using the [Link]
package.

” Understand encryption algorithms.

” Describe the methods in the Cipher class.

” Encrypt input and output streams.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 217


Advanced Java Programming

Cryptography Concepts

” Cryptography is generally concerned with keeping communication private.

” Cryptography is based on the use of a key to encrypt and decrypt sensitive data.

” There are two kinds of cryptography systems:

¾ Symmetric cryptography uses the same secret key to encrypt and decrypt.

¾ Asymmetric cryptography uses one key to encrypt the data and a second
key for decryption.

” The Cipher class provides methods to encrypt and decrypt arrays or streams.

” You need to provide three values when creating an instance of the Cipher class:

1. The algorithm used to actually perform the encryption and decryption.

2. The mode, to further alter the encryption in order to make it harder to


break.

3. Since encryption is generally done in blocks, padding is also required to


ensure block length.

Page 218 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 11 Encryption with the [Link] Package

The Java Cryptography Extension (JCE) is bundled with the JDK platform, adding support for ciphers,
key agreement, and authentication codes. JCE 1.2 comes standard with the provider SunJCE, which
supplies many services, including various encryption algorithms, a padding scheme, and key generator
implementations.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 219


Advanced Java Programming

Encryption Keys

” An encryption key is a secret value used to encrypt and decrypt messages.

” The algorithm in use and secrecy of the private key determine the effectiveness
of the key encryption.

¾ Keys can be stored in a keystore database, a file-based repository for


keys.

” There are two forms of keys used for encryption.

¾ Secret (Symmetric) keys are used to both encrypt and decrypt.

ƒ The [Link] class provides the functionality


to create secret keys.

¾ Public/Private (Asymmetric) keys encrypt with one key and decrypt with
the other.

ƒ The [Link] class generates public/


private key pairs.

Page 220 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 11 Encryption with the [Link] Package

[Link] uses a KeyGenerator to create a secret key object and store it in a file.

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
Use the DES algorithm to
import [Link]; generate the key.

public class KeyFileGen {


public static void main(String[] args) {
try {
KeyGenerator kg = [Link]("DES"); Pass a random
[Link](new SecureRandom()); number generator into
the init() method.
SecretKey key = [Link]();

ObjectOutputStream oos = new ObjectOutputStream(


new FileOutputStream("[Link]"));
[Link](key);
[Link]();
}
catch (Exception e) {
[Link]([Link]());
}
}
}

Try It:
Compile and run [Link] to use a KeyGenerator to create a file containing a secret key. This
file will be used by other applications in this chapter.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 221


Advanced Java Programming

Cipher Algorithms

” There are a variety of algorithms that can be used to encrypt and decrypt data.

” The SunJCE provides several algorithms you can use when creating your
Cipher class.

¾ Data Encryption Standard Algorithm (DES) is an asymmetric-key


encryption method developed in 1975 using a 56-bit key.

ƒ You can break this algorithm with enough computing power.

¾ Triple-DES uses a key length of 168-bits (three 56-bit DES keys) for three
rounds of encryption and decryption.

ƒ This algorithm has never been broken, but also requires more time
to perform the encryption and decryption.

¾ PBEWithMD5AndDES utilizes a password to initialize the Cipher object.

ƒ The password can be shared verbally to ensure protection.

¾ Blowfish is a 16-round public domain Feistel cipher.

ƒ A cipher splits the text into two halves and one half is encrypted
during each round using a subkey.

ƒ After each round, an exclusive-or of the two halves is performed


and they are swapped.

ƒ The process is reversed for decryption.

Page 222 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 11 Encryption with the [Link] Package

There are also algorithms that use 256-bit key encryption. This is known as Unlimited Strength
Encryption. The jurisdiction policy files shipped with the JDK allow "strong," but limited
cryptography to be used. This is due to import control restrictions of some countries. To perform Unlimited
Strength Encryption, you must download jurisdiction policy files from Sun which can be found at:
[Link]

© 2011 ITCourseware, LLC Rev 5.1.4 Page 223


Advanced Java Programming

Modes and Padding Schemes

” Modes are provided in addition to the algorithm to further alter the data being
encrypted.

” Modes help to break apart patterns that might be encountered in the original
data.

” Five different modes have been specified in the SunJCE for you to utilize.

¾ Electronic Cookbook Mode (ECB) takes an 8-byte block of data and


encrypts it all at once, then moves on to the next block.

¾ Cipher Block Chaining (CBC) uses the input from one block to encrypt
the next block of data, which helps to hide repeating data that might occur
in your input.

ƒ CBC requires a full 8-byte block to perform encryption.

¾ Cipher-feedback Mode (CFB) is similar to CBC, except it does not


require a full block of data to perform encryption.

¾ Output Feedback Mode (OFB) is used when there is a possibility of data


being corrupted during transmission.

¾ Propagating Cipher Block Chaining Mode (PCBC) is used to talk to a


computer network authentication system called Kerberos.

ƒ PCBC has some holes for attack and should be discouraged.

” Padding is used to fill the entire block size that needs to be encrypted.

¾ PKCS5Padding ensures the data is padded to an 8-byte multiple.

¾ NoPadding requires that the data being encrypted is a multiple of the


block size, or an exception will be generated.
Page 224 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 11 Encryption with the [Link] Package

The number of bits that make up a block can vary with CFB, OFB, and PCBC. Append a number to the
end of the mode name to indicate the number of bits you wish to make up a block. The number must be a
multiple of eight. For example, with CFB8, the block size would be one byte, instead of the default eight
bytes.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 225


Advanced Java Programming

The Cipher Class

” The [Link] class provides methods to create and initialize a


Cipher object that performs the encryption and decryption of data.

” Use the static getInstance() method of the Cipher class to generate Cipher
objects.

¾ getInstance() takes a String as an argument to determine the encryption


algorithm, and may optionally include the mode and padding.

Cipher c1 = [Link]("DES");
Cipher c2 = [Link]("DES/CBC/PKCS5Padding");

” Once you have obtained a Cipher object, the init() method must be called to
determine encryption or decryption, and provide a key.

¾ The key type must match the type of encryption being used.

[Link](Cipher.ENCRYPT_MODE, key);
[Link](Cipher.DECRYPT_MODE, key);

” Some of the algorithms require you to provide an initialization vector (IV) for
decryption.

¾ The initialization vector is available after the data has been encrypted.

byte initVec[] = [Link]();


IVParameterSpec ips=new IVParameterSpec(initVec);
[Link](Cipher.DECRYPT_MODE, key, ips);

Page 226 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 11 Encryption with the [Link] Package

Hands On:
Create a new program called [Link]. In this program, you will create a Cipher object that will
use the DES algorithm with ECB mode and PKCS5Padding. You will use the KeyGenerator class to
create a key to initialize the Cipher.

import [Link].*;
import [Link];

public class CipherDemo {


public static void main(String args[]) {
try {
KeyGenerator keyGen = [Link]("DES");
Key theKey = [Link]();
Cipher c = [Link]("DES/ECB/PKCS5Padding");
[Link](Cipher.ENCRYPT_MODE, theKey);
}
catch (Exception e) {
[Link]("Error : " + [Link]());
}
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 227


Advanced Java Programming

Encrypting and Decrypting Data

” The Cipher class has several overloaded methods that you can use to encrypt or
decrypt data.

¾ Encrypting or decrypting depends on whether you initialized the Cipher


with ENCRYPT_MODE or DECRYPT_MODE.

” Call the update() method to encrypt or decrypt an array of bytes.

public final byte[] update(byte[] in)


public final byte[] update(byte[] in, int offset,
int length)
public final int update(byte[] in, int offset,
int length, byte[] out)
public final int update(byte[] in, int offset,
int length, byte[] out, int outOffset)

¾ If the number of bytes passed to update() does not fill an entire block,
then the odd bytes are held in an internal buffer.

¾ The modified data is returned in a new array or placed in a given output


array.

¾ An offset and length can also be provided to limit the extent of the data
being modified.

” The doFinal() method is the last method you call for an encryption or
decryption.

¾ Any odd bytes left in the buffer are either padded, if PKCS5Padding is
used, or an IllegalBlockSizeException is thrown.

Page 228 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 11 Encryption with the [Link] Package

Hands On :
Now call the update() and doFinal() methods to encrypt and then decrypt a String.

import [Link].*;
import [Link];

public class CipherDemo {


public static void main(String args[]) {
try {
KeyGenerator keyGen = [Link]("DES");
Key theKey = [Link]();
Cipher c = [Link]("DES/ECB/PKCS5Padding");
[Link](Cipher.ENCRYPT_MODE, theKey);

String str1 = "Gilligans first name was Willie.";


String str2 = "The Professor was originally a reporter.";

byte[] encBytes1 = [Link]([Link]());


byte[] encBytes2 = [Link]([Link]());

String encStr1 = new String(encBytes1);


String encStr2 = new String(encBytes2);

[Link]("Encrypted String 1 : " + encStr1);


[Link]("Encrypted String 2 : " + encStr2);

[Link](Cipher.DECRYPT_MODE, theKey);

String decStr1 = new String([Link](encBytes1));


String decStr2 = new String([Link](encBytes2));

[Link]("String 1 : " + decStr1);


[Link]("String 2 : " + decStr2);
}
catch (Exception e) {
[Link]("Error : " + [Link]());
}
}
}

Try It:
Compile and run [Link]. Why do the decrypted Strings look different from the original
Strings?

© 2011 ITCourseware, LLC Rev 5.1.4 Page 229


Advanced Java Programming

Cipher Output Streams

” The [Link] class uses a Cipher object to encrypt


or decrypt an output stream.

” To create a CipherOutputStream you need an existing OutputStream and a


Cipher object.

public CipherOutputStream(OutputStream os, Cipher c);

¾ As the data passes through the CipherOutputStream, it is modified


using the indicated Cipher object.

¾ The Cipher will encrypt or decrypt, depending on how the Cipher was
initialized.

” Often you will use this class in conjunction with other stream classes as a filter
for encryption/decryption.

FileOutputStream fos = new FileOutputStream(filename);


CipherOutputStream cos = new CipherOutputStream(fos, c);
PrintWriter pw = new PrintWriter(cos);

” Any padding is performed when the flush() method is invoked before the
closing of the stream.

Page 230 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 11 Encryption with the [Link] Package

[Link]
import [Link].*;
import [Link];
import [Link];
import [Link];

public class EncryptOutputStream {


public static void main(String args[]) {
try {
String s;
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("[Link]")); Read key
Key theKey = (Key) [Link](); from file.
[Link]();

BufferedReader br = new BufferedReader(


new FileReader("[Link]"));
Cipher c = [Link]("DES/ECB/PKCS5Padding");
[Link](Cipher.ENCRYPT_MODE, theKey);

FileOutputStream fos = new FileOutputStream("[Link]");


CipherOutputStream cos = new CipherOutputStream(fos, c);
PrintWriter pw = new PrintWriter(cos);
Add CipherOutputStream
while((s = [Link]()) != null) { to the OutputStream to
[Link](s); encrypt data passing through
} the stream.
[Link]();
[Link]();
}
catch (Exception e) {
[Link]("Error : " + [Link]());
}
}
}

Try It:
Run [Link] to encrypt [Link] and place the encrypted data in [Link].

© 2011 ITCourseware, LLC Rev 5.1.4 Page 231


Advanced Java Programming

Cipher Input Stream

” You use the [Link] class to modify an input stream


using a Cipher object.

” Similar to the CipherOutputStream, you need an existing InputStream and


Cipher objects.

public CipherInputStream(InputStream is, Cipher c);

” The CipherInputStream will perform encryption or decryption, depending on


how the Cipher was initialized.

” Again, you will generally use this class in conjunction with other stream classes
as a filter for encryption/decryption of the input stream.

FileInputStream fis = new FileInputStream(filename);


CipherInputStream cis = new CipherInputStream(fis, c);
BufferedReader br = new BufferedReader(cis);

Page 232 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 11 Encryption with the [Link] Package

[Link]
import [Link].*;
import [Link];
import [Link].*;

public class DecryptInputStream {


public static void main(String args[]) {
try {
String s;
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("[Link]"));
Read key from file.
Key theKey = (Key) [Link]();
[Link]();

Cipher c = [Link]("DES/ECB/PKCS5Padding");
[Link](Cipher.DECRYPT_MODE, theKey);

FileInputStream fis = new FileInputStream("[Link]");


CipherInputStream cis = new CipherInputStream(fis, c);
BufferedReader br = new BufferedReader(
new InputStreamReader(cis));

while((s = [Link]()) != null) { Add CiperInputStream


[Link](s); to the BufferedReader to
} decrypt the stream.
[Link]();
}
catch (Exception e) {
[Link]("Error : " + [Link]());
}
}
}

Try It:
Compile and run [Link] to decrypt and view the contents of [Link].

© 2011 ITCourseware, LLC Rev 5.1.4 Page 233


Advanced Java Programming

Encryption Using Password Ciphers

” Password-based Ciphers requires you to provide a password for encryption and


decryption.

¾ PBEWithMD5AndDES is a password-based algorithm that is part of the


SunJCE.

” This allows the password to be shared verbally between the encryption side and
the decryption side.

¾ The password is placed in a [Link] object,


which is passed to a [Link] to generate a key.

” Password-based Ciphers need to be initialized with a random array of bytes


(the salt) and an iteration count.

¾ The salt and iteration work with the password to create a more secure
encryption.

¾ The more random the bytes and the higher the iteration count, the more
secure the encryption.

¾ Use a PBEParameterSpec object to hold the salt and iteration values for
the cipher initialization.

Page 234 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 11 Encryption with the [Link] Package

[Link]
...
Prompt for password
public class PasswordEncrypt {
to encrypt data.
public static void main(String args[]) {
try {
BufferedReader br = new BufferedReader(
new InputStreamReader([Link]));
[Link]("Enter Password for Encryption: ");
String password = [Link]();

byte[] salt = {(byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe,


(byte)0x32, (byte)0x9a, (byte)0xfa, (byte)0x71 };

PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 10);

PBEKeySpec keySpec = new PBEKeySpec([Link]());


SecretKeyFactory skf = Provide salt and iteration
[Link]("PBEWithMD5AndDES"); for cipher initialization.
SecretKey theKey = [Link](keySpec);

Cipher c = [Link]("PBEWithMD5AndDES"); Generate key using password


[Link](Cipher.ENCRYPT_MODE, theKey, paramSpec); stored in PBEKeySpec.

FileOutputStream fos = new FileOutputStream("[Link]");


CipherOutputStream cos = new CipherOutputStream(fos, c);
PrintWriter pw = new PrintWriter(cos);

[Link]("Enter data for encrypted file.");


[Link]("Type EOF on line to end.");
String s;
while(!(s = [Link]()).equals("EOF"))
[Link](s);

[Link]();
[Link]();
}
catch (Exception e) {
[Link]("Error : " + [Link]());
}
}
}

Try It:
Compile and run [Link]. Open [Link] in a text editor to see the results.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 235


Advanced Java Programming

Exchanging Encrypted Keys

” When a key needs to be exchanged between two parties, it should be encrypted


and then decrypted across the stream.

” The Cipher class provides special methods to encrypt and decrypt Key objects.

¾ The Cipher needs to be initialized with Cipher.WRAP_MODE to


perform key wrapping and Cipher.UNWRAP_MODE to unwrap.

¾ The wrap() method takes the Key object and returns the key encrypted as
a byte array.

public final byte[] wrap(Key key)

¾ The unwrap() method takes the encrypted byte array, the algorithm used
to generate the original key, and the key type, and returns a Key object.

public final Key unwrap(byte[] enckey, String alg, int type)

Page 236 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 11 Encryption with the [Link] Package

[Link]
...
public class Producer {
...
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("[Link]"));
Key key = (Key) [Link]();
[Link]();

KeyGenerator kg = [Link]("DES");
SecretKey sk = [Link]();

Cipher c = [Link]("DES/ECB/NoPadding");
[Link](Cipher.WRAP_MODE, key);
Encrypt key into a byte array.
byte[] wrappedKey = [Link](sk);
DataOutputStream dos = new DataOutputStream (
new FileOutputStream("[Link]"));
[Link](wrappedKey, 0, [Link]);
[Link]();
...
}

[Link]
...
public class Consumer {
...
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("[Link]"));
Key key = (Key) [Link]();
[Link]();

DataInputStream dis = new DataInputStream(


new FileInputStream("[Link]"));
byte[] encodedKey = new byte[[Link]()]; Use unwrap() to decrypt and
create the key object.
[Link](encodedKey, 0, [Link]());

Cipher c = [Link]("DES/ECB/NoPadding");
[Link](Cipher.UNWRAP_MODE, key);

Key k = [Link](encodedKey, "DES", Cipher.SECRET_KEY);


...
}

Try It:
Compile both [Link] and [Link]. Run [Link] to create a new key and use it to
encrypt a file. Run [Link] to read the new key and decrypt the file.
© 2011 ITCourseware, LLC Rev 5.1.4 Page 237
Advanced Java Programming

Sealed Objects

” [Link] enables you to create a Serializable object and


protect its confidentiality with a Cipher encryption.

¾ The SealedObject's constructor takes a Serializable object and a Cipher


object, and wraps the Serializable object inside the SealedObject.

public SealedObject(Serializable obj, Cipher c)

¾ The Cipher object must be initialized with Cipher.ENCRYPT_MODE


and the appropriate key.

” The encrypted content can later be decrypted (with the corresponding algorithm
using the correct decryption key) and deserialized, yielding the original object.

¾ Use the getObject() method with a Cipher to deserialize and decrypt the
encapsulated object.

public Object getObject(Cipher c)

¾ The Cipher object must be initialized with Cipher.DECRYPT_MODE


and the appropriate key.

Page 238 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 11 Encryption with the [Link] Package

[Link]
...
class StudentGrade implements Serializable {
private String studentName;
private float studentGPA;

public StudentGrade(String n, float gpa) {


studentName = n;
studentGPA = gpa;
}
public String toString() {
return studentName + " : " + studentGPA;
}
}

public class SealedDemo {


public static void main(String args[]) {
try {
StudentGrade sg = new StudentGrade("Tommy Tucker", 3.5F);
KeyGenerator kg = [Link]("DES");
SecretKey key = [Link]();

Cipher c = [Link]("DES/ECB/PKCS5Padding");
[Link](Cipher.ENCRYPT_MODE, key);
SealedObject so = new SealedObject(sg, c);

ObjectOutputStream oos = new ObjectOutputStream(


new FileOutputStream("[Link]"));
[Link](so);
[Link]();

ObjectInputStream ois = new ObjectInputStream(


new FileInputStream("[Link]"));
so = (SealedObject) [Link]();
[Link]();

[Link](Cipher.DECRYPT_MODE, key);
StudentGrade grade = (StudentGrade) [Link](c);
[Link](grade);
}
...
}
}

Try It:
Compile and run [Link] and open [Link] in a text editor. Notice that all of the data in
the object is not visible.
© 2011 ITCourseware, LLC Rev 5.1.4 Page 239
Advanced Java Programming

Labs

Write a program that reads text from the standard input (keyboard) and saves the text in
encrypted format in a file. The key used to encrypt the file needs to be saved in a second file.
(Solution: [Link])

† Write a program that reads and decrypts the file written in the previous exercise.
(Solution: [Link])

‡ Create a program to decrypt the file that was created by the [Link]
program.
(Solution: [Link])

ˆ Create a program that can store and list username/password combinations for websites that
a user may register for. To add an entry, prompt the user for the website name, the username,
and the password. Encrypt the data using a password to prevent unauthorized access.
(Solution: [Link])

Page 240 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 11 Encryption with the [Link] Package

© 2011 ITCourseware, LLC Rev 5.1.4 Page 241


Advanced Java Programming

Page 242 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 12 Java Authentication and Authorization Service

Chapter 12 - Java Authentication and


Authorization Service (JAAS)

Objectives
” Authenticate a user with JAAS.

” Use Callbacks to get information from


the user.

” Define permissions within policy files and


with the Policy class.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 243


Advanced Java Programming

Authentication and Authorization

” Authentication and authorization deal with protecting an application from a user.

” Authentication is the process of identifying a user and verifying they are who
they say they are.

¾ This is usually accomplished with a user name and password.

¾ You could also authenticate a user with a certificate, ID card, fingerprint,


retinal scan, DNA sample, etc.

ƒ Some of those alternate authentication mechanisms sound like


overkill for most applications, but as technology moves ahead they
are becoming more accessible.

” Once the user is authenticated, authorization specifies what they can do within
the system.

¾ This is usually achieved through access control lists, or ACLs.

” In Java, you authorize code to access resources through policy files, and you
authorize users the same way.

Page 244 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 12 Java Authentication and Authorization Service

© 2011 ITCourseware, LLC Rev 5.1.4 Page 245


Advanced Java Programming

JAAS Overview

” The Java Authentication and Authorization Service (JAAS) is an API for


authenticating users and authorizing them to access resources through a Java
application.

¾ Prior to Java 1.4, JAAS was a separate download, but it is now packaged
with the JDK.

¾ JAAS is a different mechanism than the one used in J2EE app servers.

” To implement JAAS, you must write some program code, as well as set up a
policy file and a login configuration file.

¾ The login configuration file is generally created by an administrator, and


contains environment-specific information.

ƒ This keeps Java source code generic and portable.

” JAAS provides classes that authenticate a user.

¾ These classes are defined in the [Link] package and its sub
packages.

¾ Some of the classes are extended by service providers and exist in other
packages.

” JAAS extends the policy file to authorize users to perform specific operations.

¾ Prior to version 1.4, a separate policy file was required for JAAS to
support the additional syntax.

¾ Since version 1.4, you can include JAAS authorizations in traditional


policy files.

¾ policytool has been updated to work with the new syntax.


Page 246 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 12 Java Authentication and Authorization Service

© 2011 ITCourseware, LLC Rev 5.1.4 Page 247


Advanced Java Programming

LoginContext

” Use a [Link] to authenticate a user and


retrieve information about the user.

” When you create a LoginContext object, you must specify a configuration


entry from a configuration file to the constructor.

¾ The configuration entry specifies the authentication method and whether


that authentication is required.

ƒ A single configuration entry may include multiple authentication


methods.

ƒ Each authentication method may result in one or more Principals.

¾ You may optionally include a CallbackHandler, which the


LoginContext can call to get information about the user.

ƒ Certain types of authentication, such as Solaris or Windows login


authentication, do not require a CallbackHandler, because the user
has already logged in.

¾ You also may include a Subject, which represents an authenticated user.

ƒ A Subject may include multiple Principals, each of which contains


some identification of a user.

” Once you have the LoginContext, call the login() method to authenticate the
current user.

¾ A LoginException is thrown if the login fails.

” To authorize a user, get the Subject from the LoginContext by calling


getSubject().

” When the user is done, call logout() to reset the Subject.


Page 248 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 12 Java Authentication and Authorization Service

[Link]
import [Link];
import [Link];
import [Link];

public class ShowSalaries {


public static void main(String[] args) {
LoginContext lc = null;

try {
lc = new LoginContext("Salaries");
[Link]();
Subject subject = [Link]();
...
}
[Link]();
}
catch (Exception e) {
[Link]();
}
}
}

[Link]
...
Salaries {
[Link] required;
};
...

The control flag in the login configuration file can have a value of required, sufficient, requisite, or
optional. The most common value is required, which means that the security module must be executed and
passed. It is possible to list multiple authentication modules for a configuration entry, and that is when the
other three options come into play.

When there are multiple security modules, they are executed in order from top to bottom.

If the control flag is optional, the user may fail that module, but must pass at least one other module in the
configuration entry.

If the control flag is sufficient, no more modules will be executed, unless they are required.

If the control flag is requisite, remaining modules will be executed, but unless they are required they can
be failed.
© 2011 ITCourseware, LLC Rev 5.1.4 Page 249
Advanced Java Programming

Subjects, Principals, and PrivilegedActions

” In JAAS, a [Link] represents all of the identities of a user.

¾ It includes a set of [Link] objects, one for each user


identity as authenticated from the login configuration.

” You can retrieve the Set of Principals from the Subject with the
getPrincipals() method.

¾ From the Principal you can call getName() to find out who the user is.

¾ You can also get the Subject's public and private credentials.

” Once you retrieve the Subject from the LoginContext, use it to run privileged
code.

¾ Call the static [Link]() method, passing the Subject object and a
PrivilegedAction.

” [Link] is an interface that declares a run() method:

public Object run();

¾ Define the code you want an authorized user to execute in this method.

¾ The run() method executes code that uses some resources that are
protected by Permissions.

¾ The SecurityManager will check to see that the appropriate Permissions


for that resource and the current Subject are defined in the current
policies.

ƒ If not, a SecurityException is thrown.

Page 250 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 12 Java Authentication and Authorization Service

[Link]
...
public class ShowSalaries {
public static void main(String[] args) {
...
Subject subject = [Link]();
Object o = [Link](subject, new SalariesAction());
...
}
}

[Link]
...
public class SalariesAction implements PrivilegedAction {
private static NumberFormat nf = [Link]();

public Object run() {


BufferedReader in = null;
double totalSalary = 0.0;
try {
in = new BufferedReader(new FileReader("[Link]"));
String line = null;
while ((line = [Link]()) != null) {
StringTokenizer t = new StringTokenizer(line, "|");
if ([Link]() >= 3) {
[Link]("Name: " + [Link]());
[Link](" Position: " + [Link]());
double salary = [Link]([Link]());
[Link](" Salary: " + [Link](salary));
totalSalary += salary;
}
}
}
...
return new Double(totalSalary);
}
}

Hands On:
Compile [Link] and [Link]. Because these classes require different permissions,
we need to put them in different codebases. We could either do that by putting them in different directories,
or by putting them in different JARs. There is a manifest file in the chapter directory that specifies the main
class and class path for the ShowSalaries application, so let's create JARs. First create the application
JAR: jar cvfm [Link] [Link] [Link]. Then create the library JAR: jar cvf [Link]
[Link].

© 2011 ITCourseware, LLC Rev 5.1.4 Page 251


Advanced Java Programming

Authentication with the NTLoginModule

” JAAS uses pluggable modules to authenticate a user.

¾ The JDK comes with four: NTLoginModule, KeyStoreLoginModule,


Krb5LoginModule, and JNDILoginModule.

ƒ Krb5LoginModule uses Kerberos protocols for authentication.

¾ You can also get third-party login modules or write your own.

” The NTLoginModule allows your Java program to take advantage of the user's
Windows identity, so they do not have to login separately to your application.

” Specify the [Link] class and


control flag in your login config file:

NTJAAS {
[Link] required
}

” When you create your LoginContext, you do not have to specify a Callback,
because the user has already logged in.

” When you retrieve the Subject, you can see the various identities of the user by
iterating through the Set of Principals.

¾ The NTUserPrincipal contains the user name.

¾ The NTDomainPrincipal contains the domain name, the workgroup


name, or the machine name, depending on what the user logged in to.

¾ NTSidUserPrincipal, NTSidDomainPrincipal,
NTSidGroupPrincipal, and NTSidPrimaryGroupPrincipal contain
the Windows security identifier of the user ID, domain, groups, and
primary group, respectively.
Page 252 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 12 Java Authentication and Authorization Service

[Link]
import [Link];
import [Link];
import [Link];
import [Link];

public class NTJAAS {


public static void main(String[] args) {
LoginContext context = null;
Subject subject = null;

try {
context = new LoginContext("NTJAAS");
[Link]();
subject = [Link]();
Set<Principal> principals = [Link]();
for (Principal p : principals) {
[Link]("Principal type: " +
[Link]().getName() + " name: " + [Link]());
}
}
catch (Exception e) {
[Link]();
}
}
}

[Link]
NTJAAS {
[Link] required;
};
...

[Link]
grant codeBase "[Link] {
permission [Link];
}

Try It:
If you are on a Windows system, this program will show you the user identities. Compile [Link].
When you run it, you need to install a SecurityManager, and specify a policy file and login configuration
file:
java -[Link] -[Link]=[Link]
-[Link]=[Link] NTJAAS

Make a note of your NTUserPrincipal name — you will use it later.


© 2011 ITCourseware, LLC Rev 5.1.4 Page 253
Advanced Java Programming

Defining Permissions in Policy Files

” JAAS authorization is based on the same permissions, defined in the same


policy files, that are used in code access security.

¾ Users are authorized to access secured resources, such as files or


sockets, not sections of code.

” A JAAS program is divided in (at least) two parts: the main code and the
privileged action.

¾ Each part has different permission requirements, so your policy file will
need (at least) two codeBase entries.

” The main code requires AuthPermission "createLoginContext.<lcName>",


AuthPermission "doAs", and whatever permissions the privileged action
requires.

¾ Often, the main code is granted AllPermission to simplify things.

” The privileged action requires permission for whatever secured resource the
user needs to access.

¾ The privileged action policy also specifies the principal type and name of
who can access the resource.

grant codeBase "[Link]


principal [Link]
"student" {
permission [Link] "[Link]", "read";
};

Page 254 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 12 Java Authentication and Authorization Service

Hands On:
Start policytool. If you have a .[Link] in your user directory, that will automatically be loaded. Select
FileÆNew. Select the Add Policy Entry button. For the CodeBase, enter [Link]
[Link].
Select the Add Permission button. In the Permission dropdown list, select AuthPermission. For the
Target, select doAs. Press OK.
Select Add Permission again. For the Permission select AuthPermission. For the Target, select
createLoginContext.<name>. In the text box to the right, replace <name> with Salaries. Press OK.

Select Add Permission a third time. For the Permission select FilePermission. For the Target, enter
[Link]. For the Action, select read. Press OK. Press Done to complete this policy entry.

Select Add Policy Entry. For the CodeBase, enter [Link]


Select the Add Principal button. For Principal Type, select NTUserPrincipal. For the Principal Name,
enter your user name from the NTJAAS example. Press OK.
Select Add Permission. For the Permission select FilePermission. For the Target, enter [Link].
For the Action, select read. Press OK. Press Done.

Select the FileÆSave As menu option, and save this as [Link] in your current chapter
directory.

Note: The CodeBase URLs require an absolute path for a .jar file. If your current chapter directory is
something else, adjust the CodeBase appropriately.

Try It:
You can now run the ShowSalaries program:

java -[Link] -[Link]=[Link]


-[Link]=[Link] -jar [Link]

© 2011 ITCourseware, LLC Rev 5.1.4 Page 255


Advanced Java Programming

KeyStoreLoginModule

” [Link] allows you to


authenticate users with certificates from a keystore.

¾ By default, it uses the .keystore file in the user directory and the default
keystore protocol, but you can specify others in the login config file.

” KeyStoreLoginModule allows several options in the login config file entry:

[Link] required
option=value, option2=value2...;

¾ Possible options include:

ƒ keyStoreURL: the location of the keystore.

ƒ keyStoreType: the keystore type.

ƒ keyStoreProvider: the keystore provider.

ƒ keyStoreAlias: the alias for the certificate to log in as; if not


provided, a callback is sent to the application.

ƒ keyStorePasswordURL: the location of the password for the


keystore; if not provided, a callback is sent to the application.

ƒ privateKeyPasswordURL: the location of the password for the


key; if not provided, a callback is sent to the application; if not
provided there, it defaults to the keystore password.

ƒ protected: set to true if the keystore uses a separate authentication


path.

Page 256 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 12 Java Authentication and Authorization Service

[Link]
...
CallbackSample {
[Link] required;
};

Hands On:
The example program that we're going to run in a couple of pages requires a certificate in your keystore. If
you have already created one, you need to find out the X.500 distinguished name, which includes the user's
name, organization, city, state, and country. To find the distinguished name, edit the [Link]
program in this chapter directory, replacing the alias, keystore file location, and keystore password
with your values. Then compile and run the program, making a note of the Certificate subject string.

If you do not have a keystore or a certificate, run keytool -genkey -alias yourname. Enter the requested
information, then compile and run [Link] as discussed above.

Now, run policytool. Select FileÆNew. Select the Add Policy Entry button. For the CodeBase, enter
[Link]
Select the Add Permission button. In the Permission dropdown list, select AllPermission. Press OK.
Press Done to complete this policy entry.

Select Add Policy Entry. For the CodeBase, enter [Link]


Select the Add Principal button. For Principal Type, select X500Principal. For the Principal Name, enter
the Certificate subject string from the ShowCert program. Press OK.
Select Add Permission. For the Permission select FilePermission. For the Target, enter [Link].
For the Action, select read. Press OK. Press Done.

Select the FileÆSave As menu option, and save this as [Link] in your current chapter
directory.

Note: The CodeBase URLs require an absolute path for a .jar file. If your current chapter directory is
something else, adjust the CodeBase appropriately.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 257


Advanced Java Programming

Callbacks

” Callbacks are the mechanism that the LoginModule uses to get information
about the user from the application.

¾ They can also provide information from the LoginModule to the user.

¾ NTLoginModule and UnixLoginModule don't use Callbacks, because


the user is logged in through the system.

” When you call login() on the LoginContext, the LoginContext calls login() on
the LoginModule specified in the login configuration file.

¾ The LoginModule's login() method creates an array of Callback objects,


one for each piece of information the module requires to authenticate a
user.

ƒ For example, the LoginModule may create two Callbacks, one to


retrieve the user name and one to retrieve the user password.

¾ The LoginModule then calls the CallbackHandler's handle() method,


passing the Callback array.

” A CallbackHandler is an object that handles Callbacks.

¾ Define a class that implements


[Link], instantiate it, and pass it
to the LoginContext constructor.

¾ Your class needs to define a single method, handle(), which is passed an


array of Callback objects.

public void handle(Callback[] callbacks)

¾ Within the method, iterate through the Callback[], prompting the user for
the requested information.
Page 258 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 12 Java Authentication and Authorization Service

Application

main() Callback Handler


prompt for name
prompt for password
user
handle(callbacks)

JAAS
login()

login()
LoginContext LoginModule

new new

NameCallback PasswordCallback

© 2011 ITCourseware, LLC Rev 5.1.4 Page 259


Advanced Java Programming

NameCallback and PasswordCallback

” There are many types of callbacks, and they all implement the Callback
interface.

¾ Each one is used to retrieve or display a specific type of information to


the user.

¾ If your CallbackHandler does not handle a specific type of Callback,


throw an UnsupportedCallback exception.

” NameCallback is used to get the username from the application.

¾ Your CallbackHandler should display the return value from the


getPrompt() method to prompt the user for their name.

¾ After the user enters their name, call setName() to add it to the
NameCallback object.

¾ The LoginModule will call getName() to retrieve the name to be


authenticated.

” PasswordCallback is used to get the user's password.

¾ As with the NameCallback, your handler should display the return value
from the getPrompt() method.

¾ The PasswordCallback also has an isEchoOn() method, telling you


whether you should echo the password to the user as they type it.

¾ After the user enters their password, add it to the PasswordCallback


with the setPassword() method.

¾ The LoginModule will call getPassword() to retrieve the password.

Page 260 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 12 Java Authentication and Authorization Service

[Link]
...
public class LoginHandler implements CallbackHandler {
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException {
for (Callback cb : callbacks) {
if (cb instanceof NameCallback) {
NameCallback ncb = (NameCallback) cb;
[Link]([Link]() + " ");
BufferedReader in = new BufferedReader(
new InputStreamReader([Link]));
String name = [Link]();
[Link](name);
}
else if (cb instanceof PasswordCallback) {
PasswordCallback pcb = (PasswordCallback) cb;
[Link]([Link]() + " ");
BufferedReader in = new BufferedReader(
new InputStreamReader([Link]));
String password = [Link]();
[Link]([Link]()); Handlers for TextOutputCallback
} and ConfirmationCallback used by
... KeyStoreLoginModule.
else {
throw new UnsupportedCallbackException(cb);
}
}
}
}

[Link]
...
lc = new LoginContext("CallbackSample", new LoginHandler());
...

CallbackSample is very similar to ShowSalaries, the only difference being we pass a LoginHandler
to the LoginContext constructor.

Try It:
Compile [Link] and [Link]. This program uses the SalariesAction from a
previous example, so you should already have compiled that and packaged it in a .jar.
Create your application .jar file:
jar cvfm [Link] [Link] [Link] [Link]

Run the program: java -[Link] -[Link]=[Link]


-[Link]=[Link] -jar [Link]
© 2011 ITCourseware, LLC Rev 5.1.4 Page 261
Advanced Java Programming

The Policy Class

” The [Link] class provides an interface into the policies defined in


the policy files.

¾ You can use this class to work with standard policies as well as JAAS
policies.

¾ Prior to Java 1.4, there was a separate [Link] class


for JAAS policies.

ƒ [Link] is deprecated in version 1.4.

” Get the current Policy with the static [Link]() method.

¾ Policy is an abstract class, so you are actually getting an instance of a


subclass.

” Retrieve the permissions from the Policy with the getPermissions() method.

¾ This returns a PermissionCollection, which allows you to add() a new


Permission, iterate through the Permissions, and find out if a Permission
is included with the implies() method.

¾ You will need to pass either a ProtectionDomain or a CodeSource to


the getPermissions() method.

ƒ Create a CodeSource with a URL specifying the codebase, and


either an array of Certificates or CodeSigners.

ƒ Create a ProtectionDomain with a CodeSource and a


PermissionsCollection.

ƒ You can optionally include a ClassLoader and a Principal[].

Page 262 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 12 Java Authentication and Authorization Service

[Link]
...
public class ShowPolicies {
public static void main(String[] args) {
LoginContext lc = null;

try {
lc = new LoginContext("Salaries");
[Link]();
Subject subject = [Link]();
Principal[] principals =
[Link]().toArray(new Principal[0]);

URL url = new URL("[Link]


CodeSource cs = new CodeSource(url, new Certificate[0]);
ProtectionDomain pd = new ProtectionDomain(cs, null,
[Link](), principals);
Policy policy = [Link]();
PermissionCollection pc = [Link](pd);

Enumeration<Permission> e = [Link]();
while ([Link]()) {
Permission p = [Link]();
[Link]("Permission: " + p);
}
[Link]();
}
...
}
}

[Link]
grant codeBase "[Link] {
permission [Link] "doAs";
permission [Link] "[Link]";
permission [Link] "[Link]", "read";
permission [Link] "getPolicy";
};

Try It:
Compile and run [Link] with the [Link] file: java -[Link]
-[Link]=[Link] -[Link]=[Link] ShowPolicies

Try running the program with [Link]: java -[Link]


-[Link]=[Link] -[Link]=[Link] ShowPolicies

© 2011 ITCourseware, LLC Rev 5.1.4 Page 263


Advanced Java Programming

Labs

What is required to convert the [Link] example to use the KeyStoreLoginModule? Go


ahead and do it to see what the X500Principal looks like.
(Solution: [Link], [Link], [Link], [Link])

† In this chapter directory there is a sample login module called EgLoginModule. It uses a
NameCallback and a PasswordCallback to authenticate a user, then adds an EgPrincipal to
the Subject. Write a callback handler to handle the callbacks from EgLoginModule.
(Solution: [Link])

‡ Change the [Link] program from this chapter directory to use your callback
handler from †. Create a login config file for your program that uses [Link].
(Solutions: [Link], [Link])

ˆ Compile your source code from † and ‡, as well as [Link] and


[Link]. Using [Link] as a sample, create a manifest for your .jar file, then
package the four class files you just compiled in a .jar with your manifest.
(Solution: [Link], [Link])

‰ Create a policy file that grants AllPermission to your .jar file from ˆ and
[Link] "[Link]", "read" to [Link]. Because policytool does not know
about EgPrincipal, you will need to edit the policy file manually. The users are defined in the users
file in the chapter directory, which is a standard Java properties file.
(Solution: [Link])

Š Run your program, entering the appropriate user name and password from the users file.
(Solution: [Link])

Page 264 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 12 Java Authentication and Authorization Service

© 2011 ITCourseware, LLC Rev 5.1.4 Page 265


Advanced Java Programming

Page 266 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 13 Java Naming and Directory Interface (JNDI)

Chapter 13 - Java Naming and Directory


Interface (JNDI)

Objectives

” Describe the purpose of a naming and


directory service, and list several examples.

” Use a service provider to connect to a naming


service.

” Look up objects using JNDI.

” Manipulate name-to-object bindings.

” Search a directory service.

” Use JNDI to integrate Java applications with


naming and directory services.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 267


Advanced Java Programming

Naming and Directory Services

” A naming service associates names with objects.

¾ Directly, as a name bound to an actual remote Java object in RMI.

¾ Indirectly, as a hostname bound to a remote host's IP address.

” A directory is a naming system that allows objects to have attributes.

¾ Attributes describe the object bound to a name.

” There are many systems providing naming and directory services:

¾ LDAP: A subset of X.500; general-purpose directory service.

¾ NIS: Centralized directory of usernames and other information.

¾ RMI Registry: Binding of names to Java objects.

¾ File Systems: Hierarchical mapping of filenames to file contents.

¾ DNS: Distributed, hierarchical database of hostname-to-IP-address


mappings.

¾ Windows Registry: Application and system settings.

¾ CORBA Naming Service: Centralized repository of name-to-object


mappings for objects written in various languages.

” JNDI uses service providers which interface with these and other systems.

Page 268 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 13 Java Naming and Directory Interface (JNDI)

The JDK version 5.0 ships with:

ƒ LDAP service provider


ƒ CORBA Naming Service
ƒ RMI registry service provider
ƒ DNS service provider

In some of the examples in this chapter we will use JNDI to access the RMI Registry. For most basic
RMI applications, you would probably use the [Link] or [Link]
classes instead of JNDI to access a registry. Using JNDI can provide some additional flexibility with regards
to configuration, but more interesting is the ability of a client application to dynamically use a completely
different service, such as an LDAP directory, to locate remote objects. This strategy is especially useful for
generic applications such as frameworks.

Setup:
To run the examples that use RMI in this chapter, you will first need to start the RMI Registry, then run
the server application to create some remote objects. Compile the source files, then execute the following
commands, each in their own window (make sure you run these in the directory with the class files or
otherwise set an appropriate classpath):

rmiregistry

java Server

Note:
The examples for directory services require access to LDAP and DNS services. If your firewall allows
access to such services, then you should be able to access the public services used in the sample code.
There are lists of some public services you can also try in public_ldap_servers.txt and
public_dns_servers.txt, both extracted from internet searches.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 269


Advanced Java Programming

Namespaces and Contexts

” JNDI gives you a common set of tools for dealing with naming and directory
services, including:

¾ Direct lookup by name.

¾ Searching.

¾ Binding a name to an object, within the context of the service you're


using.

” To use a service, you must:

1. Choose a service provider class for the service.

2. Establish an initial context for your application within that service.

” The initial context is your starting point in the service.

¾ Think of your current working directory within a file system.

” To establish the initial context, use the InitialContext constructor.

¾ You can pass it a Hashtable to select the service provider and to provide
other necessary information.

Hashtable<String, String> env = new Hashtable<String, String>();


[Link](Context.INITIAL_CONTEXT_FACTORY,
"[Link]");
[Link](Context.PROVIDER_URL, "rmi:///");
InitialContext ctx = new InitialContext(env);

Page 270 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 13 Java Naming and Directory Interface (JNDI)

The InitialContext constructors will also look at the system properties or applet parameters, if
appropriate, and then at the file [Link] (located anywhere in the classpath) for the properties
needed to define and initialize the context. This provides a convenient, standardized mechanism for
applications to allow the end-user to configure the application to use an arbitrary naming service.

[Link]=[Link]
[Link]=rmi:///

Given the above [Link] file, the client code could create an InitialContext using the no-
argument constructor.

InitialContext ctx = new InitialContext();

© 2011 ITCourseware, LLC Rev 5.1.4 Page 271


Advanced Java Programming

Naming Operations

” To look up an object, use the [Link]() method.

¾ lookup() returns an Object, which you can cast to the type of object you
are looking up.

AccountFactory fact =
(AccountFactory)[Link]("[Link]");

” To list the contents of your context, use [Link]().

¾ list() returns a NamingEnumeration<NameClassPair>, which you can


traverse as you would any enumeration.

¾ Its values are NameClassPair objects.

NamingEnumeration<NameClassPair> objectList = [Link]("");


NameClassPair item = null;
while ([Link]()) {
item = [Link]();
}

ƒ You can use the name in a lookup:

Object o = [Link]([Link]());

” The name passed into these methods can also be a full URL, potentially referring
to a separate context or even a different service provider.

NamingEnumeration<NameClassPair> stoogesOrg =
[Link]("ldap://[Link]/o=stooges");

Page 272 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 13 Java Naming and Directory Interface (JNDI)

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class Lister {


public static void main(String args[]) {
String name = "";
if ([Link] > 0) {
name = args[0];
}

Hashtable<String, String> env = new Hashtable<String, String>();


[Link](Context.INITIAL_CONTEXT_FACTORY,
"[Link]");
[Link](Context.PROVIDER_URL, "rmi:///");
try {
InitialContext ctx = new InitialContext(env);

NamingEnumeration<NameClassPair> list = [Link](name);


while ([Link]()) {
NameClassPair ncp = [Link]();
[Link]([Link]());
}
}
catch (NamingException ne) {
[Link](ne);
}
}
}

Try It:
Run Lister without parameters to list the names bound in the RMI Registry.

Try passing a full URL to [Link] to list a directory service:

java Lister ldap://[Link]

© 2011 ITCourseware, LLC Rev 5.1.4 Page 273


Advanced Java Programming

Bindings

” You can create, replace, delete, or rename a binding using Context methods.

¾ bind() creates a new binding.

[Link]("NewObject", newObject);

¾ rebind() replaces the object bound to a name.

[Link]("NewObject", otherObject);

¾ rename() replaces the name bound to an object.

[Link]("NewObject", "OtherObject");

¾ unbind() removes a binding.

[Link]("OtherObject");

” These methods may throw [Link]


if the service provider does not support creating or modifying bindings.

¾ This exception is also thrown if the type of the object is not supported by
the service provider.

Page 274 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 13 Java Naming and Directory Interface (JNDI)

A binding is the association of a name with an object. Managing name-to-object bindings is the purpose of a
naming system.

The Binding class represents a binding as a String (the name) and an Object (the object). A Binding also
includes the class name of the bound object. A NameClassPair encapsulates a bound name and just the
class name of the bound object without a reference to the object.

For example, when using the RMI context service provider, the name will be an arbitrary name bound to the
object by the server, the class name will be [Link], and the object will be an instance of the
generated stub class which implements the remote interface and is connected to the remote object. Note
that the class name is not particularly useful to an RMI application; you will need to examine the object itself
to determine its class.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 275


Advanced Java Programming

Attributes

” An attribute consists of a name and a list of values.

¾ The name is just a string.

¾ The values can be of any type.

” The Attributes interface provides access to all of an object's attributes.

Attributes attlist = [Link](objname);

” The Attribute interface provides access to attribute values.

Attribute att = [Link](attrname);

” The attribute value list is either ordered or unordered.

¾ For ordered lists, you can retrieve a value by index.

Object val = [Link](index);

¾ For unordered attribute lists, getAll() retrieves an enumeration.

Page 276 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 13 Java Naming and Directory Interface (JNDI)

[Link]
...
public class DirLookup {
public static void main(String args[]) {
...
try {
InitialDirContext ctx = new InitialDirContext(env);

NamingEnumeration<? extends Attribute> attrs =


[Link](name).getAll();
while ([Link]()) {
Attribute attr = [Link]();
[Link](" ").append([Link]());
if ([Link]() > 1) {
[Link](" has ").append([Link]());
if ([Link]()) {
[Link](" ordered");
}
else { getAll() works for
[Link](" unordered"); both ordered and
} unordered lists
[Link](" values:\n");
NamingEnumeration values = [Link]();
while ([Link]()) {
[Link](" ").append([Link]()).append('\n');
}
} get() returns a single value
else {
[Link](": ").append([Link]()).append('\n');
}
}
[Link]([Link]());
}
...
}

Try It:
[Link] by default looks up the command-line argument in the top-level entry in the test LDAP
server at [Link]:

java DirLookup "cn=Larry Fine,ou=MemberGroupA"

You can also query another directory service by passing a URL on the command-line:

java DirLookup "dns://[Link]/[Link]"

© 2011 ITCourseware, LLC Rev 5.1.4 Page 277


Advanced Java Programming

Directory Operations

” JNDI's DirContext interface allows you to look up attributes, perform attribute


searches, and manipulate attribute values.

DirContext ctx = new InitialDirContext(env);

¾ DirContext extends the Context interface.

” Use DirContext to look up attributes associated with a name.

Attributes att = [Link](name);

” You can also search a directory service using attribute names and values.

¾ Search by attribute values using BasicAttributes.

¾ [Link]() returns a NamingEnumeration<SearchResult>.

ƒ SearchResult is a subclass of Binding, adding a method to


retrieve Attributes.

Page 278 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 13 Java Naming and Directory Interface (JNDI)

[Link]
...
public class StoogeSearch {
public static void main(String args[]) {
Hashtable<String, String> env = new Hashtable<String, String>();
[Link](Context.INITIAL_CONTEXT_FACTORY,
"[Link]"); We search for an entry
[Link](Context.PROVIDER_URL, with an attribute named
"ldap://[Link]/o=stooges"); sn with value Howard.
try {
InitialDirContext ctx = new InitialDirContext(env);

BasicAttributes searchParms = new BasicAttributes();


[Link](new BasicAttribute("sn", "Howard"));

NamingEnumeration<SearchResult> results =
[Link]("ou=MemberGroupA", searchParms);
while ([Link]()) { The search will only
search within the
StringBuilder buf = new StringBuilder();
subcontext of
SearchResult aResult = [Link]();
organizational unit
[Link]([Link]()).append('\n'); MemberGroupA.

NamingEnumeration<? extends Attribute> attrs =


[Link]().getAll();
while ([Link]()) {
[Link](" ").append([Link]()).append('\n');
}

[Link]([Link]()); The toString() method


} returns the name and all
values of the attribute.
}
catch (NamingException ne) {
[Link](ne);
}
}
}

Try It:
Compile and run [Link] to see Moe Howard's attribute values.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 279


Advanced Java Programming

DNS Lookups with JNDI

” Use a DirContext for DNS lookups.

Hashtable<String, String> env =


new Hashtable<String, String>();
[Link](Context.INITIAL_CONTEXT_FACTORY,
"[Link]");
[Link](Context.PROVIDER_URL,
"dns://[Link]/");
DirContext ctx = new InitialDirContext(env);

¾ Specify your domain in the provider URL.

¾ You can specify multiple nameservers in the provider URL.

[Link](Context.PROVIDER_URL,
"dns://[Link]/ dns://[Link]/");

¾ DNS Resource Records (RRs) are listed as attributes.

¾ Some commonly-used DNS RR types include:

A — A host's IP address.
MX — The host's mail exchanger(s), with preference values.
CNAME — Canonical name for a host.
SOA — Start-of-authority for a DNS zone.
PTR — Reverse DNS records.

¾ getAttributes() returns all available records by default.

¾ Use a String array to specify other RR types.

Attributes att = [Link](host,


new String[]{"A","MX"});

Page 280 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 13 Java Naming and Directory Interface (JNDI)

© 2011 ITCourseware, LLC Rev 5.1.4 Page 281


Advanced Java Programming

JNDI in J2EE

” J2EE uses JNDI for various lookups:

¾ Servlets and EJBs use JNDI to look up EJBs.

¾ Servlets and EJBs use JNDI to look up JDBC Data Sources.

¾ EJBs use JNDI to look up JMS destinations.

” A J2EE application might also use JNDI to integrate with any number of existing
systems.

ƒ DNS

ƒ LDAP

ƒ etc.

Page 282 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 13 Java Naming and Directory Interface (JNDI)

Application Server

Web Container
EJB Container

look
up(e
jb) Naming jb)
up(e loo
look Service ku
p(d
) ata Session Bean
Servlet
ource loo
ku
sou
tas p(j rce
a )
ku p(d ms
-de
loo sti Entity Bean
na
Servlet tio
n)
Message-Driven
Bean

© 2011 ITCourseware, LLC Rev 5.1.4 Page 283


Advanced Java Programming

Labs

Write a program that uses JNDI to locate the RateInfo object registered in the RMI Registry,
using RateInfo as the lookup name, and displays the rate information by calling the getInfo()
method. Make sure that the rmiregistry and the Server application are running as described at the
beginning of the chapter.
(Solution: [Link])

† Write a program that locates all ServerStatus objects registered in the RMI Registry using JNDI
and displays their statuses by calling their getStatus() method. Looking up every object in the
registry could be expensive, so take advantage of our naming convention to identify which objects
are ServerStatus objects before calling lookup(). Make sure that the rmiregistry and the Server
application are running as described at the beginning of the chapter. (Hint: Run the Lister example
application to observe the naming convention. This will also show you how many results you should
get.)
(Solution: [Link])

‡ (Optional. Requires DNS nameserver.) Write a program that takes a hostname as a command-line
argument, and uses JNDI to look up and print out the DNS A record for the hostname.
(Solution: [Link])

ˆ (Optional. Requires DNS nameserver.) Modify your solution to ‡ so that, after the hostname, any
number of resource record types can be listed on the command-line. Print all such resource records
for the named host.
(Solution: [Link])

Page 284 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 13 Java Naming and Directory Interface (JNDI)

Se rvice Configuration Se tting Value

RMI INITIAL_CONTEXT_FACTORY [Link]


PROVIDER_URL rmi://rmiServerHostorIP/
Context type Context
DNS INITIAL_CONTEXT_FACTORY [Link]
PROVIDER_URL dns://dnsServerNameorIP/
Context type DirContext

© 2011 ITCourseware, LLC Rev 5.1.4 Page 285


Advanced Java Programming

Page 286 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 14 Processing XML with Java — JAXP

Chapter 14 - Processing XML with Java — JAXP

Objectives
” Describe the Java API for XML Processing
(JAXP).

” Use SAX callbacks to parse XML.

” Traverse and manipulate the DOM tree.

” Use JAXP to transform an XML document


with XSLT.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 287


Advanced Java Programming

The Java API for XML Processing

” Java API for XML Processing (JAXP) enables Java applications to parse and
transform XML documents without constraint from a particular XML
implementation.

¾ You can develop programs independent of the underlying XML parser by


using the JAXP APIs; then the XML parser can be changed without
changing a single line of application code.

¾ The underlying XML parser can be determined at runtime by setting the


appropriate switch.

java -[Link]=[Link]

” JAXP supports both object-based and event-based parsing of XML files.

¾ Object-based parsing using the Document Object Model (DOM) involves


the creation of an internal data structure to represent the XML document
content.

¾ Event-based parsing using Simple API for XML (SAX) treats the contents
of the XML document as a series of events and calls various methods in
response to those events.

” JAXP also provides a common interface for working with XSLT.

¾ XSLT is an XML specification that provides instructions on how to


transform a source document into a result document.

¾ You can create a new XML, HTML, or text document using an XSLT
Processor.

¾ Just as SAX and DOM parsers can be switched at runtime, so can XSLT
processors.

Page 288 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 14 Processing XML with Java — JAXP

JAXP is bundled with the JDK, standard edition, version 1.4 or later.

App

JAXP
Parsing Transformation

SAX DOM

Xerces Xalan

Xerces and Xalan are Apache implementations that come bundled with Java 5.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 289


Advanced Java Programming

Introduction to SAX Parsing

” SAX uses an event-driven model to parse XML data.

¾ The XML content is seen as a series of events, triggering the SAX parser
to call various handler methods.

” SAX has the advantage of low memory consumption.

¾ The entire document does not need to be loaded into memory at one time,
thus enabling SAX to parse larger documents.

” A disadvantage is the necessity of maintaining event state in your application


code.

” A SAX-compliant parser specifies handler interfaces to respond to parser


events.

¾ The ContentHandler interface is used to respond to basic parsing events.

¾ The ErrorHandler interface methods are called in response to problems


in the XML file.

” The DefaultHandler class implements all the basic SAX interfaces and
provides default implementations.

¾ By extending the DefaultHandler you can implement only the methods


you are interested in.

¾ As the parser operates on the XML data, it calls your methods in


response to the document.

Page 290 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 14 Processing XML with Java — JAXP

Application

class MyHandler
extends DefaultHandler

setDocumentLocator()

startDocument()

endDocument()
XML Data SAX Parser
startElement()

characters()

. .
. .
. .

© 2011 ITCourseware, LLC Rev 5.1.4 Page 291


Advanced Java Programming

SAXParser and JAXP

” There are four basic steps when using JAXP with SAX:

1. Get an instance of the SAXParserFactory.

SAXParserFactory factory = [Link]();

2. Use the SAXParserFactory to retrieve an instance of the SAXParser.

SAXParser parser = [Link]();

3. Create an instance of your class that extends DefaultHandler.

DefaultHandler handler = new SAXHandler();

4. Call the parser's parse() method, passing a reference to the XML data and
the handler implementation class.

[Link](new File("[Link]"), handler);

Page 292 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 14 Processing XML with Java — JAXP

[Link]
import [Link];
import [Link];
import [Link];
import [Link];

public class SAXGarage {


public static void main(String args[]) {
if ([Link] != 1) {
[Link]("Usage: java SAXGarage [Link]");
[Link](1);
}
SAXParserFactory factory = [Link]();

try {
SAXParser parser = [Link]();
DefaultHandler handler = new SAXHandler();
[Link](new File(args[0]), handler);
}
catch (Exception e) {
[Link] ("ERROR " + e);
}
}
}

[Link]
<?xml version="1.0"?>
<garage>
<car miles="0">
<make>Porsche</make><model>911</model><year>2001</year>
</car>
<car miles="250000">
<make>VW</make><model>Beetle</model><year>1974</year>
</car>
<van miles="50000">
<make>Ford</make><model>E350</model><year>2000</year>
</van>
</garage>

Try It:
Compile [Link] and run it using [Link] as the input file to list the make and model of each
car or van.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 293


Advanced Java Programming

SAX Event Methods

” Developers usually focus on implementing the methods in the ContentHandler


interface when extending DefaultHandler.

” setDocumentLocator() —This method is called to pass a Locator object to


your application.

¾ Use the Locator object to determine the current parsing location.

” startDocument(), endDocument() — These methods are called when the


beginning or end of the XML document is encountered.

” startElement(), endElement() — These methods are called when encountering


an open or close tag.

startElement(String uri, String localName, String qName,


Attributes atts)

ƒ uri — the namespace name that is associated with this element.


ƒ localName — the tagname without any namespace prefix.
ƒ qName — the fully-qualified tagname of the element (prefix +
localName).
ƒ atts — the list of attributes associated with this element.

” characters() — This method is called when character data is encountered.

characters(char[] ch, int start, int length)

ƒ ch — the character array that contains the actual character data that was
found.
ƒ start — the starting point in the array.
ƒ length — the number of characters to read from the array.

Page 294 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 14 Processing XML with Java — JAXP

[Link]
import [Link];
import [Link]; DefaultHandler provides
import [Link]; stubs for all SAX event
handler interfaces.
class SAXHandler extends DefaultHandler {
private boolean printChars = false;

public void startDocument() throws SAXException {


[Link]("Vehicles In My Garage");
}
public void endDocument() throws SAXException {
[Link]("\nGarage Door Closed");
}
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException {

if ([Link]("make")) {
[Link]("\n");
}
if ([Link]("make") || [Link]("model")) {
[Link](qName + " : ");
printChars = true;
}
}
public void characters(char ch[], int start, int length)
throws SAXException {

if (printChars) {
String s = new String(ch, start, length);
[Link](s);
}
printChars = false;
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 295


Advanced Java Programming

Introduction to DOM

” DOM is a platform- and language-independent interface for accessing XML


documents.

” The parser creates an internal, tree-like data structure containing objects that
represent the various parts of the XML document.

¾ The classes that make up the objects in the tree implement various
interfaces specified by the World Wide Web Consortium (W3C).

¾ Your application can be DOM-compliant, instead of vendor-specific.

” After the parser is finished building the tree structure, it returns a reference to
the top node of the tree, called the Document.

” An advantage of DOM is the ability to manipulate the document after it has been
parsed.

¾ You can also use DOM to create a new document from scratch.

” High memory use is a disadvantage of DOM when parsing large XML


documents.

Page 296 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 14 Processing XML with Java — JAXP

© 2011 ITCourseware, LLC Rev 5.1.4 Page 297


Advanced Java Programming

Parsing DOM with JAXP

” Parsing an XML document using JAXP and DOM involves four steps:

1. Get an instance of the DocumentBuilderFactory.

DocumentBuilderFactory factory =
[Link]();

2. Use the DocumentBuilderFactory to retrieve an instance of a


DocumentBuilder.

DocumentBuilder builder = [Link]();

3. Call the parse() method, passing a reference to the XML data.

Document doc = [Link](new File("[Link]"));

4. Use the returned reference to the Document object to examine and


manipulate the tree structure.

Page 298 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 14 Processing XML with Java — JAXP

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class DOMGarage {


public static void main(String args[]) {
if ([Link]!=1) {
[Link] ("Usage: java DOMGarage [Link]");
[Link](1);
}

DocumentBuilderFactory factory =
[Link]();

try {
DocumentBuilder builder = [Link]( );
Document document = [Link]( new File(args[0]) );
[Link]("Vehicles In My Garage\n");
searchForVehicles(document);
[Link]("Garage Door Closed");
}
catch (Exception e) {
[Link](e);
}
}
...
}

Try It:
Compile and run [Link] to list the make and model of each vehicle in the garage using a
DOM parser.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 299


Advanced Java Programming

The DOM API

” DOM specifies twelve types of objects that can be included in the DOM data
structure.

¾ Each object represents something that exists in the XML document.

¾ Each object implements an interface that is specific for that object.

¾ All of the interfaces inherit from the Node interface.

” You can use NodeList and NamedNodeMap to store collections of Nodes.

” The root node of the structure is the Document node.

” From the Document node you can traverse the structure by calling various
methods.

¾ getDocumentElement() returns a reference to the root element.

¾ getElementByTagName() returns a NodeList of all elements with the


given tag name.

” Element nodes represent the various elements in the structure.

¾ You can append child nodes and manipulate attributes from the Element
node.

” Text nodes are children of Element nodes and contain the actual text.

Page 300 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 14 Processing XML with Java — JAXP

«interface»
Node

«interface» «interface» «interface» «interface»


Attr Document CharacterData Element

«interface»
NodeList «interface» «interface»
Comment Text
«interface»
NamedNodeMap «interface»
CDATASection
Note:
All interfaces are in the [Link] package.

[Link]
...
public static void searchForVehicles(Document doc) {
NodeList list = [Link]("car");
processVehicleList(list);
list = [Link]("van");
processVehicleList(list);
}
public static void processVehicleList(NodeList autoList) {
for (int i = 0; i < [Link](); i++) {
Node auto = [Link](i);
NodeList autoFeatures = [Link]();

for (int j = 0; j < [Link](); j++) {


Node featureNode = [Link](j);

if ([Link]() == Node.ELEMENT_NODE) {
Element feature = (Element) featureNode;
String name = [Link]();

if ([Link]("make") || [Link]("model"))
[Link] (name + " : " +
[Link]().getNodeValue());
}
}
Element has various methods
[Link](); for querying node content.
}
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 301


Advanced Java Programming

Validation

” There are two types of XML validation documents:

1. Document Type Definitions (DTD) define the structure of the XML


documents, but not the content.

2. An XML Schema defines the valid structure, as well as content types for
XML documents.

” The ErrorHandler interface provides three methods to deal with different types
of errors.

¾ fatalError() is called by the parser to report XML that is not well-formed.

¾ error() is called to report that the XML document will not validate
against the DTD or Schema.

¾ warning() is called when the condition is not an error or fatal error.

” To validate with a DTD you must call setValidating() on the factory.

[Link](true)

” If you are validating against a schema you must instead call


setNamespaceAware() and provide the schema document via the setSchema()
method.

¾ Use a SchemaFactory to retrieve a Schema object.

SchemaFactory f =
[Link](XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = [Link](new File("[Link]"));

Page 302 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 14 Processing XML with Java — JAXP

SAXValidator will validate an XML file against a DTD.

[Link]
...
public class SAXValidator {
public static void main(String args[]) {
if ([Link] != 2) {
[Link](
"Usage: java SAXValidator [Link] [Link]");
[Link](1);
}

try {
SchemaFactory schemaFactory =
[Link](XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = [Link](new File(args[1]));

SAXParserFactory factory = [Link]();


[Link](true);
[Link](schema);

SAXParser parser = [Link]();


[Link](new File(args[0]), new SAXValidatorHandler());
}
catch (Exception e) { Pass object that implements
[Link](e); the ErrorHandler interface to
} the parse() method.
}
}

class SAXValidatorHandler extends DefaultHandler {


private Locator locator;
public void setDocumentLocator(Locator loc) {
locator = loc;
}
public void error(SAXParseException e) {
[Link]("Validation error on line " +
[Link]() + ":\n" + [Link]());
}
public void fatalError(SAXParseException e) {
[Link]("Well-formedness error on line " +
[Link]() + ":\n" + [Link]());
}
}

Try It:
Run SAXValidator using [Link] and then [Link] passing in [Link] as the second
parameter.
© 2011 ITCourseware, LLC Rev 5.1.4 Page 303
Advanced Java Programming

Transformation

” Transformation is the process of editing an existing document with the goal of


producing a different document.

” XSLT can transform an XML document into an HTML file, a text file, or another
XML document.

¾ XSLT is the W3C standard for creating XML documents that contain
transformation templates.

¾ The templates are applied to the data in an existing XML document to


produce a new document.

” JAXP contains several interfaces and classes used to simplify the transformation.

¾ Use TransformerFactory to create a Transformer object that contains


the XSLT document.

TransformerFactory tFactory =
[Link]();
Transformer transformer =
[Link](xslSource);

¾ You use Transformer's transform() method to create the new document.

[Link](xmlSource, xmlResult);

ƒ transform() takes a Source and Result objects as paramters.

ƒ The Source and Result interfaces have implementations allowing


you to work with DOM (DOMSource), SAX (SAXSource) or just
regular streams (StreamSource).

Page 304 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 14 Processing XML with Java — JAXP

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class GarageTransform {


public static void main(String[] args) throws Exception {
Source xmlSource = new StreamSource("[Link]");
Source xslSource = new StreamSource("[Link]");
Result xmlResult = new StreamResult("[Link]");

TransformerFactory tFactory = [Link]();


Transformer transformer = [Link](xslSource);
[Link](xmlSource, xmlResult);
}
}

[Link]
<xsl:stylesheet xmlns:xsl="[Link]
version="1.0">
<xsl:template match="/">
<html><body><div align="center">
<table border="1">
<xsl:apply-templates select="garage/*"/>
</table>
</div></body></html>
</xsl:template>

<xsl:template match="car|van">
<tr>
<td><xsl:value-of select="year"/></td>
<td><xsl:value-of select="make"/></td>
<td><xsl:value-of select="model"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>

Try It:
Run [Link] and then open [Link] in a browser.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 305


Advanced Java Programming

Labs

Create an application that will use SAX to read through [Link] and count the number of
vehicles that have less than 20,000 miles.
(Solution: [Link])

† Create an application that will parse [Link] into a DOM structure. Create a new car Element
node using Document's createElement() method. Append the Element as a new child of the
garage Element. Create three new Element nodes for make, model, and year, adding them as
children of your new car Element. Create text nodes using Document's createTextNode()
method and add them as children to make, model, and year with appropriate data.
(Solution: [Link])

‡ Modify your program from † to send your DOM structure to a Transformer to run against
[Link], creating an HTML file. Open the HTML file in a browser to view your results.
(Solution: [Link])

Page 306 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 14 Processing XML with Java — JAXP

© 2011 ITCourseware, LLC Rev 5.1.4 Page 307


Advanced Java Programming

Page 308 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 15 Native Methods

Chapter 15 - Native Methods

Objectives

” Create library files containing native-language


methods that are callable from your Java code.

” Use javah to generate information necessary to


write and compile native method libraries.

” Implement native methods in C.

” Configure the runtime Java environment so your


native methods are available.

” Use JNI methods in your native code.

” Pass arguments to and return values from native


methods.

” Call Java methods in your native code.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 309


Advanced Java Programming

Overview of Java Native Methods and JNI

” Your application may need functionality not available in the Java language, its
standard classes, or any other available classes.

¾ Access unusual hardware, drivers, or other platform-specific features.

¾ Integrate Java with legacy code or other products.

¾ Implement critical code in a low-level language for performance.

” Native methods are functions implemented in some other programming


language, and made available through methods of a Java class.

¾ The compiled native method implementation must be available to the VM


in a shared library.

” In addition to general support for native methods, Java provides the Java Native
Interface (JNI); a specification and a utility library for C/C++ native-method
programmers.

¾ Utility functions.

¾ C-to-Java/Java-to-C data-compatibility types.

¾ Invocation of a Java VM from a native application.

Page 310 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 15 Native Methods

© 2011 ITCourseware, LLC Rev 5.1.4 Page 311


Advanced Java Programming

How to Create and Use Native Methods

” The details of writing and compiling native method implementations vary with
the native language and operating platform.

” In this section, we will demonstrate native method implementation in the C


programming language.

” Creating and using native methods in C:

1. Create a Java class as a "wrapper" for the native methods.

2. Compile the Java code.

3. Use javah to generate corresponding C header files.

4. Write or modify the C implementation code.

5. Compile the C implementation code into a shared library.

6. Create a Java program that instantiates an object of the wrapper class and
calls the native methods.

Page 312 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 15 Native Methods

How to go about it:

You might think you would implement the native method first, then integrate it with your Java code; but,
since you need to compile and test it from your Java code, and use javah to create headers before you can
compile your native code, you will probably set up your Java application (or a test app) first (as we will in
this chapter), then complete the native implementation.

[Link] (Java Source Code)


public class CCCheck {
public native int validCC(String ccNumber, int digitCount);
static {
[Link]("CCCheck");
}
}

[Link] (Java Source Code)


class CCCheckTest {
public static void main (String args[]){
int valid = 0;
String testNumber = "12344";
CCCheck checker = new CCCheck();
valid = [Link](testNumber, [Link]());
...
javac
javac
[Link] [Link]
feca beba 0000 3100 1800 000a 0005 080f feca beba 0000 3100 3f00 000a 0013 081c
1000 000a 0011 0712 1300 0007 0114 0600 1d00 0007 0a1e 0300 1c00 000a 001f 0a20

javah Java VM
CCCheck.h
ClassLoader
#include <jni.h>
JNIEXPORT jint JNICALL Java_CCCheck_validCC [Link](...)
(JNIEnv *, jobject, jstring, jint);

CCCheck.c (Programmer-created C Source Code)


#include "CCCheck.h"
#include <string.h>
JNIEXPORT jint JNICALL Java_CCCheck_validCC
(JNIEnv *env, jobject obj, jstring ccNumber, jint count) {
...
return total;
}

[Link] on Windows or [Link] on Windows or


cc
libLegacyCCCheck.a on Unix (Static Library) [Link] on Unix (Shared Library)
457f 464c 0101 0001 0000 0000 0000 0000 457f 464c 0101 0001 0000 0000 0000 0000
0003 0003 0001 0000 05a8 0000 0034 0000 0003 0003 0001 0000 05a8 0000 0034 0000

© 2011 ITCourseware, LLC Rev 5.1.4 Page 313


Advanced Java Programming

Native Method Declaration

” Define a new Java class; the native methods will be methods of this class.

¾ This class acts as a wrapper for the native methods.

” Declare any native methods as native.

¾ Do not write implementations of the native methods, since they will,


obviously, be implemented in the native language.

” Declare native methods just like abstract methods, replacing abstract with
native.

¾ Terminate these method definitions with a semi-colon:

public native int validCC(String ccNumber, int digitCount);

ƒ The function definition is in the native C module.

” Define parameters and return types using Java types as appropriate.

” Use a static initializer in this wrapper class to load the library containing the
compiled native method implementations.

¾ [Link]() will load the appropriate .dll or .so library file for
dynamic linking.

static {
[Link]("CCCheck");
}

Page 314 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 15 Native Methods

[Link]
public class CCCheck {
public native int validCC(String ccNumber, int digitCount);
static {
[Link]("CCCheck");
} Don't add the .dll or .so on
} the end of the file name.

Hands On:
Create [Link]:

javac [Link]

© 2011 ITCourseware, LLC Rev 5.1.4 Page 315


Advanced Java Programming

Using javah

” The javah utility, part of the standard JDK, creates a C header file (.h file) from
the class definition of the wrapper class.

” javah produces a .h file with the function prototype for the function
implementing the Java native method.

” The function prototype will use datatypes defined in header files under the JDK's
include/ directory.

¾ The #include <jni.h> at the top includes all the necessary headers.

” As the comment says, do not edit this .h file — not because you will break it,
but because you are likely to regenerate it with javah as you enhance your class.

” Use the function definition from the .h file in your C implementation by copying
the prototype from .h, and adding variable names.

Page 316 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 15 Native Methods

Hands On:

javah CCCheck

This produces the C header file CCCheck.h, which contains the function prototype for the C
implementation of the validCC() Java method:

CCCheck.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class CCCheck */

#ifndef _Included_CCCheck
#define _Included_CCCheck
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: CCCheck
* Method: validCC Use this function
* Signature: (Ljava/lang/String;I)I prototype in your C
*/ implementation.
JNIEXPORT jint JNICALL Java_CCCheck_validCC
(JNIEnv *, jobject, jstring, jint);

#ifdef __cplusplus
}
#endif
#endif

© 2011 ITCourseware, LLC Rev 5.1.4 Page 317


Advanced Java Programming

Creating the Implementation Code

” Create a C program with the definition of the function declared in the .h file
created by javah.

” Be sure to #include the javah-created header file.

¾ This should also #include <jni.h> for you.

” Copy the prototype from the header file to get started.

” Note that JNI declares two parameters for every native function:

¾ JNIEnv *env is a pointer to the JNI interface functions.

ƒ Use env to access the C functions defined in the JNI specification.

¾ jobject obj is a reference to the invoking Java object.

ƒ If the native method is declared static, obj is a reference to the


wrapper class.

” Primitive datatypes will be passed by value and can be used as is.

¾ Java objects require special conversion, such as String to char[] and


back.

¾ Functions that do this are defined in jni.h.

Page 318 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 15 Native Methods

LegacyCCCheck.c contains code for validating credit card information.

LegacyCCCheck.c
#include <string.h>
#include <stdio.h>

int ccCheck (char *string, int count){


char graphic;
...
for (i = count-1; i >= 0; i--, j++) {
graphic = string[i];
value = graphic - 48;
...
}
for (i = 0; i < numberDigits; i++){
total += digits[i];
}
if (total % 10 == 0){
return total;
}
else {
return 0;
}
}
...

CCCheck.c is the new code used to call the legacy code.

CCCheck.c
#include "CCCheck.h" These are the two
#include <string.h> parameters defined
#include "LegacyCCCheck.h" in the Java method.

JNIEXPORT jint JNICALL Java_CCCheck_validCC


(JNIEnv *env, jobject obj, jstring ccNumber, jint count) {
char cardNumber[40];
/* Convert Java String to C char array for reference */
const char *str = (*env)->GetStringUTFChars(env, ccNumber, NULL);

int valid = 0;
strcpy(cardNumber, str);
valid = ccCheck(cardNumber, count);
(*env)->ReleaseStringUTFChars(env, ccNumber, str);

return valid;
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 319


Advanced Java Programming

Compilation

” Use your preferred native compiler to build a shared library file from your
implementation code.

¾ Use the appropriate compiler option for creating a shared library.

¾ The compiler's include path must have the standard and the platform-
specific Java include directories.

¾ For many UNIX C compilers, the command-line switch to create a shared


object library is -G.

ƒ For the GNU gcc compiler, it is -shared.

On UNIX/Linux:

JAVA_HOME=/opt/j2sdk_nb/j2sdk1.5.0_03
export JAVA_HOME
gcc -shared -o [Link] -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \
nativeCCCheck.c

Page 320 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 15 Native Methods

Hands On:

On Windows:
JAVA_HOME=c:\Program Files\java\jdk1.5.0_03

In Visual Studio 6.0:


1. Create a Win32 Dynamic-Link Library project.
2. Under the Tools menu, click on Options.
3. On the Options window, click on the Directories tab.
4. Be sure that the show directories for box says Include files.
5. Add a new entry under Directories referencing the %JAVA_HOME%\include directory.
6. Add another directory for the %JAVA_HOME%\include\Win32 directory.
7. Click OK in the Options box.
8. In the File View window, right click on the project name, and choose to Add Files to Project.
9. In the File window, select CCCheck.c, CCCheck.h and LegacyCCCheck.h to insert them into
the project.
10. Click on ProjectÆSettingsÆLink.
11. Change the Category to Input.
12. In the object/library modules box add [Link] to the list.
13. Manually copy [Link] into your Project directory.
14. Choose BuildÆBuild Solution to build the DLL.
15. Copy the DLL from the Project/Debug directory to your chapter directory.

In Visual Studio .NET:


1. On the File Menu, click NewÆProject.
2. In the New Project window, select Visual C++ Projects. Underneath Templates, select Win32
Project.
3. In the Name text field, enter CCCheck and press OK.
4. In the Win32 Application Wizard window, click on Application Settings and make the Application
Type DLL and check Empty Project. Press Finish.
5. Click on ProjectÆProperties. In the Property Pages windows, click on LinkerÆInput.
6. In the Additional Dependencies box, add [Link]. Click OK.
7. Under the Tools menu, click on OptionsÆProjectsÆVC++ directories.
8. In the Show directories for box, select Include files.
9. Add a new entry referencing the %JAVA_HOME%\include directory.
10. Add another directory for the %JAVA_HOME%\include\Win32 directory.
11. Click OK on the Options box.
12. In the Solution Explorer window, right click on the project name, click AddÆAdd Existing Item.
13. In the Add Existing Item window, select CCCheck.c, CCCheck.h and LegacyCCCheck.h to insert
them into the project.
14. Manually copy [Link] into your Project directory.
15. Choose BuildÆBuild Solution to build the DLL.
16. Copy the DLL from the Project/Debug directory to your chapter directory.
© 2011 ITCourseware, LLC Rev 5.1.4 Page 321
Advanced Java Programming

Distribution

” The shared library containing compiled native method implementation must be


available to the VM.

¾ The path to the shared library file must be known to the VM — for
example, listed in the PATH on Windows, or in LD_LIBRARY_PATH
or LD_RUN_PATH on UNIX.

” You can instead specify on the command-line where Java will look for the
library by setting the [Link] system property.

¾ The following command example will look for the library in the current
directory:

java -[Link]=. CCCheckTest

Page 322 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 15 Native Methods

Hands On:

On UNIX/Linux:

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
export LD_LIBRARY_PATH

On Windows:

PATH=%PATH%;.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 323


Advanced Java Programming

Using the Native Methods

” Simply instantiate an object of the wrapper class and call its methods normally.

Page 324 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 15 Native Methods

[Link]
public class CCCheckTest {
public static void main (String args[]) {
int valid = 0;
String testNumber = "12344";
CCCheck checker = new CCCheck();

valid = [Link](testNumber, [Link]());


[Link]("Number " + testNumber + " is " + valid);

testNumber = "12341";
valid = [Link](testNumber,[Link]());
[Link]("Number " + testNumber + " is " + valid);
}
}

[Link]
public class CCCheck {
public native int validCC(String ccNumber, int digitCount);
static {
[Link]("CCCheck");
}
}

Hands On:

Compile and run [Link]:


javac [Link]
java CCCheckTest

© 2011 ITCourseware, LLC Rev 5.1.4 Page 325


Advanced Java Programming

JNI

” The JNI specification defines an implementation-independent way of integrating


Java with native code.

” The JNI defines native types that map to Java primitives, references, and
objects.

” The JNI provides C functions for:

ƒ Version Information
ƒ Class Operations
ƒ Exceptions
ƒ Global and Local References
ƒ Object Operations
ƒ Accessing Fields of Objects
ƒ Calling Instance Methods
ƒ Accessing Static Fields and Methods
ƒ String and Array Operations

” Each native method call starts with a pointer to the JNI program interface, which
is a list of function pointers to standard JNI functions.

(JNIEnv *env, jobject obj ...)

¾ For example, in C you can retrieve the current version number with the
following call to the GetVersion() function:

jint v = (*env)->GetVersion(env);

¾ The C++ the syntax would be slightly simpler:

jint v = env->GetVersion();

Page 326 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 15 Native Methods

The jni.h file provides java compatible types for use in native C code when passing information between C
and Java.

Primitive Type s — Pas s e d By Value


Java Type JNI Type De s cription C Type
boole an jboole an 8- bit unsigned uns igne d char
byte jbyte 8- bit signed char
char jchar 16- bit unsigned uns igne d s hort
abort js hort 16- bit signed s hort
int jint 32- bit signed long
long jlong 64- bit signed long long
float jfloat 32- bit float
double jdouble 64- bit double
void jvoid void

Re fe re nce Type s
JNI Type Hie rarchy Java Type
jobje ct Any Java Object
jclas s [Link] s
js tring [Link]
jthrowable [Link]
jarray Java arrays
jbyte aray byte []
jchararray char[]
js hortarray s hort[]
jintarray int[]
jlongarray long[]
jfloatarray float[]
jdouble array double []
jboole anarray boole an[]
jobje ctarray Any Object array

© 2011 ITCourseware, LLC Rev 5.1.4 Page 327


Advanced Java Programming

Passing Arguments

” Parameters you declare for native methods in your wrapper class will be
declared as JNI types by javah.

” Primitive types are passed by value.

” Java objects, including arrays and Strings, are passed by reference.

¾ All references passed to native methods, or returned by JNI functions


called in the native method, are local to the native method.

” Strings require some special handling in C.

¾ To convert a jstring (String object) to a C char array:

1. Pass the jstring to GetStringUTFChars() storing the result in a


const char *.

2. The function returns a C character array.

const char * GetStringUTFChars(JNIEnv *, jstring, jboolean *)

3. Call ReleaseStringUTFChars() when you have finished with the


string, to prevent a memory leak in your native code.

void ReleaseStringUTFChars(JNIEnv *, jstring, const char *)

¾ To create a jstring from a C char array:

1. Pass a char * to NewStringUTF().

jstring NewStringUTF(JNIEnv *, const char *);

2. NewStringUTF() returns a jstring.

Page 328 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 15 Native Methods

[Link]
public class CCCheckTest {
public static void main (String args[]) {
int valid = 0;
String testNumber = "12344";
CCCheck checker = new CCCheck();

valid = [Link](testNumber, [Link]());


...
}
}

[Link]
public class CCCheck {
public native int validCC(String ccNumber, int digitCount);
static {
[Link]("CCCheck");
}
}

CCCheck.c
#include "CCCheck.h"
#include <string.h>
#include "LegacyCCCheck.h"

JNIEXPORT jint JNICALL Java_CCCheck_validCC


(JNIEnv *env, jobject obj, jstring ccNumber, jint count) {
char cardNumber[40];
/* Convert Java String to C char array for reference */
const char *str = (*env)->GetStringUTFChars(env, ccNumber, NULL);

int valid = 0; Boolean to flag whether to make local copy of jstring.


strcpy(cardNumber, str);
valid = ccCheck(cardNumber, count);
(*env)->ReleaseStringUTFChars(env, ccNumber, str);

return valid;
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 329


Advanced Java Programming

Calling Java Methods in Native Code

” To call methods of the native method's wrapper class, or of a Java object


passed to a native method:

¾ Obtain the jclass associated with the Java object:

jclass jc = (*env)->GetObjectClass(env,obj);

ƒ You can also load the jclass class name:

jclass jc = (*env)->FindClass(env,"MyJavaClass");

¾ Obtain an objects method ID using the class, method name, and signature:

jmethodID mid = (*env)->GetMethodID


(env, jc, "callBackMethod", "(I)V");

ƒ You can obtain a method ID for a static method using


GetStaticMethod().

¾ Call the method, using the appropriate JNI CallTypeMethod() function


where Type is the method's return type.

(*env)->CallVoidMethod(env, obj, mid, 4);

” You can use the NewGlobalRef() function to create global references to


jobjects, enabling them to be passed between functions.

jobject jo = (*env)->NewGlobalRef(env,obj);

Page 330 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 15 Native Methods

[Link]
public class StockBroker implements StockListener {
int brokerID;

public StockBroker(int id) {


brokerID = id;
}
public void tradeNotification(String sym, int shares) {
[Link]("Broker " + brokerID + " : " );
[Link](shares + " shares of " + sym + " were traded");
}
}

StockMarketEngine.c
#include <jni.h>
#include "StockMarketEngine.h"

jobject listener[10];
int lCount = 0;

JNIEXPORT void JNICALL Java_StockMarketEngine_addStockListener


(JNIEnv * env, jobject obj, jobject javaStockListener)
{
listener[lCount] = (*env)->NewGlobalRef(env,javaStockListener);
lCount ++;
}

JNIEXPORT void JNICALL Java_StockMarketEngine_startEngine


(JNIEnv * env, jobject obj)
{
jstring js;
jclass jc;
jmethodID mid;
char * stockSymbol[10] = {"bh","itc","ms","y"};
int x,y;
for (x = 0; x < 4; x++) {
for (y=0; y < lCount; y++) {

js = (*env)->NewStringUTF(env, stockSymbol[y]);
jc = (*env)->GetObjectClass(env,listener[y]);
mid = (* env)->GetMethodID
(env, jc,"tradeNotification","(Ljava/lang/String;I)V");
(*env)->CallVoidMethod(env,listener[y],mid,js,x*100);
(*env)->ReleaseStringUTFChars(env,js,stockSymbol[y]);
}
}
}
© 2011 ITCourseware, LLC Rev 5.1.4 Page 331
Advanced Java Programming

JNI Signatures

” Signatures consisting of the name and the parameter configuration identify


unique entry points and specify return types.

public native int validCC([Link], int);


Signature: (Ljava/lang/String;I)I

¾ The first part of the signature is the entry point name.

¾ The first part of the parameter signature ( ) is the parameter list, followed
by the return type.

” Primitive types are abbreviated with standard abbreviation letters.

” Non-primitives specify the Java-qualified type using Lclass and ending with ;.

¾ This example defines an entry that receives a String object and returns a
String result.

(Ljava/lang/String;)Ljava/lang/String;

” You can use javap to determine the method signature of a Java method.

Page 332 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 15 Native Methods

Method Signatures: (argtypes)returntype

Type abbrev. Java types


V void
Z boolean
B byte
C char
S short
I int
J long
F float
D double
Lclass; Class class (fully-qualified)
[type type array

javap -s CCCheck

Compiled from "[Link]"


public class CCCheck extends [Link]{
public CCCheck();
Signature: ()V
public native int validCC([Link], int);
Signature: (Ljava/lang/String;I)I
static {};
Signature: ()V
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 333


Advanced Java Programming

Labs

We have an emergency help notification system installed that pages a System Administrator
when attention is needed. It needs a message and an ID (pager number as a character string). The
files LegacyPager.c and LegacyPager.h contain the pageThem() function. Create and test a
wrapper function to invoke the pager mechanism.
(Solution: [Link], [Link], Pager.c)

† Add a who() method to the Pager class to return your name as a character string when who()
receives an ID. To return a string, you will need to create a String object to return using the
followingline:

return (*env)->NewStringUTF(env, cCharArray);

(Solution: [Link], [Link], Pager2.c)

Page 334 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 15 Native Methods

© 2011 ITCourseware, LLC Rev 5.1.4 Page 335


Advanced Java Programming

Page 336 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 16 Java Design Patterns — Creational Patterns

Chapter 16 - Java Design Patterns —


Creational Patterns

Objectives
” Understand the need for Design
Patterns.

” Describe the purpose of Creational


Patterns.

” Implement the Singleton, Factory


Method, and Builder patterns.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 337


Advanced Java Programming

What Are Design Patterns?

” A design pattern is a description of a collaboration of objects that are used to


solve a general design problem in a particular context.

¾ These patterns have been used countless times by programmers in many


different situations and applications.

¾ Design patterns are not created, they are discovered.

” The use of design patterns has many advantages.

¾ They capture the expertise of many developers and make it available to all.

¾ A system that uses known patterns will be easier to understand and


modify.

¾ They provide a common vocabulary for developers.

¾ Design patterns assist in avoiding the duplication of code.

¾ They facilitate the restructuring of a system, whether the system was


originally built with patterns or not.

” While patterns are published in styles that vary, all include the following
important features:

¾ Name: A lot of effort is put into creating good pattern names.

¾ Problem: Describes when to apply the design pattern.

¾ Solution: A description of the objects and relationships involved.

¾ Consequences: The results and trade-offs involved in applying the pattern.

Page 338 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 16 Java Design Patterns — Creational Patterns

Some Background

The pattern concept was co-opted from the architect Christopher Alexander. While his writings (A Pattern
Language: Towns, Buildings, Construction and The Timeless Way of Building, 1977) described
the patterns used in buildings, the central idea of reusing solutions to common problems can be applied in
many areas.

Ward Cunningham and Kent Beck published a paper entitled "Using Pattern Languages for Object-
Oriented Programs" at the OOPSLA-87 conference, in which they described how patterns could be
applied to user-interface design.

Design Patterns, by Gamma, Helm, Vlissides, and Johnson (Gang of Four or GoF) was published in
1995 and has become the top-selling computer book of all time. The 23 patterns found in that book are still
the cornerstone of the most recent design pattern books.

The 23 GoF patterns are divided into three groups:

Creational
Structural
Behavioral

© 2011 ITCourseware, LLC Rev 5.1.4 Page 339


Advanced Java Programming

What Are Creational Patterns?

” Creational patterns encapsulate the process of instantiating objects and allow


that process to change without affecting the rest of the system.

¾ Client code only needs to know about the exposed interfaces or abstract
base classes.

¾ The concrete implementation of those abstractions can be changed


without affecting the rest of the system.

” Creational patterns come in two flavors: class creational and object creational.

¾ Class creational patterns use inheritance.

ƒ If a new instantiation process is needed, simply create a new


derived class.

ƒ Client code, which references an interface or abstract base class, is


not affected by the addition of a new creation process.

¾ Object creational patterns use composition.

ƒ Composition is more flexible than inheritance.

ƒ Client code works with an object that implements an interface.

ƒ The concrete creational process used by the system can be


changed at runtime when composition is used.

ƒ Since the interface has no implementation, there are no compile-


time dependencies to worry about.

ƒ A new implementation may even be received over the network.

Page 340 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 16 Java Design Patterns — Creational Patterns

Client Creator

ConcreteCreator1 ConcreteCreator2

UML class diagram of a class-creational pattern.

«interface»
Client
Creator

ConcreteCreator1 ConcreteCreator2

UML class diagram of a object-creational pattern.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 341


Advanced Java Programming

Singleton — Introduction

” The singleton pattern ensures that a class has only one instance.

¾ You may need a system-wide counter.

¾ You may need to control access to scarce resources like a database


connection.

¾ It may be more efficient to allow only a single object of a class to be


created and used.

” A mechanism to access to this object must be provided.

¾ A simple solution would be to allow some "global" to hold the reference


to this single object.

¾ Access to this object also needs to be controlled.

¾ In Java, the best solution is to make the class responsible for creating this
single instance and controlling access to it.

” The exact number of instances available may be changed as well.

¾ It is easy to change the singleton class to allow two or three objects


instead of just one.

¾ This technique could be used to create a simple object pool.

Page 342 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 16 Java Design Patterns — Creational Patterns

© 2011 ITCourseware, LLC Rev 5.1.4 Page 343


Advanced Java Programming

Singleton — Implementation

” The key to this pattern is encapsulating the object creation process so that the
class itself has full control.

¾ Eliminate the default constructor by explicitly declaring one.

¾ Make access to that constructor available only within the class by marking
it as private.

private MyConnection() ...

¾ Provide a static method that client code can use to access the singleton
instead of using a constructor.

public static MyConnection getInstance() ...

¾ The implementation of the getInstance() method demonstrates lazy


instantiation, in which the singleton is created the first time it is
requested.

” There are several issues to be aware of:

¾ The singleton instance must be static.

¾ Concurrency issues should be carefully considered.

¾ Since Java does not allow us to override static methods, extending a


singleton class is not recommended.

ƒ Instead of subclassing, the singleton pattern could be used in


conjunction with another creational pattern.

¾ If your singleton class extends a Cloneable class, be sure to override the


clone() method to prevent client code from cloning your singleton.

Page 344 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 16 Java Design Patterns — Creational Patterns

[Link]
import [Link];
import [Link];

public class MyConnection {


private Connection connection;
private static MyConnection theInstance;

private MyConnection() {
try {
String driverClass = "[Link]";
String url = "jdbc:derby://localhost:1527/j2se";
String username = null;
String password = null;

[Link](driverClass);
connection =
[Link](url, username, password);
}
catch (Exception e) {
[Link](e);
}
}
public static synchronized MyConnection getInstance() {
if (theInstance == null) {
theInstance = new MyConnection();
}
return theInstance;
}
public synchronized Connection getConnection() {
return connection;
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 345


Advanced Java Programming

Singleton — When to Use?

” Anytime the number of instances of a class should be limited and access to


those objects should to be controlled, the singleton pattern should be used.

¾ Use when only one object should ever be created.

ƒ A counter
ƒ A database connection
ƒ An application-wide log file
ƒ A print spooler
ƒ A window manager
ƒ A class that controls access to a JNDI server

¾ Use when only a few objects should be created.

ƒ A database connection pool


ƒ A set of worker processes used to handle incoming requests
ƒ An application-scope object that has backup copies

” There may be situations where an instance may become stale.

¾ In this case, the static accessor method could be implemented to


periodically refresh this object.

Page 346 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 16 Java Design Patterns — Creational Patterns

Java uses a singleton to represent the environment in which an application is running. To access this singleton
you call the static getRuntime() method defined within the Runtime class. This class uses an older naming
convention for the static singleton instance method: getClassname(). The method name getInstance is
more common today.

Several classes in the [Link] and [Link] packages also use the singleton pattern.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 347


Advanced Java Programming

Factory Method — Introduction

” Use the factory method pattern when you need to separate the object creation
logic from the rest of the application.

¾ The application may need to reference an abstract class that defers


object creation to one of several subclasses.

¾ A subclass has the knowledge required to create concrete products that


the application refers to generically via an interface or abstract base
class.

¾ A framework is an example of such an application.

” The factory method pattern provides flexibility over instantiating objects directly.

¾ The factory method in the base class could be abstract or a default


implementation could be provided.

¾ New products can be supported by simply creating a new concrete


creator that overrides or implements the base factory method.

” This pattern can be used to connect parallel class hierarchies.

¾ The product hierarchy and the creator hierarchy could have matching
subclasses.

¾ Alternatively, one concrete creator could know how to create most


products, but special cases could be handled by other creator subclasses.

Page 348 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 16 Java Design Patterns — Creational Patterns

«interface» Client Creator


Product

factoryMethod()

«create»
ConcreteProduct ConcreteCreator

factoryMethod()

[Link]
public interface Product {
public void whatAmI();
}

[Link]
public class MyProduct implements Product {
public void whatAmI() {
[Link]("I'm a MyProduct");
}
}

[Link]
public class OtherProduct implements Product {
public void whatAmI() {
[Link]("I'm an OtherProduct");
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 349


Advanced Java Programming

Factory Method — Implementation

” There are two primary implementations of this pattern.

¾ In the first, the factory method in the base class is abstract.

ƒ This option is used when there is no reasonable default


implementation of the factory method.

¾ The second style provides a default factory method in the base class.

ƒ Subclasses may choose to override this factory method.

ƒ The base class could also be marked as abstract, forcing


subclasses to be used even though the factory method was
implemented in the base class.

” Factory methods can also accept parameters.

¾ The parameter could indicate which concrete product to create.

¾ Creator subclasses are rarely used in this case.

” Factories implemented in Java often use other means to determine which


concrete product to create.

¾ Property files are commonly used.

ƒ A property value could be a product classname that can be used to


dynamically instantiate an object via reflection.

¾ Values from a database or JNDI server could be used as well.

Page 350 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 16 Java Design Patterns — Creational Patterns

[Link]
...
public class DynamicFactory {
private static final String DEFAULT = "MyProduct";
Factory method.
public Product createProduct() {
String product = getProductName();
Product p = null;
try {
Class clazz = [Link](product);
p = (Product) [Link]();
}
...
return p;
}
private String getProductName() {
Properties p = new Properties();
String productToCreate = DEFAULT;
try {
FileInputStream inputStream = new Get product name
FileInputStream("[Link]"); from .properties file.
if (inputStream != null) {
[Link](inputStream);
productToCreate = [Link]("product");
}
}
catch (IOException ignore) { }

return productToCreate;
}
public static void main(String[] args) {
DynamicFactory df = new DynamicFactory();
Product p = [Link]();
...
}
}

[Link]
product=OtherProduct

Try It:
Compile [Link] as well as [Link], [Link] and [Link]. Run
DynamicFactory. Delete [Link] and run it again.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 351


Advanced Java Programming

Factory Method — When to Use?

” Anytime a system can be made more flexible by separating object creation from
object use, think of using a factory.

” If new subclasses within a hierarchy are expected to be added in the future, the
use of a factory method can insulate the rest of the application from this churn.

¾ This is a common driving force in the application of design patterns:


separate the things that change from those that do not.

¾ The client application will not need to be changed if the impact of the
addition of a new subclass can be isolated to the factory method.

” Creational patterns often complement each other.

¾ Be aware of opportunities to leverage the use of several cooperating


patterns.

¾ This also applies across all three pattern types (Creational, Structural, and
Behavioral).

Page 352 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 16 Java Design Patterns — Creational Patterns

EJBHome interfaces contain create() methods, which are factory methods used to create Enterprise
JavaBeans.

The [Link] is an interface that can be used to pass a concrete creator


with a factory method to a URL. The URL will then use this factory method to create a stream protocol
handler.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 353


Advanced Java Programming

Builder — Introduction

” If you need to create a variety of complex objects, the builder pattern can
separate the construction process from the rest of your code.

¾ An abstract builder class describes the methods required to build the


individual parts of the complex object.

¾ Concrete builders implement those methods, encapsulating the


construction details and the resulting data representation (e.g., a flatfile, an
XML file, etc.).

¾ A director class is used to control the construction sequence and provide


the content to the builder.

” The client application communicates with the director and a concrete builder.

¾ The client creates a concrete builder.

ƒ The builder base class often provides a static method to return a


concrete derived class.

¾ The builder is given to the director, which uses the builder within its
internal algorithm.

¾ The director has the content for the complex object, or knows how to get
it.

¾ Finally, the client asks the director for the complex object.

Page 354 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 16 Java Design Patterns — Creational Patterns

c: Client Builder

getInstance(param) new
cb: ConcreteBuilder
cb
new(cb)
d: Director

build()

buildPartA(x)
buildPartB(y)
buildPartC(z)
getProduct()
complexProduct
complexProduct

UML sequence diagram of the Builder pattern.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 355


Advanced Java Programming

Builder — Implementation

” There are several options for creating the concrete builders.

¾ The client can instantiate a builder itself.

¾ The client can ask the builder base class for a concrete builder based on
an input parameter.

¾ A factory method could be used instead.

” The mechanism used to return the complex object may vary.

¾ The client could ask the director for the object explicitly.

¾ The construction method could return the object as the return argument.

Page 356 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 16 Java Design Patterns — Creational Patterns

Director Builder
«create»
-builder Client -file:File
+Director(Builder) +getInstance(format)
+construct():File +buildPartA()
+buildPartB()
«interface» +buildPartC()
File +getFile()

«create» FlatFileBuilder XMLFileBuilder


XMLFile FlatFile
+buildPartA() +buildPartA()
+buildPartB() +buildPartB()
+buildPartC() +buildPartC()

«create»

© 2011 ITCourseware, LLC Rev 5.1.4 Page 357


Advanced Java Programming

Builder — When to Use?

” When you have an algorithm that controls the object creation process you
should investigate the possible application of the builder pattern.

¾ The algorithm should be separable from the details of the process.

” There should be at least two complex product types or the strong possibility
that new types will be added.

¾ The different complex product types may have a common base class or
may be so different that it does not make sense to factor out a superclass.

ƒ For example, the builder pattern could be used to convert an RTF


document to ASCII, PDF, XML, etc.

¾ Sometimes data is simply appended to the complex object (e.g., the


document conversion program).

” The builder pattern may be used to create a complex collaboration of objects.

¾ Entire GUI screens can be created via builders.

¾ The composite pattern is often used to represent complex objects.

ƒ Look for opportunities to use these patterns together.

Page 358 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 16 Java Design Patterns — Creational Patterns

The builder pattern is used by the [Link] package in the creation of certificate chains.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 359


Advanced Java Programming

Labs

Run the HumanResourcesApp that is located in the chapter directory. It is designed to handle
incoming requests via separate threads (like a servlet) and create a unique employee id for each
request. It does not work correctly. Fix it by applying the appropriate pattern.
(Solutions: [Link], [Link])

† Modify your code from to allow your program to create ids that start from zero (like in
) or start from a number that is read from a property file. Hint: Use the factory method
pattern to use one of two singletons based on the existence of the property file.
(Solutions: [Link], [Link], [Link],
[Link], [Link], [Link], [Link])

‡ Run BuilderWannabe from the chapter directory and investigate the code. Refactor this class
to a pattern. emember that refactoring is taking code that works and changing it so that it is
better organized with respect to readability and maintenence without changing the behavior.
(Solutions: [Link], [Link], [Link], [Link],
[Link], [Link], [Link], [Link])

Page 360 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 16 Java Design Patterns — Creational Patterns

© 2011 ITCourseware, LLC Rev 5.1.4 Page 361


Advanced Java Programming

Page 362 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 17 Java Design Patterns — Structural Patterns

Chapter 17 - Java Design Patterns —


Structural Patterns

Objectives
” Describe the purpose of Structural
Patterns.

” Implement the Façade pattern to


provide a simple interface to a
subsystem.

” Use the Adapter pattern to convert


from one interface to another.

” Create hierarchical designs with the


Composite pattern.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 363


Advanced Java Programming

What Are Structural Patterns?

” Structural patterns deal with building larger structures by combining classes


and objects.

” There are two types of structural patterns: class and object.

¾ Structural class patterns are centered on the use of inheritance.

ƒ Abstract classes or interfaces are typically defined at the root of the


structure.

ƒ Their basis in inheritance allows these patterns to take advantage of


polymorphism.

ƒ The drawback to this model is that the structure is set at compile


time.

¾ Structural object patterns compose their structures at runtime.

ƒ You gain flexibility by allowing the structure to dynamically


change.

ƒ As new functionality is needed, these patterns can adapt without


affecting other code.

ƒ Favoring composition over inheritance is a common goal


throughout many patterns.

Page 364 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 17 Java Design Patterns — Structural Patterns

© 2011 ITCourseware, LLC Rev 5.1.4 Page 365


Advanced Java Programming

Façade — Introduction

” Complex applications are often composed of multiple smaller subsystems.

¾ Within each subsystem, you define public classes with public methods
that are accessible to other subsystems.

ƒ This leads to high coupling between subsystems.

ƒ If you change the public interface defined by a class in one


subsystem, that change can cascade to other dependent subsystems.

” The façade pattern allows you to create a single, simple interface to an entire
subsystem.

¾ Your clients can use the façade if they want an easy-to-use, unified way of
accessing the most common functionality of the subsystem.

ƒ The façade hides the details and complexity of the subsystem.

¾ You can still allow for bypassing the façade for those clients that would
like to continue communicating directly with the underlying classes.

ƒ This allows you to expose advanced functionality not available


through the façade.

Page 366 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 17 Java Design Patterns — Structural Patterns

Client

Façade
subsystem classes

© 2011 ITCourseware, LLC Rev 5.1.4 Page 367


Advanced Java Programming

Façade — Implementation

” Implementing the façade pattern in Java involves creating an additional public


class for each façade you intend to develop.

¾ Within that class, define public methods for the functionality that you
intend to expose.

¾ Your method implementation can:

ƒ Forward or delegate requests to the underlying subsystem methods


without modification.

ƒ Add extra functionality, such as logging or auditing.

ƒ Translate calls that have been exposed in the simple façade interface
to the more complex signatures of the underlying methods.

ƒ Simplify the interface to clients by giving a series of subsystem


method calls a single, course-grained entry point.

” If your subsystem is made up of a single package, you can take advantage of


Java's package access control when building your façade.

¾ You should mark the façade and its methods as public.

¾ Any methods and classes that should not be available to external clients
should use package or private access control rather than public.

ƒ If you choose to allow expert users to bypass the façade, then mark
those classes and methods as public, as well.

” You should use the singleton pattern to handle object creation, because you will
typically only need one façade instance per subsystem.

Page 368 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 17 Java Design Patterns — Structural Patterns

[Link]
import [Link].*;

public class IOFacade {


...
public void writeToTextFile(String filename, String text)
throws IOException {

PrintWriter out = null;


boolean append = true;

try {
File file = new File(filename);
out = new PrintWriter(new BufferedWriter(
new FileWriter(file, append))); This façade simplifies
[Link](text); the process of writing to
} a text or binary file.
catch (IOException e) {
log(e);
throw e;
}
finally {
[Link]();
}
}
public void writeToBinaryFile(String filename, byte[] bytes)
throws IOException {

BufferedOutputStream out = null;


boolean append = true;

try {
File file = new File(filename);
out = new BufferedOutputStream(
new FileOutputStream(file, append));
[Link](bytes);
}
catch (IOException e) {
log(e);
throw e;
}
finally {
...
}
}
...
}
© 2011 ITCourseware, LLC Rev 5.1.4 Page 369
Advanced Java Programming

Façade — When to Use?

” Use the façade pattern if you want to expose an easy-to-understand interface to


clients of your subsystem, rather than requiring them to understand the details of
each public class within it.

¾ The façade is the application programming interface (API) for your


subsystem.

¾ It allows you to present a complex system in a simple way.

ƒ Not all clients will need all of the functionality.

ƒ A method in the façade can invoke multiple methods on the


subsystem.

” Use the façade pattern to decouple the class implementations from their external
clients.

¾ Changes to the underlying code will not impact external clients that use the
façade.

Page 370 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 17 Java Design Patterns — Structural Patterns

[Link]
public class FacadeClient {
public static void main(String[] args) {
IOFacade facade = [Link]();
String text = "To be, or not to be: that is the question";
byte[] bytes = {70, 65, 67, 65, 68, 69, 1, 1, 1};
This client uses the façade to simplify writing to a file.
try {
[Link]("[Link]", text);
[Link]("[Link]", bytes);
}
catch (Exception e) {
[Link](e);
}
}
}

[Link]
public class AdvancedClient {
public static void main(String[] args) {
String s = "To sleep: perchance to dream: ay, there's the rub;\n";
insertTextInFile("[Link]", s, 395);
}
This client bypasses the
private static void insertTextInFile(String filename, façade because it needs
String textToInsert, int position) { advanced functionality that
the façade does not expose.
RandomAccessFile rac = null;
try {
rac = new RandomAccessFile(new File(filename), "rw");

int currentFileLength = (int)[Link]();


int numCharsInRestOfFile = currentFileLength - position;
byte[] savedText = new byte[numCharsInRestOfFile];

[Link](position);
[Link](savedText);

[Link](position);
[Link](textToInsert);
[Link](new String(savedText));
...
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 371


Advanced Java Programming

Adapter — Introduction

” When incorporating an existing class into an application, you must decide how
to merge the existing class' interface with the interface that you would have used
if you were writing the code from scratch.

¾ You may be tempted to modify your design to embrace the existing class'
interface.

ƒ Client code would be tightly coupled to the existing class.

ƒ Method signatures could be awkward, because you've made your


new code backwards compatible with the existing class' interface.

¾ If you have access to the source code, you could modify the existing class
to more closely match the new design.

ƒ The existing class may have legacy clients that would be affected.

¾ You can use the adapter pattern to leverage a design that has been used
thousands of times to address this exact dilemma.

” The adapter pattern allows you to convert a class' interface into an interface that
is more compatible with your design.

¾ An adapter serves as a translator, receiving requests from clients and


forwarding them on to the existing class, the adaptee.

¾ With the adapter in place, neither the client class nor the existing class
would need to be modified.

¾ The adapter also serves as a wrapper; it allows you to swap the adaptee
without affecting the client.

Page 372 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 17 Java Design Patterns — Structural Patterns

There are two types of adapters: object adapters and class adapters.

With object adapters, an adaptee instance is stored within the adapter. Whenever a method is invoked on
the adapter, it delegates the request to the adaptee. The client typically references a parent interface (or
abstract class) that the adapter implements (or extends) to decouple the client from the adapter and allow
for polymorphism.

With a class adapter, the adapter inherits from both the adaptee and the target that the client
references. Any calls to the adapter method are forwarded directly to the corresponding method within the
adaptee.

In the diagram below, the Target represents the interface that the Client interacts with, but the Adapter
relies on the Adaptee to provide the actual implementation.

«interface»
Client Target

request()

Adapter Adaptee

request() specificRequest()

public void request() {


[Link]();
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 373


Advanced Java Programming

Adapter — Implementation

” Implementing the object adapter pattern in Java involves two classes and one
interface.

¾ Create an interface that defines the method(s) that the client expects to
call.

¾ Implement the interface in your adapter class.

ƒ Initialize a reference to the adaptee in the adapter's constructor.

ƒ Delegate each interface method call to the corresponding adaptee's


method.

ƒ Your adapter can also add additional methods that aren't available
in the adaptee.

¾ The adaptee class remains unchanged.

Page 374 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 17 Java Design Patterns — Structural Patterns

AdapterClient «interface»
[Link]
main()
add()
addAll()
clear()
contains()
containsAll()
isEmpty()
iterator()
...

GenericArrayAdapter GenericArray
adaptee:GenericArray addElement()
add() indexOfObject()
addAll() getArray()
clear() getElement()
contains() getLength()
containsAll() getSize()
isEmpty() removeElement()
iterator() removeAllElement()
...

[Link]
...
public class GenericArrayAdapter<E> implements Collection<E> {
private GenericArray<E> adaptee;

public GenericArrayAdapter() {
adaptee = new GenericArray<E>();
}
public GenericArrayAdapter(int initialSize) {
adaptee = new GenericArray<E>(initialSize);
}

public boolean add(E o) {


[Link](o);
return true;
The adapter translates
} calls to the adaptee.
...
public void clear() {
[Link]();
}
...
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 375


Advanced Java Programming

Adapter — When to Use?

” Use the adapter pattern any time you want to convert from one interface to
another.

¾ The adapter will translate an incompatible interface in an existing class to


a domain-specific interface.

” Use the object adapter pattern if you would like to dynamically substitute the
adaptee.

¾ The adaptee reference that is contained by the adapter can actually refer to
any children of the adaptee, as well.

” The adapter pattern can be confused with the façade pattern, because both
provide wrapping behavior, but the intent of each pattern is different:

¾ A façade defines a simple interface for a subsystem.

¾ An adapter converts one interface to another.

Page 376 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 17 Java Design Patterns — Structural Patterns

[Link]
public class GenericArray<T> {
private T[] array;
private int currentIndex = 0;
The GenericArray is our
private int initialSize = 0;
"legacy" class that serves as
the adaptee. It does not
public GenericArray() { implement Collection.
this(1000);
}
public GenericArray(int size) {
initialSize = size;
array = getNewArray(initialSize);
}

public void addElement(T element) {


array[currentIndex++] = element;
}
...
public void removeAllElements() {
array = getNewArray(initialSize);
currentIndex = 0;
}
...
}

[Link]
...
public class AdapterClient { The adapter
makes our
public static void main(String[] args) {
GenericArray
Collection<String> c1 = new ArrayList<String>(); compatible with
populateCollection(c1); Collection.
printCollection(c1);
Collection<String> c2 = new GenericArrayAdapter<String>();
populateCollection(c2);
printCollection(c2);
}
private static void populateCollection(Collection<String> c) {
[Link]("Class " + [Link]().toString());
[Link]("HashCode " + [Link]());
}
private static void printCollection(Collection<String> c) {
Iterator it = [Link]();
while ([Link]()) {
[Link]([Link]());
}
}
}
© 2011 ITCourseware, LLC Rev 5.1.4 Page 377
Advanced Java Programming

Composite — Introduction

” Complex application designs sometimes yield part-whole relationships that are


implemented as tree structures.

¾ XML DOM trees are typical examples.

” Clients interacting with the tree structure would benefit if they could treat branch
and leaf nodes identically.

¾ Otherwise, client code would have to use conditional statements to


determine what kind of object they are currently traversing and treat it
accordingly.

” The composite pattern allows you to represent part-whole relationships as tree


structures, where clients work with nodes of the tree identically.

¾ The pattern consists of component, leaf, and composite classes.

ƒ The component class defines the common interface that clients


interact with.

ƒ Each leaf instance inherits from component and represents a node


in the tree without children.

ƒ The composite also inherits from component and is responsible for


storing child components.

¾ Your client code only depends on the component's interface.

ƒ Any additional leaf or composites added to the tree will not affect
the client code.

ƒ Your client code should not know or care if it is dealing with a leaf
or a composite at any time.

Page 378 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 17 Java Design Patterns — Structural Patterns

The class diagram below illustrates the fact that the client always interacts with the base Component
class.

CompositeClient Component

main() operation()
add(Component)
remove(Component)
getChild(int)

Leaf Composite

operation() operation()
add(Component)
remove(Component)
getChild(int)

This object diagram shows how the composite pattern manifests itself at runtime:

:Client :Composite

:Leaf :Composite :Leaf

:Leaf :Leaf :Leaf

© 2011 ITCourseware, LLC Rev 5.1.4 Page 379


Advanced Java Programming

Composite — Implementation

” You should implement the component as an abstract class where each method
defines default behavior.

¾ Code each method so it throws an exception that identifies it as an


unsupported method.

¾ Alternatively, the methods could provide no-op implementations.

” Your composite's primary responsibility is to support addition, removal, and


retrieval of child nodes.

¾ Extend the component and override the appropriate methods to support


this behavior.

ƒ Store children in an appropriate data structure, such as an


ArrayList.

¾ Also override any other methods to recursively call the same methods on
the stored child nodes.

” The leaf is only responsible for defining the non-child-related methods.

¾ Use the default implementations in component to return an "unsupported"


exception to the client if one of these methods is invoked.

” You can define an extra field and methods within the component to manage a
reference to its parent.

¾ This can make traversal and cleanup easier.

Page 380 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 17 Java Design Patterns — Structural Patterns

CompositeClient ArithmeticComponent

main() evaluate()
add(ArithmeticComponent)
remove(ArithmeticComponent)
getChild(int)

Operand Operator
op:int children:ArrayList
operator:String
evaluate()
evaluate()
add(Component)
remove(Component)
getChild(int)

[Link]
public abstract class ArithmeticComponent { Each method in the component
public void add(ArithmeticComponent component) { class throws an
UnsupportedOperationException.
throw new UnsupportedOperationException();
}
public void remove(ArithmeticComponent component) {
throw new UnsupportedOperationException();
}
public ArithmeticComponent getChild(int i) {
throw new UnsupportedOperationException();
}
public int evaluate() {
throw new UnsupportedOperationException();
}
}

Note:
The methods in the component class deal with maintaining child nodes and exposing the logic that each
leaf defines. These two distinct responsibilities make the component class less cohesive than most
designers would like. In fact, defining methods in a parent class that are not applicable to a child class is also
typically considered bad design. The composite pattern accepts this practice in the name of transparency.
Clients work with leaves and composites without needing to understand which type they are working with at
the expense of safety. A client may try to add a child to a leaf and get a runtime exception.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 381


Advanced Java Programming

Composite — When to Use?

” Use the composite pattern whenever you need to define a part-whole tree
structure where clients access the leaves and branches of the tree in the same
way.

¾ The parent component class defines methods that are visible to clients and
inherited by child leafs and composites.

” The Java libraries contain multiple examples of composites:

¾ AWT uses the composite pattern to model the user interface component
hierarchy.

ƒ Components, such as Buttons and TextAreas, make up leaf


nodes, while other Components (Containers), such as Panels and
Frames, are composites.

ƒ When a Frame is asked to display itself, it recursively asks its


children to do the same.

¾ The Document Object Model (DOM) API defined in the [Link]


package also uses the composite pattern.

ƒ Nodes such as Text and Attr serve as leaf nodes, while Elements
and Documents are composites.

ƒ The getChildNodes() method defined in Node returns all children


of a composite and an empty NodeList for a leaf.

¾ The Java Naming and Directory Interface (JNDI) API defined in the
[Link] package is another example of the composite pattern.

ƒ A Context serves as the composite and a Binding represents a leaf.

Page 382 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 17 Java Design Patterns — Structural Patterns

[Link]
public class Operand extends ArithmeticComponent {
private int op; This is a
... leaf class.
public int evaluate() {
return op;
}
}

[Link] This is a
... composite class.
public class Operator extends ArithmeticComponent {
private ArrayList<ArithmeticComponent> children;
private String operator;

public Operator(String operator) {


[Link] = operator;
children = new ArrayList<ArithmeticComponent>();
}
public void add(ArithmeticComponent component) {
[Link](component);
} Composites store
children in an
...
internal list.
public int evaluate() {
int result = 0;
boolean firstChild = true;
Iterator<ArithmeticComponent> it = [Link]();
while ([Link]()) {
ArithmeticComponent comp = [Link]();

if (firstChild == true) {
result = [Link]();
firstChild = false; Composites typically
continue; use recursion.
}
if ([Link]("+"))
result += [Link]();
...
}
return result;
}
}

Try It:
Compile and run [Link] to test out the composite design pattern implementation.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 383


Advanced Java Programming

Labs

Modify [Link] to write out an object using object serialization in addition to writing
text and binary files.
(Solution: [Link])

† Test the new functionality you added in .


(Solution: [Link])

‡ [Link] is incomplete. It throws an UnsupportedOperationException if a


client calls the remove() or removeAll() methods. Add the proper functionality to both methods
using GenericArray as the adaptee.
(Solution: [Link])

ˆ Test the remove() and removeAll() methods that you added in ‡.


(Solution: [Link])

‰ Add print functionality to the composite example that was covered in the chapter so that the
actual expression to evaluate can be displayed to the screen.
(Solutions: [Link], [Link], [Link])

Š Write an application that tests the print() method you added in ‰.


(Solution: [Link])

Page 384 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 17 Java Design Patterns — Structural Patterns

© 2011 ITCourseware, LLC Rev 5.1.4 Page 385


Advanced Java Programming

Page 386 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 18 Java Design Patterns — Behavioral Patterns

Chapter 18 - Java Design Patterns —


Behavioral Patterns

Objectives
” Describe the purpose of Behavioral
Patterns.

” Use the Template Method pattern to define


the major steps of an algorithm in a
superclass and allow subclasses to
implement some or all of the steps.

” Convert a UML state diagram into Java


code using the State pattern.

” Use the Observer pattern to keep multiple


display objects consistent with the
underlying data that they are presenting.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 387


Advanced Java Programming

What Are Behavioral Patterns?

” Behavioral patterns deal with distributing responsibilities among the objects in


your system.

¾ They are concerned with how objects communicate with each other and
encapsulate flow control.

¾ As their name implies, they deal with the behavior of your system, not the
structure or creation.

” Just like creational and structural patterns, behavioral patterns come in two
varieties: class behavioral and object behavioral.

¾ Class behavioral patterns use inheritance to model flow control.

¾ Object behavioral patterns use composition to spread behavioral


responsibility between objects.

Page 388 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 18 Java Design Patterns — Behavioral Patterns

© 2011 ITCourseware, LLC Rev 5.1.4 Page 389


Advanced Java Programming

Template — Introduction

” Most algorithms are made up of a series of individual steps, where each step
defines a portion of the algorithm.

¾ The algorithm can be defined in a class, where each step is embedded


within a method.

” When you have multiple similar algorithms that contain the same series of steps
in the same order, but one or more of the individual steps has to be implemented
differently, you have several implementation choices:

¾ Rookie programmers would duplicate the common code across two


classes.

¾ Structured programmers might implement the algorithm with an if or a


switch statement that controls when to invoke each of the steps that vary.

¾ Object-oriented programmers may recognize an opportunity to use


inheritance to extract the common functionality into a superclass and
place the code that varies into subclasses.

¾ Enlightened OO developers with knowledge of design patterns (you!)


would see this as the perfect opportunity to apply the template method
design pattern.

” The template method pattern defines a framework for an algorithm in a


superclass and defers to subclasses to vary one or more steps of the algorithm.

¾ Use a template method in the superclass (which contains calls to each of


the methods that make up the algorithm) to define the order of the steps.

¾ Define each step as a method in the superclass.

¾ You can substitute a new implementation for some or all of the superclass
methods by overriding them in a subclass.
Page 390 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 18 Java Design Patterns — Behavioral Patterns

When using this pattern, a client will call the template method that is inherited from the superclass. The
template method will invoke methods in the superclass and subclass as necessary. The subclass methods do
not call the superclass methods unless they've been called first. Even then, the call would be through the
implicit super reference. This model is often referred to as the Hollywood principle: "Don't call us, we'll
call you."

The diagram below uses the term "primitive method" to identify those methods which make up the
individual steps of the algorithm and whose implementation is deferred to a subclass.

AbstractClass

templateMethod() public void templateMethod {


primitiveMethod1() primitiveMethod1();
primitiveMethod2() concreteMethod()
concreteMethod() primitiveMethod2();
}

ConcreteClass ConcreteClass2

primitiveMethod1() primitiveMethod1()
primitiveMethod2() primitiveMethod2()

© 2011 ITCourseware, LLC Rev 5.1.4 Page 391


Advanced Java Programming

Template — Implementation

” To implement this pattern, you should declare an abstract class with methods
for each step in the algorithm.

¾ Mark each method as abstract if its implementation will be deferred to


the subclass.

ƒ These methods are often referred to as primitive methods.

¾ Implement methods that contain common, or default, functionality in the


superclass; these methods are called concrete methods.

¾ You can also provide hook methods in the superclass.

ƒ A hook is a concrete method with an empty implementation that can


optionally be overridden in a subclass whose algorithm requires it.

¾ Each method should be protected: clients should access the template


method, not the individual primitive and concrete methods.

” You should write the template method as a public, final member of the
superclass.

¾ Your template method will call the algorithm methods in the appropriate
order.

” Create one or more subclasses that override any abstract methods, providing
concrete implementations.

¾ You can also override hook methods if you would like.

Page 392 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 18 Java Design Patterns — Behavioral Patterns

[Link]
import [Link];
import [Link];
import [Link]; template method

public abstract class DatabaseAccessTemplate {


public void executeSQL(String driverClass, String url, String sql,
String username, String password) {
Connection conn = null;
Statement stmt = null;
try {
conn = createConnection(driverClass, url, username, password);
stmt = createStatement(conn);
runStatement(stmt, sql);
processResults();
}
catch (Exception e) {
[Link](e);
}
finally {
cleanup(stmt, conn);
} primitive method
}
protected abstract void runStatement(Statement stmt, String sql)
throws Exception; hook method
protected void processResults() throws Exception {
}
protected Connection createConnection(String driverClass,
String url, String user, String pw) throws Exception {
[Link](driverClass);
Connection conn = [Link](url, user, pw);
return conn;
}
protected Statement createStatement(Connection c) throws Exception {
Statement stmt = [Link]();
return stmt;
}
protected final void cleanup(Statement stmt, Connection conn) {
try {
[Link](); concrete methods
[Link]();
}
catch (Exception e) {
[Link](e);
}
}
}
© 2011 ITCourseware, LLC Rev 5.1.4 Page 393
Advanced Java Programming

Template — When to Use?

” Use the template method pattern when you want to define the constant parts of
an algorithm once in a superclass and allow the parts that vary to be defined by
subclasses.

¾ The parts that vary are embedded in primitive methods and hooks.

ƒ Use hooks to define optional behavior.

” This pattern makes sense when you want control of the order of an algorithm,
providing opportunities for overriding certain parts.

” The template method pattern can be created as a result of refactoring.

¾ You may find situations where many classes have the same behavior.

¾ Refactor the commonality into a superclass using the template method


pattern.

¾ Keep the differences in the subclasses by overriding the primitive


methods.

” The Java libraries use the template method in applets:

¾ When you write an applet, you extend the [Link] class.

¾ You override the init(), start(), and stop() methods to provide the applet's
implementation.

¾ The template method is defined within Applet itself and guarantees that it
will call init() first, then start(), then stop().

Page 394 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 18 Java Design Patterns — Behavioral Patterns

[Link]
public class TemplateClient {
public static void main(String[] args) {
String driverClass = "[Link]";
String url = "jdbc:derby://localhost:1527/j2se";
String username = null;
String password = null;
DatabaseAccessTemplate db = new DML();
String sql = "UPDATE Employee SET lastname='Smith' WHERE id=9883";
[Link](driverClass, url, sql, username, password);
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 395


Advanced Java Programming

State — Introduction

” The term state is typically defined as an object's awareness of its attributes.

¾ Designers model the state that affects an object's behavior with a state
machine.
power button press

power button press

key press
Active
Standby
Hibernate
Shutdown
standby
hibernate
shutdown

¾ In the above state machine, a computer can be in one of four different


states, as identified by the rounded rectangles.

¾ The arrows represent state transitions.

” You may choose to implement your state machine with a series of conditional
statements.

¾ When you add an additional state or transition, the change will propagate
throughout each of the conditionals.

” The state pattern defines a mechanism that objects use to change their behavior
based on changes to the state of the system.

¾ The object will refer to a different state object each time a transition
occurs.

ƒ The state object will embed the logic applicable to that state.

ƒ Any method calls on the base object will be forwarded to the


current state object.
Page 396 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 18 Java Design Patterns — Behavioral Patterns

Context «interface»
State
state:State
request() handle()

public void request { ConcreteStateA ConcreteStateB


[Link]();
} handle() handle()

© 2011 ITCourseware, LLC Rev 5.1.4 Page 397


Advanced Java Programming

State — Implementation

” At the core of the state pattern implementation is an interface where you define
the common methods to all of the states.

” For each state you plan to support, create a concrete class that implements the
interface.

” Finally, create a "context" class whose state you are trying to abstract.

¾ Store a reference to the state interface as a field that is initialized to the


initial state of the system.

¾ Delegate state-specific methods to the current state object.

” You have two choices for who should create the state objects:

¾ You could create each state as it is needed, especially if you anticipate


having few state transitions or if some states may never be used.

¾ Alternatively, you could store all of the state instances within the context
class.

ƒ Do this if your system will change states often to keep from


creating and destroying the same objects repeatedly.

” Another choice to make is who should control the state transitions.

¾ The context class can handle this responsibility, provided that there are a
fixed number of transitions.

¾ The state classes themselves could know which state comes next, thereby
adding coupling between the individual states.

ƒ You will have to add a method to the context class that the state can
call to change states.
Page 398 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 18 Java Design Patterns — Behavioral Patterns

Computer «interface»
State
currentState:State
hibernate() hibernate()
keyPress() keyPress()
powerOn() powerOn()
shutdown() shutdown()
standBy() standBy()
setState(State)
...

ActiveState HibernateState ShutdownState StandByState

hibernate() hibernate() hibernate() hibernate()


keyPress() keyPress() keyPress() keyPress()
powerOn() powerOn() powerOn() powerOn()
shutdown() shutdown() shutdown() shutdown()
standBy() standBy() standBy() standBy()

[Link]
public class Computer {
State activeState = new ActiveState(this);
State hibernateState = new HibernateState(this);
State shutdownState = new ShutdownState(this); We will store all of
State standByState = new StandByState(this); our state instances in
State currentState; the context object.

public Computer() {
currentState = shutdownState; The initial state of the
} system is set to shutdown.
public void hibernate() {
[Link]();
}
public void keyPress() {
[Link]();
}
public void powerOn() {
[Link]();
}
...
public void setState(State state) {
currentState = state;
}
...
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 399


Advanced Java Programming

State — When to Use?

” Use the state pattern when designing a system with objects whose behavior
changes at runtime based on their current state.

” Use the state pattern when you are refactoring existing code that contains
conditional statements that depend on the state of an object.

¾ The state pattern isolates changes to the state objects themselves, rather
than spread the change across conditional statements.

ƒ Adding a new state is easy; just add a new state class.

ƒ All state information is embedded in the state object itself.

” Each state object is usually implemented as a singleton, since they typically


contain client-independent operations.

Page 400 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 18 Java Design Patterns — Behavioral Patterns

[Link]
public interface State {
public void hibernate();
public void keyPress();
public void powerOn();
public void shutdown();
public void standBy();
}

[Link]
public class ShutdownState implements State {
private Computer computer;

public ShutdownState(Computer comp) {


computer = comp;
}

public void hibernate() {


[Link]("You can't hibernate a shutdown computer");
}
public void keyPress() {
[Link]("Keypress doesn't wake a shutdown computer");
}
public void powerOn() {
[Link]("Starting up. . .");
[Link]([Link]()); Modify the
computer's class.
}
public void shutdown() {
[Link]("You can't shutdown a shutdown computer");
}
public void standBy() {
[Link]("You can't standby a shutdown computer");
}
}

Try It:
Compile and run [Link] to see each state and transition exercised.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 401


Advanced Java Programming

Observer — Introduction

” When designing user interfaces, it may be necessary to display the same


information in multiple ways.

¾ Two challenging design tasks are:

ƒ Keeping each display consistent with the underlying data.

ƒ Adding a new display so that its addition does not propagate


change into any other code.

” Use the observer pattern to define a relationship between an object that contains
state, and one or more objects that need to be notified when that state changes.

¾ Objects that are notified of state changes are call observers.

¾ The object that contains the state of interest is called the subject (or
observable).

” Each of your observers is responsible for updating itself each time a notification
occurs.

¾ This ensures that each observer remains consistent with the underlying
subject.

” Adding additional observers is easy because the subject maintains a list that can
be dynamically added to and removed from.

¾ Each observer instance you write will implement a parent interface that
defines the method that is called by the subject when a notification occurs.

” You may also have heard of this pattern referred to as the publish-subscribe
pattern.

¾ The subject is the publisher and each observer is a subscriber.


Page 402 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 18 Java Design Patterns — Behavioral Patterns

«interface» «interface»
Subject Observer

addObserver() update()
removeObserver()
notify()

ConcreteSubject
subject ConcreteObserver
listOfObservers
state
update()
addObserver()
removeObserver()
notifyObservers()
getState()
setState()
public void notify() {
Iterator<Observer> it = [Link]();
while ([Link]()) {
Observer obs = [Link]();
[Link]();
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 403


Advanced Java Programming

Observer — Implementation

” Implementing the observer pattern involves creating two interfaces and at least
two concrete classes.

” You should create an interface to define the subject's addObserver(),


removeObserver(), and notify() methods.

” Write another interface that specifies the update() method for the observer(s).

” You will build one concrete class that implements the subject's interface.

¾ Register the observer with the subject by storing it into a Collection when
the addObserver() method is called, using the observer interface as the
datatype for the Collection.

¾ Remove the observer from the Collection when removeObserver() is


called.

¾ Your notify() method should iterate through all registered observers and
call the update() method on them.

ƒ Call the notify() method whenever this object's state changes,


usually within a setXXX() method.

ƒ Alternatively, your client can call the notify() method when it has
completed all changes to the subject.

” Write at least one concrete observer class that implements the update() method
from your observer interface.

¾ Pass a reference to the subject into the constructor and register the
observer with the subject by calling the subject's addObserver() method.

¾ Within the update() method you should query the subject for new state
information.
Page 404 Rev 5.1.4 © 2011 ITCourseware, LLC
Chapter 18 Java Design Patterns — Behavioral Patterns

«interface» «interface»
Subject Observer

addObserver() update()
removeObserver()
notify()

BankAccount
subject CurrentBalancePanel
listOfObservers:List
balance:double update()
addObserver() ...
removeObserver()
notifyObservers() subject
getBalance() StatusPanel
setBalance()
update()
...

[Link]
public interface Subject {
public void addObserver(Observer observer);
public void removeObserver(Observer observer);
public void notifyObservers();
}

[Link]
public interface Observer {
public void update();
}

Note:
If you find that introducing this pattern has introduced too many calls to the update() method, then you may
need to modify the pattern. The pattern as described uses a "pull" method to update the observer. The
observer calls getXXX() methods on the subject to determine what state has changed; the subject is
unaware of what data the observer is interested in.

An alternate design would use a "push" model instead. The state that has changed could be passed directly
to the update() method. The drawback to this model is that the coupling of the system has increased; the
subject knows what the observers needs.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 405


Advanced Java Programming

Observer — When to Use?

” You should use the observer pattern when you have, or anticipate having, two
or more different views on underlying data.

¾ This pattern loosely couples the subject to the observers.

ƒ The subject only knows about the parent interface that all observers
implement.

ƒ The observers store a reference to the subject and call get()


methods on it when notified of state changes.

¾ You can still get the loose coupling benefit of this pattern even if you only
have one observer.

” You should use the observer pattern when you want to be able to add new
observers without changing the subject code.

¾ The subject merely stores a collection of objects that implement the


observer interface and calls update() on each of them as part of the
notification process.

Page 406 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 18 Java Design Patterns — Behavioral Patterns

[Link]
...
public class CurrentBalancePanel extends JPanel implements Observer {
private Subject subject;
private JLabel balanceLabel;

public CurrentBalancePanel(Subject subject) {


The observer stores a
[Link] = subject; reference to the subject.
balanceLabel = new JLabel();
[Link](new JLabel("Current Balance: "));
[Link](balanceLabel);
[Link](this);
}

public void update() {


double currentBalance = ((BankAccount)subject).getBalance();
[Link]("" + currentBalance);
}
}

[Link]
...
public void update() {
double currentBalance = ((BankAccount)subject).getBalance();

if (currentBalance < 0) {
[Link]([Link]());
[Link]([Link]());
[Link]([Link]);
}
...
}
...

Try It:
Compile and run [Link]. Press the deposit and withdraw buttons to change the account balance.
Watch the display to see the StatusPanel and CurrentBalancePanel automatically update themselves
whenever the balance changes.

Note:
Java has built-in support for the observer pattern within the [Link] package as defined by the
Observable class and Observer interface.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 407


Advanced Java Programming

Labs

Modify the template method example that was discussed in the chapter. Create a new class called
[Link] that subclasses [Link]. Your new class should execute a
SQL SELECT statement and display the results to standard out. Test your program by listing the
contents of the Employee table.
(Solutions: [Link], [Link])

† Modify the state example that was discussed in the chapter to reflect the state diagram below. Test
it out by modifying the existing client.
(Solutions: [Link], [Link], [Link], [Link],
[Link], [Link])

power button press


power button press
power button press
key press
Active
Standby
Hibernate
Shutdown
standby
hibernate
shutdown

‡ Using the observer example that was covered in the chapter, add another observer that acts as
a logger. It should print the current balance to standard out every time it's notified of a change.
(Solution: [Link], [Link])

Page 408 Rev 5.1.4 © 2011 ITCourseware, LLC


Chapter 18 Java Design Patterns — Behavioral Patterns

© 2011 ITCourseware, LLC Rev 5.1.4 Page 409


Advanced Java Programming

Page 410 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix A JDBC SQL Programming

Appendix A - JDBC SQL Programming

Objectives

” Use SQLExceptions and SQLWarnings to detect


and handle DBMS errors and warnings.

” Describe the most important JDBC interfaces, and


use their methods.

” Use the JDBC datatypes to convert DBMS-specific


data to Java data.

” Use ResultSetMetaData to handle dynamically-


generated SQL.

” Manage DBMS transactions.

” Use PreparedStatement objects to more efficiently


run a SQL statement repeatedly.

” Invoke DBMS stored procedures and functions


from Java.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 411


Advanced Java Programming

Error Checking and the SQLException Class

” A runtime error from the DBMS triggers a SQLException.

” The SQLException's methods provide the standard DBMS error information:

¾ getSQLState() returns the ANSI-standard SQLSTATE value (if your


DBMS supports it).

¾ getErrorCode() returns the vendor-specific SQLCODE error code.

¾ getMessage() is overridden by the SQLException class to return the


vendor-specific error message.

” A single action might result in multiple database errors, so a SQLException


may have one or more additional SQLExceptions chained to it.

¾ getNextException() returns the next exception in the chain.

” Most methods defined under [Link] throw SQLException; assume that your
JDBC code needs to either catch or declare SQLException.

Page 412 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix A JDBC SQL Programming

Database programmers rely on a simple mechanism for obtaining error information from the database
engine: after every database operation, the DBMS sets an error value that the programmer can check. An
error is typically identified by a numeric error code (SQLCODE) and a brief error message. By convention,
DBMS error codes are negative numbers; a SQLCODE value of 0 means no error has occured; and a
special value, typically (but not always) +100, means there was no error, but no data was found to satisfy
the operation.

SQLCODE values are vendor-specific, however, so programmers must learn the specific code values for
each product they program against. To relieve this situation, standards organizations introduced the
SQLSTATE, a standardized, 5-character string encoding the error condition.

Some DBMSs now implement SQLSTATE, though most still also return their own, vendor-specific,
SQLCODE values and messages.

With JDBC, when you call certain methods, Java automatically checks the SQLSTATE/SQLCODE and
throws a SQLException when there is an error.

[Link]
...
public class SQLUtils {
public static String formatSQLException(SQLException e) {
StringBuilder msg = new StringBuilder("");
if (e != null) {
[Link](" SQLState: " + [Link]() + "\n");
[Link](" Code: " + [Link]() + "\n");
[Link](" Message: " + [Link]() + "\n\n");
}
return [Link]();
}
public static String formatSQLExceptions(SQLException e) {
String msg = "";
while (e != null) {
msg += formatSQLException(e); Call this method from a
e = [Link](); catch handler to print nice
} error messages.
return msg;
}
public static void printSQLErrors(SQLException e) {
if (e != null) {
[Link]("SQL Error:\n" + formatSQLExceptions(e));
}
}
...

© 2011 ITCourseware, LLC Rev 5.1.4 Page 413


Advanced Java Programming

The SQLWarning Class

” The SQLWarning class extends SQLException.

” Calls to certain methods of a Connection, Statement, or ResultSet object may


generate one or more SQLWarnings.

¾ SQLWarning exceptions are never actually thrown; they do not need to


be declared or caught.

ƒ When a SQLWarning is generated, it is silently chained to the


object that generated it.

¾ Use the getWarnings() method in each of these classes to get the first
SQLWarning.

¾ Additional SQLWarnings will be chained to the first one.

ƒ SQLWarning's getNextWarning() method retrieves the next


warning in an object's chain.

” The SQLWarning chain of a Statement object is cleared each time one of its
execute methods is called; a ResultSet's SQLWarnings are cleared when each
row is read.

Page 414 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix A JDBC SQL Programming

Example:
A method for checking and printing SQLWarning information:
{
...
Connection conn;
Statement stmt;
conn = [Link](connectURL,
username, password );
stmt = [Link]();
printSQLWarnings([Link]());
...
}

[Link]
...
public class SQLUtils {
...
public static boolean printSQLWarnings(SQLWarning w)
throws SQLException {

if (w != null) {
[Link]("SQL Warning:");
while (w != null) {
[Link](formatSQLException(w));
w = [Link]();
}
return true;
}
else {
return false;
}
}
...
}

Note:
SQLWarnings may not be generated by your driver. Check your driver documentation.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 415


Advanced Java Programming

JDBC Types

” JDBC defines datatypes to separate the Java developer from the database
implementation.

¾ Database vendors often support different types of data or use different


names for the datatypes.

¾ The driver is responsible for converting DBMS types to JDBC types.

¾ JDBC datatypes are based on standard SQL datatypes.

” When you use a getXXX() method on a ResultSet, the XXX refers to the Java
type that is returned.

int id = [Link](1);
String lastName = [Link](2);

¾ There is a suggested getXXX() method for each JDBC datatype, but there
is usually more than one choice.

ƒ getObject() works for any JDBC type.

¾ Look in the mapping table to see which JDBC types are supported by
which getXXX() methods.

” The [Link] class defines a static final int for each JDBC datatype.

” These constants are the way that JDBC references the type.

Page 416 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix A JDBC SQL Programming

Mapping Table

LONGVARBINARY
LONGVARCHAR

JAVA OBJECT
VARBINARY

TIMESTAMP
SMALLINT

VARCHAR
NUMERIC
DECIMAL
INTEGER
TINYINT

DOUBLE

STRUCT
BINARY
BIGINT

ARRAY
FLOAT

CHAR

CLOB
BLOB
REAL

DATE
TIME

REF
BIT
getByte() 8 9 9 9 9 9 9 9 9 9 9 9 9
getShort() 9 8 9 9 9 9 9 9 9 9 9 9 9
getInt() 9 9 8 9 9 9 9 9 9 9 9 9 9
getLong() 9 9 9 8 9 9 9 9 9 9 9 9 9
getFloat() 9 9 9 9 8 9 9 9 9 9 9 9 9
getDouble() 9 9 9 9 9 8 8 9 9 9 9 9 9
getBigDecimal() 9 9 9 9 9 9 9 8 8 9 9 9 9
getBoolean() 9 9 9 9 9 9 9 9 9 8 9 9 9
getString() 9 9 9 9 9 9 9 9 9 9 8 8 9 9 9 9 9 9 9
getBytes() 8 8 9
getDate() 9 9 9 8 9
getTime() 9 9 9 8 9
getTimestamp() 9 9 9 9 9 8
getAsciiStream() 9 9 8 9 9 9
getBinaryStream() 9 9 8
getCharacterStream() 9 9 8 9 9 9
getClob() 8
getBlob() 8
getArray() 8
getRef() 8
getObject() 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 8 8
8 — Preferred 9 — Optional (can implicitly convert)

© 2011 ITCourseware, LLC Rev 5.1.4 Page 417


Advanced Java Programming

Executing SQL Queries

” Use Statement's executeQuery() method to run a SQL SELECT statement,


which will return a single ResultSet.

¾ If the Statement already had an open ResultSet, it is automatically


closed first.

” executeQuery() takes a single String argument: the SQL SELECT statement.

” Dynamic SQL is simple with JDBC.

¾ Your program builds SQL query strings and passes them to


executeQuery().

¾ The database parses and compiles the query string each time you call
executeQuery().

¾ Use a PreparedStatement to create a pre-compiled or parameterized


statement for improved performance when executing the same SQL
statement repeatedly.

Page 418 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix A JDBC SQL Programming

[Link]
...
public class EmpSals {

public static void main(String args[]) {


try {
[Link]("[Link]");
String url = "jdbc:derby://localhost:1527/j2se";
Connection conn = [Link](url);
Statement stmt = [Link]();

String sqltxt;
sqltxt = "SELECT firstname, lastname, salary, department_name" +
" FROM employee, department " +
" WHERE employee.department_code=department.department_code";
ResultSet rs = [Link](sqltxt);

String name; List all of the employees


String dept; and their departments.
float salary;
while ([Link]()) {
name = [Link]("FIRSTNAME") + " " +
[Link]("LASTNAME");
dept = [Link]("DEPARTMENT_NAME");
salary = [Link]("SALARY");
[Link](name + "\t" + dept + "\t" + salary);
}

[Link]();
[Link]();
}
catch (ClassNotFoundException cnfe) {
[Link]("Unable to load driver class: " + cnfe);
[Link](1);
}
catch (SQLException sqle) {
[Link]("SQL Error:");
[Link](" Code: " + [Link]());
[Link](" Message: " + [Link]());
[Link](1);
}
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 419


Advanced Java Programming

ResultSetMetaData

” For queries built at runtime for which you need to determine the number, types,
names, etc. of columns of a ResultSet, get the ResultSet's metadata.

ResultSetMetaData rsmd = [Link]();

” A ResultSetMetaData object's methods return information about the columns


of its ResultSet.

int getColumnCount()
String getColumnName(int column)
String getColumnLabel(int column)
int getColumnType(int column)
String getColumnTypeName(int column)
int getPrecision(int column)
int getScale(int column)
int getColumnDisplaySize(int column)
int isNullable(int column)
boolean isReadOnly(int column)
boolean isCurrency(int column)
etc...

¾ All of these methods may throw SQLException.

” getColumnType() returns an int corresponding to a constant defined in


[Link].

¾ This can be useful in determining which getXXX() method to call.

” ResultSetMetaData is valuable when:

¾ execute() was used to run some arbitrary query.

¾ executeQuery() was used to run a query statement that was generated at


runtime.

Page 420 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix A JDBC SQL Programming

[Link]
...
public class ExecuteFormat {

public static void main(String args[])


throws ClassNotFoundException {
...
ResultSetMetaData rsmd = [Link]();
int cols = [Link]();
int colWidth[] = new int[cols];

String resultLine = "";


for (int col=1; col <= cols; col++) {
colWidth[col-1] = getAppDisplayWidth(rsmd, col);
resultLine += [Link]([Link](col),
colWidth[col-1]);
if (col < cols) {
resultLine += " ";
}
}
[Link](resultLine);
...
}

static int getAppDisplayWidth(ResultSetMetaData rsmd, int col)


throws SQLException {

switch ([Link](col)) {
case [Link]:
case [Link]:
return 9;
case [Link]:
return 22;
case [Link]:
return 10;
case [Link]:
return 8;
default :
return [Link](col);
}
}
}

Try It:
Run [Link] to see all Department data printed out in columns with headers.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 421


Advanced Java Programming

Executing SQL Updates

” Use Statement's executeUpdate() method to run SQL statements that do not


generate result sets.

¾ Data Manipulation Language (DML): INSERT, UPDATE, DELETE.

[Link]( "DELETE FROM employee " +


" WHERE id = 2895");

¾ Data Definition Language (DDL): CREATE, ALTER, DROP, GRANT,


REVOKE.

[Link]( "GRANT SELECT ON employee " +


" TO PUBLIC");

” executeUpdate() returns an int, the update count, which is one of two values:

int uc;
uc = [Link]( "UPDATE employee "
+ " SET salary = salary * 1.1 "
+ "WHERE title = 'Engineer'");

¾ The number of rows affected by a DML statement (may be 0).

¾ 0 for DDL or other statements.

” executeUpdate() throws an exception if you use it to run a SELECT or other


statement that generates a result set.

Page 422 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix A JDBC SQL Programming

The Statement interface's execute() method can execute an arbitrary SQL string that might generate
either a result set or an update count. The price of this generality is some extra coding to retrieve the actual
results. Usually, though, you will use executeQuery() for queries and executeUpdate() for DML and
DDL.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 423


Advanced Java Programming

Using a PreparedStatement

” If your program executes the same SQL statement repeatedly, perhaps just with
different values in certain places, you may benefit by using a
PreparedStatement.

¾ Use Connection’s prepareStatement() method to instantiate a


PreparedStatement object.

PreparedStatement pst;
pst=[Link]("SELECT department_name"
+ " FROM department"
+ " WHERE department_code = 'RD'");
ResultSet rs = [Link]();

¾ You must supply the SQL syntax when you create the
PreparedStatement, not when you execute it.

” Where a Statement’s execute methods (execute(), executeQuery(),


executeUpdate()) cause the DBMS to parse, compile, and execute the SQL
syntax each time, a PreparedStatement’s SQL syntax may be parsed and
compiled by the DBMS only once.

” PreparedStatement descends from Statement.

¾ Note that a PreparedStatement’s execute methods don’t take a SQL


String argument — thus they do not override the Statement’s
execute(String sqlstr) methods.

ƒ Do not use the Statement’s execute(String sqlstr) methods with a


PreparedStatement object.

Page 424 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix A JDBC SQL Programming

<<interface>>
Statement

<<interface>>
PreparedStatement

© 2011 ITCourseware, LLC Rev 5.1.4 Page 425


Advanced Java Programming

Parameterized Statements

” You can execute a prepared statement multiple times with different values
inserted into the statement syntax.

” When creating the statement, use a question mark, ?, as a placeholder for any
value you will change later.

PreparedStatement pst;
pst = [Link]( "SELECT department_name"
+ " FROM department"
+ " WHERE department_code = ?");

” You must set values for all placeholders before executing the statement.

¾ Use a PreparedStatement's setXXX() methods, where XXX is the Java


datatype (the JDBC driver implicitly converts to the appropriate JDBC
datatype).

[Link](1, "RD");
ResultSet rs = [Link]();

¾ The setXXX() methods take the index of the placeholder, from left-to-
right starting at 1, as the first argument.

String dept = "RD";


int mgrid = 9188;
pst = [Link]("UPDATE department "
+ " SET manager_id = ? "
+ " WHERE department_code = ?");
[Link](1, mgrid);
[Link](2, dept);
int uc = [Link]();
[Link](uc + " row(s) updated.");

” Parameters assigned to a PreparedStatement are sometimes referred to as IN


parameters: values passed into the statement.

Page 426 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix A JDBC SQL Programming

This example uses a prepared statement to retrieve the department name using the department code.

[Link]
...
public class PrepParamExample {
private PreparedStatement pst;

public PrepParamExample() {
try {
[Link]("[Link]");
String url = "jdbc:derby://localhost:1527/j2se";
Connection conn = [Link](url);

pst = [Link]("SELECT department_name " +


"FROM department WHERE department_code = ?");

[Link](getDeptName("RD"));
[Link](getDeptName("HR"));
[Link]();
[Link]();
}
catch (Exception e) {
[Link]();
}
}

private String getDeptName(String deptid) throws SQLException {


[Link](1, deptid);
This sets the search criteria
ResultSet rs = [Link]();
for the WHERE clause.
String dept = "";
while ([Link]()) {
dept += [Link](1) + "\n";
}
return dept;
}

public static void main(String args[]) {


new PrepParamExample();
}
}

Try It:
Compile and run this program. The output will be the department names for the "RD" and "HR"
departments.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 427


Advanced Java Programming

Stored Procedures

” Use CallableStatement, which extends PreparedStatement, to execute DBMS


stored procedures and functions.

¾ Connection's prepareCall() method creates a CallableStatement object.

” To prepare stored procedures, you can use:

¾ JDBC escape syntax:

CallableStatement cst;
cst = [Link]("{call myproc()}");

¾ Vendor-specific syntax (see their documentation):

cst = [Link]("BEGIN myproc(); END;");

” A CallableStatement can also take placeholders for arguments.

cst = [Link]("{call assignDeptHead(?,?)}");

¾ Use the setXXX() methods to assign values for IN parameter placeholders


before executing the statement.

[Link](1, "SM")
[Link](2, 9144);
[Link]();

” Use registerOutParameter() to set up OUT (or IN OUT) parameters before


executing the statement.

cst = [Link]( "{call getDeptHead(?,?)}");


[Link](1, "SM")
[Link](2, [Link]);
[Link]();
int mgrid = [Link](2);
Page 428 Rev 5.1.4 © 2011 ITCourseware, LLC
Appendix A JDBC SQL Programming

<<interface>>
Statement

<<interface>>
PreparedStatement

<<interface>>
CallableStatement

© 2011 ITCourseware, LLC Rev 5.1.4 Page 429


Advanced Java Programming

Transaction Management

” A DBMS logs all DML operations in a session as part of a transaction.

¾ At your request, the DBMS will either:

ƒ Commit the entire transaction, making your operations permanent


and visible to other users.

ƒ Rollback the entire transaction, completely undoing all DML


operations.

¾ When you commit or rollback a transaction, a new transaction begins.

” The default behavior of a Connection object is to automatically commit after


executing each statement.

¾ In this case, each statement is a single, independent transaction.

” To turn off autocommit mode, use setAutoCommit(false).

¾ You can then use the commit() or rollback() methods of your


Connection object to manage your transactions.

¾ The getAutoCommit() method of your Connection object returns true


when autocommit mode is on.

Page 430 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix A JDBC SQL Programming

In most cases, autocommit is not desirable — you don't have the ability to check errors and warnings
and program appropriately, or to treat multiple individual statements as parts of a single transaction, or
to set transaction savepoints (if your DBMS supports them).

Transaction Side Effects

¾ Some DBMSs, notably Oracle, automatically commit the current transaction any time you
execute a DDL statement.

¾ Committing or rolling back the current transaction frees all locks.

¾ Committing the current transaction frees the update locks associated with an updatable cursor,
thus forcing the cursor closed.

Isolation Level

Your transaction isolation level describes how your session behaves in regard to ongoing,
uncommitted transactions performed by other users.

[Link]() retrieves an integer value identifying your current isolation


level, and setTransactionIsolation() sets it for your current session. The values for these are defined as
static finals in the Connection interface:

Connection.TRANSACTION_NONE Transactions are not supported.

Connection.TRANSACTION_READ_UNCOMMITTED Dirty reads, non-repeatable reads, and


phantom reads can occur.

Connection.TRANSACTION_READ_COMMITTED Dirty reads are prevented; non-


repeatable reads and phantom reads
can occur.

Connection.TRANSACTION_REPEATABLE_READ Dirty reads and non-repeatable reads


are prevented; phantom reads can
occur.

Connection.TRANSACTION_SERIALIZABLE Dirty reads, non-repeatable reads, and


phantom reads are prevented.

Note:
Your DBMS may not provide all isolation levels.
© 2011 ITCourseware, LLC Rev 5.1.4 Page 431
Advanced Java Programming

Labs

Write a program to print a listing of all employee names and salaries, and the total of all salaries at
the end.
(Solution: [Link])

† Modify the salary report program from [Link] so that after the list of all employee
names, it prints a list of the department names with salary totals for each. (Hint: Use a HashMap to
accumulate the salary total for each department.)
(Solution: [Link])

‡ (Optional) Modify the salary report program to use rPadTrunc(), found in the provided
[Link], to format the output.
(Solutions: [Link], [Link])

ˆ Write a program that uses a PreparedStatement to retrieve the id, name, and title of all employees
of a department. The statement should take the department code as its only parameter. Prompt the
user for a department code and use the response to run the query and print the results.
(Solution: [Link])

‰ Write a program that prompts the user to enter a SQL statement (using [Link] or a simple GUI,
as you prefer). The program should then determine if the statement is a query or not, and execute it
using the appropriate method. If it is a query, just print out the number of rows found. If it is a DML
or other statement, print the number of rows affected.
(Solution: [Link])

Š Modify your solution to [Link]: if the statement is executed as a query, use


ResultSetMetaData to determine the number of columns retrieved by the query. For each row,
print out all columns.
(Solution: [Link])

Page 432 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix A JDBC SQL Programming

© 2011 ITCourseware, LLC Rev 5.1.4 Page 433


Advanced Java Programming

Page 434 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix B Eclipse

Appendix B - Eclipse

Objectives
” Install and configure Eclipse.

” Create and manage Java projects.

” Debug Java programs in Eclipse.

” Use various shortcuts to increase your


productivity in Eclipse.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 435


Advanced Java Programming

Introduction to Eclipse

” IBM started the Eclipse project in April of 1999 with the goal of "eclipsing" the
dominance of Microsoft Visual Studio within the integrated development
environment (IDE) space.

¾ IBM donated the initial Eclipse code base to the open source community
in November of 2001 — just one month after version 1.0 was released.

” Eclipse has become much more than a pure Java, open source IDE; it is a
framework on which companies can develop their own tools.

¾ Users can combine tools from different vendors to accomplish their goals.

” The Eclipse Project is made up of multiple sub-projects, including:

¾ The Eclipse Platform is the core IDE that most people associate with the
term "Eclipse."

ƒ It is extensible: you can plug-in tools from various vendors to


customize it to your needs.

¾ The Java Development Tools (JDT) project provides the necessary plug-
ins to support development of Java applications.

ƒ These tools include the incremental compiler, the debugger, and the
editor.

¾ The Plug-in Development Environment (PDE) project provides tools that


allow you to build your own plug-ins for Eclipse.

Page 436 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix B Eclipse

Eclipse has had numerous releases since its inception:

Eclipse 1.0 — October, 2001


Eclipse 2.0 — June, 2002
Eclipse 3.0 — June, 2004
Eclipse 3.1 — June, 2005
Eclipse 3.2 (Callisto) — June, 2006
Eclipse 3.3 (Europa) — June, 2007
Eclipse 3.4 (Ganymede) — June, 2008
Eclipse 3.5 (Galileo) — June, 2009
Eclipse 3.6 (Helios) — June, 2010
Eclipse 3.7(Indigo) — June, 2011

© 2011 ITCourseware, LLC Rev 5.1.4 Page 437


Advanced Java Programming

Installing Eclipse

” Download the most recent Eclipse SDK release build from


[Link]

¾ You will find versions supporting Windows, Linux, and Mac-OSX.

¾ The file you download will be a .zip file (or [Link]), rather than an install
program.

¾ The download does not include a Java Runtime Environment (JRE).

ƒ You must install a JRE version 5+ for Eclipse to work.

ƒ You do not need the full Java Development Kit (JDK), unless you
want to be able to step through the library source code during
debug.

” Extract the downloaded file to your local drive.

¾ An eclipse directory will be created with several subdirectories.

” That is all there is to it — you have successfully downloaded and installed


Eclipse!

Page 438 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix B Eclipse

© 2011 ITCourseware, LLC Rev 5.1.4 Page 439


Advanced Java Programming

Running Eclipse for the First Time

” Run the Eclipse executable to start the Eclipse IDE.

¾ The executable is found in the eclipse directory and is called [Link]


on Windows and eclipse on Linux.

¾ Eclipse will use the first Java VM it finds in your PATH when it runs.

ƒ To explicitly set the VM, pass the -vm argument to the Eclipse
executable:

eclipse -vm c:\jre\bin\[Link]

” The first time you run Eclipse, it will ask you to select a workspace location.

¾ A workspace is a directory where your projects will be stored.

¾ This value can be passed in on the command-line with the -data


argument:

eclipse -data c:\code\myworkspace

” After you have selected a workspace, you will see a welcome screen that
provides links to tutorials, sample applications, overview topics, and
information on what's new in the current version of Eclipse.

¾ You can skip this introductory content by choosing the Workbench link in
the upper right corner of the screen or by clicking the x next to the word
Welcome in the upper left corner of the screen.

ƒ To get back to the welcome screen in the future, you can choose the
HelpÆWelcome menu item.

Page 440 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix B Eclipse

Click here to switch


to the workbench.

For more command-line options, see:


[Link]
[Link]?topic=%[Link]%2Freference%2Fmisc%[Link]

© 2011 ITCourseware, LLC Rev 5.1.4 Page 441


Advanced Java Programming

Editors, Views, and Perspectives

” You use an editor to enter text into Eclipse.

¾ The JDT Java Editor provides syntax coloring, code completion, and code
formatting, among other things.

¾ A simple text editor is also included as part of the Eclipse Platform.

¾ Other editors, such as an HTML editor, can be added as plug-ins.

¾ Multiple editors can be open at once and they will appear as stacked
instances with individual tabs for selection.

” Views display information about an object; they typically supplement the data
that is visible in the current editor.

¾ The JDT provides a Packages View, Type Hierarchy View, and Java
Outline View.

¾ Display additonal views by choosing WindowÆShow Views.

” Perspectives are combinations of editors and views arranged in the workbench.

¾ You can switch from one perspective to another to see the appropriate
combination of views and editors for your current needs by choosing
WindowÆOpen Perspective.

¾ The Window menu also allows you to save, customize, reset, and close
Perspectives.

” The Java Perspective is the default perspective that you will see after
dismissing the welcome screen.

Page 442 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix B Eclipse

© 2011 ITCourseware, LLC Rev 5.1.4 Page 443


Advanced Java Programming

Setting up a Project

” Before you can edit any Java code, you must first create a project.

¾ A project is a group of packages.

¾ You can have one default package per project, at most.

¾ You can find the .java files that correspond to the code you are editing
within your workspace directory.

” To create a new project, choose FileÆNewÆProject . . .

¾ Select Java Project from the list of choices and click Next.

¾ Enter a project name into the Project Name text box.

ƒ The project name will become a subdirectory within your


workspace directory.

¾ You can also specify which version of Java your project should be
compliant with.

¾ Click Finish to create the project.

” Once your project has been created, you will see the project name listed in the
Package Explorer view.

Page 444 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix B Eclipse

© 2011 ITCourseware, LLC Rev 5.1.4 Page 445


Advanced Java Programming

Creating a New Java Application

” To create a Java class, click on FileÆNewÆClass.

¾ You can enter the name of the package to which your new class should
belong.

ƒ Leave the Package text field blank to place the class in the default
package.

¾ You must specify a name for the new class in the Name text field.

¾ Check the appropriate radio button and checkboxes to apply the


appropriate modifiers to the new class.

¾ The Superclass and Interfaces text boxes allow you to identify the
extends and implements clauses for your new class.

¾ Eclipse can also automatically generate the main() method, any parent
abstract methods, constructors, and javadoc comments for you.

¾ Click Finish to create the new class.

” The new class will automatically open up in a Java editor where you can add
your code to the class.

” Every time you save the file, Eclipse will compile your class for you.

¾ Any compiler errors are visible in the Problems view at the bottom of the
screen.

Page 446 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix B Eclipse

Look for compiler


errors here.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 447


Advanced Java Programming

Running a Java Application

” To run your program, click the Run button in the toolbar.

¾ The results will be displayed in the Console view at the bottom of the
screen.

” If you would like to run your program with custom options, choose RunÆRun
Configurations.

¾ Choose Java Application and click New.

¾ The next dialog allows you to pass in arguments and customize the
environment before you invoke the program.

¾ Click the Run button to execute your program.

Page 448 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix B Eclipse

This is the Run button.

Standard out
and standard
err are shown in
the console.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 449


Advanced Java Programming

Debugging a Java Application

” Before debugging your program, set at least one breakpoint by double-clicking


on the gray margin of the Java editor to the left of the line of code where you
wish to set the breakpoint.

” Click the Debug button in the toolbar.

¾ You will be notified that the perspective will change to the debug
perspective before the debugger starts.

” Within the debug perspective, you are presented with multiple views.

¾ The Debug view contains toolbar buttons that allow you to step through
the program as it runs.

ƒ It also displays the current location within the method call stack.

¾ The Variables view shows you the current value of the variables in your
program.

ƒ You can also hover your mouse over any variable reference in the
Editor to see its current value.

¾ The Breakpoints view allows you to manage the breakpoints in your


debug session.

¾ The Console view displays the current results that have been written to
standard out.

¾ The Outline view displays the structure of your class and highlights the
current method you have stepped into.

” After you have completed debugging your program, switch back to the Java
Perspective by clicking WindowÆOpen PerspectiveÆJava or you can click
the Java button in the upper right corner of the screen.
Page 450 Rev 5.1.4 © 2011 ITCourseware, LLC
Appendix B Eclipse

Use this toolbar to step


through your application.

Note:
If you have installed a JDK rather than a JRE, Eclipse can step into the source code for the Java API
libraries.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 451


Advanced Java Programming

Shortcut Key Sequences

” <Ctrl><Space> — Content Assist

¾ Use this key sequence to have Eclipse generate a list of possible matches
for the current entry in the code.

” <Ctrl><Shift>M — Add Import

¾ Click on a class that has been flagged as "not resolved" and use this key
sequence to have Eclipse automatically discover and add an import for
the class.

” <Ctrl>M — Maximize Active View or Editor

¾ This will take the current view or editor you are working in and maximize
it; use the sequence again to go back to the original size.

” <Ctrl><Shift>F — Format Code

¾ After you have configured Eclipse to understand your coding standards


(WindowÆPreferencesÆJavaÆCode Style), this handy key sequence
will modify the current open Java file to match them.

” <Ctrl>/ — Quick Comment

¾ This key sequence will comment out the current line or lines with a //
comment; press it again to uncomment.

” <Ctrl><Shift>/ — Quick Block Comment

¾ Use this key sequence to comment out the current block of lines with a
block comment /* */; use a backslash to remove a block comment.

Page 452 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix B Eclipse

Eclipse is loaded with features that tend to be hidden deep beneath menu options. To see a list of all of the
shortcut keys, use <Ctrl><Shift>L.

Another handy set of shortcuts to remember can be found under the Source menu. For example, the
SourceÆGenerate Getters and Setters menu item will create gets and sets for any of the fields in your
class.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 453


Advanced Java Programming

More Shortcut Key Sequences

” <Alt>È, <Alt>Ç— Move Lines Down, Move Lines Up

¾ These key sequences will move the current line(s) down or up.

” <Ctrl><Shift>T — Open Type

¾ Use the Open Type dialog to quickly jump to a class or interface in your
project or in the Java libraries

¾ For example, type Str for all classes that start with these three characters
(String, StringBuffer, etc.)

” <Ctrl><Shift>R — Open Resource

¾ Use the Open Resource dialog to find any kind of file in your project.

” <F3> — Open Declaration

¾ Any time you have clicked on a method call in code, you can click F3 to
jump to the method declaration in the Java editor.

” <Alt>Å, <Alt>Æ — Backwards History, Forwards History

¾ Use these key sequences like back and forward buttons in a browser.

” <Ctrl>O — Quick Outline

¾ Use this key sequence to launch a dialog that helps you quickly find a
method within the current file by simply typing in the first few letters of
the method you are looking for.

Page 454 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix B Eclipse

In addition to key sequences, Eclipse also provides templates that allow you to quickly insert common
code snippets. Type the template, followed by <Ctrl><Space> to see the template replaced with the
full syntax.

ƒ sysout — [Link]()
ƒ syserr — [Link]()
ƒ try — try/catch block
ƒ catch — catch block
ƒ main — main() method

For more templates, see WindowÆPreferencesÆJavaÆEditor ÆTemplates.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 455


Advanced Java Programming

Setting the Classpath

” If you are using Java code that is external to your project, then you need to tell
Eclipse where to find it.

¾ You can reference a .jar file or a directory that contains .class files.

” Set a project-specific build path by clicking ProjectÆPropertiesÆJava Build


Path.

¾ On the Libraries tab, choose either the Add External JARs button or the
Add Class Folder button to select the .jar or directory where your .class
files are located.

” To set these values at a more global level, click WindowÆPreferencesÆJavaÆ


Build PathÆClasspath Variables.

¾ Click the New button and choose a unique name for your variable.

¾ Use the File button to browse to a .jar file, or the Folder button to choose
a directory structure that contains the .class files, to add to the Classpath
variable

¾ You can reference the global variables from your individual projects using
ProjectÆPropertiesÆJava Build Path.

ƒ On the Libraries tab, choose the Add Variable button to select the
global Classpath variable you just created.

Page 456 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix B Eclipse

© 2011 ITCourseware, LLC Rev 5.1.4 Page 457


Advanced Java Programming

Importing Existing Java Code into Eclipse

” To load pre-existing Java files into an Eclipse project, use the Import feature by
choosing FileÆImport.

¾ Choose File System to tell Eclipse to look on your local drives for the
existing Java files.

¾ Browse to the directory immediately above where your packages are


located.

¾ Choose the checkboxes for the packages to import into your project.

¾ Make sure the Into folder text field specifies the name of the workspace
folder within your project you wish to import into.

¾ Click Finish.

” You can also copy the files into the workspace folder using your file system's
copy utilities.

¾ Choose FileÆRefresh and the files will be automatically imported into


your project.

” On Windows systems, you can even drag the files from your file system into an
Eclipse project!

” To load existing Eclipse projects into your workspace, choose


FileÆImportÆExisting Projects into Workspace and select either the root
directory or archive file to load the projects from.

Page 458 Rev 5.1.4 © 2011 ITCourseware, LLC


Appendix B Eclipse

Note:
If you are creating a new project for your existing files and you do not want to copy all of the files into a
new workspace, then you can create your new Java project and set its workspace location to where your
Java source files are already located. Just choose FileÆNewÆProject, choose Java Project, and then
choose to Create project from existing source. Browse to the proper directory and you are done.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 459


Advanced Java Programming

Page 460 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

Solutions

© 2011 ITCourseware, LLC Rev 5.1.4 Page 461


Advanced Java Programming

Chapter 2

[Link]
import [Link];
import [Link];
import [Link];

public class Employee implements Serializable {


private int id;
private String firstName;
private String lastName;
private String title;
private String departmentCode;
private int supervisorId;
private Date hireDate;
private float salary;

public Employee(int i, String first, String last, String ti,


String deptCode, int supId, Date hire, float sal) {
id = i;
firstName = first;
lastName = last;
title = ti;
departmentCode = deptCode;
supervisorId = supId;
hireDate = hire;
salary = sal;
}

public boolean equals(Object o) {


if (o instanceof Employee) {
Employee eTest = (Employee) o;
return id == [Link] &&
[Link]([Link]) &&
[Link]([Link]) &&
[Link]([Link]) &&
[Link]([Link]);
}
else
return false;
}
public String toString() {
SimpleDateFormat df = new SimpleDateFormat("MMM d, yyyy");
StringBuilder result = new StringBuilder();
[Link](title);
Page 462 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
[Link](" ").append(firstName);
[Link](" ").append(lastName);
[Link](" hired ").append([Link](hireDate));
return [Link]();
}
public String getName() {
return firstName + " " + lastName;
}
public String getTitle() {
return title;
}
public Date getHireDate() {
return hireDate;
}
public int getId() {
return id;
}
public int getSupervisorId() {
return supervisorId;
}
}

[Link]
import [Link];

public class Department implements Serializable {


private String code;
private String name;
private Employee manager;
private String city;
private String state;

public Department(String cd, String nm, Employee mg, String ct,


String st) {
code = cd;
name = nm;
manager = mg;
city = ct;
state = st;
}
public boolean equals(Object o) {
if (o instanceof Department) {
Department dTest = (Department) o;
return [Link]([Link]) &&

© 2011 ITCourseware, LLC Rev 5.1.4 Page 463


Advanced Java Programming

Chapter 2 (cont'd)

[Link] (cont'd)
[Link]([Link]) &&
[Link]([Link]);
}
else
return false;
}
public String toString() {
return code + " " + name + " manager: " + manager;
}
public String getCode(){
return code;
}
public String getName(){
return name;
}
public Employee getManager(){
return manager;
}
public void setName(String nm){
name = nm;
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class WriteDept {


public static void main(String args[]) throws ParseException {
SimpleDateFormat f = new SimpleDateFormat("M/d/yyyy");
Date d = [Link]("08/05/1960");
Employee armstrong = new Employee(5, "Neil", "Armstrong",
"Astronaut", "SP", 1, d, 30000);
Department space = new Department("SP", "Space Division",
armstrong, "Edwards", "CA");
ObjectOutputStream out = null;

Page 464 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link] (cont'd)
try {
out = new ObjectOutputStream(new FileOutputStream("[Link]"));
}
catch (IOException e) {
[Link]("Error opening output file: "
+ [Link]());
[Link](1);
}

try {
[Link](space);
[Link]("Wrote \"" + space + "\" to file");
}
catch (IOException e) {
[Link]("Error writing to file: " + [Link]());
[Link](2);
}
finally {
try {
[Link]();
}
catch (IOException e) {
[Link](3);
}
}
}
}

[Link]
import [Link];
import [Link];
import [Link];

public class ReadDept {


public static void main(String[] args) {
ObjectInputStream in = null;
try {
in = new ObjectInputStream(new FileInputStream("[Link]"));
}
catch (IOException e) {
[Link]("Error opening input file: " +
[Link]());
[Link](1);
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 465


Advanced Java Programming

Chapter 2 (cont'd)

[Link] (cont'd)
Department d = null;

try {
d = (Department) [Link]();
}
catch (ClassCastException e) {
[Link]("Error casting object to a Department: " +
[Link]());
[Link](2);
}
catch (IOException e) {
[Link]("Error reading object: " + [Link]());
[Link](3);
}
catch (ClassNotFoundException e) {
[Link]([Link]() + " class not found");
[Link](4);
}
finally {
try {
[Link]();
}
catch (IOException e) {
[Link](5);
}
}
// write to the screen
[Link](d);
}
}

[Link]
import [Link];
import [Link];
import [Link];

public class ReadJunk {


public static void main(String[] args) {
ObjectInputStream in = null;
try {
in = new ObjectInputStream(new FileInputStream("[Link]"));
Page 466 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
}
catch (IOException e) {
[Link]("Error opening input file: " +
[Link]());
[Link](1);
}

Department d = null;

try {
d = (Department) [Link]();
}
catch (ClassCastException e) {
[Link]("Error casting object to a Department: " +
[Link]());
[Link](2);
}
catch (IOException e) {
[Link]("Error reading object: " + [Link]());
[Link](3);
}
catch (ClassNotFoundException e) {
[Link]([Link]() + " class not found");
[Link](4);
}
finally {
try {
[Link]();
}
catch (IOException e) {
[Link](5);
}
}
// write to the screen
[Link](d);
}
}

[Link]
SP Space Division manager: Astronaut Neil Armstrong hired Aug 5, 1960

[Link].4
import [Link];
import [Link];
import [Link];
© 2011 ITCourseware, LLC Rev 5.1.4 Page 467
Advanced Java Programming

Chapter 2 (cont'd)
[Link].4 (cont'd)
public class Employee implements Serializable {
static final long serialVersionUID = -8853382621975997090L;
private int id;
private String firstName;
private String lastName;
private String title;
private String departmentCode;
private int supervisorId;
private Date hireDate;
private float salary;
private Date departmentStartDate;

public Employee(int i, String first, String last, String ti,


String deptCode, int supId, Date hire, float sal)
{
this(i, first, last, ti, deptCode, supId, hire, hire, sal);
}

public Employee(int i, String first, String last, String ti,


String deptCode, int supId, Date hire,
Date deptDate, float sal) {
id = i;
firstName = first;
lastName = last;
title = ti;
departmentCode = deptCode;
supervisorId = supId;
hireDate = hire;
departmentStartDate = deptDate;
salary = sal;
}

public boolean equals(Object o) {


if (o instanceof Employee) {
Employee eTest = (Employee) o;
return id == [Link] &&
[Link]([Link]) &&
[Link]([Link]) &&
[Link]([Link]) &&
[Link]([Link]);
}
else
return false;
Page 468 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link].4 (cont'd)
}
public String toString() {
SimpleDateFormat df = new SimpleDateFormat("MMM d, yyyy");
StringBuilder result = new StringBuilder();
[Link](title);
[Link](' ').append(firstName);
[Link](' ').append(lastName);
[Link](" hired ").append([Link](hireDate));
return [Link]();
}
public String getName() {
return firstName + " " + lastName;
}
public String getTitle() {
return title;
}
public Date getHireDate() {
return hireDate;
}
public int getId() {
return id;
}
public int getSupervisorId() {
return supervisorId;
}
public Date getDepartmentStartDate() {
return departmentStartDate;
}
}

[Link].5
import [Link];
import [Link];
import [Link];

public class Employee implements Serializable {


static final long serialVersionUID = -8853382621975997090L;
private int id;
private String firstName;
private String lastName;
private String title;
private String departmentCode;
private int supervisorId;
private Date hireDate;

© 2011 ITCourseware, LLC Rev 5.1.4 Page 469


Advanced Java Programming

Chapter 2 (cont'd)

[Link].5 (cont'd)
private float salary;
private Date departmentStartDate;

public Employee(int i, String first, String last, String ti,


String deptCode, int supId, Date hire, float sal)
{
this(i, first, last, ti, deptCode, supId, hire, hire, sal);
}

public Employee(int i, String first, String last, String ti,


String deptCode, int supId, Date hire,
Date deptDate, float sal) {
id = i;
firstName = first;
lastName = last;
title = ti;
departmentCode = deptCode;
supervisorId = supId;
hireDate = hire;
departmentStartDate = deptDate;
salary = sal;
}

public boolean equals(Object o) {


if (o instanceof Employee) {
Employee eTest = (Employee) o;
return id == [Link] &&
[Link]([Link]) &&
[Link]([Link]) &&
[Link]([Link]) &&
[Link]([Link]);
}
else
return false;
}
public String toString() {
SimpleDateFormat df = new SimpleDateFormat("MMM d, yyyy");
StringBuilder result = new StringBuilder();
[Link](title);
[Link](" ").append(firstName);
[Link](" ").append(lastName);
[Link](" hired ").append([Link](hireDate));
Page 470 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link].5 (cont'd)
[Link](" department start date ");
[Link]([Link](departmentStartDate));
return [Link]();
}
public String getName() {
return firstName + " " + lastName;
}
public String getTitle() {
return title;
}
public Date getHireDate() {
return hireDate;
}
public int getId() {
return id;
}
public int getSupervisorId() {
return supervisorId;
}
public Date getDepartmentStartDate() {
return departmentStartDate;
}
}

[Link]
When you run ReadDept using the new class on the old object it throws
a NullPointerException because the [Link](Date)
method receives a null parameter when we pass departmentStartDate.

A newly constructed object will never have this problem because the
constructors provide a default value for departmentStartDate. However,
when we deserialize an old version of the class in which that field is
missing, it is set to null by the default deserialization mechanism.

[Link].6
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class Employee implements Serializable {


static final long serialVersionUID = -8853382621975997090L;

© 2011 ITCourseware, LLC Rev 5.1.4 Page 471


Advanced Java Programming

Chapter 2 (cont'd)

[Link].6 (cont'd)
private int id;
private String firstName;
private String lastName;
private String title;
private String departmentCode;
private int supervisorId;
private Date hireDate;
private float salary;
private Date departmentStartDate;

public Employee(int i, String first, String last, String ti,


String deptCode, int supId, Date hire, float sal) {
this(i, first, last, ti, deptCode, supId, hire, hire, sal);
}

public Employee(int i, String first, String last, String ti,


String deptCode, int supId, Date hire,
Date deptDate, float sal) {
id = i;
firstName = first;
lastName = last;
title = ti;
departmentCode = deptCode;
supervisorId = supId;
hireDate = hire;
departmentStartDate = deptDate;
salary = sal;
}

private void readObject(ObjectInputStream in)


throws IOException, ClassNotFoundException {
[Link]();
if (departmentStartDate == null) {
departmentStartDate = hireDate;
}
}
public boolean equals(Object o) {
if (o instanceof Employee) {
Employee eTest = (Employee) o;
return id == [Link] &&
[Link]([Link]) &&

Page 472 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link].6 (cont'd)
[Link]([Link]) &&
[Link]([Link]) &&
[Link]([Link]);
}
else return false;
}
public String toString() {
SimpleDateFormat df = new SimpleDateFormat("MMM d, yyyy");
StringBuilder result = new StringBuilder();
[Link](title);
[Link](" ").append(firstName);
[Link](" ").append(lastName);
[Link](" hired ").append([Link](hireDate));
[Link](" department start date ");
[Link]([Link](departmentStartDate));
return [Link]();
}
public String getName() {
return firstName + " " + lastName;
}
public String getTitle() {
return title;
}
public Date getHireDate() {
return hireDate;
}
public int getId() {
return id;
}
public int getSupervisorId() {
return supervisorId;
}
public Date getDepartmentStartDate() {
return departmentStartDate;
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

© 2011 ITCourseware, LLC Rev 5.1.4 Page 473


Advanced Java Programming

Chapter 2 (cont'd)

[Link] (cont'd)
public class WriteDept7 {
public static void main(String args[]) throws ParseException {
SimpleDateFormat f = new SimpleDateFormat("M/d/yyyy");
Date hd = [Link]("08/05/1960");
Date dsd = [Link]("01/01/1962");
Employee armstrong = new Employee(5, "Neil", "Armstrong",
"Astronaut", "SP", 1, hd, dsd, 30000);
Department space = new Department("SP", "Space Division",
armstrong, "Edwards", "CA");
ObjectOutputStream out = null;

try {
out = new ObjectOutputStream(new FileOutputStream("[Link]"));
}
catch (IOException e) {
[Link]("Error opening output file: "
+ [Link]());
[Link](1);
}

try {
[Link](space);
[Link]("Wrote \"" + space + "\" to file");
}
catch (IOException e) {
[Link]("Error writing to file: " + [Link]());
[Link](2);
}
finally {
try {
[Link]();
}
catch (IOException e) {
[Link](3);
}
}
}
}

Page 474 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

Chapter 3

[Link]
import [Link];
import [Link];
import [Link];
import [Link];

public class CopyScatter {


public static void main(String[] args) {
try {
FileInputStream fin = new FileInputStream("[Link]");
FileChannel fcin = [Link]();
FileOutputStream fout = new FileOutputStream("JavaSource");
FileChannel fcout = [Link]();

ByteBuffer buf = [Link](1024);


while (([Link](buf)) != -1) {
[Link]();
[Link](buf);
[Link]();
}
[Link]();
[Link]();
}
catch (Exception e) {
[Link]();
}
}
}

[Link]
import [Link];
import [Link];
import [Link];

public class BufferlessCopy {


public static void main(String[] args) {
try {
FileInputStream fin = new FileInputStream("[Link]");
FileChannel fcin = [Link]();
FileOutputStream fout = new FileOutputStream("JavaSource");
FileChannel fcout = [Link]();

© 2011 ITCourseware, LLC Rev 5.1.4 Page 475


Advanced Java Programming

Chapter 3 (cont'd)

[Link] (cont'd)
[Link](0, [Link](), fcout);

[Link]();
[Link]();
}
catch (Exception e) {
[Link]();
}
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class WriteCharsets {


public static void main(String[] args) {
try {
String fileName = "charsets";
RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
FileChannel channel = [Link]();
ByteBuffer buf = [Link](1024);

Map<String, Charset> charsets = [Link]();


for (String csName : [Link]()) {
if ([Link]() + 1 > [Link]() - [Link]()) {
[Link]();
[Link](buf);
[Link]();
}
[Link]([Link]());
[Link]((byte) '\n');
}
[Link]();
[Link](buf);
[Link]();
}
catch (Exception e) {
[Link]();
Page 476 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
}
}
}

[Link]
The second version uses UTF-16 encoding, so when we look at the result file it looks like the
characters are spaced out.

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class WriteCharsets2 {


public static void main(String[] args) {
try {
String fileName = "charsets2";
RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
FileChannel channel = [Link]();
ByteBuffer buf = [Link](1024);
CharBuffer cbuf = [Link]();

Map<String, Charset> charsets = [Link]();


for (String csName : [Link]()) {
if ([Link]() + 1 > ([Link]() - [Link]())) {
[Link]();
[Link](buf);
[Link]();
[Link]();
}
[Link](csName);
[Link]('\n');
}
[Link]();
[Link](buf);
[Link]();
}
catch (Exception e) {
[Link]();
}
}
}
© 2011 ITCourseware, LLC Rev 5.1.4 Page 477
Advanced Java Programming

Chapter 4

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class Reflect1 implements IReflect {


public static void main(String[] args) {
Reflect1 reflect = new Reflect1();
ReflectFrame frame = new ReflectFrame(reflect);
[Link](true);
}
public Vector<Constructor> getCtors(String className) {
Vector<Constructor> v = new Vector<Constructor>();
try {
Class cls = [Link](className);
Constructor[] ctors = [Link]();
for (Constructor ctor : ctors) {
[Link](ctor);
}
}
catch (ClassNotFoundException cnfe) {
[Link]();
}
return v;
}
public Object instantiate(Constructor ctor, Object[] args) {
Object o = null;
// fill in code here

return o;
}
public Vector<Method> getMethods(Object obj) {
Vector<Method> v = new Vector<Method>();
// fill in code here

return v;
}
public Object invoke(Method method, Object target, Object[] args) {
Object retValue = null;
// fill in code here

Page 478 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link] (cont'd)
return retValue;
}
public Vector<String> getClasses() {
Vector<String> v = new Vector<String>();
File curDir = new File(".");
File[] classFiles = [Link](new FileFilter() {
public boolean accept(File f) {
return [Link]().contains(".class");
}});
for (File file : classFiles) {
String name = [Link]();
name = [Link](0, [Link](".class"));
[Link](name);
}
return v;
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class Reflect2 implements IReflect {


public static void main(String[] args) {
Reflect2 reflect = new Reflect2();
ReflectFrame frame = new ReflectFrame(reflect);
[Link](true);
}
public Vector<Constructor> getCtors(String className) {
Vector<Constructor> v = new Vector<Constructor>();
try {
Class cls = [Link](className);
Constructor[] ctors = [Link]();
for (Constructor ctor : ctors) {
[Link](ctor);
}
}
catch (ClassNotFoundException cnfe) {
[Link]();
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 479


Advanced Java Programming

Chapter 4 (cont'd)

[Link] (cont'd)
return v;
}
public Object instantiate(Constructor ctor, Object[] args) {
Object o = null;
try {
o = [Link](args);
}
catch (Exception e) {
[Link]();
}
return o;
}
public Vector<Method> getMethods(Object obj) {
Vector<Method> v = new Vector<Method>();
// fill in code here

return v;
}
public Object invoke(Method method, Object target, Object[] args) {
Object retValue = null;
// fill in code here

return retValue;
}
public Vector<String> getClasses() {
Vector<String> v = new Vector<String>();
File curDir = new File(".");
File[] classFiles = [Link](new FileFilter() {
public boolean accept(File f) {
return [Link]().contains(".class");
}});
for (File file : classFiles) {
String name = [Link]();
name = [Link](0, [Link](".class"));
[Link](name);
}
return v;
}
}

Page 480 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class Reflect3 implements IReflect {


public static void main(String[] args) {
Reflect3 reflect = new Reflect3();
ReflectFrame frame = new ReflectFrame(reflect);
[Link](true);
}
public Vector<Constructor> getCtors(String className) {
Vector<Constructor> v = new Vector<Constructor>();
try {
Class cls = [Link](className);
Constructor[] ctors = [Link]();
for (Constructor ctor : ctors) {
[Link](ctor);
}
}
catch (ClassNotFoundException cnfe) {
[Link]();
}
return v;
}
public Object instantiate(Constructor ctor, Object[] args) {
Object o = null;
try {
o = [Link](args);
}
catch (Exception e) {
[Link]();
}
return o;
}
public Vector<Method> getMethods(Object obj) {
Vector<Method> v = new Vector<Method>();
Class cls = [Link]();
Method[] methods = [Link]();
for (Method method : methods) {
[Link](method);
}
return v;

© 2011 ITCourseware, LLC Rev 5.1.4 Page 481


Advanced Java Programming

Chapter 4 (cont'd)

[Link] (cont'd)
}
public Object invoke(Method method, Object target, Object[] args) {
Object retValue = null;
// fill in code here

return retValue;
}
public Vector<String> getClasses() {
Vector<String> v = new Vector<String>();
File curDir = new File(".");
File[] classFiles = [Link](new FileFilter() {
public boolean accept(File f) {
return [Link]().contains(".class");
}});
for (File file : classFiles) {
String name = [Link]();
name = [Link](0, [Link](".class"));
[Link](name);
}
return v;
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class Reflect4 implements IReflect {


public static void main(String[] args) {
Reflect4 reflect = new Reflect4();
ReflectFrame frame = new ReflectFrame(reflect);
[Link](true);
}
public Vector<Constructor> getCtors(String className) {
Vector<Constructor> v = new Vector<Constructor>();
try {
Class cls = [Link](className);
Constructor[] ctors = [Link]();
Page 482 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
for (Constructor ctor : ctors) {
[Link](ctor);
}
}
catch (ClassNotFoundException cnfe) {
[Link]();
}
return v;
}
public Object instantiate(Constructor ctor, Object[] args) {
Object o = null;
try {
o = [Link](args);
}
catch (Exception e) {
[Link]();
}
return o;
}
public Vector<Method> getMethods(Object obj) {
Vector<Method> v = new Vector<Method>();
Class cls = [Link]();
Method[] methods = [Link]();
for (Method method : methods) {
[Link](method);
}
return v;
}
public Object invoke(Method method, Object target, Object[] args) {
Object retValue = null;
try {
retValue = [Link](target, args);
}
catch (Exception e) {
[Link]();
}
return retValue;
}
public Vector<String> getClasses() {
Vector<String> v = new Vector<String>();
File curDir = new File(".");
File[] classFiles = [Link](new FileFilter() {
public boolean accept(File f) {
return [Link]().contains(".class");
}});

© 2011 ITCourseware, LLC Rev 5.1.4 Page 483


Advanced Java Programming

Chapter 4 (cont'd)

[Link] (cont'd)
for (File file : classFiles) {
String name = [Link]();
name = [Link](0, [Link](".class"));
[Link](name);
}
return v;
}
}

Page 484 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

Chapter 5

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class ImageToFile {


public static void main(String args[]) {
try {
[Link]("[Link]");
String url = "jdbc:derby://localhost:1527/j2se";
Connection conn = [Link](url);
Statement stmt = [Link]();

ResultSet rs = [Link]("SELECT lastname, mugshot " +


"FROM employee " +
"WHERE mugshot IS NOT NULL");

while ([Link]()) {
String filepath = [Link](1) + ".gif";
Blob b = [Link](2);

FileOutputStream ostream = new FileOutputStream(filepath);


[Link]([Link](1, (int)[Link]()));
[Link]();

[Link]("Image saved as " + filepath);


}
[Link]();
[Link]();
}
catch (Exception e) {
[Link]();
}
}
}

[Link]
import [Link];
import [Link];
© 2011 ITCourseware, LLC Rev 5.1.4 Page 485
Advanced Java Programming

Chapter 5 (cont'd)

[Link] (cont'd)
import [Link];
import [Link];
import [Link];
import [Link];

public class LongTermEmps {


public static void main(String args[]){
try {
[Link]("[Link]");
String url = "jdbc:derby://localhost:1527/j2se";
Connection conn = [Link](url);
Statement stmt = [Link]();

ResultSet result = [Link](


"SELECT lastname, hire_date, salary " +
"FROM employee " +
"WHERE hire_date < {d '1995-01-01'}");

CachedRowSet crs = new CachedRowSetImpl();


[Link](result);
while ([Link]()) {
[Link]([Link]("lastname") + " " +
[Link]("hire_date") + " " +
[Link]("salary"));
}
[Link]();
[Link]();
[Link]();
}
catch (Exception e) {
[Link]();
}
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
Page 486 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
import [Link];

public class LongTermEmps2 {


public static void main(String args[]){
try {
[Link]("[Link]");
String url = "jdbc:derby://localhost:1527/j2se";
Connection conn = [Link](url);
Statement stmt = [Link]();

ResultSet result = [Link](


"SELECT lastname, hire_date, salary " +
"FROM employee " +
"WHERE hire_date < {d '1995-01-01'}");

CachedRowSet crs = new CachedRowSetImpl();


[Link](result);
[Link]();

while ([Link]()) {
[Link]([Link]("lastname") + " " +
[Link]("hire_date") + " " +
[Link]("salary"));

if ([Link]("salary") < 50000)


[Link]("salary",50000);
[Link]();
}
[Link](conn);
[Link]();
[Link]();
}
catch (Exception e) {
[Link]();
}
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

© 2011 ITCourseware, LLC Rev 5.1.4 Page 487


Advanced Java Programming

Chapter 5 (cont'd)

[Link] (cont'd)
import [Link];

public class LongTermEmps3 {


public static void main(String args[]){
try {
[Link]("[Link]");
String url = "jdbc:derby://localhost:1527/j2se";
Connection conn = [Link](url);
Statement stmt = [Link]();

ResultSet result = [Link](


"SELECT id, lastname, firstname, hire_date, salary " +
"FROM employee " +
"WHERE hire_date < {d '1995-01-01'}");

CachedRowSet crs = new CachedRowSetImpl();


[Link](result);
[Link]();
[Link]("id",1000);
[Link]("lastname","Seitz");
[Link]("firstname","Robert");
[Link]("salary",100000);
[Link]();
[Link]();

while ([Link]()) {
[Link]([Link]("lastname") + " " +
[Link]("hire_date") + " " +
[Link]("salary"));
}
[Link]("employee");
[Link](conn);
[Link]();
[Link]();
}
catch (Exception e) {
[Link]();
}
}
}

Page 488 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

Chapter 6

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class GetImage {


public static void main(String args[]) {
if ([Link] == 0) {
[Link]("usage: java GetImage image_URL");
[Link](1);
}

URL imgURL = null;


URLConnection imgConn = null;
String imgType = null;
try {
imgURL = new URL(args[0]);
imgConn = [Link]();

// connect explicitly to catch connection problem exceptions


[Link]();

// Check the content-type to make sure it is an image


imgType = [Link]();
if (! [Link]("image/")) {
[Link](args[0] + ": not an image");
[Link](2);
}
// extract the specific image type from the content-type value
imgType = [Link]([Link]('/') + 1);
}
catch (IOException e) {
[Link]("Error establishing URL connection: " + e);
[Link](3);
}

String fileName = "image." + imgType;


byte[] buffer = new byte[1000];
FileOutputStream imgFile = null;
InputStream imgStream = null;
try {
© 2011 ITCourseware, LLC Rev 5.1.4 Page 489
Advanced Java Programming

Chapter 6 (cont'd)

[Link] (cont'd)
imgFile = new FileOutputStream(fileName);
imgStream = [Link]();
int len = -1;
while ((len = [Link](buffer)) != -1) {
[Link](buffer, 0, len);
}
}
catch (IOException ioex) {
[Link]("Error copying image: " + ioex);
[Link](3);
}
finally {
if (imgFile != null) {
try {
[Link]();
}
catch (IOException ignore) {}
}
if (imgStream != null) {
try {
[Link]();
}
catch (IOException ignore) {}
}
}
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class SendFile {


public static void main(String[] args) {
String file = "[Link]";
int port = 8000;

ServerSocket ss = null;
Socket s = null;
Page 490 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
OutputStream sockout = null;

byte[] data = null; // contents of the file

try {
FileInputStream in = new FileInputStream(file);
data = new byte[[Link]()];
[Link](data);
[Link]();
}
catch (IOException e) {
[Link]("Error reading " + file + ": " + e);
[Link](1);
}

try {
ss = new ServerSocket(port);

while (true) {
// wait for the connection
s = [Link]();

// build sockout from the socket's Output Stream


sockout = [Link]();

// Tell the user that we've connected


[Link]("Connected to " +
[Link]() + ":"+ [Link]());

// Send the client the contents of the file


[Link](data);

[Link]();
}
}
catch (IOException e) {
[Link](e) ;
}
finally {
// Always be sure to close the sockets to release resources
if (ss != null) {
try {
[Link]();
}
catch (IOException ignore) {}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 491


Advanced Java Programming

Chapter 6 (cont'd)

[Link] (cont'd)
}
if (s != null) {
try {
[Link]();
}
catch (IOException ignore) {}
}
}
}
}

[Link]
There's nothing very mysterious about you, except that
nobody really knows your origin, purpose, or destination.

Tact, n.:
The unsaid part of what you're thinking.

The most exciting phrase to hear in science, the one that heralds new
discoveries, is not "Eureka!" (I found it!) but "That's funny ..."
-- Isaac Asimov

My pen is at the bottom of a page,


Which, being finished, here the story ends;
'Tis to be wished it had been sooner done,
But stories somehow lengthen when begun.
-- Byron

Speaking of love, one problem that recurs more and more frequently these
days, in books and plays and movies, is the inability of people to communicate
with the people they love; Husbands and wives who can't communicate, children
who can't communicate with their parents, and so on. And the characters in
these books and plays and so on (and in real life, I might add) spend hours
bemoaning the fact that they can't communicate. I feel that if a person can't
communicate, the very _____ least he can do is to shut up!
-- Tom Lehrer, "That Was the Year that Was"

My idea of roughing it is when room service is late.


A list is only as strong as its weakest link.
-- Don Knuth
Page 492 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
Her days were spent in a kind of slow bustle; always busy without getting
on, always behind hand and lamenting it, without altering her ways;
wishing to be an economist, without contrivance or regularity; dissatisfied
with her servants, without skill to make them better, and whether helping, or
reprimanding, or indulging them, without any power of engaging their respect.
-- J. Austen

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class GetFile {


public static void main(String[] args) {
Socket s = null;
BufferedReader sockin = null;

try {
// create the connection
s = new Socket([Link](), 8000);

// create a BufferedReader to read lines from the server output


sockin = new BufferedReader(
new InputStreamReader([Link]()));

// Tell the user that we've connected


[Link]("Connected to " +
[Link]() + ":"+ [Link]());

// read what the server sends


String linein = null;
while((linein = [Link]()) != null) {
[Link](linein);
}
}
catch (IOException e) {
[Link](e);
}
// Always be sure to close the socket to release resources
finally {
if (s != null) {
try {
[Link]();
© 2011 ITCourseware, LLC Rev 5.1.4 Page 493
Advanced Java Programming

Chapter 6 (cont'd)

[Link] (cont'd)
}
catch (IOException ignore) {}
}
}
}
}

[Link]
public class ServerStatistics implements [Link] {
private String fileName;
private int connectionCount;
private int port;

public ServerStatistics(String fnam, int port, int count) {


fileName = fnam;
[Link] = port;
connectionCount = count;
}

public String getFileName() {


return fileName;
}
public int getConnectionCount() {
return connectionCount;
}
public int getPort() {
return port;
}
public void incrementConnectionCount() {
connectionCount += 1;
}
public String toString() {
StringBuilder result = new StringBuilder("ServerStatistics:");
[Link](" serving file ").append(fileName);
[Link](" on port ").append(port);
[Link](" ").append(connectionCount);
[Link](" connections.");
return [Link]();
}
}

Page 494 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class SendFile2 {

public static void main(String[] args) {


String file = "[Link]";
int port = 8000;
int adminPort = 9000;
ServerStatistics statistics = new ServerStatistics(file, port, 0);

ServerSocket ss = null;
Socket s = null;
OutputStream sockout = null;

byte[] data = null; // contents of the file

try {
FileInputStream in = new FileInputStream(file);
data = new byte[[Link]()];
[Link](data);
[Link]();
}
catch (IOException e) {
[Link]("Error reading " + file + ": " + e);
[Link](1);
}

// start a thread listening for admin requests


new AdminThread(adminPort, statistics).start();

try {
ss = new ServerSocket(port);

while (true) {
// wait for the connection
s = [Link]();

[Link]();

// build sockout from the socket's Output Stream

© 2011 ITCourseware, LLC Rev 5.1.4 Page 495


Advanced Java Programming

Chapter 6 (cont'd)

[Link] (cont'd)
sockout = [Link]();

// Tell the user that we've connected


[Link]("Connected to " +
[Link]() +
":"+ [Link]());

// Send the client the contents of the file


[Link](data);

[Link]();
}
}
catch (IOException e) {
[Link](e) ;
}
finally {
// Always be sure to close the sockets to release resources
if (ss != null) {
try {
[Link]();
}
catch (IOException ignore) {}
}
if (s != null) {
try {
[Link]();
}
catch (IOException ignore) {}
}
}
}

}
class AdminThread extends Thread {
private int adminPort;
private ServerStatistics statistics;

AdminThread(int adminPort, ServerStatistics statistics) {


[Link] = adminPort;
[Link] = statistics;
}
Page 496 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
public void run() {
ServerSocket ss = null;
Socket s = null;
ObjectOutputStream sockout = null;
try {
ss = new ServerSocket(adminPort);

while (true) {
s = [Link]();
sockout = new ObjectOutputStream([Link]());

// Tell the user that we've connected


[Link]("Connected to admin client " +
[Link]() + ":"+ [Link]());

[Link](statistics);
[Link]();
}
}
catch (IOException e) {
[Link]("Error in admin thread: " + e) ;
}
finally {
// Always be sure to close the sockets to release resources
if (ss != null) {
try {
[Link]();
}
catch (IOException ignore) {}
}
if (s != null) {
try {
[Link]();
}
catch (IOException ignore) {}
}
}
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 497


Advanced Java Programming

Chapter 6 (cont'd)

[Link]
import [Link];
import [Link];
import [Link];
import [Link];

public class AdminClient {


public static void main(String args[]) {
Socket s = null;
ObjectInputStream sockin = null;

try {
// Connect to the server's admin port
s = new Socket([Link](), 9000);

sockin = new ObjectInputStream([Link]());

// Tell the user that we've connected


[Link]("Connected to " +
[Link]() + ":" + [Link]());

// get the statistics object


ServerStatistics stats = (ServerStatistics)[Link]();
[Link](stats);
}
catch (IOException ioe) {
[Link]("Error connecting to server: " + ioe);
}
catch (ClassNotFoundException e) {
[Link](
"Error reading ServerStatistics obj from admin server " + e);
}
finally {
if (s != null) {
try {
[Link]();
}
catch (IOException ignore) {}
}
}
}
}

Page 498 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

Chapter 7

[Link]
import [Link];

public class Customer1 {


public static void main(String[] args) {
try {
Store store = (Store) [Link]("///Store");
Attendant attendant = [Link]();
int orderNumber = [Link]("hdw123", 5);
[Link]("The order number is: " + orderNumber);
[Link]();
}
catch (Exception e) {
[Link](e);
}
}
}

[Link]
import [Link];
import [Link];

public interface Attendant2 extends Remote {


public int submitOrder(Order order) throws RemoteException;
public boolean release() throws RemoteException;
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class AttendantServer2 extends UnicastRemoteObject


implements Attendant2 {
private DateFormat tf;
private StoreServer2 store;
© 2011 ITCourseware, LLC Rev 5.1.4 Page 499
Advanced Java Programming

Chapter 7 (cont'd)

[Link] (cont'd)
public AttendantServer2(StoreServer2 store) throws RemoteException {
[Link] = store;
tf = [Link]();
[Link]([Link]());
}

public int submitOrder(Order order) {


int orderNum = [Link]();

[Link]("Order #" + orderNum + " received at " +


[Link](new Date()));

HashMap<String, Integer> items = [Link]();


for ([Link]<String, Integer> item : [Link]() ) {
[Link](" Item: " + [Link]() +
" quantity: " + [Link]());
}

return orderNum;
}
public boolean release() {
boolean success = false;
try {
success = [Link](this, false);
}
catch (NoSuchObjectException e) {
[Link](e);
}
return success;
}
}

[Link]
import [Link];

public class Customer2 {


public static void main(String[] args) {
try {
Store2 store = (Store2) [Link]("///Store2");
Attendant2 attendant = [Link]();

Page 500 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link] (cont'd)
Order order = new Order();
[Link]("hdw123", 5);
[Link]("app456", 2);
[Link]("per789", 3);
int orderNumber = [Link](order);
[Link]("The order number is: " + orderNumber);

[Link]();
}
catch (Exception e) {
[Link](e);
}
}
}

[Link]
import [Link];

public class Order implements [Link] {


private HashMap<String, Integer> orderItems;

public Order() {
orderItems = new HashMap<String, Integer>();
}

public void add(String itemCode, int quantity) {


[Link](itemCode, new Integer(quantity));
}
public HashMap<String, Integer> getItems() {
return orderItems;
}
}

[Link]
import [Link];
import [Link];

public interface Store2 extends Remote {


public Attendant2 getAttendant() throws RemoteException;
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 501


Advanced Java Programming

Chapter 7 (cont'd)

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class StoreServer2 extends UnicastRemoteObject


implements Store2 {
private HashMap<String, Item> items;
private static int nextOrder=1;

public StoreServer2() throws RemoteException {


items = new HashMap<String, Item>();
[Link]("hdw123", new ItemImpl("hdw123", "1 GB SIM", 50));
[Link]("hdw124", new ItemImpl("hdw124", "60 GB HD", 30));
[Link]("hdw125", new ItemImpl("hdw125", "80 GB HD", 25));
[Link]("per456", new ItemImpl("per456", "InkJet Printer", 36));
[Link]("per457", new ItemImpl("per457", "Laser Printer", 4));
}
public Attendant2 getAttendant() throws RemoteException {
return new AttendantServer2(this);
}
public Set<String> getCodes() {
return [Link]();
}
public Collection<Item> getItems() {
return [Link]();
}
public Item getItem(String code) {
return [Link](code);
}
public static synchronized int getOrderNumber() {
return nextOrder++;
}
public static void main(String[] args) {
try {
StoreServer2 store = new StoreServer2();
[Link]("///Store2", store);
}
catch ([Link] e) {
[Link](e);
Page 502 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
}
catch (RemoteException e) {
[Link](e);
}
}
}

[Link]
import [Link];
import [Link];

public interface Attendant3 extends Remote {


public String[] listItems() throws RemoteException;
public Item3 getItem(String code) throws RemoteException;

public int submitOrder(Order order) throws RemoteException;


public boolean release() throws RemoteException;
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class AttendantServer3 extends UnicastRemoteObject


implements Attendant3 {
private DateFormat tf;
private StoreServer3 store;

public AttendantServer3(StoreServer3 store) throws RemoteException {


[Link] = store;
tf = [Link]();
[Link]([Link]());
}

public String[] listItems() {


Set<String> codeSet = [Link]();
© 2011 ITCourseware, LLC Rev 5.1.4 Page 503
Advanced Java Programming

Chapter 7 (cont'd)

[Link] (cont'd)
String[] codes = new String[[Link]()];
return [Link](codes);
}
public Item3 getItem(String code) {
return [Link](code);
}
public int submitOrder(Order order) throws RemoteException {
int orderNum = [Link]();

[Link]("Order #" + orderNum + " received at " +


[Link](new Date()));

HashMap<String, Integer> items = [Link]();


for ([Link]<String, Integer> item : [Link]() ) {
Item3 invItem = [Link]([Link]());
int onHand = [Link]();
int orderQuantity = [Link]().intValue();

[Link](" Item: " + [Link]() + " quantity: " +


[Link]());

if (onHand < orderQuantity) {


[Link](" backordered");
}
else {
ItemImpl3 impl = (ItemImpl3) invItem;
[Link](onHand - orderQuantity);
}
}
return orderNum;
}
public boolean release() {
boolean success = false;
try {
success = [Link](this, false);
}
catch (NoSuchObjectException e) {
[Link](e);
}
return success;
}
}
Page 504 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link]
import [Link];

public class Customer3 {


public static void main(String[] args) {
try {
Store3 store = (Store3) [Link]("///Store3");
Attendant3 attendant = [Link]();

String[] itemCodes = [Link]();


[Link]("All item codes: ");
for (String code : itemCodes) {
[Link]("Item Code: " + code);
}
[Link]();

Item3 i = [Link]("hdw123");
[Link]("Item Code: " + [Link]() +
" Description: " + [Link]() +
" Quantity On Hand: " + [Link]());

Order order = new Order();


[Link]("hdw123", 5);
[Link]("per456", 3);
int orderNumber = [Link](order);
[Link]("The order number is: " + orderNumber);

[Link]("Item Code: " + [Link]() +


" Description: " + [Link]() +
" Quantity On Hand: " + [Link]());

[Link]();
}
catch (Exception e) {
[Link](e);
}
}
}

[Link]
import [Link];
import [Link];
import [Link];

public interface Item3 extends Remote {

© 2011 ITCourseware, LLC Rev 5.1.4 Page 505


Advanced Java Programming

Chapter 7 (cont'd)

[Link] (cont'd)
public String getItemCode() throws RemoteException;
public String getDescription() throws RemoteException;
public int getQuantityOnHand() throws RemoteException;
}

class ItemImpl3 extends UnicastRemoteObject implements Item3 {


private String itemCode;
private String description;
private int quantityOnHand;

public ItemImpl3() throws RemoteException {


}
public ItemImpl3(String code, String desc, int quantity)
throws RemoteException {
itemCode = code;
description = desc;
quantityOnHand = quantity;
}

public String getItemCode() {


return itemCode;
}
public void setItemCode(String code) {
itemCode = code;
}
public String getDescription() {
return description;
}
public void setDescription(String desc) {
description = desc;
}
public int getQuantityOnHand() {
return quantityOnHand;
}
public void setQuantityOnHand(int q) {
quantityOnHand = q;
}
}

Page 506 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link]
import [Link];
import [Link];

public interface Store3 extends Remote {


public Attendant3 getAttendant() throws RemoteException;
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class StoreServer3 extends UnicastRemoteObject


implements Store3 {
private HashMap<String, Item3> items;
private static int nextOrder=1;

public StoreServer3() throws RemoteException {


items = new HashMap<String, Item3>();
[Link]("hdw123", new ItemImpl3("hdw123", "1 GB SIM", 50));
[Link]("hdw124", new ItemImpl3("hdw124", "60 GB HD", 30));
[Link]("hdw125", new ItemImpl3("hdw125", "80 GB HD", 25));
[Link]("per456", new ItemImpl3("per456", "InkJt Printer", 36));
[Link]("per457", new ItemImpl3("per457", "Laser Printer", 4));
}
public Attendant3 getAttendant() throws RemoteException {
return new AttendantServer3(this);
}
public Set<String> getCodes() {
return [Link]();
}
public Collection<Item3> getItems() {
return [Link]();
}
public Item3 getItem(String code) {
return [Link](code);
}
public static synchronized int getOrderNumber() {
return nextOrder++;
}
public static void main(String[] args) {

© 2011 ITCourseware, LLC Rev 5.1.4 Page 507


Advanced Java Programming

Chapter 7 (cont'd)

[Link] (cont'd)
try {
StoreServer3 store = new StoreServer3();
[Link]("///Store3", store);
}
catch ([Link] e) {
[Link](e);
}
catch (RemoteException e) {
[Link](e);
}
}
}

Page 508 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

Chapter 8

[Link]
import [Link];
import [Link];

public interface ChatIF extends Remote {


public void postChat(String msg, String sender)
throws RemoteException;
public void registerForNotification(Notifiable n)
throws RemoteException;
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class ChatServer extends UnicastRemoteObject


implements ChatIF {

private HashSet<Notifiable> listeners = null;

public ChatServer() throws RemoteException {


listeners = new HashSet<Notifiable>();
}

public void postChat(String msg, String sender) {


[Link](sender + ": " + msg);
Iterator<Notifiable> it = [Link]();
while ([Link]()) {
Notifiable not = [Link]();
try {
[Link](msg, sender);
}
catch (Exception e) {
[Link](e);
}
}
}
public void registerForNotification(Notifiable n) {
if (![Link](n)) {
© 2011 ITCourseware, LLC Rev 5.1.4 Page 509
Advanced Java Programming

Chapter 8 (cont'd)

[Link] (cont'd)
[Link](n);
}
}
public static void main(String[] args) {
try {
ChatServer c = new ChatServer();
[Link]("//localhost:1099/chat", c);
[Link]("Chat bound.");
}
catch (Exception e) {
[Link](e);
}
}
}

[Link]
import [Link];
import [Link];

public interface Notifiable extends Remote {


public void notify(String msg, String sender)
throws RemoteException;
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class ChatClient extends UnicastRemoteObject


implements Notifiable {

public ChatClient() throws RemoteException{


BufferedReader in =
new BufferedReader(new InputStreamReader([Link]));
[Link]("Please enter alias: ");
try {
String alias = [Link]();
Page 510 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
ChatIF c = (ChatIF)[Link]("//localhost:1099/chat");
[Link](this);

while (true) {
[Link]("Enter a chat message, '##' to quit: ");
String line = [Link]();
if ([Link]("##")) {
[Link](0);
}
[Link](line, alias);
}
}
catch (Exception e) {
[Link](e);
}
}
public void notify(String msg, String sender) {
[Link]("\n" + sender + ": " + msg);
}
public static void main(String[] args) {
try {
new ChatClient();
}
catch (RemoteException e) {
[Link](e);
}
}
}

ISBN_IF.java
import [Link];
import [Link];

public interface ISBN_IF extends Remote {


public String getTitle(String isbn) throws RemoteException;
}

ISBN_Impl.java
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
© 2011 ITCourseware, LLC Rev 5.1.4 Page 511
Advanced Java Programming

Chapter 8 (cont'd)

ISBN_Impl.java (cont'd)
public class ISBN_Impl extends Activatable implements ISBN_IF {
private HashMap<String, String> map = null;

public ISBN_Impl(ActivationID id, MarshalledObject data)


throws RemoteException {
super(id, 0);
map = new HashMap<String, String>();
[Link]("0131483986", "Java How to Program");
[Link]("1586639161 ", "Java");
[Link]("0201310058", "Effective Java Programming Language Guide");
[Link]("0321305027 ", "The Java Developer's Guide to Eclipse");
[Link]("0596009208 ", "Head First Java");
[Link]("0596007736", "Java in a Nutshell");
}

public String getTitle(String isbn) {


String title = [Link](isbn);
return title;
}
}

[Link]
/* allow the JVM for an activation group to specify a security policy */
grant {
permission [Link] "-
[Link]=*";
};

[Link]
/* allow remote objects in the activation group to accept
* connetcionts on any non-privileged port
*/
grant {
permission [Link] "*:1024-", "accept,resolve";
};

Page 512 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class ISBNSetup {


public static void main(String[] args) throws Exception {
if ([Link] != 1) {
[Link](
"usage: java -[Link]=codebase_url" +
"ISBNSetup activation_group_policy_file");
[Link](1);
}

String policy = args[0];


Properties props = new Properties();
[Link]("[Link]", policy);

ActivationGroupDesc group = new ActivationGroupDesc(props, null);


ActivationGroupID groupId =
[Link]().registerGroup(group);

// copy the activation group's codebase from the system property


String codebase = [Link]("[Link]");

ActivationDesc desc =
new ActivationDesc (groupId, "ISBN_Impl", codebase, null);

// Register the interface with the activation system (rmid)


ISBN_IF isbn = (ISBN_IF)[Link](desc);
[Link]("Got stub for ISBN");

// Bind it in the registry (rmiregistry)


[Link]("ISBNImpl", isbn);
[Link]("Exported ISBN_Impl");
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 513


Advanced Java Programming

Chapter 8 (cont'd)

[Link]
0131483986, Java How to Program
1586639161, Java
0201310058, Effective Java Programming Language Guide
0321305027, The Java Developer's Guide to Eclipse
0596009208, Head First Java
0596007736, Java in a Nutshell

[Link]
import [Link];

public class ISBNClient {


public static void main(String args[]) {
try {
String loc = "rmi://localhost/ISBNImpl";
ISBN_IF isbn = (ISBN_IF) [Link](loc);

String result = [Link]("0201310058");


[Link]("Title for 0201310058: " + result);
}
catch (Exception e) {
[Link](e);
}
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class StockServer2 extends PortableRemoteObject


implements Stock {
Map<String, Set<StockListener>> clients;

Page 514 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link] (cont'd)
Map<String, Float> stocks = null;

public StockServer2() throws RemoteException {


clients = new HashMap<String, Set<StockListener>>();
stocks = new HashMap<String, Float>();
[Link]("ORCL", new Float(12.55));
[Link]("OATS", new Float(11.20));
[Link]("FLEX", new Float(14.12));
[Link]("MSFT", new Float(25.66));
[Link]("AUO", new Float(17.23));
[Link]("EBAY", new Float(99.55));
}
public float getQuote(String ticker) throws RemoteException {
if ([Link](ticker)) {
Float f = [Link](ticker);
return [Link]();
}
else {
return -1.0F;
}
}
public void setQuote(String ticker, float value) throws Exception {
[Link]("Setting " + ticker + " to " + value);
[Link](ticker, new Float(value));
if ([Link](ticker)) {
Set<StockListener> c = [Link](ticker);
Iterator<StockListener> it = [Link]();
while ([Link]()) {
StockListener n = [Link]();
[Link](ticker, value);
}
}
}
public void registerForStockEvents(String ticker, StockListener n) {
Set<StockListener> notifList = null;
if ([Link](ticker)) {
notifList = [Link](ticker);
[Link](n);
}
else {
notifList = new HashSet<StockListener>();
[Link](n);
[Link](ticker,notifList);
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 515


Advanced Java Programming

Chapter 8 (cont'd)

[Link] (cont'd)
public static void main(String[] args) {
try {
StockServer2 s = new StockServer2();
Context ctx = new InitialContext();
[Link]("StockService", s);

[Link]("Stock bound.");
for (int i = 0; i < 100; i++ ) {
[Link](1000);
[Link]("MSFT", [Link]("MSFT") * 1.03f);
[Link]("OATS", [Link]("OATS") * 1.05f);
[Link]("EBAY", [Link]("EBAY") * 1.08f);
}
[Link]("StockService");
[Link](0);
}
catch(Exception e) {
[Link](e);
}
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];

public class StockClient2 extends PortableRemoteObject


implements StockListener {
private String[] stocks = {"OATS", "MSFT", "AUO"};

public StockClient2() throws RemoteException {


try {
Context context = new InitialContext();
Object o = [Link]("StockService");
Stock s = (Stock) [Link](o, [Link]);

for (int i = 0; i < [Link]; i++) {


[Link](stocks[i], this);
[Link](stocks[i] + "=" + [Link](stocks[i]));
Page 516 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
}
}
catch(Exception e) {
[Link](e);
}
}

public void stockEvent(String ticker, float value) {


[Link]();
[Link](ticker + " has changed value to " + value);
}
public static void main(String[] args) throws Exception {
new StockClient2();
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 517


Advanced Java Programming

Chapter 9

[Link]
Your policy file should include:

permission [Link] "C:\\advj2se\\ch09\\*", "write";

Or something like it, depending upon your setup.

[Link]
Command:
appletviewer [Link]

Clicking the applet's Close button should throw an AccessControlException,


because the applet lacks the [Link] for the target exitVM.
The appletviewer checks for this permission when [Link]() is called.

[Link]
Your .[Link] file should now contain the added permission:

permission [Link] "exitVM";

Command:

appletviewer [Link]

Clicking the applet's Close button should now exit the appletviewer without
throwing an exception.

[Link]
When you run ShowTimeClient, TimeServer has an exception:
Exception in thread "RMI TCP Connection(2)-[Link]" [Link]
Exception: access denied ([Link] [Link]:1121 accept,resolve
)

The exception tells you TimeServer needs a SocketPermission with accept and
resolve actions.

After adding the accept permission, your .[Link] file should look something like
this:

Page 518 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link] (cont'd)
grant codeBase "[Link] {
permission [Link] "*:*", "connect, resolve, accept";
permission [Link] "C:\\advj2se\\ch09\\server\\-", "read";
permission [Link] "C:\\advj2se\\ch09\\*", "write";
permission [Link] "exitVM";
};

Or something like it, depending upon your setup.

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class TimeServer1 extends UnicastRemoteObject implements Time {


public TimeServer1() throws RemoteException {
}
public String getSystemTime() {
DateFormat df = [Link]();
[Link]([Link]());
return [Link](new Date());
}
public static void main(String args[]) {
[Link](new SecurityManager());
try {
TimeServer1 ts = new TimeServer1();
[Link]("///Time", ts);
}
catch (MalformedURLException e) {
[Link](e);
}
catch (RemoteException e) {
[Link](e);
}
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 519


Advanced Java Programming

Chapter 9 (cont'd)

[Link]
Your [Link] file should look like this:

grant codeBase "[Link] {


permission [Link] "*:*", "accept, connect, listen, resolve";
};

Your .[Link] file should look like this:


grant codeBase "[Link] {
permission [Link] "*:*", "connect, resolve";
permission [Link] "C:\\advj2se\\ch09\\server\\-", "read";
permission [Link] "C:\\advj2se\\ch09\\*", "write";
permission [Link] "exitVM";
};

Run the TimeServer with the following command:


java -[Link]=[Link]
-[Link]==[Link] TimeServer

Page 520 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

Chapter 10

[Link]
Volume in drive C is ENTERPRISE
Volume Serial Number is 3926-10F1

Directory of C:\advj\ch16\META-INF

08/06/2002 12:25p <DIR> .


08/06/2002 12:25p <DIR> ..
08/06/2002 12:25p 349 [Link]
08/06/2002 12:25p 402 [Link]
08/06/2002 12:25p 1,140 [Link]
3 File(s) 1,891 bytes
2 Dir(s) 755,441,664 bytes free

[Link]
Keystore type: jks
Keystore provider: SUN

Your keystore contains 2 entries

ladybug, Aug 6, 2002, keyEntry,


Certificate fingerprint (MD5): ED:3F:A1:AD:02:18:72:76:43:2E:0F:C0:A4:73:1D:96
firefly, Aug 6, 2002, keyEntry,
Certificate fingerprint (MD5): 1C:39:84:E0:72:30:17:1E:85:55:C9:59:73:CF:68:69

[Link]
Volume in drive C is ENTERPRISE
Volume Serial Number is 3926-10F1

Directory of C:\advj\ch16\meta-inf

08/06/2002 12:25p <DIR> .


08/06/2002 12:25p <DIR> ..
08/06/2002 12:34p 349 [Link]
08/06/2002 12:34p 402 [Link]
08/06/2002 12:34p 1,140 [Link]
08/06/2002 12:34p 402 [Link]
08/06/2002 12:34p 1,114 [Link]
5 File(s) 3,407 bytes
2 Dir(s) 755,380,224 bytes free
© 2011 ITCourseware, LLC Rev 5.1.4 Page 521
Advanced Java Programming

Chapter 10 (cont'd)

[Link]
import [Link].*;
import [Link];
import [Link];
import [Link];
import [Link].X509Certificate;
import [Link];

public class ShowDates {


public static void main(String[] args) {
try {
String keyStoreLocation = [Link]("[Link]");
String keyStoreFile = ".keystore";
// String password = "Hello, I must be going";
String password = "password";

KeyStore keyStore = [Link]("jks");


FileInputStream fis = new FileInputStream(
keyStoreLocation + [Link] + keyStoreFile);
[Link](fis, [Link]());

Enumeration aliases = [Link]();


while ([Link]()) {
String a = [Link]().toString();
[Link](a);

if ([Link](a)) {
[Link](a + " is a key.");
Key key = [Link](a, [Link]());
[Link]("Private Key:");
[Link](key);
}
else if ([Link](a)) {
[Link](a + " is a certificate.");
}

Certificate cert = [Link](a);

if (cert instanceof X509Certificate) {


X509Certificate x509cert = (X509Certificate) cert;
[Link]("Not valid before: " +
[Link]());

Page 522 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link] (cont'd)
[Link]("Not valid after: " +
[Link]());
}
}
}
catch (Exception e) {
[Link]();
}
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 523


Advanced Java Programming

Chapter 11
[Link]
import [Link].*;
import [Link];
import [Link];
import [Link];
import [Link];

public class EncryptText {


public static void main(String args[]) {
try {
[Link]("Enter data for encrypted file.");
[Link]("Type EOF on line to end.");
BufferedReader br = new BufferedReader(
new InputStreamReader([Link]));

KeyGenerator keyGen = [Link]("DES");


Key theKey = [Link]();

Cipher c = [Link]("DES/ECB/PKCS5Padding");
[Link](Cipher.ENCRYPT_MODE, theKey);

// write encrypted input text to a file


FileOutputStream fos = new FileOutputStream("[Link]");
CipherOutputStream cos = new CipherOutputStream(fos,c);
PrintWriter pw = new PrintWriter(cos);

String s;
while(!(s = [Link]()).equalsIgnoreCase("EOF")) {
[Link](s);
}
[Link]();
[Link]();

// Save key to a file


ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("[Link]"));
[Link](theKey);
[Link]();
}
catch (Exception e) {
[Link]("Error : " + [Link]());
}
}
}
Page 524 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link]
import [Link].*;
import [Link];
import [Link];
import [Link];

public class DecryptText {


public static void main(String args[]) {
try {
// read key from file
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("[Link]"));
Key theKey = (Key) [Link]();
[Link]();

Cipher c = [Link]("DES/ECB/PKCS5Padding");
[Link](Cipher.DECRYPT_MODE, theKey);

// Read encrypted text from file


FileInputStream fis = new FileInputStream("[Link]");
CipherInputStream cis = new CipherInputStream(fis,c);
BufferedReader br = new BufferedReader(
new InputStreamReader(cis));

String s;
while((s = [Link]()) != null) {
[Link](s);
}
[Link]();
}
catch (Exception e) {
[Link]("Error : " + [Link]());
}
}
}

[Link]
import [Link].*;
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

© 2011 ITCourseware, LLC Rev 5.1.4 Page 525


Advanced Java Programming

Chapter 11 (cont'd)

[Link] (cont'd)
public class PasswordDecrypt {
public static void main(String args[]) {
try {
BufferedReader br = new BufferedReader(
new InputStreamReader([Link]));
[Link]("Enter Password for Decryption: ");
String password = [Link]();

byte[] salt = {(byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe,


(byte)0x32, (byte)0x9a, (byte)0xfa,
(byte)0x71 };

PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 10);

PBEKeySpec keySpec = new PBEKeySpec([Link]());


SecretKeyFactory skf =
[Link]("PBEWithMD5AndDES");
SecretKey theKey = [Link](keySpec);

Cipher c = [Link]("PBEWithMD5AndDES");
[Link](Cipher.DECRYPT_MODE, theKey, paramSpec);

FileInputStream fis = new FileInputStream("[Link]");


CipherInputStream cis = new CipherInputStream(fis, c);
BufferedReader br2 = new BufferedReader(
new InputStreamReader(cis));

String s;
while((s = [Link]()) != null)
[Link](s);
}
catch (Exception e) {
[Link]("Error : " + [Link]());
}
}
}

Page 526 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

class UsernamePassword implements Serializable {


private String username;
private String password;
private String website;

public UsernamePassword(String w, String u, String p) {


username = u;
password = p;
website = w;
}
public String toString() {
return "website: "+ website + " username: " + username +
" password: " + password;
}
}

public class PasswordList {


private BufferedReader buf;
private ArrayList<UsernamePassword> passwords = null;
PBEParameterSpec paramSpec = null;
Cipher cipher = null;
Key theKey = null;

public PasswordList() {
try {
buf = new BufferedReader(new InputStreamReader([Link]));
String password = promptForPassword();
createCipher(password);
passwords = getPasswordList();

int opt;
while ((opt = displayMenu() ) != 3) {
switch(opt) {
case 1: addPassword();
break;
case 2: showPasswords();
break;
© 2011 ITCourseware, LLC Rev 5.1.4 Page 527
Advanced Java Programming

Chapter 11 (cont'd)

[Link] (cont'd)
default: [Link]("Invalid Option");
}
}

savePasswords();
}
catch (Exception e) {
[Link]();
}
}

private String promptForPassword() throws IOException {


[Link]("Enter decrypt password: ");
String password = [Link]();
return password;
}
private void createCipher(String password) throws Exception {
byte[] salt = {(byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe,
(byte)0x32, (byte)0x9a, (byte)0xfa, (byte)0x71 };

paramSpec = new PBEParameterSpec(salt, 10);

PBEKeySpec keySpec =
new PBEKeySpec([Link]());
SecretKeyFactory skf =
[Link]("PBEWithMD5AndDES");

theKey = [Link](keySpec);
cipher = [Link]("PBEWithMD5AndDES");
[Link](Cipher.DECRYPT_MODE, theKey, paramSpec);
}

@SuppressWarnings("unchecked") // Not supported in 1.5.0


private ArrayList<UsernamePassword> getPasswordList() {
ArrayList<UsernamePassword> pw =
new ArrayList<UsernamePassword>();
try {
File file = new File ("[Link]");
if ([Link]())
{
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(file));
Page 528 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
SealedObject so = (SealedObject) [Link]();
pw = (ArrayList<UsernamePassword>) [Link](cipher);
[Link]();
}
}
catch (Exception e) {
[Link](e);
}
return pw;
}
private int displayMenu() {
int choice = 0;
String input;
try {
[Link]("\n Menu");
[Link]("1 - Add Password");
[Link]("2 - Show Passwords");
[Link]("3 - Quit");
[Link]("\nEnter Option: ");
input = [Link]();
choice = [Link](input);
}
catch (IOException e) {
[Link](e);
}
catch (NumberFormatException e) {
[Link](e);
}
return choice;
}
private void addPassword() {
try {
UsernamePassword up;
String ws,u,p;
[Link]("Website: ");
ws = [Link]();
[Link]("Username: ");
u = [Link]();
[Link]("Password: ");
p = [Link]();
up = new UsernamePassword(ws, u, p);
[Link](up);
}
catch (Exception e) {
[Link]([Link]());
}
© 2011 ITCourseware, LLC Rev 5.1.4 Page 529
Advanced Java Programming

Chapter 11 (cont'd)

[Link] (cont'd)
}
private void showPasswords() {
Iterator<UsernamePassword> iter = [Link]();
while ([Link]())
[Link]([Link]());
}
private void savePasswords() throws Exception {
ObjectOutputStream ois = new ObjectOutputStream(
new FileOutputStream("[Link]"));
[Link](Cipher.ENCRYPT_MODE, theKey, paramSpec);
SealedObject so = new SealedObject(passwords, cipher);
[Link](so);
[Link]();
}
public static void main(String[] args) {
new PasswordList();
}
}

Page 530 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

Chapter 12

[Link]
import [Link];
import [Link];
import [Link];
import [Link];

public class KSJAAS {


public static void main(String[] args) {
LoginContext context = null;
Subject subject = null;

try {
context = new LoginContext("KSJAAS", new LoginHandler());
[Link]();
subject = [Link]();
Set<Principal> principals = [Link]();
for (Principal p : principals) {
[Link]("Principal type: " +
[Link]().getName() + " name: " + [Link]());
}
}
catch (Exception e) {
[Link]();
}
}
}

[Link]
You need to change the login config file to specify
[Link].

You also need to create a policy file for the application. Because we're only
looking at the Subject, and not calling doAs(), you don't need a separate policy
entry specifying the principal. Because of that, the [Link] file in the
chapter directory will do the job.

Normally, that's all you would have to do. But since NTJAAS doesn't use a
callback handler, you need to edit the source code to pass a LoginHandler to the
LoginContext constructor.

© 2011 ITCourseware, LLC Rev 5.1.4 Page 531


Advanced Java Programming

Chapter 12 (cont'd)

[Link]
REM [Link]
java -[Link] -[Link]=..\[Link] -
[Link]=[Link] KSJAAS

[Link]
KSJAAS {
[Link] required;
};

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class EgLoginHandler implements CallbackHandler {


public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException {

for (Callback cb : callbacks) {

if (cb instanceof NameCallback) {


NameCallback ncb = (NameCallback) cb;
[Link]([Link]() + " ");
BufferedReader in = new BufferedReader(
new InputStreamReader([Link]));
String name = [Link]();
[Link](name);
}

else if (cb instanceof PasswordCallback) {


PasswordCallback pcb = (PasswordCallback) cb;
[Link]([Link]() + " ");
BufferedReader in = new BufferedReader(
new InputStreamReader([Link]));
Page 532 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
String password = [Link]();
[Link]([Link]());
}

else {
throw new UnsupportedCallbackException(cb);
}
}
}
}

[Link]
import [Link];
import [Link];
import [Link];

public class EgCallback {


public static void main(String[] args) {
LoginContext lc = null;

try {
lc = new LoginContext("EgCallback", new EgLoginHandler());
[Link]();
Subject subject = [Link]();
Object o = [Link](subject, new SalariesAction());

if (o instanceof Double) {
double d = ((Double) o).doubleValue();
[Link]("Total salary: " +
[Link]().format(d));
}
[Link]();
}
catch (Exception e) {
[Link]();
}
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 533


Advanced Java Programming

Chapter 12 (cont'd)

[Link]
EgCallback {
EgLoginModule required;
};

[Link]
REM [Link]
javac Eg*.java
jar cvfm [Link] [Link] Eg*.class

[Link]
Manifest-Version: 1.0
Main-Class: EgCallback
Class-Path: [Link]

[Link]
grant codeBase "[Link] {
permission [Link];
};

grant codeBase "[Link]


principal EgPrincipal "Mary" {
permission [Link] "[Link]", "read";
};

[Link]
REM [Link]
java -[Link] -[Link]=[Link] -
[Link]=[Link] -jar [Link]

Page 534 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

Chapter 13

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class GetRates {


public static void main(String[] args) {
Hashtable<String, String> env = new Hashtable<String, String>();
[Link](Context.INITIAL_CONTEXT_FACTORY,
"[Link]");
[Link](Context.PROVIDER_URL, "rmi:///");

try {
InitialContext ctx = new InitialContext(env);
RateInfo rates = (RateInfo) [Link]("RateInfo");
[Link]([Link]());
}
catch (RemoteException re) {
[Link](re);
}
catch (NamingException ne) {
[Link](ne);
}
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class ServerStatusLister {


public static void main(String args[]) {
Hashtable<String, String> env = new Hashtable<String, String>();

© 2011 ITCourseware, LLC Rev 5.1.4 Page 535


Advanced Java Programming

Chapter 13 (cont'd)

[Link] (cont'd)
[Link](Context.INITIAL_CONTEXT_FACTORY,
"[Link]");
[Link](Context.PROVIDER_URL, "rmi:///");

try {
InitialContext ctx = new InitialContext(env);

NamingEnumeration<NameClassPair> list = [Link]("");


while ([Link]()) {
NameClassPair ncp = [Link]();
String name = [Link]();
if ([Link]("ServerStatus.")) {
try {
ServerStatus stat = (ServerStatus)[Link](name);
[Link]([Link]());
}
catch (RemoteException re) {
[Link]("Remote method failed for " + name +
": " + re);
}
catch (NamingException ne) {
[Link]("Failed looking up " + name +
": " + ne);
}
}
}
}
catch (NamingException ne) {
[Link](ne);
}
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
Page 536 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
import [Link];

public class NSLookup1 {


public static void main(String[] arg) {
String host = "";
String[] rrtypes = new String[] {"A"};

if ([Link] > 0) {
host = arg[0];
}
else {
[Link]("Usage: java NSLookup1 hostname");
[Link](1);
}

Hashtable<String, String> env = new Hashtable<String, String>();


[Link](Context.INITIAL_CONTEXT_FACTORY,
"[Link]");
[Link](Context.PROVIDER_URL, "dns://[Link]/");

try {
DirContext ctxt = new InitialDirContext(env);
Attributes att = [Link](host, rrtypes);

NamingEnumeration attlist = [Link]();


while ([Link]()) {
Attribute a = (Attribute) [Link]();
// Normally we would iterate through attribure values.
// [Link]() gives nice enough output.
[Link](a);
}
}
catch (NamingException ne) {
[Link](ne);
}
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

© 2011 ITCourseware, LLC Rev 5.1.4 Page 537


Advanced Java Programming

Chapter 13 (cont'd)
import [Link];
[Link] (cont'd)
import [Link];

public class NSLookup2 {


public static void main(String[] arg) {
String host = "";
String[] rrtypes = new String[] {"A"};

if ([Link] > 0) {
host = arg[0];
if ([Link] > 1) {
rrtypes = new String[[Link] - 1];
for (int i = 1; i < [Link]; i++) {
rrtypes[i - 1] = arg[i];
}
}
}
else {
[Link]("Usage: java NSLookup2 hostname RRtype(s)");
[Link](1);
}

Hashtable<String, String> env = new Hashtable<String, String>();


[Link](Context.INITIAL_CONTEXT_FACTORY,
"[Link]");
[Link](Context.PROVIDER_URL, "dns://[Link]/");

try {
DirContext ctxt = new InitialDirContext(env);
Attributes att = [Link](host, rrtypes);

NamingEnumeration attlist = [Link]();


while ([Link]()) {
Attribute a = (Attribute)[Link]();
// Normally we would iterate through attribure values.
// [Link]() gives nice enough output.
[Link](a);
}
}
catch (NamingException ne) {
[Link](ne);
}
}
}
Page 538 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

Chapter 14

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class MileageCounter {


public static void main(String args[]) {
if ([Link] != 1) {
[Link]("Usage: java MileageCounter [Link]");
[Link](1);
}

SAXParserFactory factory = [Link]();

try {
SAXParser parser = [Link]();
MileageHandler handler = new MileageHandler();
[Link](new File(args[0]), handler);
[Link]("The number of cars with less than 20,000 " +
"miles is " + [Link]());
}
catch (Exception e) {
[Link] ("ERROR " + e);
}
}
}

class MileageHandler extends DefaultHandler {


private int counter = 0;

public void startElement(String namespaceURI, String localName,


String qName, Attributes atts) throws SAXException {

if ([Link]("car") || [Link]("van")) {
String miles = [Link]("miles");
if ( [Link](miles) < 20000) {
counter ++;
}
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 539


Advanced Java Programming

Chapter 14 (cont'd)

[Link] (cont'd)
public int getCount() {
return counter;
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class AddNewCar {


public static void main (String args[]) {
DocumentBuilderFactory factory =
[Link]();

try {
DocumentBuilder builder = [Link]();
Document document = [Link](new File("[Link]") );
addCar(document,"Saturn", "SL2", "2002");
}
catch (Exception e) {
[Link](e);
}
}

public static void addCar(Document d, String carMake,


String carModel, String carYear) {

Element car = [Link]("car");

Element make = [Link]("make");


Text text = [Link](carMake);
[Link](text);

Element model = [Link]("model");


text = [Link](carModel);
[Link](text);

Page 540 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link] (cont'd)
Element year = [Link]("year");
text = [Link](carYear);
[Link](text);

[Link](make);
[Link](model);
[Link](year);
[Link]("miles", carYear);

Element garage = [Link]();


[Link](car);
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class AddNewCar2 {


public static void main (String args[]) {
DocumentBuilderFactory factory =
[Link]();

try {
DocumentBuilder builder = [Link]();
Document document = [Link](new File("[Link]") );

addCar(document,"Saturn","SL2","2002");

Source xslSource = new StreamSource("../[Link]");


DOMSource domSource = new DOMSource(document);
Result result = new StreamResult("[Link]");

© 2011 ITCourseware, LLC Rev 5.1.4 Page 541


Advanced Java Programming

Chapter 14 (cont'd)

[Link] (cont'd)
TransformerFactory tFactory = [Link]();
Transformer transformer = [Link](xslSource);
[Link](domSource, result);
}
catch (Exception e) {
[Link](e);
}
}

public static void addCar(Document d, String carMake,


String carModel, String carYear) {

Element car = [Link]("car");

Element make = [Link]("make");


Text text = [Link](carMake);
[Link](text);

Element model = [Link]("model");


text = [Link](carModel);
[Link](text);

Element year = [Link]("year");


text = [Link](carYear);
[Link](text);

[Link](make);
[Link](model);
[Link](year);
[Link]("miles", carYear);

Element garage = [Link]();


[Link](car);
}
}

Page 542 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

Chapter 15

[Link]
public class Pager {
public native void page(String message, String id);

static {
[Link]("Pager");
}
}

[Link]
public class PagerTest {
public static void main(String args[]) {
String message = "Houston, we have a problem...";
String id = "SysDBA";

Pager p = new Pager();


[Link](message, id);
}
}

Pager.c
#include <stdio.h>
#include "Pager.h"
#include "LegacyPager.h"

JNIEXPORT void JNICALL Java_Pager_page


(JNIEnv *env, jobject obj, jstring message, jstring id)
{
const char *localMessage =
(*env)->GetStringUTFChars(env, message, NULL);
const char *localId = (*env)->GetStringUTFChars(env, id, NULL);

pageThem(localMessage, localId);

(*env)->ReleaseStringUTFChars(env, message, localMessage);


(*env)->ReleaseStringUTFChars(env, id, localId);
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 543


Advanced Java Programming

Chapter 15 (cont'd)

[Link]
public class Pager2 {
public native void page(String message, String id);
public native String who(String id);

static {
[Link]("Pager2");
}
}

[Link]
public class PagerTest2 {
public static void main(String args[]) {
String message = "Houston, we have a problem...";
String id = "SysDBA";

Pager2 p = new Pager2();


[Link](message, id);

String person = [Link](id);


[Link]("id belongs to " + person);
}
}

Pager2.c
#include <stdio.h>
#include "Pager2.h"
#include "LegacyPager.h"

JNIEXPORT void JNICALL Java_Pager2_page


(JNIEnv *env, jobject obj, jstring message, jstring id)
{
const char *localMessage =
(*env)->GetStringUTFChars(env, message, NULL);
const char *localId = (*env)->GetStringUTFChars(env, id, NULL);

pageThem(localMessage, localId);

(*env)->ReleaseStringUTFChars(env, message, localMessage);


(*env)->ReleaseStringUTFChars(env, id, localId);
}
Page 544 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

Pager2.c (cont'd)
JNIEXPORT jstring JNICALL Java_Pager2_who
(JNIEnv *env, jobject obj, jstring id)
{
const char *localMessage = {"Isaac Newton"};
return (*env)->NewStringUTF(env, localMessage);
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 545


Advanced Java Programming

Chapter 16

[Link]
public class IdGenerator2 {
private int counter;
private static IdGenerator2 theInstance;

private IdGenerator2() {
counter = 0;
}

public static synchronized IdGenerator2 getInstance() {


if (theInstance == null) {
theInstance = new IdGenerator2();
}
return theInstance;
}
public synchronized int getNextId() {
return counter++;
}
/*
* This method is not strictly necessary in this example, but if
* your Singleton class were to extend a class that implemented
* clone(), without this method it would be possible to create more
* than one instance via cloning.
*/
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}

[Link]
public class HumanResourcesApp2 {
public static void main(String[] args) {
NewHireHelper2 h1 = new NewHireHelper2();
NewHireHelper2 h2 = new NewHireHelper2();
[Link]();
[Link]();
}
}

class NewHireHelper2 extends Thread {


public void createNewEmployee() {
IdGenerator2 gen = [Link]();
Page 546 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
int id = [Link]();
Employee e = new Employee(id);
// add new employee to database
}
public void run() {
createNewEmployee();
}
}

[Link]
public class IdGeneratorFactory {

//Factory Method
public IdGenerator3 getIdGenerator() {
if ([Link]()) {
return [Link]();
}
else {
return [Link]();
}
}
}

[Link]
public class SimpleIdGenerator implements IdGenerator3 {
private int counter;
private static SimpleIdGenerator theInstance;

public static synchronized SimpleIdGenerator getInstance() {


if (theInstance == null) {
theInstance = new SimpleIdGenerator();
}
return theInstance;
}

private SimpleIdGenerator() {
counter = 0;
}
public synchronized int getNextId() {
return counter++;
}
/*
* This method is not strictly necessary in this example, but if
© 2011 ITCourseware, LLC Rev 5.1.4 Page 547
Advanced Java Programming

Chapter 16 (cont'd)

[Link] (cont'd)
* your Singleton class were to extend a class that implemented
* clone(), without this method it would be possible to create more
* than one instance via cloning.
*/
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}

[Link]
import [Link];
import [Link];
import [Link];

public class Configuration {


private static boolean valid;
private static int next;

static {
Properties p = new Properties();
try {
FileInputStream inputStream =
new FileInputStream("[Link]");

if (inputStream != null) {
[Link](inputStream);
String value = [Link]("next");
Integer i = new Integer(value);
valid = true;
next = [Link]();
}
}
catch (NumberFormatException nfe) {
valid = false;
}
catch (IOException e) {
valid = false;
}
}

public static boolean isConfigValid() {


Page 548 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
return valid;
}
public static int getNext() {
return next;
}
}

[Link]
public class FileIdGenerator implements IdGenerator3 {
private int counter;
private static FileIdGenerator theInstance;

private FileIdGenerator() {
counter = [Link]();
}

public static synchronized FileIdGenerator getInstance() {


if (theInstance == null) {
theInstance = new FileIdGenerator();
}
return theInstance;
}

public synchronized int getNextId() {


return counter++;
}
/*
* This method is not strictly necessary in this example, but if
* your Singleton class were to extend a class that implemented
* clone(), without this method it would be possible to create more
* than one instance via cloning.
*/
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}

[Link]
public class HumanResourcesApp3 {
public static void main(String[] args) {
NewHireHelper3 h1 = new NewHireHelper3();
NewHireHelper3 h2 = new NewHireHelper3();
[Link]();
© 2011 ITCourseware, LLC Rev 5.1.4 Page 549
Advanced Java Programming

Chapter 16 (cont'd)

[Link] (cont'd)
[Link]();
}
}

class NewHireHelper3 extends Thread {


public void createNewEmployee() {
IdGeneratorFactory factory = new IdGeneratorFactory();
IdGenerator3 gen = [Link]();
int id = [Link]();
Employee e = new Employee(id);
// add new employee to database
}
public void run() {
createNewEmployee();
}
}

[Link]
public interface IdGenerator3 {
public int getNextId();
}

[Link]
next=22

[Link]
public class BuilderClient {
public static void main(String[] args) {
Director d = new Director();

Builder b = [Link]("FlatFile");
[Link](b);
OutputFile flat = [Link]();
[Link]("[Link]");

b = [Link]("PropertyFile");
[Link](b);
OutputFile prop = [Link]();

Page 550 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link] (cont'd)
[Link]("[Link]");

[Link]("output files created");


}
}

[Link]
public class Director {
private Builder builder;
private Manager manager;

public Director() {
manager = new Manager(42);
[Link]("303 867-5309");
[Link]("Gunnison");
}

public void setBuilder(Builder builder) {


[Link] = builder;
}
public OutputFile construct() {
[Link]([Link]());
[Link]([Link]());
[Link]([Link]());
return [Link]();
}
}

[Link]
public abstract class Builder {

public static Builder getInstance(String source) {


if ([Link]("PropertyFile")) {
return new PropertyBuilder();
}
return new FlatFileBuilder();
}

public abstract void buildId(int id);


public abstract void buildFaxNumber(String fax);
public abstract void buildLocation(String loc);
public abstract OutputFile getFile();
}
© 2011 ITCourseware, LLC Rev 5.1.4 Page 551
Advanced Java Programming

Chapter 16 (cont'd)

[Link]
public class PropertyBuilder extends Builder {
private PropertyFile file;

public PropertyBuilder() {
file = new PropertyFile();
}

public void buildId(int id) {


[Link]("id=" + id);
}
public void buildFaxNumber(String fax) {
[Link]("faxNumber=" + fax);
}
public void buildLocation(String location) {
[Link]("location=" + location);
}
public OutputFile getFile() {
return file;
}
}

[Link]
public class FlatFileBuilder extends Builder {
private static String EOL = [Link]("[Link]");
FlatFile file = new FlatFile();

public void buildId(int id) {


[Link]("" + id + EOL);
}
public void buildFaxNumber(String fax) {
[Link](fax + EOL);
}
public void buildLocation(String location) {
[Link](location + EOL);
}
public OutputFile getFile() {
return file;
}
}

Page 552 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link]
public interface OutputFile {
public void write(String filename);
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class PropertyFile implements OutputFile {


private Properties props = new Properties();
private Pattern pattern = [Link]("=");

public void append(String s) {


String[] tokens = [Link](s);
[Link](tokens[0], tokens[1]);
}
public void write(String file) {
try {
FileOutputStream fos = new FileOutputStream(file);
[Link](fos, null);
}
catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class FlatFile implements OutputFile {


private StringBuffer content = new StringBuffer();

© 2011 ITCourseware, LLC Rev 5.1.4 Page 553


Advanced Java Programming

Chapter 16 (cont'd)

[Link] (cont'd)
public void append(String s) {
[Link](s);
}
public void write(String file) {
try {
OutputStreamWriter osw =
new OutputStreamWriter(new FileOutputStream(file));
BufferedWriter bw = new BufferedWriter(osw);
[Link]([Link]());
[Link]();
}
catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
}

Page 554 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

Chapter 17

[Link]
import [Link].*;

public class IOFacade2 {


private static IOFacade2 theInstance = null;

private IOFacade2() {
}

public static IOFacade2 getInstance() {


if (theInstance == null) {
theInstance = new IOFacade2();
}
return theInstance;
}
public void writeToSerializedObjectFile(String filename, Object obj)
throws IOException {

ObjectOutputStream out = null;


boolean append = true;

try {
File file = new File(filename);
out = new ObjectOutputStream(
new FileOutputStream(file, append));
[Link](obj);
}
catch (IOException e) {
log(e);
throw e;
}
finally {
[Link]();
}
}
public void writeToTextFile(String filename, String text)
throws IOException {

PrintWriter out = null;


boolean append = true;

try {
File file = new File(filename);
© 2011 ITCourseware, LLC Rev 5.1.4 Page 555
Advanced Java Programming

Chapter 17 (cont'd)

[Link] (cont'd)
out = new PrintWriter(new BufferedWriter(
new FileWriter(file, append)));
[Link](text);
}
catch (IOException e) {
log(e);
throw e;
}
finally {
[Link]();
}
}
public void writeToBinaryFile(String filename, byte[] bytes)
throws IOException {

BufferedOutputStream out = null;


boolean append = true;

try {
File file = new File(filename);
out = new BufferedOutputStream(
new FileOutputStream(file, append));
[Link](bytes);
}
catch (IOException e) {
log(e);
throw e;
}
finally {
try {
[Link]();
}
catch (IOException ioe) {
log(ioe);
throw ioe;
}
}
}
private void log(Exception e) {
try {
writeToTextFile("[Link]", [Link]());
}
Page 556 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
catch (IOException ioe) {
[Link](ioe);
}
}
}

[Link]
public class FacadeClient2 {
public static void main(String[] args) {
IOFacade2 facade = [Link]();

String text = "To be, or not to be: that is the question";

byte[] bytes = {70, 65, 67, 65, 68, 69, 1, 1, 1};

try {
[Link]("[Link]", text);
[Link]("[Link]", text);
[Link]("[Link]", bytes);
}
catch (Exception e) {
[Link](e);
}
}
}

[Link]
import [Link];
import [Link];
import [Link];

public class GenericArrayAdapter2<E> implements Collection<E> {


private GenericArray<E> adaptee;

public GenericArrayAdapter2() {
adaptee = new GenericArray<E>();
}
public GenericArrayAdapter2(int initialSize) {
adaptee = new GenericArray<E>(initialSize);
}

public boolean add(E o) {


[Link](o);
return true;
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 557


Advanced Java Programming

Chapter 17 (cont'd)

[Link] (cont'd)
public boolean addAll(Collection<? extends E> c) {
Iterator<? extends E> it = [Link]();
while ([Link]()) {
add([Link]());
}
return true;
}
public void clear() {
[Link]();
}
public boolean contains(Object obj) {
if ([Link](obj) < 0) {
return false;
}
return true;
}
public boolean containsAll(Collection<?> c) {
Iterator<?> it = [Link]();
while ([Link]()) {
if (!contains([Link]())) {
return false;
}
}
return true;
}
public boolean isEmpty() {
if ([Link]() == 0)
return true;
else
return false;
}
public Iterator<E> iterator() {

return new Iterator<E>() {


int current = 0;
public boolean hasNext() {
return current != [Link]();
}
public E next() {
try {
E nextElem = (E)[Link](current++);
return nextElem;
Page 558 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
}
catch(IndexOutOfBoundsException e) {
throw new NoSuchElementException();
}
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
public boolean remove(Object obj) {
int index = [Link](obj);

if (index != -1) {
[Link](index);
return true;
}
return false;
}
public boolean removeAll(Collection<?> c) {
boolean flag = false;

Iterator<?> it = [Link]();
while ([Link]()) {
if (remove([Link]())) {
if (flag == false) {
flag = true;
}
}
}
return flag;
}
public boolean retainAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
public int size() {
return [Link]();
}
public Object[] toArray() {
return [Link]();
}
@SuppressWarnings("unchecked") // Not supported in 1.5.0
public <T> T[] toArray(T[] array){
// make sure array is big enough
int size = [Link]();

© 2011 ITCourseware, LLC Rev 5.1.4 Page 559


Advanced Java Programming

Chapter 17 (cont'd)

[Link] (cont'd)
if ([Link] < size) {
array = (T[])[Link](
[Link]().getComponentType(), size);
}
// add elements to array
Iterator<E> it = [Link]();
Object[] temp = array;
for (int i = 0; i < size; i++) {
temp[i] = [Link]();
}
// add null terminator
if ([Link] > size) {
array[size] = null;
}
return array;
}
public boolean equals(Object o) {
return [Link](o);
}
public int hashCode() {
return [Link]();
}
}

[Link]
import [Link].*;

public class AdapterClient2 {


public static void main(String[] args) {
Collection<String> c = new GenericArrayAdapter2<String>();
populateCollection(c);
[Link]("Original Collection: " );
printCollection(c);
removeItemFromCollection(c);
[Link]("Collection After Remove: " );
printCollection(c);
removeItemsFromCollection(c);
[Link]("Collection After Remove All: " );
printCollection(c);
}
private static void populateCollection(Collection<String> c) {
Page 560 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
for (int i = 0; i < 10; i++) {
[Link]("Element: " + i);
}
}
private static void removeItemFromCollection(Collection<String> c) {
[Link]("Element: 8");
}
private static void removeItemsFromCollection(Collection<String> c){
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < 5; i++) {
[Link]("Element: " + i);
}
[Link](list);
}
private static void printCollection(Collection<String> c) {
Iterator it = [Link]();
while ([Link]()) {
[Link]([Link]());
}
}
}

[Link]
public abstract class ArithmeticComponent2 {
public void add(ArithmeticComponent2 component) {
throw new UnsupportedOperationException();
}
public void remove(ArithmeticComponent2 component) {
throw new UnsupportedOperationException();
}
public ArithmeticComponent2 getChild(int i) {
throw new UnsupportedOperationException();
}
public int evaluate() {
throw new UnsupportedOperationException();
}
public void print() {
throw new UnsupportedOperationException();
}
}

[Link]
import [Link];
import [Link];

© 2011 ITCourseware, LLC Rev 5.1.4 Page 561


Advanced Java Programming

Chapter 17 (cont'd)

[Link] (cont'd)
public class Operator2 extends ArithmeticComponent2 {
private ArrayList<ArithmeticComponent2> children;
private String operator;

public Operator2(String operator) {


[Link] = operator;
children = new ArrayList<ArithmeticComponent2>();
}
public void add(ArithmeticComponent2 component) {
[Link](component);
}
public void remove(ArithmeticComponent2 component) {
[Link](component);
}
public ArithmeticComponent2 getChild(int i) {
return [Link](i);
}
public int evaluate() {
int result = 0;
boolean firstChild = true;
Iterator<ArithmeticComponent2> it = [Link]();
while ([Link]()) {
ArithmeticComponent2 comp = [Link]();

if (firstChild == true) {
result = [Link]();
firstChild = false;
continue;
}
if ([Link]("+"))
result += [Link]();
else if ([Link]("-"))
result -= [Link]();
else if ([Link]("*"))
result *= [Link]();
else if ([Link]("/"))
result /= [Link]();
}
return result;
}
public void print() {
Iterator<ArithmeticComponent2> it = [Link]();
Page 562 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
while ([Link]()) {
ArithmeticComponent2 comp = [Link]();
[Link]();
if ([Link]())
[Link](" " + operator + " ");
}
}
}

[Link]
public class Operand2 extends ArithmeticComponent2 {
private int op;

public Operand2(int op) {


[Link] = op;
}
public void print() {
[Link](op);
}
public int evaluate() {
return op;
}
}

[Link]
public class CompositeClient2 {
public static void main(String[] args) {
// 5 * 12 + 3 * 9
ArithmeticComponent2 expression = new Operator2("+");
ArithmeticComponent2 subExpression1 = new Operator2("*");
ArithmeticComponent2 subExpression2 = new Operator2("*");

[Link](subExpression1);
[Link](new Operand2(5));
[Link](new Operand2(12));

[Link](subExpression2);
[Link](new Operand2(3));
[Link](new Operand2(9));

[Link]();
[Link]("= " + [Link]());
}
}
© 2011 ITCourseware, LLC Rev 5.1.4 Page 563
Advanced Java Programming

Chapter 18

[Link]
import [Link];
import [Link];
import [Link];

public class Query extends DatabaseAccessTemplate {


private ResultSet rs;

protected void runStatement(Statement stmt, String sql)


throws Exception {
rs = [Link](sql);
}
protected void processResults()
throws Exception {

ResultSetMetaData rsmd = [Link]();


int numColumns = [Link]();

for (int i = 1; i <= numColumns; i++) {


[Link]([Link](i) + "\t");
}
[Link]();

while ([Link]()) {
for (int i = 1; i < numColumns; i++) {
[Link]([Link](i) + "\t");
}
[Link]();
}
[Link]();
}
}

[Link]
public class TemplateClient2 {
public static void main(String[] args) {
String driverClass = "[Link]";
String url = "jdbc:derby://localhost:1527/j2se";
String username = null;
String password = null;
DatabaseAccessTemplate db = new Query();

Page 564 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link] (cont'd)
String sql = "SELECT * FROM Employee";
[Link](driverClass, url, sql, username, password);
}
}

[Link]
public class StandByState2 implements State {
private Computer2 computer;

public StandByState2(Computer2 comp) {


computer = comp;
}

public void hibernate() {


[Link]("You can't hibernate a standBy computer");
}
public void keyPress() {
[Link]("Waking up. . .");
[Link]("Power on display and drives");
[Link]([Link]());
}
public void powerOn() {
// NEW CODE:
[Link]("Waking up. . .");
[Link]("Power on display and drives");
[Link]([Link]());
}
public void shutdown() {
[Link]("You can't shutdown a standBy computer");
}
public void standBy() {
[Link]("You can't standby a standBy computer");
}
}

[Link]
public class Computer2 {
State activeState = new ActiveState2(this);
State hibernateState = new HibernateState2(this);
State shutdownState = new ShutdownState2(this);
State standByState = new StandByState2(this);
State currentState;

© 2011 ITCourseware, LLC Rev 5.1.4 Page 565


Advanced Java Programming

Chapter 18 (cont'd)

[Link] (cont'd)
public Computer2() {
currentState = shutdownState;
}
public void hibernate() {
[Link]();
}
public void keyPress() {
[Link]();
}
public void powerOn() {
[Link]();
}
public void shutdown() {
[Link]();
}
public void standBy() {
[Link]();
}
public void setState(State state) {
currentState = state;
}
public State getActiveState() {
return activeState;
}
public State getHibernateState() {
return hibernateState;
}
public State getShutdownState() {
return shutdownState;
}
public State getStandByState() {
return standByState;
}
}

[Link]
public class StateClient2 {
public static void main(String[] args) {
Computer2 comp = new Computer2();

Page 566 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link] (cont'd)
[Link]();
[Link]();
[Link]();
[Link]();
[Link]();
[Link]();
}
}

[Link]
public class ActiveState2 implements State {
private Computer2 computer;

public ActiveState2(Computer2 comp) {


computer = comp;
}

public void hibernate() {


[Link]("Hibernating . . .");
[Link]("Saving current desktop state to disk");
[Link]("Press the power on button to wake up");
[Link]([Link]());
}
public void keyPress() {
[Link]("Key press doesn't wake an active computer");
}
public void powerOn() {
[Link]("Power on doesn't wake an active computer");
}
public void shutdown() {
[Link]("Shutting down . . .");
[Link]("Clearing all active state");
[Link]("Press the power on button to start up");
[Link]([Link]());
}
public void standBy() {
[Link]("Standing by . . .");
[Link]("Power off display and drives");
[Link]("Press any key to wake up");
[Link]([Link]());
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 567


Advanced Java Programming

Chapter 18 (cont'd)

[Link]
public class HibernateState2 implements State {
private Computer2 computer;

public HibernateState2(Computer2 comp) {


computer = comp;
}

public void hibernate() {


[Link]("You can't hibernate a hibernating computer");
}
public void keyPress() {
[Link]("Keypress doesn't wake hibernating computer");
}
public void powerOn() {
[Link]("Waking up. . .");
[Link]("Restore desktop state from disk");
[Link]([Link]());
}
public void shutdown() {
[Link]("You can't shutdown a hibernating computer");
}
public void standBy() {
[Link]("You can't standby a hibernating computer");
}
}

[Link]
public class ShutdownState2 implements State {
private Computer2 computer;

public ShutdownState2(Computer2 comp) {


computer = comp;
}

public void hibernate() {


[Link]("You can't hibernate a shutdown computer");
}
public void keyPress() {
[Link]("Keypress doesn't wake a shutdown computer");
}
public void powerOn() {
Page 568 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
[Link]("Starting up. . .");
[Link]([Link]());
}
public void shutdown() {
[Link]("You can't shutdown a shutdown computer");
}
public void standBy() {
[Link]("You can't standby a shutdown computer");
}
}

[Link]
public class Logger implements Observer {
private Subject subject;

public Logger(Subject subject) {


[Link] = subject;
[Link](this);
}

public void update() {


double currentBalance = ((BankAccount)subject).getBalance();
[Link]("Balance updated: " + currentBalance);
}
}

[Link]
import [Link];
import [Link];
import [Link];

public class TellerGUI2 extends JFrame {


private JPanel currentBalancePanel;
private JPanel modifyBalancePanel;
private JPanel statusPanel;

public TellerGUI2() {
[Link]("Teller");
BankAccount account = new BankAccount(0);

// New code:
Logger logger = new Logger(account);

© 2011 ITCourseware, LLC Rev 5.1.4 Page 569


Advanced Java Programming

Chapter 18 (cont'd)

[Link] (cont'd)
initializePanels(account);

[Link](new BorderLayout(10, 10));


[Link](modifyBalancePanel, [Link]);
[Link](currentBalancePanel, [Link]);
[Link](statusPanel, [Link]);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
// trigger first notify
[Link](0);
}
private void initializePanels(Subject subject) {
currentBalancePanel = new CurrentBalancePanel(subject);
modifyBalancePanel = new ModifyBalancePanel(subject);
statusPanel = new StatusPanel(subject);
}
public static void main(String[] args) {
new TellerGUI2();
}
}

Page 570 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

Appendix A

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class SalRpt1 {


public static void main(String args []) {
Connection conn;
try {
[Link]("[Link]");
String url = "jdbc:derby://localhost:1527/j2se";
conn = [Link](url);
Statement stmt = [Link]();

String sqltxt;
sqltxt = "SELECT FIRSTNAME, LASTNAME, SALARY FROM EMPLOYEE";
ResultSet rs = [Link](sqltxt);

String name;
String dept;
float salary;
float totalsalary = 0.0F;

while ([Link]()) {
name = [Link](1) + " " + [Link](2);
salary = [Link](3);
totalsalary += salary;
[Link]("%1s \t %2.2f %n", name, salary);
}
[Link]("----------\nTotal salary: " + totalsalary);
[Link]();
[Link]();
}
catch (ClassNotFoundException cnfe) {
[Link]("Unable to load driver class: " + cnfe);
}
catch (SQLException sqle) {
[Link](sqle);
}
}
}
© 2011 ITCourseware, LLC Rev 5.1.4 Page 571
Advanced Java Programming

Appendix A (cont’d)

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class SalRpt2 {


public static void main(String args[]) {
Connection conn;
try {
[Link]("[Link]");
String url = "jdbc:derby://localhost:1527/j2se";
conn = [Link](url);
Statement stmt = [Link]();

String sqltxt;
sqltxt = "SELECT FIRSTNAME, LASTNAME, SALARY, DEPARTMENT_NAME " +
"FROM EMPLOYEE, DEPARTMENT " +
"WHERE EMPLOYEE.DEPARTMENT_CODE = DEPARTMENT.DEPARTMENT_CODE";
ResultSet rs = [Link](sqltxt);

String name;
String dept;
float salary;
float totalsalary = 0.0F;
float tempsal;
Map<String, Float> map = new HashMap<String, Float>();

while ([Link]()) {
name = [Link](1) + " " + [Link](2);
salary = [Link](3);
totalsalary += salary;

[Link]("%1s \t %2.2f %n", name, salary);


dept = [Link](4);

if ([Link](dept)) {
// unboxing and generics simplify this process
Page 572 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
tempsal = [Link](dept);
}
else {
tempsal = 0.0F;
}
[Link](dept, new Float(tempsal + salary));
}

[Link]("------%nTotal salary: %1.2f %n", totalsalary);


[Link]();
[Link]();

[Link]("\nTotal Salary for Department");


Set<String> keys = [Link]();
Iterator<String> it = [Link]();
while ([Link]() ) {
dept = [Link]();
[Link]("%1.2f \t %2s %n", [Link](dept), dept);
}
}
catch (ClassNotFoundException cnfe) {
[Link]("Unable to load driver class: " + cnfe);
}
catch (SQLException sqle) {
[Link](sqle);
}
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class SalRpt3 {


public static void main(String args[]) {
Connection conn;
try {

© 2011 ITCourseware, LLC Rev 5.1.4 Page 573


Advanced Java Programming

Appendix A (cont’d)

[Link] (cont'd)
[Link]("[Link]");
String url = "jdbc:derby://localhost:1527/j2se";
conn = [Link](url);
Statement stmt = [Link]();

String sqltxt;
sqltxt = "SELECT FIRSTNAME, LASTNAME, SALARY, DEPARTMENT_NAME " +
"FROM EMPLOYEE, DEPARTMENT " +
"WHERE EMPLOYEE.DEPARTMENT_CODE = DEPARTMENT.DEPARTMENT_CODE";
ResultSet rs = [Link](sqltxt);

String name;
String dept;
float salary;
float totalsalary = 0.0F;
float tempsal;
Map<String, Float> map = new HashMap<String, Float>();

while ([Link]()) {
name = [Link](1) + " " + [Link](2);
salary = [Link](3);
totalsalary += salary;

[Link]([Link](name, 30));
[Link]("%1.2f %n", salary);
dept = [Link](4);

if ([Link](dept)) {
// unboxing and generics simplify this process
tempsal = [Link](dept);
}
else {
tempsal = 0.0F;
}
[Link](dept, new Float(tempsal + salary));
}

[Link]( [Link]("", 38, '-'));


[Link]([Link]("Total salary:", 28));
[Link]("%1.2f%n", totalsalary);
[Link]();
[Link]();
Page 574 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
[Link]("\nTotal Salary for Department");
Set<String> keys = [Link]();
Iterator<String> it = [Link]();
while ([Link]() ) {
dept = [Link]();
[Link]("%1.2f \t %2s %n", [Link](dept), dept);
}
}
catch (ClassNotFoundException cnfe) {
[Link]("Unable to load driver class: " + cnfe);
}
catch (SQLException sqle) {
[Link](sqle);
}
}
}

[Link]
import [Link];
import [Link];

public class SQLUtils {


public static String formatSQLException(SQLException e) {
StringBuilder msg = new StringBuilder("");
if (e != null) {
[Link](" SQLState: " + [Link]() + "\n");
[Link](" Code: " + [Link]() + "\n");
[Link](" Message: " + [Link]() + "\n\n");
}
return [Link]();
}
public static String formatSQLExceptions(SQLException e) {
String msg = "";
while (e != null) {
msg += formatSQLException(e);
e = [Link]();
}
return msg;
}
public static void printSQLErrors(SQLException e) {
if (e != null) {
[Link]("SQL Error:\n" + formatSQLExceptions(e));
}
}
public static boolean printSQLWarnings(SQLWarning w)
throws SQLException {
© 2011 ITCourseware, LLC Rev 5.1.4 Page 575
Advanced Java Programming

Appendix A (cont’d)

[Link] (cont'd)

if (w != null) {
[Link]("SQL Warning:");
while (w != null) {
[Link](formatSQLException(w));
w = [Link]();
}
return true;
}
else {
return false;
}
}
public static String rPadTrunc(String s, int len) {
return rPadTrunc(s, len, ' ');
}
public static String rPadTrunc(String s, int len, char c) {
if ( s == null ) {
s = "";
}
if (len <= [Link]()) {
return [Link](0,len);
}
StringBuilder sb = new StringBuilder(s);
for (int k=0; k < (len - [Link]()); k++) {
[Link](c);
}
return [Link]();
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

Page 576 Rev 5.1.4 © 2011 ITCourseware, LLC


Solutions

[Link] (cont'd)
public class DeptEmps {
public static void main (String args []) {
Connection conn;
try {
String dept = "";
try {
BufferedReader br = new BufferedReader(
new InputStreamReader([Link]));
[Link]("Enter a dept code and press <Return>: ");
dept = [Link]();
if (dept == null) {
[Link]("No department entered. Exiting.");
[Link](0);
}
} catch(IOException ioe) {
[Link]();
}
[Link]("[Link]");
conn = [Link]
("jdbc:derby://localhost:1527/j2se");

String sqltxt = "SELECT id, firstname, lastname, title " +


" FROM employee WHERE department_code = ?";
PreparedStatement pstmt = [Link]( sqltxt);
[Link](1, dept);
ResultSet rs = [Link]();

if ([Link]()) {
[Link]("Employees of department " + dept + ":");
do {
String id = [Link](1);
String name = [Link](2) + " " + [Link](3);
String title = [Link](4);
[Link](id + "\t" + name + "\t" + title);
} while ([Link]());
}
else {
[Link]("No employees found for " + dept + ".");
}
[Link]();
[Link]();
[Link]();
}
catch (ClassNotFoundException cnfe) {
[Link]("Unable to load driver class: " + cnfe);

© 2011 ITCourseware, LLC Rev 5.1.4 Page 577


Advanced Java Programming

Appendix A (cont’d)

}
catch (SQLException sqle) {
[Link](sqle);
}
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class SQLExec {


public static void main(String args[]) {
try {
[Link]("[Link]");
String url = "jdbc:derby://localhost:1527/j2se";
String buf;
String sqlString = "";

try {
BufferedReader br = new BufferedReader(
new InputStreamReader([Link]));
[Link]("Enter a SQL statement. Enter 'q' to quit");

while ((buf = [Link]()) != null) {


if ([Link]("q")) {
break;
}
sqlString += buf + " ";
}
}
catch(IOException ioe) {
[Link]();
[Link](1);
}
[Link]("Executing SQL statement:");
[Link](sqlString);
Page 578 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
Connection conn = [Link](url);
Statement stmt = [Link]();

int count = 0;
if ([Link]().toUpperCase().startsWith("SELECT")) {
ResultSet rs = [Link](sqlString);
while ([Link] ()) {
count++;
}
[Link]();
[Link]("%n%1d row(s) retrieved.%n", count);
}
else {
count = [Link](sqlString);
[Link]("%n%1d row(s) updated.%n", count);
}
[Link]();
[Link]();
}
catch (ClassNotFoundException cnfe) {
[Link]("Unable to load driver class: " + cnfe);
}
catch (SQLException sqle) {
[Link](sqle);
}
}
}

[Link]
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class SQLExec2 {


public static void main(String args[]) {
try {
[Link]("[Link]");
String url = "jdbc:derby://localhost:1527/j2se";
String buf;

© 2011 ITCourseware, LLC Rev 5.1.4 Page 579


Advanced Java Programming

Appendix A (cont’d)

[Link] (cont'd)
String sqlString = "";

try {
BufferedReader br = new BufferedReader(
new InputStreamReader([Link]));
[Link]("Enter a SQL statement. Enter 'q' to quit");

while ((buf = [Link]()) != null) {


if ([Link]("q")) {
break;
}
sqlString += buf + " ";
}
}
catch(IOException ioe) {
[Link]();
[Link](1);
}
[Link]("Executing SQL statement:");
[Link](sqlString + "\n");

Connection conn = [Link](url);


Statement stmt = [Link]();

int count = 0;
if ([Link]().toUpperCase().startsWith("SELECT")) {
ResultSet rs = [Link](sqlString);
ResultSetMetaData rsmd = [Link]();
int cols = [Link]();

while ([Link] ()) {


for (int c = 0; c < cols; c++) {
[Link]([Link](c+1));
if (c < cols - 1) {
[Link](" ");
}
}
[Link]();
count++;
}
[Link]();
[Link]("%n%1d row(s) retrieved.%n", count);
Page 580 Rev 5.1.4 © 2011 ITCourseware, LLC
Solutions

[Link] (cont'd)
}
else {
count = [Link](sqlString);
[Link]("%n%1d row(s) updated.%n", count);
}
[Link]();
[Link]();
}
catch (ClassNotFoundException cnfe) {
[Link]("Unable to load driver class: " + cnfe);
}
catch (SQLException sqle) {
[Link](sqle);
}
}
}

© 2011 ITCourseware, LLC Rev 5.1.4 Page 581


Advanced Java Programming

Page 582 Rev 5.1.4 © 2011 ITCourseware, LLC


Index

Index

Symbols Attributes 276


AudioPermission 177
-[Link] 322 authentication 244, 248
-[Link] 253 authorization 244
-[Link] 174, 186, 253 AuthPermission 177, 254
-[Link] 180, 253 autoCommit 90
-idl 166 autocommit 430
-iiop 166 automatic stub generation 135
.dll 314 AWTPermission 177
.h file 316
.[Link] file 180 B
.keystore file 200
.so file 314 BasicAttributes 278
? 426 batch update 90
BatchUpdateException 90
A BeanShell 81
behavioral pattern 388
accept 118 bind 140, 274
acceptChanges 100 Binding 275
AccessController 174 Blob 94
activatable Blowfish 222
object 158 Buffer 44
[Link] 158 buffer 42
[Link] 160 builder pattern 354, 356, 358
activation 156 ByteBuffer 44, 50
group 156
ActivationDesc 160 C
ActivationID 158
ActivatonGroupDesc 160 C 326
activator 156 C program 318
adapter C++ 326
class 373 CachedRowSet 100
object 373 CachedRowSetImpl 100
adapter pattern 372, 374, 376 CallableStatement 428
addBatch 90 Callback 258, 260
address 110 callback 152, 258
algorithm 218, 222, 392 CallbackHandler 248, 258
AllPermission 177 CallVoidMethod 330
Applet 394 cancelRowUpdates 92
applet 172, 184 capacity 46
array 48 certificate 204
asymmetric Certificate Authority (CA) 204, 206
cryptography 218 certificate chain 206
key 220 Certificate Signing Request file 206
asynchronous 152 channel 42
Attribute 276 char * 328
attribute 268 character set 58

© 2011 ITCourseware, LLC Rev 5.1.4 Page 583


Advanced Java Programming

CharBuffer 44 DefaultHandler 290, 292


CharsetDecoder 58 defaultReadObject 30
CharsetEncoder 58 defaultWriteObject 30
Cipher 218, 222, 228, 230, 232, 236, 238 DelegationPermission 177
password-based 234 deleteRow 92
Cipher Block Chaining (CBC) 224 design pattern 338
Cipher-feedback Mode (CFB) 224 digital signature 198
Cipher.DECRYPT_MODE 238 DirContext 278
Cipher.ENCRYPT_MODE 238 [Link] 278
Cipher.UNWRAP_MODE 236 directory 268
Cipher.WRAP_MODE 236 disconnected RowSet 98
class adapter 373 distributed application 130
class literal 66 distributed transaction 102
ClassNotFoundException 28 DNS 268
classpath 142, 456 DNS lookup 280
clear 46 DNS Resource Records (RR) 280
clearBatch 90 Document 298, 300
client 108, 130, 152 Document Object Model (DOM) 288, 296, 298, 382
client callback 152 Document Type Definitions (DTD) 302
Clob 94 DocumentBuilder 298
clone 344 DocumentBuilderFactory 298
Cloneable 344 doFinal 228
codeBase 178, 254 DOMSource 304
codebase 142, 154 dynamic class loading 154
CodeSource 262
[Link] 256 E
commit 90, 430 Eclipse 436, 453, 455
Common Object Request Broker Architecture (CORBA) editor 442
166 Electronic Cookbook Mode (ECB) 224
composite pattern 358, 378, 380, 382 Element 300
composition 340, 364 encode 58
concurrent server 116, 120 ENCRYPT 228
connected RowSet 98 encryption 226
connection pooling 102 endDocument 294
Constructor 68, 70 endElement 294
ContentHandler 290 Enterprise Java Beans (EJB) 80
[Link] 272 error 302
[Link] 272 ErrorHandler 290, 302
control flag 249 exchanging encrypted keys 236
creational pattern 340 exclusive (write) lock 52
cryptography 218 execute 88, 100
asymmetric 218 executeBatch 90
symmetric 218 executeQuery 418
D executeUpdate 422
Externalizable 22
Data Encryption Standard Algorithm (DES) 222
DataSource 98, 102 F
debug perspective 450 façade pattern 366, 368, 370, 376
decode 58 factory design pattern 146
decouple 370 factory method pattern 348, 350, 352, 356
DECRYPT 228 fatalError 302
decryption 226
Page 584 Rev 5.1.4 © 2011 ITCourseware, LLC
Index

Field 68, 72 GetVersion 326


file GNU gcc compiler 320
.keystore 200 Groovy 81
.so 314
Certificate Signing Request 206 H
[Link] 180 Hollywood principle 391
property 350 hook 392
signature 202
signature block 202 I
FileChannel 42, 52, 54, 56
[Link] 54 IIOP 166
FileLock 52 IllegalAccessException 73, 74
FilePermission 177 IllegalBlockSizeException 228
FindClass 330 Import 458
flip 46 inheritance 340, 364
force 50, 54 InitialContext 164, 270
forName 66 initialization vector (IV) 226
interface
G remote 134
InvocationTargetException 74, 76
Gang of Four (GoF) 339 invoke 74
gather 50 isLoaded 54
get 42, 46 iterative server 116, 118
getBlob 94
getClass 66 J
getClob 94
getContentLength 124 jarsigner 198, 202
getContentType 124 Java 2 Enterprise Edition (J2EE) 282
getDeclaredField 72 Java 5 135
getDeclaredFields 72 Java API for XML Processing (JAXP) 288, 292, 298, 304
getDeclaredMethod 74 Java Archive (JAR) 192
getDeclaredMethods 74 Java Authentication and Authorization Service (JAA 246
getDocumentElement 300 Java Cryptography Architecture (JCA) 212
getElementByTagName 300 Java Cryptography Extension (JCE) 212
getExceptionTypes 76 Java Naming and Directory Interface (JNDI)
getField 72 102, 164, 268, 270, 382
getFields 72 Java Native Interface (JNI) 310, 326
getInputStream 114, 124 Java Perspective 442
getMethod 74 Java Plug-In 184
GetMethodID 330 Java Remote Method Protocol (JRMP) 166
getMethods 74 Java security model 176
getModifiers 72 Java Web Start 172
getObject 238 [Link] 32
GetObjectClass 330 [Link] 22
getOutputStream 114, 124 [Link] 66
getPermissions 262 [Link] 184
getPrincipals 250 [Link] 64, 68
getResultSet 88 [Link] 322
getSavepointName 96 [Link] 112
GetStringUTFChars 328 [Link] 40
getSubject 248 [Link] 46
getUpdateCount 88 [Link] 48
[Link] 50
© 2011 ITCourseware, LLC Rev 5.1.4 Page 585
Advanced Java Programming

[Link] 58 public 198, 220


[Link] file 180 secret 220
[Link] 158 symmetric 220
[Link] 140 keypair 198
[Link] 134, 140 keystore 200, 208, 256
[Link] 134 KeyStoreLoginModule 252
[Link] 186 keytool 200, 204, 206, 208
[Link] 134, 140 Krb5LoginModule 252
[Link] 194
[Link] 205 L
[Link] 220 LD_LIBRARY_PATH 322
[Link] 200, 208 LD_RUN_PATH 322
[Link] 262 LDAP 268
[Link] 250 legacy code 310
[Link] 250 limit 46
[Link] 416 Linux 320, 323
JavaBean 78 load 54
javah 312, 316, 328 localName 294
javap 332 lock 52
JavaServer Faces (JSF) 80 exclusive (write) 52
JavaServer Pages (JSP) 80 shared (read) 52
[Link] 226 LoggingPermission 177
[Link] 232 login 248, 258
[Link] 230 login configuration file 246
[Link] 220 LoginContext 250, 252
[Link] 238 LoginException 248
[Link] 234 LoginModule 258
[Link] 234 logout 248
[Link] 246 lookup 140, 164
[Link] 258
[Link] 248 M
[Link] 250
[Link] 98, 102 map 54
JCEKS 208 MappedByteBuffer 54
jclass 330 MarshalledObject 158
JDBC escape syntax 86 marshalling 132
JDBC type 416 Member 68
JKS 208 message digest 196
[Link] file 271 Method 68
JNDILoginModule 252 method
JNI signature 332 accept 118
jni.h file 316, 318 acceptChanges 100
JNIEnv *env 318 [Link] 158
jobject 330 [Link] 160
jobject obj 318 addBatch 90
jstring 328 array 48
bind 140, 274
K CallVoidMethod 330
cancelRowUpdates 92
Key 236 clear 46
key clearBatch 90
asymmetric 220 clone 344
private 198, 220
Page 586 Rev 5.1.4 © 2011 ITCourseware, LLC
Index

commit 90 GetVersion 326


[Link] 272 invoke 74
[Link] 272 isLoaded 54
decode 58 load 54
defaultReadObject 30 lock 52
defaultWriteObject 30 login 248, 258
deleteRow 92 logout 248
[Link] 278 lookup 140, 164
doFinal 228 map 54
encode 58 [Link] 138, 160
endDocument 294 [Link] 136
endElement 294 [Link] 138, 160
error 302 newDecoder 58
execute 88, 100 newEncoder 58
executeBatch 90 NewGlobalRef 330
executeQuery 418 newInstance 70
executeUpdate 422 NewStringUTF 328
fatalError 302 notify 404
FindClass 330 openConnection 122, 124
flip 46 openStream 122
force 50, 54 parse 292, 298
forName 66 [Link] 262
get 42, 46 populate 100
getBlob 94 [Link] 166
getClass 66 prepareCall 428
getClob 94 prepareStatement 424
getContentLength 124 put 46
getContentType 124 read 42, 50
getDeclaredField 72 readExternal 32
getDeclaredFields 72 readObject 26, 30
getDeclaredMethod 74 rebind 140, 164, 274
getDeclaredMethods 74 registerGroup 160
getDocumentElement 300 registerOutParameter 428
getElementByTagName 300 release 52
getExceptionTypes 76 releaseSavepoint 96
getField 72 ReleaseStringUTFChars 328
getFields 72 rename 274
getInputStream 114, 124 rollback 90, 96
getMethod 74 setDocumentLocator 294
GetMethodID 330 setDoOutput 124
getMethods 74 setSavepoint 96
getModifiers 72 setValidating 302
getObject 238 size 50
GetObjectClass 330 startDocument 294
getOutputStream 114, 124 startElement 294
getPermissions 262 [Link] 250
getPrincipals 250 [Link] 314
getResultSet 88 transferFrom 56
getSavepointName 96 transferTo 56
GetStringUTFChars 328 transform 304
getSubject 248 truncate 50
getUpdateCount 88 tryLock 52

© 2011 ITCourseware, LLC Rev 5.1.4 Page 587


Advanced Java Programming

unbind 274 Observer 407


[Link] 134 observer pattern 402, 404, 406
unwrap 236 openConnection 122, 124
update 228, 404 openStream 122
updateRow 92 Output Feedback Mode (OFB) 224
updateXXX 92
warning 302 P
wrap 48, 236 padding 218, 224
write 42, 46, 50 NoPadding 224
writeExternal 32 PKCS5Padding 224
writeObject 24, 30 parse 288, 290, 292, 298
mode 218, 224 part-whole tree structure 382
Modifier 72 passed by reference 146
N passed by value 146
password-based Cipher 234
NameCallback 260 PasswordCallback 260
NameClassPair 272 PATH 322
NamedNodeMap 300 pattern
Naming 141 adapter 372, 374, 376
naming service 268 behavioral 388
[Link] 138, 160 builder 354, 356, 358
[Link] 136 class creational 340
[Link] 138, 160 composite 358, 378, 380, 382
native 314 creational 340
native method 310 design 338
NetPermission 177 façade 366, 368, 370, 376
New I/O library (NIO) 40 factory design 146
newDecoder 58 factory method 348, 350, 352, 356
newEncoder 58 object creational 340
NewGlobalRef 330 observer 402, 404, 406
newInstance 70 publish-subscribe 402
NewStringUTF 328 singleton 342, 344, 346, 368
Node 300 state 396, 398, 400
NodeList 300 structural 364
NoPadding 224 template method 390, 392, 394
NoSuchFieldException 72 PBEParameterSpec 234
NoSuchMethodException 74 PBEWithMD5AndDES 222, 234
notify 404 Permission 250, 262
NotSerializableException 25, 28 perspective 442
NTDomainPrincipal 252 PKCS12 208
NTLoginModule 252, 258 PKCS5Padding 224
NTUserPrincipal 252, 254 placeholder 426
policy file 154, 162, 178, 182, 246, 254
O system 180
object user-specific 180
remote 132 [Link] 262
object adapter 373 policytool 182, 210, 246
ObjectInputStream 20, 26 populate 100
ObjectOutputStream 20, 24 port 110
ObjectStreamClass 24, 26, 32 PortableRemoteObject 166
Observable 407 [Link] 166
position 46
Page 588 Rev 5.1.4 © 2011 ITCourseware, LLC
Index

prepareCall 428 RMI Registry 138, 142, 164, 268


PreparedStatement 424, 426 RMI-IIOP 166
prepareStatement 424 rmic 132, 134, 144, 166
Principal 248 rmid 156, 162
private key 198, 220 rmiregistry 144
PrivateCredentialPermission 177 RMISecurityManager 162
privileged action 254 rollback 90, 96, 430
PrivilegedAction 250 RowSet 98
project 444 connected 98
Propagating Cipher Block Chaining Mode (PCBC) 224 disconnected 98
Properties 160 RuntimePermission 177
properties 78
property file 350 S
PropertyPermission 177 savepoint 96
ProtectionDomain 262 SaxParser 292
protocol 110, 140 SaxParserFactory 292
public key 198, 220 SAXSource 304
publish-subscribe pattern 402 scatter 50
put 46 secret key 220
Q security 172
manager 154
qName 294 policy 176
SecurityException 176, 250
R SecurityManager 174, 186, 250
read 42, 50 SecurityPermission 177
ReadableByteChannel 56 Serializable 78, 114, 238
readExternal 32 SerializablePermission 177
readObject 26, 30 serialization 20
rebind 140, 164, 274 serialver utility 34
refactoring 394, 400 serialVersionUID 24, 34
reflection 22 server 108, 130, 152
Reflection API 64 concurrent 116, 120
ReflectPermission 177 iterative 116, 118
registerGroup 160 ServerSocket 118
registerOutParameter 428 service provider 268
release 52 ServicePermission 177
releaseSavepoint 96 setDocumentLocator 294
ReleaseStringUTFChars 328 setDoOutput 124
Remote 152 setSavepoint 96
remote interface 134 setValidating 302
Remote Method Invocation (RMI) 130 shared (read) lock 52
remote object 132 shortcut 453
RemoteException 138 signature block file 202
rename 274 signature file 202
Result 304 Simple API for XML (SAX) 288, 290, 292
ResultSet 92, 420 singleton 344
ResultSetMetaData 420 singleton pattern 342, 346, 368
RMI size 50
client 136 Socket 118
server 138 SocketChannel 56
stub 172 SocketPermission 177
Source 304
© 2011 ITCourseware, LLC Rev 5.1.4 Page 589
Advanced Java Programming

SQLException 412 UnixLoginModule 258


SQLPermission 177 UnknownHostException 112
SQLWarning 414 untrusted code 172
SSLPermission 177 unwrap 236
startDocument 294 updatable result set 92
startElement 294 update 228, 404
state machine 396 updateRow 92
state pattern 396, 398, 400 updateXXX 92
state transition 398 URL 122, 124
Statement 88, 418, 422 URLConnection 124
static initializer 314 user-specific policy file 180
stored procedure 428 utility
StreamCorruptedException 26 jarsigner 198, 202
structural pattern 364 keytool 200, 204, 206, 208
stub 132, 134, 142 policytool 182, 210, 246
automatic stub generation 135 rmic 132, 134, 144, 166
RMI 172 rmid 156, 162
Subject 248, 252 serialver 34
[Link] 250
SunJCE 222, 224, 234 V
symmetric cryptography 218 validation 302
symmetric key 220 view 442
system policy file 180 Visual Studio .NET 321
[Link] 314 Visual Studio 6.0 321
T W
TCP 110 warning 302
template 455 Windows 321, 323
template method pattern 390, 392, 394 workspace 440
Text 300 wrap 48, 236
transaction 430 write 42, 46, 50
transaction isolation level 431 writeExternal 32
transferFrom 56 writeObject 24, 30
transferTo 56
transform 288, 304 X
transformation 304
Transformer 304 XML 288, 290
TransformerFactory 304 XML Schema 302
transient 30 XSLT 288, 304
tree structure 378
part-whole 382
Triple-DES 222
truncate 50
tryLock 52

U
UDP 110
unbind 274
UnicastRemoteObject 138, 141
[Link] 134
UNIX 320, 323

Page 590 Rev 5.1.4 © 2011 ITCourseware, LLC


ITCourseware, LLC.
7245 South Havana Street, Suite 100
Centennial, CO 80112

(800) 292-2652 or (303) 302-5280


7245 South Havana Street, Suite 100
Centennial, Colorado 80112-1562
Ph: 303-302-5280 FX: 303-302-5281
[Link]

9-00-00017-000-08-05-11
*9-00-00017-000-08-05-11*

Common questions

Powered by AI

Java RMI facilitates client-server application development by enabling method calls on an object that exists in a different JVM, making the remote interaction appear as if it were local. In this model, a client looks up the remote object in the server's registry and uses the object's methods. Stubs and skeletons play essential roles: the stub on the client side acts as a local representative or proxy and forwards calls to the remote object; the skeleton on the server side receives incoming requests, processes them, and sends responses back to the stub. This abstraction simplifies remote method invocation by managing low-level network communication seamlessly .

In a pre-Java 5 environment, developers had to manually generate stub classes by using the `rmic` compiler. In Java 5 and above, the Java platform supports automatic stub generation. The stub class is automatically generated by the JVM when the remote object is exported, provided the stub class is not already available in the classpath. However, `rmic` is still required if there is a need to support clients running on a pre-Java 5 VM .

Java RMI uses exception handling extensively to manage remote object references, given the potential issues in remote communication. Key exceptions include `java.rmi.AccessException` if the calling code lacks permission, `java.net.MalformedURLException` for invalid URL formats, `java.rmi.UnknownHostException` if the host is not available, `java.rmi.RemoteException` for unavailable server registries, and `java.rmi.NotBoundException` if an object with the requested name is not found in the registry. This structured use of exceptions allows developers to gracefully handle different areas of failure during remote method invocation .

Java design patterns, specifically creational patterns, are vital in encapsulating the process of object instantiation, allowing this process to change without impacting the rest of the system. They lead to more flexible and reusable code by segregating the construction logic from the client. The advantages include capturing expert knowledge, facilitating system restructuring, avoiding duplicate code, and providing a common vocabulary among developers. By using abstract classes or interfaces, client code remains unaffected by changes in the concrete implementation, which also allows for improved code maintainability and scalability .

The RMI Registry is a server-side service in Java RMI that binds a name to a remote object. It tracks the remote objects available on a particular host. Multiple servers can register objects with the registry, and it can either bind or rebind objects using methods like `Naming.bind()` or `Naming.rebind()`. Programmatically, developers interact with the registry by registering remote objects with these methods and fetching them using the `Naming.lookup()` method. This allows clients to obtain references to remote objects using a URL format .

Local methods in Java are always executed directly within the same machine, where objects are passed by reference and primitive datatypes by value. For remote methods, objects implementing the Remote interface are passed by reference and need to be exported before being used as parameters or returned; these objects do not need binding to a registry. Remote methods must handle RemoteExceptions due to network transmission, and objects implementing Serializable are serialized and passed by value, with primitive datatypes also passed by value .

The Factory Method pattern supports the dynamic selection of a builder class in systems utilizing the builder pattern by determining which specific builder to instantiate based on input parameters. This pattern creates an instance of a class implementing a common interface without depending on its specific class, allowing the system to decide at runtime which builder class to use. This is helpful when a system must support multiple complex product types or when these types might change, as it separates the construction logic from the product instantiation logic .

Behavioral patterns in Java differ from structural and creational patterns as they focus on the interaction and collaboration between objects rather than the system's structure or the creation of objects. Their primary purpose is to enable distribution of responsibility among objects, defining how they communicate, manage task assignments, and encapsulate control flows. This separation addresses the object communication dynamics, resulting in systems that are more flexible regarding interactions and behaviors. Behavioral patterns also encourage encapsulation of algorithms and promote an easier refactoring process when behavior needs to change .

The Composite design pattern is most beneficial in Java-based applications when dealing with hierarchical data structures like file systems, UI components, or document structures. Its ability to treat individual objects and compositions of objects uniformly makes it especially useful when the application needs to process tree structures. By using recursion, the pattern simplifies client code, as it allows clients to work with complex tree structures without needing separate logic for leaf and composite nodes. The pattern is also suitable for scenarios that require adding new types of components without altering the existing code structure, enhancing the system's scalability and flexibility .

To set up and run a Java RMI application, follow these steps: 1) Define the remote interface extending `java.rmi.Remote`. 2) Implement the interface in a server class, having constructors that throw `RemoteException`. 3) Compile the Java files with `javac` to produce class files. 4) Use `rmic` to generate the stub and skeleton classes if not using Java 5 or later, where dynamic generation is supported. 5) Start the RMI Registry using `rmiregistry`. 6) Register the server object within the RMI Registry using `Naming.bind()` or `Naming.rebind()`. 7) Start the server application. 8) Run the client application, which will look up the remote object and invoke methods as needed .

You might also like