Вы находитесь на странице: 1из 8

16 Предисловие

Условные обозначения
Как это принято во многих компьютерных книгах, моноширинный шрифт исполь­
зуется для представления исходного кода.

НА ЗАМЕТКУ! Этой пиктограммой выделяются примечания.

СОВЕТ. Этой пиктограммой выделяются советы.

ВНИМАНИЕ! Этой пиктограммой выделяются предупреждения о потенциальной опасности.

НА ЗАМЕТКУ C++! В этой книге имеется немало примечаний к синтаксису C++, где разъясняются
отличия между языками Java и C++. Вы можете пропустить их, если у вас нет опыта программи­
рования на C++ или же если вы склонны воспринимать этот опыт как страшный сон, который
лучше забыть.

Язык Java сопровождается огромной библиотекой в виде прикладного программ­


ного интерфейса (API). При упоминании вызова какого-нибудь метода из приклад­
ного интерфейса API в первый раз в конце соответствующего раздела приводится его
краткое описание. Эти описания не слишком информативны, но, как мы надеемся,
более содержательны, чем те, что представлены в официальной оперативно доступ­
ной документации на прикладной интерфейс API. Имена интерфейсов выделены
полужирным, как это делается в официальной документации. А число после имени
класса, интерфейса или метода обозначает версию JDK, в которой данное средство
было внедрено, как показано ниже.

Н а з в а н и е п р и к л а д н о г о п р о г р а м м н о г о и н т е р ф е й с а 1 .2

Программы с доступным исходным кодом организованы в виде примеров, как по­


казано ниже.

Листинг 1.1. Исходный код из файла ScriptTest. jav a

Примеры исходного кода


Все примеры исходного кода, приведенные в этом томе в частности и в данной
книге вообще, доступны в архивированном виде на посвященном ей веб-сайте по
адресу h ttp : / /horstm ann. с о т /co reja v a .
46 Глава 1 ■ Потоки ввода-вывода и файлы

in.seek((n - 1) * RECORD_SIZE);
e .writeData(out);

Для определения общего количества байтов в файле служит метод length (). Об­
щее количество записей определяется путем деления длины файла на размер каж­
дой записи:
long nbytes ® in.length(); // длина файла в байтах
int nrecords = (int) (nbytes / RECORD_SIZE);

Целочисленные значения и числовые значения с плавающей точкой имеют фик­


сированный размер в двоичном формате, тогда как с символьными строками дело
обстоит немного сложнее. Для записи и чтения символьных строк фиксированного
размера придется ввести два вспомогательных метода. В частности, приведенный
ниже метод writeFixedString () записывает указанное количество кодовых единиц,
отсчитывая от начала символьной строки. (Если кодовых единиц слишком мало, сим­
вольная строка дополняется нулевыми значениями.)
public static void writeFixedString(String s, int size, DataOutput out)
throws IOException
{
for (int i = 0; i < size; i++)
{
char ch = 0;
if (i < s.length()) ch = s.charAt(i);
out.writeChar(ch);
}
}
А приведенный ниже метод readFixedString () считывает символы из потока
ввода (типа InputStream) до тех пор, пока не прочитает указанное в качестве пара­
метра size количество кодовых единиц или пока не встретится символ с нулевым
значением. В последнем случае все остальные нулевые значения в поле ввода про­
пускаются. Для повышения эффективности чтения символьных строк в этом методе
используется класс StringBuilder.
public static String readFixedString(int size, Datalnput in)
throws IOException
{
StringBuilder b = new StringBuilder(size);
int i = 0;
boolean more = true;
while (more && i < size)
{
char ch = in.readChar();
i++;
if (ch == 0) more = false;
else b .append(ch);
}
in.skipBytes(2 * (size - i));
return b .toString();
}
Методы writeFixedString () и readFixedString () введены во вспомогатель-
ный класс DatalO. Для сохранения записи фиксированного размера все поля просто
записываются в двоичном формате следующим образом:
Пример интернационализации прикладной программы 347

