Tải bản đầy đủ (.pdf) (599 trang)

Java™ Application Development on Linux pptx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (3.23 MB, 599 trang )

Java

Application Development
on Linux
®

Java

Application Development
on Linux
®
Carl Albing
Michael Schwarz
Prentice Hall Professional Technical Reference
Boston
Many of the designations used by manufacturers and sellers to distinguish their products are
claimed as trademarks. Where those designations appear in this book, and the publisher was
aware of a trademark claim, the designations have been printed with initial capital letters or in
all capitals.
The authors and publisher have taken care in the preparation of this book, but make no
expressed or implied warranty of any kind and assume no responsibility for errors or omissions.
No liability is assumed for incidental or consequential damages in connection with or arising
out of the use of the information or programs contained herein.
The publisher offers excellent discounts on this book when ordered in quantity for bulk
purchases or special sales, which may include electronic versions and/or custom covers and
content particular to your business, training goals, marketing focus, and branding interests.
For more information, please contact:
U. S. Corporate and Government Sales
(800) 382-3419

For sales outside the U. S., please contact:


International Sales

Visit us on the Web: www.phptr.com
Library of Congress Cataloging-in-Publication Data:
CIP data on file.
© 2005 Pearson Education, Inc.
ISBN 0–13–143697-X
Text printed in the United States on recycled paper at Pheonix Color in Hagerstown Maryland.
First printing, November 2004
To my mother, for her love of words.
—Michael


To my wife, Cynthia.
—Carl

xxiPreface
xxviiIntroduction
1Getting Started PART I
3An Embarrassment of Riches: The Linux Environment Chapter 1
3What You Will Learn 1.1
4The Command Line: What’s the Big Deal? 1.2
5Basic Linux Concepts and Commands 1.3
6Redirecting I/O 1.3.1
9The ls Command 1.3.2
9Filenames 1.3.3
10Permissions 1.3.4
12File Copying 1.3.5
13Seeing Stars 1.3.6
15File Contents 1.3.7

19The grep Command 1.3.8
vii
Contents
20The find Command 1.3.9
21The Shell Revisited 1.3.10
26The tar and zip Commands 1.3.11
29The man Command 1.3.12
30Review 1.4
30What You Still Don’t Know 1.5
30Resources 1.6
33An Embarrassment of Riches: Editors Chapter 2
33What You Will Learn 2.1
34Eye to Eye with vi 2.2
40Exiting 2.2.1
41Search and Replace 2.2.2
43The Joy of Regular Expressions 2.2.3
44Starting Off Right: .exrc 2.2.4
45Editors Galore 2.3
47Editing Your Pipes (sed, the Stream EDitor) 2.3.1
47Simple Graphical Editors 2.3.2
49Review 2.4
49What You Still Don’t Know 2.5
49Resources 2.6
51An Experienced Programmer’s Introduction to Java Chapter 3
51What You Will Learn 3.1
52Fundamental Language Elements 3.2
53Scalar Types 3.2.1
57Object Types 3.2.2
65Statements 3.2.3
74Error Handling, Java Style 3.2.4

78print(), println(), printf() 3.2.5
82Using (and Making) Java APIs 3.3
82The package Statement 3.3.1
84The import Statement 3.3.2
85Encapsulation, Inheritance, and Polymorphism 3.4
85Encapsulation 3.4.1
86Inheritance 3.4.2
Contentsviii
91Polymorphism 3.4.3
93O, Templates! Where Art Thou? 3.5
94Virtually Final 3.6
95A Useful Simple Application 3.7
95Review 3.8
97What You Still Don’t Know 3.9
97Resources 3.10
98Exercises 3.11
99Where Am I? Execution Context Chapter 4
100What You Will Learn 4.1
100A Simple Start 4.2
100Command-Line Arguments 4.2.1
102Unit Testing Made Easy 4.2.2
102The System Class 4.3
102Java and Standard I/O 4.3.1
104Environment Variables 4.3.2
105Java and Environment Variables 4.3.3
109The Properties Class 4.4
111The Runtime Class 4.5
111exec() 4.5.1
113Portability 4.5.2
113Review 4.6

113What You Still Don’t Know 4.7
114Resources 4.8
115The Sun Microsystems Java Software Development Kit Chapter 5
116What You Will Learn 5.1
116All You Need, and Not One Thing More 5.2
117The Java Compiler 5.3
117Compiler Behavior, Defaults, and Environment Variables 5.3.1
119javac Options 5.3.2
121The Java Runtime Engine 5.4
121The Basics 5.4.1
122java Options 5.4.2
122Complete, Up-to-Date Program Documentation Made Easy 5.5
ixContents
123Running javadoc 5.5.1
124Javadoc Command-Line Options 5.5.2
128Javadoc Comments 5.5.3
131Dispensing with Applets 5.6
132Going Native 5.7
137Introducing RMI 5.8
137A Brief Introduction to RMI 5.8.1
143The rmic Tool 5.8.2
144The rmiregistry Tool 5.8.3
144Setting Up Servers and Clients 5.8.4
147RMI Summary 5.8.5
148The Java Debugger 5.9
157Return to the Source: The Java Decompiler 5.10
157Bundling a Java Program: Put It in a JAR 5.11
160Deploying Applications 5.11.1
163Basic jar Operation 5.11.2
164The Rest of the Toolkit 5.12

166Review 5.13
166What You Still Don’t Know 5.14
166Resources 5.15
167The IBM Developer Kit for Linux, Java 2 Technology Edition Chapter 6
167What You Will Learn 6.1
168
Use Linux Features to Make Multiple Java SDKs Play Nicely
Together
6.2
168Links 6.2.1
173Switching Java Versions by Symlink 6.2.2
174How the IBM JDK Differs from the Sun JDK 6.3
175Performance 6.3.1
175Differences in the Commands 6.3.2
175IBM Classes 6.3.3
176What Are All These “_g” Versions? 6.4
176Review 6.5
177What You Still Don’t Know 6.6
177Resources 6.7
Contentsx
179The GNU Compiler for Java (gcj) Chapter 7
179What You Will Learn 7.1
179A Brand GNU Way 7.2
180The GNU Compiler Collection 7.3
181Compiling Our Simple Application with gcj 7.4
182Compiling FetchURL with gcj 7.4.1
184Compiling a Multiclass Program 7.4.2
185Options and Switches 7.5
186Reasons to Use gcj 7.6
187Reasons Not to Use gcj 7.7

187Review 7.8
187What You Still Don’t Know 7.9
188Resources 7.10
189Know What You Have: CVS Chapter 8
190What You Will Learn 8.1
190Source Control: Whys and Hows 8.2
193Setup 8.2.1
195Import 8.2.2
198Normal Use 8.2.3
201Update 8.2.4
201Merges 8.2.5
203Log 8.2.6
205cvs status 8.2.7
205cvs tag 8.2.8
207Branching Tags 8.2.9
210cvs export 8.2.10
210A Quick Look behind the Scenes 8.2.11
211A GUI: jCVS 8.3
211Installing jCVS 8.3.1
213Review 8.4
214What You Still Don’t Know 8.5
214Resources 8.6
xiContents
215Ant: An Introduction Chapter 9
215What You Will Learn 9.1
216The Need for a Different Build Tool 9.2
217Obtaining and Installing Ant 9.3
217Installing a Binary Tarball 9.3.1
219Installing a Source Tarball 9.3.2
220A Sample Ant Buildfile 9.4

220XML for the Uninitiated 9.4.1
222The Buildfile Tags 9.4.2
229A Real, Live Buildfile 9.4.3
232Review 9.5
232What You Still Don’t Know 9.6
232Resources 9.7
235Integrated Development Environments Chapter 10
236What You Will Learn 10.1
236NetBeans: The Open Source IDE 10.2
236A Brief History of NetBeans 10.2.1
237Installing NetBeans 10.2.2
241Getting Around in NetBeans 10.2.3
245Integration with CVS 10.2.4
248Integration with Ant 10.2.5
250Other Add-on Tools 10.2.6
251SunONE Studio Community Edition 10.3
251Eclipse: The Source of SWT 10.4
251Selecting and Installing Eclipse 10.4.1
254Using Eclipse for a New Project 10.4.2
256Using Eclipse for an Existing Project 10.4.3
257Working with Eclipse 10.4.4
258Review 10.5
259What You Still Don’t Know 10.6
259Resources 10.7
Contentsxii
261Developing Business Logic PART II
263Balancing Acts: An Imaginary Scenario Chapter 11
263What You Will Learn 11.1
264Statement of the Need 11.2
264How to Develop Software 11.3