398 }
399
400 /**
401 * Устанавливает предполагаемую продолжительность жизни
402 * Oparam newValue Предполагаемая продолжительность жизни
403 */
404 public void setDeathAge(int newValue)
405 {
406 deathAge = newValue;
407 }
408
409 /**
410 * Получает предполагаемый уровень инфляции в процентах
411 * @return Возвращает уровень инфляции в процентах
412 */
413 public double getlnflationPercent()
414 {
415 return inflationPercent;
416 }
417
418 /**
419 * Устанавливает предполагаемый уровень инфляции в процентах
420 * Oparam newValue Уровень инфляции в процентах
421 */
422 public void setlnflationPercent(double newValue)
423 {
424 inflationPercent = newValue;
425 }
426
427 /**
428 * Получает предполагаемый доход от капиталовложений
429 * @return Возвращает доход от капиталовложений
430 */
431 public double getlnvestPercent()
432 {
433 return investPercent;
434 }
435
436 /**
437 * Устанавливает предполагаемый доход от капиталовложений
438 * Oparam newValue Доход от капиталовложений в процентах
439 */
440 public void setlnvestPercent(double newValue)
441 {
442 investPercent = newValue;
443 }
444 }
445
446 /**
447 * Этот компонент рисует график результатов пенсионных вложений
448 */
449 class RetireComponent extends JComponent
450 {
451 private static final int DEFAULT_WIDTH = 800;
452 private static final int DEFAULT_HEIGHT = 600;
453 private static final int PANEL_WIDTH = 400;
454 private static final int PANEL_HEIGHT = 200;
Таблицы 401

5 import javax.swing.table.*;
6
7 /**
8 * Этот фрейм содержит таблицу с данными о планетах
9 */
10 public class TableCellRenderFrame extends JFrame
11 {
12 private static final int DEFAULT_WIDTH = 600;
13 private static final int DEFAULT_HEIGHT = 400;
14
15 public TableCellRenderFrame()
16 {
17 setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
18
19 TableModel model = new PlanetTableModel();
20 JTable table = new JTable(model);
21 table.setRowSelectionAllowed(false);
22
23 // установить средства воспроизведения и
24 // редактирования ячеек таблицы
25 table.setDefaultRenderer(
26 Color.class, new ColorTableCellRenderer());
27 table.setDefaultEditor(Color.class, new ColorTableCellEditor());
28
29 JComboBox<Integer> moonCombo = new JComboBoxo();
30 for (int i = 0; i <= 20; i++)
31 moonCombo.addltem(i);
32
33 TableColumnModel columnModel = table.getColumnModel();
34 TableColumn moonColumn =
35 columnModel.getColumn(PlanetTableModel.MOONS_COLUMN);
36 moonColumn.setCellEditor(new DefaultCellEditor(moonCombo));
37 moonColumn.setHeaderRenderer(
38 table.getDefaultRenderer(Imagelcon.class));
39 moonColumn.setHeaderValue(
40 new Imagelcon(getClass().getResource("Moons.gif")));
41
42 // показать таблицу
43 table.setRowHeight(100);
44 add(new JScrollPane(table), BorderLayout.CENTER);
45 }
46 }

Л и с т и н г 6 . 9 . Исходный код из файла tableCellRender/PlanetTableModel .java 1

1 package tableCellRender;
2
3 import java.awt.*;
4 import javax.swing.*;
5 import javax.swing.table.*;
6
7 /**
8 * Модель таблицы планет, определяющая значения, свойства
9 * воспроизведения и редактирования данных о планетах
10 */
11 public class PlanetTableModel extends AbstractTableModel
12 {
Индикаторы состояния 479

101 url.setText(urlString);
102 editorPane.se,tPage (urlString);
103 }
104 catch (IOException e)
105 {
106 editorPane.setText("Exception: " + e);
107 }
108 }
Ю9 });
110
111 add(new JScrollPane(editorPane), BorderLayout.CENTER);
112
113 // разместить все элементы управления на панели
114
115 JPanel panel = new JPanelO;
116 panel.add(new JLabel("URL"));
117 panel.add(url);
118 panel.add(loadButton);
119 panel.add(backButton);
120 panel.add(new JLabel("Editable"));
121 panel.add(editable);
1,22
123 add(panel, BorderLayout.SOUTH) ;
124 }
125 }

javax.swing.JEditorPane 1.2

• void setPage(URL url)


Загружает на панели редактирования веб-страницу по указанному URL.
• void addHyperlinkListener(HyperLinkListener listener)
• Добавляет к панели редактирования приемник событий от гипертекстовых ссылок.