267What Makes a Good Requirement 11.4
268Whom to Ask for Requirements 11.5
269Requirements for the Budget Application 11.6
269Monday Morning, 10 A.M. 11.6.1
272Back at His Desk 11.6.2
272Documenting, Prototyping, and Stakeholder Buy-In 11.7
272Documenting 11.7.1
274Stakeholder Buy-In 11.7.2
275Prototyping 11.7.3
276Review 11.8
276What You Still Don’t Know 11.9
276Resources 11.10
277Exercises 11.11
279Analysis and Design: Seeking the Objects Chapter 12
279What You Will Learn 12.1
280Facing the Blank Page 12.2
280Using CRC Cards 12.3
280Finding the Objects 12.4
283Finding the Methods and Attributes 12.5
284Essential and Nonessential 12.6
287Analysis Paralysis 12.7
288Real Software Engineering 12.8
289Core Classes 12.9
289Review 12.10
289What You Still Don’t Know 12.11
289Resources 12.12
292Exercises 12.13
xiiiContents
295JUnit: Automating Unit Testing Chapter 13
295What You Will Learn 13.1

296JUnit: Why All the Fuss? 13.2
296Design Then Test Then Code 13.3
297Installing and Running JUnit 13.4
299Downloading and Unzipping 13.4.1
301Using JUnit 13.4.2
303Writing Test Cases 13.5
306JUnit Assertions 13.5.1
308Running a Test Case 13.5.2
309Running Test Suites 13.6
312Review 13.7
312What You Still Don’t Know 13.8
313Resources 13.9
313Exercises 13.10
315Storing the Data Chapter 14
315What You Will Learn 14.1
316Follow the Objects 14.2
316Of Persistence 14.3
316Thinking of the Future, or Painting in Corners 14.4
316Oracle, PostgreSQL, MySQL 14.5
317MySQL 14.5.1
317PostgreSQL 14.5.2
318Oracle 14.5.3
318Selection Criteria 14.5.4
318Being Self-Contained 14.6
319Beyond the Basics 14.7
322Persistence Is Not the Whole Story 14.8
322Setting Up PostgreSQL for BudgetPro 14.9
322Installing PostgreSQL 14.9.1
323Creating a postgres User 14.9.2
324Creating Our Database 14.9.3

325Straight JDBC 14.9.4
325Review 14.10
Contentsxiv
326What You Still Don’t Know 14.11
326Resources 14.12
326Exercises 14.13
327Accessing the Data: An Introduction to JDBC Chapter 15
327What You Will Learn 15.1
328Introducing JDBC 15.2
329Making Connections 15.3
332Downloading JDBC for MySQL 15.3.1
332Querying Data 15.4
334Getting Results 15.5
336Updates, Inserts, Deletes 15.6
336Review 15.7
336What You Still Don’t Know 15.8
337Resources 15.9
338Exercises 15.10
339Developing Graphical User Interfaces PART III
341
Getting in the Swing of Things: Designing a GUI for
BudgetPro
Chapter 16
341What You Will Learn 16.1
342A Simple Swing Program 16.2
343Stompin’ at the Savoy, or The Swing Paradigm 16.3
345Slow, Slow, Quick-Quick, Slow: The Basic Swing Objects 16.4
347Layout Managers 16.5
348Beyond Arthur Murray: Actions, Listeners, Events 16.6
348Getting Down to Cases: Designing a GUI for BudgetPro 16.7

350Overview 16.7.1
352Creating Pieces 16.7.2
373Review 16.8
374What You Still Don’t Know 16.9
375Resources 16.10
375Exercises 16.11
xvContents
377Other Ways: Alternatives to Swing Chapter 17
377What You Will Learn 17.1
378The IBM SWT Toolkit 17.2
378Another GUI Toolkit. Why? 17.2.1
379Duplicated Effort. Why Cover It? 17.2.2
380Portability: Better and Worse 17.2.3
380The Rest of the Chapter 17.2.4
380SWT: Close to the Metal 17.2.5
381“Hello, world” SWT Style 17.2.6
384Porting BudgetPro to SWT 17.3
387Step 1: Convert the Class Members 17.3.1
389Step 2: Converting the main() Method 17.3.2
391
Step 3: Converting the GUI build() and init()
Methods
17.3.3
394Completing the Conversion of the BudgetPro Class 17.3.4
395Completing the Conversion of the Application 17.3.5
395Closing Thoughts 17.3.6
396SWT and gcj 17.4
398Review 17.5
398What You Still Don’t Know 17.6
398Resources 17.7

399Exercises 17.8
401Developing Web Interfaces PART IV
403Servlets: Java Pressed into Service Chapter 18
403What You Will Learn 18.1
404Servlets: Program-Centric Server-Side Documents 18.2
405Perspective 18.3
407How to Write a Servlet 18.4
411Input, Output 18.5
413
Matters of State: Cookies, Hidden Variables, and the Dreaded
“Back” Button
18.6
414Cookies 18.6.1
416Designing a BudgetPro Servlet 18.7
Contentsxvi
416Prototype 18.7.1
417Design 18.7.2
420Review 18.8
420What You Still Don’t Know 18.9
421Resources 18.10
421Exercises 18.11
423JSP: Servlets Turned Inside Out Chapter 19
424What You Will Learn 19.1
424Servlets Turned Inside Out: JSP 19.2
426How to Write a JSP Application 19.3
427Scriptlet 19.3.1
429Declaration 19.3.2
430Expression 19.3.3
431Directive 19.3.4
434New Syntax 19.3.5

434JavaBeans in JSP 19.3.6
437Tag Libraries 19.3.7
438Using JSP with BudgetPro 19.4
439Review 19.5
440What You Still Don’t Know 19.6
440Resources 19.7
441Exercises 19.8
443Open Source Web Application Servers Chapter 20
443What You Will Learn 20.1
444Downloading JBoss 20.2
444Be an Enabler, or “Let’s Be Codependent!” 20.3
445Nonroot-Installed Software 20.3.1
450Finer Grained Control 20.3.2
450Installing JBoss 20.4
451Things That Make It Go 20.5
451System V Init System 20.5.1
458RedHat/Fedora chkconfig 20.5.2
463Other Distributions 20.5.3
464IDE Integration 20.5.4
xviiContents
464Disposition of Forces 20.6
464Apache Geronimo 20.7
467Installing Geronimo 20.8
468Running the Geronimo Server 20.9
468Review 20.10
469What You Still Don’t Know 20.11
469Resources 20.12
471Developing Enterprise Scale Software PART V
473Introduction to Enterprise JavaBeans Chapter 21
473What You Will Learn 21.1

473Expanding to EJBs 21.2
474EJB Concepts 21.2.1
477Bean Types 21.2.2
482Under the Hood 21.2.3
482What’s in a Name? An Introduction to JNDI 21.3
482Naming and Directory System Concepts 21.3.1
484Common Directory Services 21.3.2
487Putting a Face to a Name: JNDI 21.3.3
491Using JNDI with JBoss 21.3.4
491Review 21.4
492What You Still Don’t Know 21.5
492Resources 21.6
493Building an EJB Chapter 22
493What You Will Learn 22.1
493EJBs: You Don’t Know Beans? 22.2
495SessionBean 22.2.1
497EJBObject 22.2.2
498EJBHome 22.2.3
499Summarizing the Pieces 22.2.4
499EJBLocalHome and EJBLocalObject 22.2.5
501Compiling Your Beans 22.2.6
502Review 22.3
Contentsxviii
502What You Still Don’t Know 22.4
503Resources 22.5
505Deploying EJBs Chapter 23
505What You Will Learn 23.1
506Lend Me Your EAR: Enterprise Packaging and Deployment 23.2
508What’s in an EJB-JAR File 23.2.1
511Using Our Bean 23.2.2

512Packaging the Servlet 23.2.3
514Deploying the EAR 23.3
515JBoss 23.3.1
515Geronimo 23.3.2
516Maintaining a Distributed Application 23.4
516Ant and CVS 23.4.1
517XDoclet 23.4.2
518Abstracting Legacy Applications 23.5
518Review 23.6
519What You Still Don’t Know 23.7
519Resources 23.8
521Parting Shots Chapter 24
521The Future’s So Bright, I Squint and Look Confused 24.1
522Our Book Is Yours 24.2
522Came the Revolution 24.3
523What You Still Don’t Know 24.4
523Resources 24.5
525ASCII Chart Appendix A
527A Java Swing GUI for BudgetPro Appendix B
539GNU General Public License Appendix C
549Index
xixContents