j a v a x .s w i n g .e v e n t .HyperlinkListener 1.2

• void hyperlinkUpdate(HyperlinkEvent event)


Вызывается всякий раз, когда выбирается гипертекстовая ссылка.

javax.swing.event.HyperlinkEvent 1.2

• URL getURL()
Возвращает URL по выбранной гипертекстовой ссылке.

Индикаторы состояния
В этом разделе рассматриваются три класса, предназначенные для отобра­
жения хода выполнения длительных заданий и процессов. В частности, класс
J P r o g r e s s B a r — это компонент Swing, который наглядно представляет ход
570 Глава 7 ■ Расширенные средства AWT

58 {
59 canvas.setAlpha(alphaSlider.getValue());
60 }
61 }) ;
62 JPanel panel = new JPanelO;
63 panel.add(ruleCombo);
64 panel.add(new JLabel("Alpha"));
65 panel.add(alphaSlider);
66 add(panel, BorderLayout.NORTH);
67
68 explanation = new JTextFieldO;
69 add(explanation, BorderLayout.SOUTH);
70
71 canvas.setAlpha(alphaSlider.getValue());
72 Rule r = ruleCombo.getItemAt(ruleCombo.getSelectedlndex());
73 canvas.setRule(r.getValue());
74 explanation.setText(r .getExplanation());
75 }
76 }

Л и с т и н г 7 . 4 . Исходный код из файла composite/CompositeComponent.java1