JAVA AND LINUX
Why another book on Java? Why a book on Java and Linux? Isn’t Java a plat-
form-independent system? Aren’t there enough books on Java? Can’t I learn
everything I need to know from the Web?
No doubt, there are a host of Java books on the market. We didn’t wake
up one morning and say, “You know what the world really needs? Another book
about Java!” No. What we realized was that there are a couple of “holes” in the

Java book market.
First, Linux as a development platform and deployment platform for Java
applications has been largely ignored. This is despite the fact that the *nix
platform (meaning all UNIX and UNIX-like systems, Linux included) has long
been recognized as one of the most programmer-friendly platforms in existence.
Those few resources for Java on Linux that exist emphasize tools to the exclu-
sion of the Java language and APIs.
Second, books on the Java language and APIs have focused on pedagogical
examples that serve to illustrate the details of the language and its libraries, but
very few of these examples are in themselves practically useful, and they tend
Preface
xxi
to deal only with the issues of writing programs, and not at all with deploying
and maintaining them. Anyone who has worked on a major software project,
especially a software project that is developed and deployed in a business for a
business, knows that designing and coding are only about half of the work in-
volved. Yes, writing Java code is only slightly affected by the development and
the deployment platform, but the process of releasing and maintaining such
applications is significantly different between platforms.
To address these missing pieces, we decided to cover development and
deployment of a Java application that has command-line, GUI, servlet, and
enterprise components on a Linux platform. We’re writing the guide book we
wish we had had when we started writing and deploying Java applications on
Linux. We’re going to show you a simplistic enterprise application, “from cradle
to grave,” but along the way cover issues of design process, production environ-
ment, setup, administration, and maintenance that few books bother to cover.
1
If you are considering buying this book and you are wondering if there is
any information in here that you can’t get for free on the Web, then, no. There
is not. In fact, there is little information in any Java or Linux book that is not

available for free on the Internet. In fact, in each of our chapters we will tell
you where on the Web to find virtually all of the information we present, and
then some. And yet books continue to sell, and we have the chutzpah to ask
you to buy the book. The reason is that Web information is scattered, unorga-
nized, and of highly variable quality. We will be trying to bring all the relevant
information together in this book, in a clearly organized manner (and, we
would like to believe, at an acceptably high level of quality). We think that
has value.
Also, this book is part of the Bruce Perens’ Open Source Series. This book
is part of the Web literature. And you may freely read it and use it on the Web.
We hope this book will be one of those you use on the Web and buy on paper.
We don’t know about you, but we like to use Web books for reference, but for
reading, we like books. We own at least three books that are available for free
on the Web: Thinking in C++, Thinking in Java, and O’Reilly’s Docbook: The
Definitive Guide. We hope that open publishing will be the new model.
1. This is not to say this book is without purely pedagogical examples. Especially in Part I we
make use of your typical “throwaway” examples and single classes. To try to illustrate the basics
with a complete application would obscure and confuse the points being illustrated.
Prefacexxii
FREE SOFTWARE AND JAVA
GNU/Linux
2
is Free Software. It is Open Source. I don’t even want to start
the debate on what each term means and which one is “right.” One of the two
authors of this book is a Free Software advocate, and the other is of a purely
laissez-faire attitude towards the question (we won’t tell you which, although
we invite you to guess). But even with a deliberate decision to cease-fire, the
question remains: Is Java Open Source or Free Software?
The answer is mixed. Neither Sun’s nor IBM’s Java implementations are
Open Source or Free Software. You may download and use them for free, but