1 package composite;
2
3 import java.awt.*;
4 import java.awt.geom.*;
5 import java.awt.image.*;
6 import javax.swing.*;
7
8 /**
9 * Этот компонент рисует две формы, составленные по правилу композиции
10 */
11 class CompositeComponent extends JComponent
12 {
13 private int rule;
14 private Shape shapel;
15 private Shape shape2;
16 private float alpha;
17
18 public CompositeComponent()
19 {
20 shapel = new Ellipse2D.Double(100, 100, 150, 100);
21 shape2 = new Rectangle2D.Double(150, 150, 150, 100);
22 }
23
24 public" void paintComponent (Graphics g)
25 {
26 Graphics2D g2 = (Graphics2D) g;
27
28 Bufferedlmage image = new Buf feredlmage (getWidth (), getHeightO,
29 Bufferedlmage.TYPE_INT_ARGB);
30 Graphics2D glmage = image.createGraphics();
31 glmage.setPaint(Color.red);
32 glmage.fill(shapel);
33 AlphaComposite composite = AlphaComposite.getInstance(rule, alpha);
34 glmage.setComposite(composite);
35 glmage.setPaint(Color.blue);
36 glmage.fill(shape2);
Аутентификация пользователей 793

java.security.Permission 1.2

• P erm ission (S trin g nam e)

Создает полномочия с указанным именем целевого объекта.


• S trin g getN am e()

Возвращает имя целевого объекта для данных полномочий.


• boolean im p lies(Perm ission other)

Проверяет, предполагают ли данные полномочия другие полномочия. Это имеет место в том слу­
чае, если в других полномочиях описывается более конкретное условие, вытекающее из условия,
указанного в данных полномочиях.

Аутентификация пользователей
Начиная с версии Java SE 1.4 в состав платформы Java входит JAAS (Java
Authentication and Authorization Service — служба аутентификации и авторизации
Java ). Слово "Authentication" в названии этой службы указывает на возможность опо­
знавания пользователей программ, а слово "Authorization" — на возможность провер­
ки их полномочий.
Служба JAAS, по существу, представляет собой встраиваемый прикладной интер­
фейс API, отделяющий прикладные программы на Java от конкретной технологии,
применяемой для реализации средств аутентификации. Помимо прочего, эта служ­
ба поддерживает механизмы регистрации в UNIX и NT, механизм аутентификации
Kerberos и механизмы аутентификации по сертификатам.
После аутентификации за пользователем может быть закреплен определенный
набор полномочий. Ниже приведен пример, в котором пользователю h a r r y предо­
ставляется особый ряд полномочий, которых нет ни у кого из других пользователей.
grant p rin cip al co m .su n .se cu rity .a u th .U n ix P rin cip a l "harry”
{
p erm ission j a v a . u t i l . P ropertyPerm ission "u se r.*", "read";
• • •

};
В данном пример класс c o m . s u n . s e c u r i t y . a u t h . U n i x P r i n c i p a l выполня­
ет проверку имени запускающего данную программу пользователя UNIX. Ме­
тод g e t N a m e () из этого класса возвращает имя пользователя, зарегистрированное
в UNIX, которое затем сравнивается на равенство с именем h a r r y .
Для того чтобы предоставить диспетчеру защиты возможность проверить пра­
вильность предоставления таких полномочий, служит класс L o g i n C o n t e x t . Ниже
приведена общая структура кода регистрации.
try
{
S ystem .setS ecu rity M an ag er(n ew S e cu rity M a n a g e r( ) ) ;
L o g i n C o n t e x t c o n t e x t = new L o g i n C o n t e x t ( " L o g i n l " ) ; / / о п р е д е л я е т с я в
/ / к о н ф и г у р а ц и о н н о м ф а й л е с л у ж б ы JAAS
c o n te x t. login ();
/ / получить аутентифицированный объект типа S u b j e c t
Subject subject = c o n te x t. getS u b ject ();
88 Глава 10 ■ Создание сценариев, компиляция и обработка аннотаций

подклассы этого класса будут автоматически аннотироваться как сохраняемые следу­


ю щ и м образом:
@Inherited @interface Persistent { }
©Persistent class Employee { . . . }
class Manager extends Employee { . . . } / / также ©Persistent
П р и поиске объектов, сохраняемых в базе данных, механизм сохраняемости будет
обнаруживать как объекты типа Employee, так и объекты типа Manager.

Обработка аннотаций на уровне исходного кода


О д н о й из сфер применения аннотаций является автоматическое генерирование
так называемых "сопроводительных файлов", с о д е р ж а щ и х дополнительные сведения
о программах. Пользуясь р а н н и м и версиями Java Enterprise Edition, программисты
в ы н у ж д е н ы б ы л и иметь дело с б о л ь ш и м и объ е м ам и шаблонного кода. А в современ­
н ы х версиях Java ЕЕ доступны аннотации, п о з в о л я ю щ и е значительно упростить м о ­
дель программирования.
В этом разделе у п о м я н у т ы й в ы ш е подход демонстрируется на прим ер е простой
программы, которая автоматически генерирует классы и н ф о р м а ц и и о компонентах
JavaBeans. Свойства компонентов JavaBeans снабжаются аннотациями, после чего за­
пускается инструментальное средство, в ы п о л н я ю щ е е синтаксический анализ исход­
ного файла и всех аннотаций, записывая результат в исходный ф а й л класса и н ф о р ­
м а ц и и о компоненте JavaBeans.
Как упоминалось в главе 8, класс и н ф о р м а ц и и о компоненте JavaBeans описывает
этот компонент точнее, чем это м о ж н о сделать в ходе автоматического самоанализа.
О н выдает перечень всех свойств компонента JavaBeans. Э т и свойства могут обладать
необязательными редакторами свойств. Т и п и ч н ы м т ому п р и м е р о м служит класс
ChartBeanBeanlnfo, рассматривавшийся в главе 8.
Д л я того чтобы избежать утомительной работы по написанию классов и н ф о р м а ­
ц и и о компонентах JavaBeans, в рассматриваемом здесь п р и м е р е вводится аннота­
ция ©Property. Такой аннотацией м о ж н о снабдить метод получения и л и установки
свойства, как показано ниже.
©Property String getTitleO { return title; }

ИЛИ

©Property(editor="TitlePositionEditor”)
public void setTitlePosition(int p) { titlePosition = p; }
Определение аннотации ©Property представлено в листинге 10.12. Следует заме­
тить, что на эту аннотацию распространяется правило сохрняемости, которому соот­
ветствует значение константы SOURCE. Это означает, что аннотация м о ж е т анализи­
роваться только на уровне исходного кода. О н а не включается в ф а й л ы классов и не
доступна во время рефлексии.

Листинг 10.12. Исходный код из файла sourceAnnotations/Property.java4


3
2
1

1 package sourceAnnotations;
2 import java.lang.annotation.*;
3
4 ©Documented

Вам также может понравиться