you do not have the source code to them, nor do you have the right to make
modifications to them.
3
This book will cover the GNU Compiler for Java,
which compiles Java source code to native machine code. The GNU Compiler
for Java (gcj) is both Open Source and Free Software. It is, however, supporting
differing levels of the Java APIs (some packages are current, some are back at
1.1.x levels) and does not fully support the AWT or Swing GUIs.
However, none of this means that you cannot write your own Java pro-
grams and release them under a Free Software or Open Source license. So you
can certainly develop Free Software in Java. Staunch Free Software partisans
(such as Richard Stallman and the Free Software Foundation) would question
the wisdom of doing so. Their argument would be that a Free Software product
that depends on non-Free tools isn’t really Free Software, since to compile, use,
or modify it, you need to make use of a proprietary tool.
There is more than one effort to produce a Free Software Java runtime
implementation. None of them is “ready for prime time.” It would, in our
opinion, be a very good thing for Sun to release their SDK and Java Virtual
Machine as Free Software. But so far, they have steadily resisted calls to do so.
2. This is the only time we will refer to it as “GNU/Linux.” See Section 7.3 for the story of
why GNU/Linux is the preferred name of some. We understand Stallman and the FSF’s posi-
tion, but “Linux” is much easier on the eyes and ears than “GNU/Linux.” And that, not prin-
ciple, is how names and words go into the language. For better or for worse, “Linux” is the
name of the operating system.
3. As we write this, a very public discussion is taking place between Sun, IBM, and Eric Ray-
mond, founder of the Open Source Initiative, about opening Java under some sort of open
source license. At this time, no one knows how this will turn out, but it is possible that Java
will be Free Software in the future.
xxiiiPreface
The fact, however, that two distinct vendors (Sun and IBM) produce ef-

fectively interchangeable development and runtime environments reduces some
of the risk that you face when you select a platform available only from a single
vendor who does not provide source code.
So, to put the case firmly: Java is free for use, but it is certainly not Free
Software as defined in The GNU Manifesto
4
or the GNU General Public Li-
cense.
5
This is a political and philosophical issue of interest only to those
aforementioned Free Software partisans. For the rest of us, this has no bearing
on Java’s technical or business merits. As for us, obviously we like the language
or we wouldn’t be writing about it.
YOU CAN HELP!
This book is part of the Bruce Perens’ Open Source Series. Shortly after this
book is published in dead-tree form, it will be on the Web,
6
free for use, redis-
tribution, and modification in compliance with the terms of the Open Publica-
tion License,
7
with no options taken. You can immediately create your own
version as permitted in that license.
Naturally enough, we plan to maintain our “official” version of the online
book, so we encourage you to send suggestions, corrections, extensions, com-
ments, and ideas to us. Please send any such to

and we will try to keep our little tome up-to-date so it continues to serve the
needs of the Java and Linux development communities.
ACKNOWLEDGMENTS

First off, we naturally wish to thank Mark L. Taub, our acquisitions editor at
Prentice Hall PTR, for believing in the book and in open publishing as the way
to put it out there. We also want to thank Bruce Perens for lending his name
and powers of persuasion to open-content publishing through the Prentice Hall
PTR Bruce Peren’s Open Source Series. Thanks, too, to Patrick Cash-Peterson
4. />5. />6. />7. />Prefacexxiv
and Tyrrell Albaugh, who worked as our in-house production contacts, for all
the behind-the-scenes work they did, including overseeing the cover.
In more direct terms of content, we owe major thanks to Kirk Vogen of
IBM Consulting in Minneapolis for his article on using SWT with gcj, and
for his kind help in allowing us to use the ideas he first presented in his IBM
developerWorks articles. In more direct terms of content, we owe major thanks
to: Kirk Vogen of IBM Consulting in Minneapolis for his article on using SWT
with gcj, and for his kind help in allowing us to use ideas he first presented in
his IBM developerWorks articles; and to Deepak Kumar
8
for graciously allow-
ing us to base our
build.xml file for EJBs off of a version that he wrote.
Thanks, too, to Andrew Albing for his help in drawing some of our dia-
grams, and to George Logajan and to Andy Miller for sharing their insights on
the more intricate details of Swing.
We also wish to express our great indebtedness to our technical reviewers,
especially Andrew Hayes, Steve Huseth, and Dan Moore. A very large thank-
you is also due to Alina Kirsanova whose eye for detail, endless patience, and
tenacity, and overall talent with proofing, layout, and more added so much
refinement and improvement to the book. We are greatful for all their contri-
butions. Any errors or omissions in this text are our fault and certainly not
theirs. The book is much stronger for all their efforts.
There are likely many more people we ought to thank, especially those at

Prentice Hall PTR, whose names and contributions we may never know, but
we do know that this was an effort of many more people than just the authors,
and we are grateful to them all.
8. />xxvPreface

×