может включать следующие атрибуты.
• •
ALIGN - выравнивание текста в ячейках строки. Значения аналогичны значениям для таблицы. VALIGN - вертикальное выравнивание текста в ячейках строки. Допустимые значения: TOP (выравнивание по верхнему краю), MIDDLE (по центру), BOTTOM (по нижнему краю).
Каждая ячейка таблицы находится между тегами … . Тег может включать следующие атрибуты.
• • • • • • •
NOWRAP - присутствие этого атрибута означает, что содержимое ячейки должно быть показано в одну строку. COLSPAN - размер ячейки в колонках по горизонтали. Например, COLSPAN=3 означает, что ячейка простирается на три колонки. ROWSPAN - размер ячейки в строках по вертикали. Например, ROWSPAN=2 означает, что ячейка занимает две строки. ALIGN - выравнивание текста в ячейке. Значения аналогичны значениям для таблицы. VALIGN - вертикальное выравнивание текста в ячейке. Значения аналогичны значениям для строки. WIDTH - ширина ячейки в пикселях, например, WIDTH=200. HEIGHT - высота ячейки в пикселях, например, HEIGHT=40.
Если ячейка таблицы пуста, вокруг нее не рисуется рамка. Если ячейка пуста, а рамка нужна, в ячейку можно ввести символьный объект (non-breaking space — не разрывающий пробел). Ячейка по-прежнему будет пустой, а рамка вокруг нее будет. Любая ячейка таблицы может содержать в себе другую таблицу. Пример 1. Таблица в HTML-документе. <TITLE> Пример таблицы Простейшая таблица Заголовок таблицы Первая строка, первая колонка Первая строка, вторая колонка Вторая строка, первая колонка
© InterTrust Co. Тел. 956-7928
16
Введение в HTML
Вторая строка, вторая колонка
Рис. 2.7 Таблица в HTML-документе
2.3.
Формы в документах HTML 2.3.1. Использование форм
Формы используются для передачи информации от клиента серверу. В качестве такой информации могут выступать строки текста, как непосредственно введенные пользователем, так и выбранные им из списка значений, и файлы. Информация передается программе – обработчику данных. В качестве обработчика данных может выступать CGI-скрипт, специальное расширение Web-сервера (ISAPI для Microsoft Internet Information Server, GWAPI для Lotus Go Web Server и т.п.), Java сервлет, программа на Perl, Microsoft Server Pages и т.п. Броузер передает информацию из форм обработчикам в виде пар ПЕРЕМЕННАЯ=ЗНАЧЕНИЕ. Мы не будем подробно останавливаться на создании обработчиков информации. Информацию о создании CGI-скриптов и Java сервлетов вы найдете в следующих главах этой книги, а о создании прочих типов обработчиков сможете прочесть в соответствующей литературе.
2.3.2. Создание форм Элементы формы содержатся внутри парных тегов . В качестве элементов форм выступают поля ввода, списки, переключатели, кнопки и другие элементы. Тег
Рис. 2.8 Пример простой формы
2.3.3. Элементы форм Существуют следующие элементы форм.
• • • • • •
Текстовое однострочное поле ввода. Текстовое многострочное поле ввода. Поле для ввода пароля (все вводимые символы заменяются «звездочками»). Переключатели (Radio Buttons). Позволяют выбрать одно из возможных значений. Опция (Check Box). Позволяет выбрать несколько значений (или ни одного). Меню. Позволяют выбрать одно или несколько (в зависимости от установленного атрибута MULTIPLE) из возможных значений. Меню с выбором одного пункта обычно отображаются броузером в виде выпадающих списков, а с выбором нескольких пунктов – в виде обычного списка.
© InterTrust Co. Тел. 956-7928
18
• • • • •
Введение в HTML
Скрытый элемент. На экране не изображается, используется для хранения значений. Файл. Используется для передачи файла от броузера на сервер. Кнопка, при нажатии на которую, данные из формы отсылаются обработчику информации (Submit). Кнопка, удаляющая введенные данные из формы (Reset). Изображение. Функции те же, что и у кнопки типа Submit, но обработчику информации передаются координаты мыши при выборе изображения. Может использоваться для создания интерактивных карт и т.п.
Большинство элементов форм создается с помощью одинарного тега , имеющему три основных атрибута: TYPE, VALUE и NAME. Атрибут TYPE задает тип элемента формы, VALUE его значение по умолчанию, а NAME его имя, которое будет передано обработчику информации вместе со значением. Значение атрибута TYPE TEXT PASSWORD
Элемент формы Текстовое однострочное поле ввода Поле для ввода пароля
RADIO
Переключатели
CHECKBOX
Опция
HIDDEN
Скрытый элемент
FILE
Файл
SUBMIT
Кнопка отправки информации
RESET
Кнопка сброса
IMAGE
Изображение
Дополнительные атрибуты SIZE определяет ширину поля для ввода MAXLENGTH определяет максимальную длину вводимого текста. Как и для поля TEXT. У серии переключателей атрибуты NAME должны быть одинаковыми, а атрибуты VALUE разными. CHECKED. Если этот элемент установлен, то переключатель выбран. Может быть выбран только один переключатель. Как и для переключателей, но может быть выбрано несколько опций. SIZE определяет ширину поля для ввода. MAXLENGTH определяет максимальную длину имени файла, Атрибут VALUE задает надпись на кнопке. Если указан атрибут NAME, то значения name=value будет передано обработчику. Таким образом, можно иметь в форме несколько кнопок типа SUBMIT и таким образом определять, какая из них была нажата. SRC задает URL изображения. ALIGN устанавливает выравнивание изображения. Атрибут NAME используется так же, как и для кнопки SUBMIT, но при нажатии обрабатывающей программе передаются координаты мыши в виде name.X=КоординатаХ и name.Y=КоординатаY.
Текстовое многострочное поле ввода создается с помощью парного тега . Между открывающим и закрывающим тегами, помещается текст, отображаемый в данном поле по умолчанию. Тег имеет атрибуты NAME, ROWS и COLS. Атрибут NAME задает имя поля, а ROWS и COLS определяют его размеры по вертикали и горизонтали соответственно. Меню создаются с использованием парного тега <SELECT>…, внутри которого содержатся одинарные теги , по одному на каждый пункт меню. © InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 19
Тег <SELECT> имеет атрибуты NAME, SIZE и MULTIPLE. Атрибут NAME задает имя поля, SIZE устанавливает высоту меню в строках. Если атрибут MULTIPLE присутствует в теге, то меню допускает выбор нескольких пунктов, в противном случае может быть выбран только один пункт. Тег имеет атрибут VALUE, который задает значение, которое будет передано обработчику информации при выборе этого пункта. Пример 2. Использование различных элементов формы, создаваемых при помощи тега <TITLE> Элементы формы
Рис. 2.9 Элементы формы, создаваемые при помощи тега
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 21 Пример 3. Использование многострочного поля ввода и меню <TITLE> Элементы формы
Рис. 2.10 Использование многострочного поля ввода и меню
© InterTrust Co. Тел. 956-7928
22
Введение в HTML
2.4.
Карты-изображения
Если обычное изображение, созданное с помощью тега объявить гипертекстовой ссылкой, то по щелчку мыши пользователь сможет перейти на некоторый URL. Картыизображения (image maps) позволяют осуществлять переход на различные URL в зависимости от того, по какой части изображения (активной области) щелкнул мышью пользователь. Создается карта-изображение с помощью парного тега <MAP>…. Этот тег имеет единственный атрибут NAME, который определяет имя карты, которое будет использоваться в атрибуте USEMAP тега . Таким образом, обычное изображение станет картойизображением. Активная область создается с помощью одинарного тега . Эти теги, по одному на каждую активную область помещается между открывающим и закрывающим тегами <MAP>…. Тег имеет следующие атрибуты.
•
SHAPE - определяет, какой геометрической фигурой будет представлена активная область. Возможные значения: RECT (прямоугольник), CIRCLE (круг), POLY (многоугольник). Если атрибут не определен, то по умолчанию предполагается RECT.
•
COORDS - определяет координаты активной области. Для прямоугольника это “XY-верхний, X–правый, Y-нижний”, для круга это “X,Y,радиус”, для многоугольника – перечисление координат вершин “X1,Y1,X2,Y2,…,Xn,Yn”. Координаты X и Y измеряются в пикселях от левого верхнего угла изображения. Если значения X и Y даны в процентах, они интерпретируются как проценты ширины и высоты изображения. HREF - определяет URL перехода. NOHREF - если данный атрибут определен, то при выборе пользователем данной активной области перехода не происходит. Этот атрибут используется, когда необходимо создать неактивную область в центре активной. ALT - определяет текстовую метку, которая будет показана при нахождении курсора мыши над активной областью, а также при загрузке изображения и броузерами, которые не поддерживают показ изображений, или в которых показ изображений отключен. левый,
• • •
Пример 1. Карта-изображение с четырьмя активными областями <TITLE> Карта-изображение <MAP NAME=”photomap”>
© InterTrust Co. Тел. 956-7928
href=”doc1.html” href=”doc2.html” href=”doc3.html” href=”doc4.html”
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 23
Рис. 2.11 Пример карты-изображения
2.5.
Фреймы
2.5.1. Устройство фреймов Фреймы используются для разбиения HTML-документа на несколько самостоятельных областей (фреймов), в качестве которых используются обычные HTML-документы. Можно разрешить пользователю самому изменять размеры этих областей. Каждая область может прокручиваться и загружаться независимо от других. Данные свойства фреймов позволяют создавать продвинутые интерфейсные решения.
• • •
Размещение статической информации, которую автор считает необходимым постоянно показывать пользователю, в одном статическом фрейме. Это может быть графический логотип фирмы, copyright, набор управляющих кнопок. Помещение в статическом фрейме оглавления всех или части WEB-документов, содержащихся на WEB-сервере, что позволяет пользователю быстро находить интересующую его информацию, создание навигаторов. Создание окна результатов запросов, когда в одном фрейме находится собственно запрос, а в другом результаты этого запроса.
Рис. 2.12 HTML-документ с двумя фреймами, слева и снизу © InterTrust Co. Тел. 956-7928
24
Введение в HTML
2.5.2. Создание фреймов Формат документа, использующего фреймы (будем называть его фрейм-документ), очень напоминает формат обычного документа HTML. . . .
Разница в том, что вместо тегов … используются парные теги … , в котором содержатся описания фреймов, на которые делится экран. Фрейм-документ не несет какой либо информационной нагрузки и лишь описывает содержащиеся в нем фреймы. Тег имеет атрибуты ROWS="список величин фреймов по горизонтали" и COLS="список величин фреймов по вертикали". Отсутствие атрибутов ROWS и COLS определяет один фрейм, величиной во все окно броузера. Список значений разделяется запятыми. Значение может быть одним из трех типов.
• • •
Абсолютное. Определяет размер в пикселях, отводимый для фрейма. Задается числом. Например: 50. Относительное. Определяет размер в процентах от размеров экрана, отводимый для фрейма. Задается числом со знаком процента. Например: 50%. Остаточное. Все оставшееся место будет принадлежать этому фрейму. Если указывается два и более фрейма с остаточным размером, то оставшееся пространство делится между ними поровну. Задается знаком «*». Пример 1. Описывает три фрейма, два по 50 точек справа и слева, и один внутри этих полосок.
Пример 2. Описывает три фрейма, первый из которых занимает 20% площади сверху экрана, второй ¾ оставшегося от первого фрейма места (т.е. 60% всей площади окна), а последний ¼ (т.е. 20% всей площади окна).
Теги могут быть вложенными, то есть внутри одного набора описания фреймов может находиться другой. Пример 3. Вложенные теги .
Парные теги … используются для указания текста, который увидит пользователь, если его броузер не поддерживает фреймы.
2.5.3. Описание фреймов Для описания фреймов используется одинарный тег .
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 25
Атрибут SRC определяет URL на документ HTML, который будет показан в данном фрейме. Если этот атрибут отсутствует, то будет отображен пустой фрейм. Атрибут NAME определяет имя фрейма, которое может быть использовано впоследствии для организации взаимодействия между фреймами. Атрибут NORSIZE запрещает изменять размеры данного фрейма. Если у одного фрейма установлен атрибут NORESIZE, то у соседних фреймов тоже не может быть изменен размер со стороны данного. Атрибут SCROLLING позволяет задавать наличие полос прокрутки у фрейма. Значение YES указывает, что полосы прокрутки будут в любом случае присутствовать у фрейма, параметр NO - что полос прокрутки не будет, а AUTO определяет наличие полос прокрутки только при их необходимости (значение по умолчанию). Пример 4. Документ HTML с пятью фреймами. Ваша версия броузера не поддерживает фреймы!
Рис. 2.13 Документ HTML с пятью фреймами
© InterTrust Co. Тел. 956-7928
26
Введение в HTML
2.6.
Java-апплеты
Java-апплеты – это небольшие программы, которые автоматически загружаются с WWWсерверов и исполняются броузером, когда вы просматриваете HTML-документ. В этой книге не затрагиваются принципы работы и создания Java-апплетов. Будет лишь объяснено, как поместить уже готовый апплет в документ HTML. Чтобы поместить Java-апплет в HTML-документ, необходимо использовать тег <APPLET>…. <APPLET CODEBASE = codebaseURL ARCHIVE = archiveList CODE = appletFile ALT = alternateText WIDTH = pixels HEIGHT = pixels > Текст, который будет показан пользователю, если его броузер не поддерживает апплеты
Тег APPLET имеет следующие атрибуты.
• • • • •
CODEBASE - URL на местоположение класса апплета или архива с кодом. ARCHIVE - список архивов (файлы с расширениями .jar или .zip), в которых хранится код апплета. CODE - класс апплета. ALT - текст, который будет показан пользователю во время загрузки апплета. WIDTH, HEIGHT - ширина и высота апплета в пикселях. Тег PARAM имеет следующие атрибуты.
• •
NAME - имя параметра для апплета. VALUE - значение параметра для апплета. Для одного тега APPLET может быть сколь угодно много тегов PARAM. Пример 1. Java-апплет в HTML-документе.
<TITLE> Java-апплет в HTML-документе <APPLET CODEBASE=”JavaCode” CODE="NervousText.class" WIDTH=200 HEIGHT=50> Если вы сейчас не видите работающего апплета, значит ваш броузер не поддерживает апплеты.
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 27
Рис. 2.14 Java-апплет в HTML-документе
2.7.
JavaScript и VBScript
Как было показано в предыдущей разделе, броузер может исполнять Java-апплеты. Но кроме этого броузер способен исполнять небольшие программы, текст которых находится в самом документе HTML. Эти программы называются скриптами (script). Они, в отличие от Java-апплетов, не компилируются, а хранятся в текстовом виде. Когда броузер считывает документ HTML, то переводит текст скрипта в свой внутренний формат. Исполняются скрипты в момент наступления определенного события: щелчка мыши, нажатие кнопки и т.п. В настоящее время широко распространено два вида скриптов: JavaScript и VBScript. JavaScript – это язык, по синтаксису напоминающий Java, но с некоторыми изменениями. Скрипты, написанные на этом языке, способны исполнять броузеры Netscape Navigator и Microsoft Internet Explorer. Однако необходимо заметить, что версия JavaScript для Internet Explorer называется JScript и не вполне совместима с исходным JavaScript. VBScript – это диалект Microsoft Visual Basic. Как и большинство разработок Microsoft в области Internet, VBScript способен исполняться только броузером корпорации Microsoft, то есть Internet Explorer. Сведения об этих языках можно найти на следующих Web-узлах:
• •
JavaScript - http://developer.netscape.com/index_home.html, VBScript и JScript - http://www.microsoft.com/scripting/default.html.
Скрипты включаются в документы HTML с помощью парного тега <SCRIPT>…. Этот тег имеет атрибут LANGUAGE, который «сообщает», на каком языке написан скрипт. Возможные значения: JavaScript, VBScript, JScript. Если атрибут LANGUAGE не определен, то для броузера Netscape Navigator подразумевается JavaScript, а для Internet Explorer – VBScript. <SCRIPT LANGUAGE=”JavaScript”> //Здесь находится программа на JavaScript <SCRIPT>
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 29
3. Введение в серверные объекты 3.1.
Что такое активный WWW-сервер
Когда технология World Wide Web только появилась, WWW-сервер и броузер были пассивными, то есть сервер умел только обрабатывать запрос на конкретный документ и передавать этот документ броузеру, а броузер мог лишь отображать присланный сервером документ. Впоследствии сервер и броузер стали активными. Активный броузер может не только отображать полученные документы, но и производить с ними некоторые действия, например, загружать с сервера и исполнять Java-апплеты, элементы управления ActiveX, а также запускать скрипты (JavaScript и VBScript). Активный сервер может не только возвращать броузеру существующие объекты, но и обрабатывать запросы, поступающие от броузера. В процессе выполнения запроса сервер может совершать некоторые действия, такие, например, как работа с сервером баз данных, чтение файлов, обработка информации, а в качестве ответа сервер динамически формирует объект, который и возвращает броузеру. Для формирования запроса серверу используется обычный формат URL: http://сервер:порт/путь?параметры
Такие части URL, как сервер, порт и путь, уже были нами рассмотрены в главе 1. Параметры для серверного объекта обычно имеют следующий формат. параметр1=значение1&параметр2=значение2&.... параметрN=значениеN
3.2.
Виды серверных объектов
Одними из самых первых серверными объектов были CGI-скрипты (Common Gateway Interface). Это программы, которые запускались при запросе пользователя, анализировали параметры запроса, производили определенные действия и осуществляли вывод в стандартный поток вывода (stdout в терминах языка C/C++), а после этого выгружались из памяти. Важным достоинством CGI-скриптов было то, что они были приняты в качестве фактического стандарта всеми производителями WWW-серверов. Это означает, что программа-обработчик, созданная для одного WWW-сервера, способна работать и на других WWW-серверах, но только в пределах данной программно-аппаратной платформе. Например, обработчик, созданный для Windows NT/Intel, не мог бы работать на Windows NT/Alpha. Главным недостатком CGI-скриптов было то, что для каждого запроса от пользователя приходилось запускать отдельную копию программы-обработчика. Это существенно снижало производительность и повышало требования к ресурсам. Следующим поколением серверных объектов стали серверно-зависимые API (Application Program Interface – интерфейсы прикладного программирования), например ISAPI для Microsoft Internet Information Server, NSAPI для Netscape Enterprise Server, GWAPI для Lotus Go WebServer и многие другие. Программы-обработчики, созданные с помощью этих API, запускались лишь однажды и работали до момента останова всего сервера. Это повышало производительность, а к тому же эти API предоставляли программисту дополнительные возможности. Однако программы, созданные с помощью таких API, были жестко привязаны не только к программно-аппаратной платформе, но и к конкретному WWW-серверу. Кроме того, если в программе, созданной с помощью серверного API, произойдет какая-либо
© InterTrust Co. Тел. 956-7928
30
Введение в серверные объекты
ошибка, способная привести к прекращению работы программы, то вместе с ней произойдет крах всего WWW-сервера. Существуют также серверные объекты, основанные на интерпретации скриптов. Таковыми, например, являются Microsoft Active Server Pages, являющиеся, начиная с версии 3.0, частью Internet Information Server. Тексты программ хранятся либо в текстовых файлах, к которым обращается интерпретатор, или находятся непосредственно в документах HTML и запускаются при обращении пользователя к этим документам. Подобные программы легко модифицировать, но они, вследствие интерпретируемости, имеют достаточно низкую производительность. Новейшим поколением серверных объектов являются сервлеты (servlets). Эти программы создаются с использованием технологии Java. Они способны работать на большинстве WWW-серверов. В настоящее время исполнение сервлетов поддерживает Sun Java WebServer, Lotus Go WebServer, Lotus Domino, Netscape Enterprise Server и другие. Используя JavaSoft Java Servlet Development Kit или IBM WebSphere Application Server, можно добавить поддержку сервлетов в такие сервера, как Apache и MS Internet Information Server. Сервлеты функционально во многом похожи на программы, созданные с помощью серверного API, но, в отличие от них, как и все, что создана на Java, не имеют ни серверной, ни программно-аппаратной зависимости. Сервлеты запускаются только один раз, постоянно находятся в памяти, обрабатывая запросы. При сбое сервлета сервер продолжает нормально функционировать. Вопросы программирования сервлетов и работы их на сервере Lotus Domino будут рассмотрены в разделе 9.3. В настоящей главе будет рассказано о программировании CGIскриптов. Данный материал подразумевает знание языка программирования C.
3.3.
Программирование CGI-скриптов 3.3.1. Жизненный цикл CGI-скриптов
Когда броузер передает на WWW-сервер запрос, сервер устанавливает переменные среды CGI и запускает CGI-скрипт. После запуска происходят следующие действия. 1. В методе main(void) CGI-скрипт анализирует значения полученных переменных с помощью стандартной функции языка C – getenv(). 2. Из переменной QUERY_STRING извлекается и анализируется запрос. 3. Если необходимо, считываются присоединенные к запросу данные из потока stdin. 4. Производятся необходимые действия для формирования ответа (например, обращение к СУБД). 5. Ответ сервера записывается в поток stdout. 6. CGI-скрипт завершает работу.
3.3.2. Переменные среды CGI Когда WWW-сервер вызывает CGI-скрипт, то устанавливает для него большое количество переменных среды, содержащих различную информацию о запросе, о инициировавшим запрос клиенте и т.п. Рассмотрим основные переменные среды.
AUTH_TYPE Тип идентификации пользователя, пославшего запрос CGI-скрипту.
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 31
CONTENT_LENGTH Размер данных в запросе (количество байт). Используется для получения и обработки запроса от броузера. Эта и следующая переменные используются только для тех видов запросов, которые поддерживают присоединенные к запросу данные, например, POST.
CONTENT_TYPE Тип данных MIME для присоединенных к запросу данных.
GATEWAY_INTERFACE Версия спецификаций CGI. Например: CGI/1.1
HTTP_ACCEPT Типы данных MIME, которые принимает клиент, как указано в заголовах HTTP.
HTTP_REFERER URL страницы, с которой пользователь «попал сюда».
HTTPS Показывает, включена ли поддержка SSL на сервере.
HTTP_USER_AGENT Броузер, который используется клиентом.
QUERY_STRING В данной переменной содержится запрос к CGI-скрипту. Запрос представляет собой текстовую строку, содержащую параметры запроса - соответствующую часть после символа «?» из URL запроса. Параметры запроса обсуждались в главе 1.
REMOTE_ADDR IP-адрес хоста, с которого пришел запрос.
REMOTE_HOST Имя хоста, с которого пришел запрос. Например: ignatov.inttrust.ru.
REMOTE_IDENT Идентификатор пользователя, от которого пришел запрос. Например: ignatov. Данная переменная может быть незаполненной, если WWW-сервер не поддерживает идентификацию пользователей.
REMOTE_USER Имя пользователя, производящего запрос.
© InterTrust Co. Тел. 956-7928
32
Введение в серверные объекты
REQUEST_METHOD Метод запроса к CGI-скрипту: GET, HEAD, POST и т.п.
REQUEST_CONTENT Данные, передаваемые методом POST.
SERVER_NAME Имя сервера, на котором выполняется CGI-скрипт, или его IP-адрес.
SERVER_PORT Номер порта, через который броузер связывается с сервером.
SERVER_PROTOCOL Информация о протоколе, который броузер использует для связи с сервером.
SERVER_SOFTWARE Информация о программной реализации WWW-сервера, на котором выполняется CGIскрипт.
3.3.3. Потоки ввода вывода stdin и stdout После запуска CGI-скрипт должен получить и проанализировать параметры запроса. Для этого он пользуется стандартной функцией языка C – getenv(). Данные для запроса получаются из стандартного потока ввода с помощью стандартной функции языка C – scanf(). В переменной окружения CONTENT_LENGTH содержится размер данных для запроса в байтах, а в переменной CONTENT_TYPE - MIME-тип данных. После обработки запроса CGI-скрипт должен послать ответ серверу. Для этого он записывает данные в стандартный поток вывода stdout. Ответ CGI-скрипта серверу состоит из заголовка, пустой строки и информативной части. В заголовок входят следующие поля. Поле Contenttype Location Status
Описание Содержит тип данных в формате MIME Указывает на местонахождение документа Значение статуса HTTP, возвращаемое сервером броузеру
Пример Content-type: text/html Location: http://www.inttrust.ru/ Status: 200
Обычно в качестве информативной части выступает текст – документ HTML (text/html). Для записи документа HTML в stdout используется стандартная функция библиотеки C printf(). Например, printf(“”) посылает серверу тег (подробнее о тегах и прочих элементах языка HTML было рассказано в предыдущей главе).
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 33
3.3.4. Пример CGI-скрипта В качестве примера CGI-скрипта приведем простейшую программу, которая передает броузеру в качестве ответа содержание переменных окружения. // // Получение переменных окружения CGI-скриптом и показ их пользователю в // виде документа HTML // #include <stdio.h> #include <stdlib.h> #include <memory.h> void main(void) { printf("Content-type: text/html\n"); printf("\n"); printf ("\n"); printf("\n"); printf("<TITLE>Переменные окружения CGI-скрипта \n"); printf("\n"); printf(" Переменные окружения CGI-скрипта \n"); printf(" \n"); printf("AUTH_PASSWORD - %s\n", getenv("AUTH_PASSWORD")); printf("AUTH_TYPE - %s\n", getenv("AUTH_TYPE")); printf("AUTH_USER - %s\n", getenv("AUTH_USER")); printf("CONTENT_TYPE - %s\n", getenv("CONTENT_TYPE")); printf("CONTENT_LENGTH - %s\n", getenv("CONTENT_LENGTH")); printf("HTTP_FROM - %s\n", getenv("HTTP_FROM")); printf("GATEWAY_INTERFACE - %s\n", getenv("GATEWAY_INTERFACE")); printf("PATH_INFO - %s\n", getenv("PATH_INFO")); printf("PATH_TRANSLATED - %s\n", getenv("PATH_TRANSLATED")); printf("QUERY_STRING - %s\n", getenv("QUERY_STRING")); printf("REMOTE_ADDR - %s\n", getenv("REMOTE_ADDR")); printf("REMOTE_HOST - %s\n", getenv("REMOTE_HOST")); printf("REMOTE_IDENT - %s\n", getenv("REMOTE_IDENT")); printf("REQUEST_METHOD - %s\n", getenv("REQUEST_METHOD")); printf("REMOTE_USER - %s\n", getenv("REMOTE USER")); printf("SCRIPT_NAME - %s\n", getenv("SCRIPT_NAME")); printf("SERVER_NAME - %s\n", getenv("SERVER_NAME")); printf("SERVER_PORT - %s\n", getenv("SERVER_PORT")); printf("SERVER_PROTOCOL - %s\n", getenv("SERVER_PROTOCOL")); printf("SERVER_SOFTWARE - %s\n", SERVER_SOFTWARE); printf("\n"); printf("\n"); }
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 35
4. Web-сервер Domino и интерпретация им URL В контексте разработки Web-приложений под Web-сервером Domino (сервером Domino, Domino) подразумевается серверная задача HTTP (запускается с консоли Notes-сервера командой load http). Задача HTTP ожидает установления соединения с ней Web-клиента по протоколу HTTP, а затем запроса от клиента (URL запроса). Если клиент обращается к базе Notes (о чем свидетельствует наличие в URL имени файла базы), то задача HTTP через Domino Engine обращается к соответствующей базе, при этом транслируя информацию из формата Notes в формат HTML или наоборот. В остальных случаях задача HTTP обрабатывает URL так же, как и любой другой из применяемых в настоящее время HTTPсерверов.
Рис. 4.1 Общая архитектура Web-сервера Domino Каталоги на сервере, в которые помещаются файлы HTML и программы CGI, указываются в секции HTTP Server документа Server из общей адресной книги. Обычно файлы типа html, gif, jpeg бывают расположены в каталоге c:\notes\data\domino\html\, а программы и скрипты CGI - в каталоге c:\notes\data\domino\cgi\. Для обращения к базам Notes Web-сервер Domino использует расширенный синтаксис URL (свой набор команд и параметров к ним), который и будет ниже подробно рассмотрен.
4.1.
Общий вид URL Domino
Наиболее общий вид использующихся в Domino URL следующий: http://Host/NotesObject/Action&Arguments , где: Host - имя хоста или IP-адрес (serg, www.inttrust.ru, 195.208.68.131); NotesObject - элемент дизайна Notes (база, вид, документ, форма, навигатор, агент и т.д.); Action - операция с объектом (по умолчанию ?Open); Arguments - дополнительные аргументы к операции. Обычно NotesObject является конструкцией исключение составляют лишь URL вида:
NotesDatabase/NotesDatabaseObject,
http://Host - открытие страницы по умолчанию (Home Page); http://Host/?OpenServer - открытие списка баз данных на сервере; http://Host/?OpenServer&Login аутентификация.
-
открытие
списка
баз
данных
на
сервере
и
© InterTrust Co. Тел. 956-7928
36
Web-сервер Domino и интерпретация им URL
Следует отметить, что на URL вида http://Host?OpenServer сервер Domino возвращает ошибку типа General Error, причем в форме для отображения этой ошибки, содержащейся в базе domcfg.nsf, не загружается встроенное в нее изображение. Зато URL вида http://Host?OpenServer&somesymbols открывает список баз данных на сервере, как можно было бы ожидать и от URL http://Host?OpenServer. Но в броузере MSIE 4 эти эффекты не наблюдаются, так как он автоматически заменяет http://Host?OpenServer на http://Host/?OpenServer.
4.2.
URL для обращения к базам
Открытие базы http://Host/DBFileName?OpenDatabase http://Host/DBReplicaID?OpenDatabase Пример 1. Открытие базы news.nsf. http://serg/site/news.nsf?OpenDatabase Пример 2. Открытие той же базы news.nsf по идентификатору реплики ReplicaID. http://serg/C32565760024B4D5?OpenDatabase
Открытие документа About http://Host/Database/$about?OpenAbout Если документ Help About не редактировался с момента создания базы и в нем ничего нет, Domino выдает ошибку типа General Error: Error 500 HTTP Web Server: Lotus Notes Exception - Special database object cannot be located.
Открытие документа Using http://Host/Database/$help?OpenHelp Eсли документ Help Using не редактировался с момента создания базы и в нем ничего нет, Domino выдает ошибку типа General Error: Error 500 HTTP Web Server: Lotus Notes Exception - Special database object cannot be located.
Открытие пиктограммы базы http://Host/Database/$icon?OpenIcon Работает и такой «недокументированный» URL http://Host/Database?OpenIcon.
Аргумент Login Добавление аргумента Login к любому корректному URL Domino, заканчивающемуся операцией (например, ?Open), приводит к попытке аутентификации пользователя (обычно к запросу ввода имени и пароля), если пользователь не был аутентифицирован до этого. Пример 1. Открывает список баз на сервере и производит аутентификацию. http://serg/?OpenServer&Login или http://serg/?Open&Login Пример 2. Открывает вид ByTopic в базе news.nsf и производит аутентификацию.
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 37 http://serg/site/news.nsf/ByTopic?OpenView&Login
Аргумент Login может использоваться в сочетании с формулами скрытия (hide formulas) для того, чтобы в зависимости от привилегий пользователя отображать те или иные объекты на странице, на которую пользователь может попасть и как Anonymous. Страницы, использующие формулы скрытия, требуют повышенного внимания и тщательного тестирования. Было замечено, что функция @UserName возвращает Anonymous всегда, если пользователь Anonymous имеет доступ к объекту (документу), в котором используется эта функция. Если аргумент Login был использован в URL, открывающем конкретный документ, функция @UserName в нем работает «как нужно» - возвращает имя пользователя.
4.3.
URL для работы с документами
Открытие документа на чтение http://Host/Database/View/DocumentKey?OpenDocument, содержимое первой сортированной колонки вида View.
где
DocumentKey
-
http://Host/Database/View/DocumentUniversalID?OpenDocument, где DocumentUniversalID - UNID документа. В случае открытия документа по UNID наличие самого вида View в базе не обязательно. http://Host/Database/View/DocumentNoteID?OpenDocument, где DocumentNoteID NoteID документа. В случае открытия документа по NoteID не обязательно, чтобы открываемый документ присутствовал в виде View. Пример 1. Открыть первый из документов со значением "Sergei Budylov" в первой сортированной колонке вида ByAuthor базы news.nsf. http://serg/site/news.nsf/ByAuthor/Sergei+Budylov Пример 2. Открыть документ с UNID 66b00570d163ea21c32565b1002bea58 в базе discuss.nsf. http://serg/site/discuss.nsf/ByAuthor/66b00570d163ea21c32565b1002bea58?Op enDocument Пример 3. Открыть документ с NoteID 0000212A в базе discuss.nsf. http://serg/site/discuss.nsf/ByAuthor/0000212A?Open
Открытие документа на редактирование http://Host/Database/View/Document?EditDocument
Удаление документа http://Host/Database/View/Document?DeleteDocument
Создание документа в базе http://Host/Database/Form?CreateDocument Domino создает документ в указанной базе, используя указанную форму, и выдает подтверждающее сообщение. Для того чтобы создать документ, вначале заполняя форму, используйте OpenForm.
© InterTrust Co. Тел. 956-7928
38
Web-сервер Domino и интерпретация им URL
Сохранение документа http://Host/Database/View/Document?SaveDocument Эта операция приводит к пересохранению документа на сервере, о чем выдается подтверждающее сообщение. Если открыть документ на редактирование, изменить его, а затем выполнить эту операцию, результаты редактирования не сохранятся. Для того, чтобы сохранить документ, используйте кнопку Submit.
Открытие присоединенного файла http://Host/Database/View/Document/$File/FileName?OpenElement В зависимости от настроек броузера может быть предложено сохранить файл на диске, стартовать ассоциированное с этим типом файлов приложение, стартовать сам этот файл (если он исполняемый), или просмотреть (при наличии соответствующих фильтров). Пример. URL для открытия присоединенного к документу файла, сгенерированный Domino. http://serg/site/discuss.nsf/2f7e57927a45373dc32565770046edbf/efe05cf133b 2422ec32565b100366959/$File/YN010.JPG Здесь discuss.nsf – база данных; 2f7e57927a45373dc32565770046edbf – UNID вида в базе discuss.nsf, из которого открывается документ; efe05cf133b2422ec32565b100366959 – UNID документа, содержащего присоединенный файл; $File – имя поля, в которое в Notes помещаются присоединенные файлы; YN010.JPG – имя присоединенного файла, который нужно открыть.
Открытие растрового изображения из поля http://Host/Database/View/Document/FieldName/ FieldOffset?OpenElement&FieldElemFormat=ImageFormat Notes разбивает информацию в поле типа Rich Text на части по 15 - 20K, создавая ряд полей-«пунктов» с таким же названием. Параметр FieldOffset является для Notes указателем на начало изображения и имеет вид xx.yy, где xx - номер поля-«пункта», а yy - смещение в байтах внутри поля-«пункта». Учитывая произвольность разбиения поля, предсказать значения параметра xx уже для второго изображения в поле не представляется возможным. Однако, если работать только с первым изображением в поле, то для него xx будет равен 0 , а yy будет постоянным, и его можно узнать опытным путем (Copy link location из броузера). Параметр ImageFormat может принимать значение gif или jpeg. Пример. URL, генерируемый Domino для открытия растрового изображения, вставленного в поле. http://serg/site/discuss.nsf/2f7e57927a45373dc32565770046edbf/efe05cf133b 2422ec32565b100366959/Body/0.70?OpenElement&FieldElemFormat=gif
Открытие объекта OLE http://Host/Database/View/Document/FieldName/ FieldOffset/$OLEOBJINFO/FieldOffset/obj.ods?OpenElement Для автора осталось непонятным, как пользоваться URL такой структуры. Дело в том, что Web-сервер Domino по запросу броузера преобразует OLE-объекты из документов в растровые изображения, а URL такой структуры для доступа к ним не использует.
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 39
Вместо OLE-объектов целесообразнее использовать присоединенные файлы, поскольку броузеры «умеют» запускать соответствующие приложения в зависимости от типа файла.
Открытие формы (аналогично созданию документа в Notes) http://Host/Database/FormName?OpenForm http://Host/Database/FormUniversalID?OpenForm http://Host/Database/FormNoteID?OpenForm http://Host/Database/$defaultform?OpenForm - открытие формы по умолчанию. Для создания ответных документов используется дополнительный параметр ParentUNID, задающий UNID родительского документа. http://Host/Database/FormName?OpenForm&ParentUNID=UNID Если не использовать параметр ParentUNID при создании ответного документа, документ создается и его можно сохранить, при этом получается «висячий» ответный документ (он не отображается в видах с иерархией ответных документов). Параметр ParentUNID можно также использовать для того, чтобы обеспечить наследование значений полей из родительского документа, определяемого этим параметром, во вновь создаваемый. Пример 1. Создание нового документа в базе discuss.nsf по форме document. http://serg/site/discuss.nsf/document?OpenForm Пример 2. Создание нового ответного документа по форме response к документу с UNID efe05cf133b2422ec32565b1003 (значения полей из родительского документа могут наследоваться). http://serg/site/discuss.nsf/response?OpenForm&ParentUNID=efe05cf133b2422 ec32565b100366959 Пример 3. Создание нового документа в базе discuss.nsf по форме document с наследованием значений полей из документа с UNID efe05cf133b2422ec32565b1003. http://serg/site/discuss.nsf/document?OpenForm&ParentUNID=efe05cf133b2422 ec32565b100366959
Существует еще одна интересная операция для работы с формами: ?ReadForm. Она применяется аналогично ?OpenForm, но открывает форму в режиме чтения. Значения полей также вычисляются и отображаются, но параметр ParentUNID игнорируется, и, соответственно, значения полей не наследуются.
Операции с секциями http://Host/Database/View/DocumentUniversalID?OpenDocument &ExpandSection=List#_SectionX, где: List - список номеров секций (через запятую), с которыми производится операция; X - номер секции, на начало которой нужно отскроллировать документ. Чтобы раскрыть секцию, которая по умолчанию «сложена», номер секции указывается без знака. Чтобы «сложить» секцию, которая по умолчанию раскрыта, номер секции указывается с минусом. Пример 1. Раскрыть «сложенные» по умолчанию секции 1,2 и «сложить» раскрытую по умолчанию секцию 3.
© InterTrust Co. Тел. 956-7928
40
Web-сервер Domino и интерпретация им URL
http://www.inttrust.ru/Site/itforum.nsf/7f7cf6ece5baf4d2c32566260026b318/ 2a0ff8acd2b69d5bc3256628004cb11d?OpenDocument&ExpandSection=1,2,-3 Пример 2. То же самое, но дополнительно отскроллировать документ на начало секции 2 (работает в версии 4.6.1a). http://www.inttrust.ru/Site/itforum.nsf/7f7cf6ece5baf4d2c32566260026b318/ 2a0ff8acd2b69d5bc3256628004cb11d?OpenDocument&ExpandSection=1,2,3#_Section2
4.4.
URL для работы с видами и папками
Открытие вида или папки http://Host/Database/ViewName?OpenView http://Host/Database/ViewUniversalID?OpenView http://Host/Database/ViewNoteID?OpenView http://Host/Database/$defaultView?OpenView Пример 1. Открытие вида по алиасу. http://serg/site/news.nsf/ByTopic?OpenView Пример 2. Открытие вида All\ByTopic по [иерархическому] имени. http://serg/site/news.nsf/All/ByTopic?OpenView Пример 3. Открытие вида, содержащего пробелы в имени (их нужно заменять на плюсы). http://serg/site/news.nsf/По+категориям?OpenView Пример 4. Открытие вида по его UNID. http://serg/site/news.nsf/16b23b1bffa57eecc32565760024b555?OpenView Пример 5. Открытие в базе news.nsf вида по умолчанию (default view). http://serg/site/news.nsf/$defaultView?OpenView
Дополнительные аргументы при открытии видов или папок Start=n , где n - номер строки в виде, с которого начинать его отображение. Для видов с категориями n должно задаваться подобно x1.x2.x3, где x1 - номер строки в первой категории, x2 - номер строки во второй категории, x3 - номер строки с документом. Count=n, где n - число строк вида, которые должны быть показаны (по умолчанию 30, но настраивается в секции HTTP Server документа Server из общей адресной книги). ExpandView - показывает вид в «раскрытом» формате (все категории раскрыты). CollapsView - показывает вид в «сложенном» формате (все категории «сложены»). Expand=n, где n - номер строки в иерархическом виде, которую нужно раскрыть. Может использоваться такой же формат n, как в параметре Start. Collapse=n, где n - номер строки в иерархическом виде, которую нужно «сложить». Может использоваться такой же формат n, как в параметре Start. #n, где n - номер строки в иерархическом виде, на которую этот вид должен быть отскроллирован. Может использоваться такой же формат n, как в параметре Start. Пример 1. Открыть вид ByTopic в «сложенном» формате. http://serg/site/news.nsf/ByTopic?OpenView&CollapseView
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 41 Пример 2. Открыть 15 строк вида ByTopic, начиная со строки 3, раскрыв строку 3.5.1, и отскроллировать на эту строку. http://serg/site/news.nsf/ByTopic?OpenView&Start=3&Count=15&Expand=3.5.1# 3.5.1
4.5.
Поисковые URL
Рассматриваемые здесь URL используются для осуществления полнотекстового поиска. http://Host/Database/View/[$SearchForm]?SearchView[Argument List] - общий вид URL для поиска по виду в базе. http://Host/Database/[$SearchForm]?SearchSite[Argument List] - общий вид URL для поиска по базе типа Search Site (при поиске по нескольким базам). Можно использовать следующие аргументы.
• •
• • • •
Query = строка запроса (обязательный аргумент). SearchOrder=[1,2,3] (по умолчанию 1) - порядок сортировки. 1 = “By Relevance” (по релевантности - больше совпадений значит выше); 2 = “By Date Ascending” (по дате модификации, более старые документы выше); 3 =“By Date Descending” (по дате модификации, более новые документы выше). SearchThesaurus=[TRUE, FALSE] (по умолчанию = FALSE) - использовать ли словарь синонимов. SearchMax=[n] (по умолчанию 0) - ограничение на количество найденных документов; 0 - все найденные документы. SearchWordVariants=[TRUE, FALSE] (по умолчанию TRUE) - искать ли варианты слов. OldSearchQuery - повторяет последний запрос.
В случае, когда для создания запроса используется поисковая форма, URL приобретает вид http://Host/Database/View/$SearchForm?SearchView. При этом, если в данной базе определена пользовательская поисковая форма (с именем $$Search), то запрос может быть «вычислен» в ней, и, следовательно, может не зависеть от Database и View, содержащихся в исходном URL. В случае, когда поисковый запрос подготовлен заранее, URL приобретает вид http://Host/Database/View/?SearchView[Argument List]. Пример 1. Открытие поисковой формы для поиска по виду ByTopic. http://serg/news.nsf/ByTopic/$SearchForm?SearchView Пример 2. Поиск слова IBM в документах из вида ByTopic. http://serg/site/news.nsf/ByAuthor/?SearchView&Query=IBM Пример 3. Поиск фразы "Lotus Notes" в документах из вида ByTopic. http://serg/site/news.nsf/ByAuthor/?SearchView&Query="Lotus Notes" Пример 4. Поиск документов, у которых в поле Creator содержится "Sergei Budylov", и дата в поле DateModifyed >= 15.01.98. http://serg/site/news.nsf/ByAuthor/?SearchView&Query=FIELD+Creator=Sergei +Budylov+AND+FIELD+DateModifyed>=15.01.98
4.6.
URL для открытия навигаторов
http://Host/Database/NavigatorName?OpenNavigator http://Host/Database/NavigatorUniversalID?OpenNavigator
© InterTrust Co. Тел. 956-7928
42
Web-сервер Domino и интерпретация им URL
http://Host/Database/NavigatorNoteID?OpenNavigator http://Host/Database/$defaultNav?OpenNavigator - открывает стандартный навигатор Folders. Навигатор Folders открывается по умолчанию также при обращении к базе и представляет собой столбец ссылок на имеющиеся в базе виды и папки.
4.7.
URL для запуска агентов
http://Host/Database/AgentName?OpenAgent http://Host/Database/AgentUniversalID?OpenAgent http://Host/Database/AgentNoteID?OpenAgent Агент запускается на сервере и по окончании работы, если он не производит никакого «собственного» вывода, выдает сообщение Agent done.
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 43
5. Разработка форм для Web-приложений Domino 5.1.
Введение
С приложениями Domino (базами данных NSF) можно работать, используя клиента (рабочую станцию) Notes или web-броузер. Поскольку возможности клиента Notes и броузера различаются, часть функций элементов дизайна баз (и, соответственно, опций в их свойствах) поддерживаются только при обращении к базе из клиента Notes или только при обращении к базе из броузера. О функциях элементов дизайна, которые работают или не работают при обращении к приложению Domino с помощью броузера, будем говорить, что они работают или не работают «в Web-приложениях Domino» или, короче, «в Web-приложениях».
5.1.1. Обзор свойств формы применительно к Web-приложениям Form/Basic
Рис. 5.1 Свойства формы. Закладка Basic Versoning (ведение версий документа), Anonymous Form, Merge replication conflicts - не работают в Web-приложениях.
Form/Defaults
Рис. 5.2 Свойства формы. Закладка Defaults © InterTrust Co. Тел. 956-7928
44
Разработка форм для Web-приложений Domino
Disable Field Exchange, Automatically refresh fields - не работают в Web-приложениях. Store form in document – документы, созданные по форме с «включенной» опцией, корректно транслируются в HTML с использованием встроенной в них формы. Однако при создании документа по такой форме из броузера эта форма не встраивается в создаваемый документ. On Create: Formulas inherit values from selected document - свойство работает в Webприложениях, когда определен документ-родитель, то есть при создании документа с указанием его родителя. On Create: Inherit entire selected document into rich text field - работает в Webприложениях, если определен документ-родитель, то есть при создании документа с указанием его родителя. Документ наследуется целиком как Rich Text. Две другие опции (Link и Collapsible rich text) не работают в Web-приложениях. On Open: Show context pane, On Close: Present mail send dialog - не работают в Webприложениях. For Web Access: Treat document contents as HTML - весь «видимый» текст из документа, созданного по форме с такой опцией (включая текст из полей, статический и вычисляемый текст из формы и ее субформ), «передается броузеру напрямую», т.е. без трансляции объектов Notes в HTML. Изображения, вставленные в форму или документ с помощью Paste или Import, а также иные объекты Notes, не содержащие текста, при этом не отображаются в броузере.
Form/Launch Auto Launch - не работает в Web-приложениях.
Form/Print Header/Footer - не работает в Web-приложениях.
Form/Access
Рис. 5.3 Свойства формы. Закладка Access Default encription keys - неприменимо в Web-приложениях. Disable printing/forwarding/copying to clipboard - не работает в Web-приложениях.
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 45
Available to public access users - установка опции должна бы позволить пользователям, имеющим к базе уровень доступа No Access, создавать в базе документы по этой форме. Это свойство было бы удобно использовать для пользовательской поисковой формы $$Search. Автору удавалось увидеть форму с такой опцией из броузера, однако не удавалось сохранить созданный по ней документ. В Notes такая форма «была видна» в меню Create, но документы по ней тоже не создавались. Вероятно, в версии 4.6a эта опция не работает.
5.1.2. Разные формы для пользователей Notes и Web Существует возможность использовать для просмотра одного и того же документа разные формы в зависимости от того, открывается ли документ из клиента Notes или из броузера. Для этого можно создать две формы с одинаковым алиасом, и у одной из них в свойствах Design Document на закладке Design установить опцию Hide design element from: Web browsers, а у другой - Hide design element from: Notes R4.6 or later clients.
Рис. 5.4 Свойства формы как элемента дизайна Notes Аналогичное свойство имеется у видов, субформ (subform), папок (folder), навигаторов и агентов.
5.2.
Простые формы
5.2.1. Использование таблиц Таблицы Notes корректно транслируются в таблицы HTML, за исключением управления обрамлением (толщиной и видимостью ограничивающих линий). Если в верхней левой ячейке таблицы в Notes есть обрамление, вся таблица в HTML будет иметь видимое обрамление. И наоборот, если в верхней левой ячейке таблицы в Notes нет обрамления, линии таблицы HTML будут невидимы. Следует учитывать, что если вся колонка или строка таблицы Notes пуста, то при трансляции в HTML она игнорируется. Добавив хотя бы один символ (но не пробел) в каждую ячейку, можно быть уверенным, что колонка или строка таблицы будет видна (если только это не противоречит формулам скрытия). Для таблиц, у которых установлено свойство Fit to window, ширина колонок устанавливается в процентах от ширины окна. Для таблиц с точно указанными размерами сантиметры пересчитываются в пиксели (37.8 pixel на 1 см). Параметры таблицы Notes наподобие промежутков между столбцами, по-видимому, никак не влияют на генерируемый HTML.
© InterTrust Co. Тел. 956-7928
46
Разработка форм для Web-приложений Domino
Поскольку лишние пробелы и табуляции в форме и документе Notes при трансляции в HTML игнорируются, для форматирования текста рекомендуется применять таблицы без обрамления. Отметим, что виды Notes для отображения в броузере Domino тоже транслирует в таблицы HTML.
5.2.2. Растровые изображения в Notes Для хранения растровых изображений в Notes версий 4.6.х и младше используется собственный платформенно-независимый формат. Возможно, это удобно в плане работы в Notes на различных платформах, но при этом теряются преимущества исходных графических форматов, из которых импортируется изображение. Как подтверждение этого можно рассматривать такой факт, что в Notes версий 5.х изображения будут храниться в форматах GIF89a или JPEG. Некоторая информация о форматах: GIF89a - 256 цветов или оттенков серого, высокая компрессия без потерь. Может содержать анимацию. Особенно удобен для хранения маленьких изображений или изображений с большим количеством мелких деталей. JPEG - 16 млн. цветов, регулируемая компрессия с потерями - чем меньше получаемый размер файла (сильнее сжатие), тем хуже качество изображения. Наиболее эффективен на больших изображениях с однородными областями.
Для вставки изображения в Notes используются два основных способа: импорт и вставка из буфера обмена. Для одного и того же изображения результат операции Create/Picture аналогичен File/Import. В версиях до 4.6 операция Paste справлялась с этим несколько хуже, отчего и рекомендовалось импортировать изображение. Но следует заметить, что даже в версии 4.6 некоторые изображения вставляются с искажениями в палитре. По мнению автора, компании Lotus не стоило использовать в Notes собственный графический формат, «не умея» корректно преобразовывать к нему изображения, созданные в других форматах.
Рис. 5.5 Свойства изображения, вставленного в документ или форму В свойствах изображения к Web-приложениям имеет отношение поле Alternate text for Web and deferred loading на закладке Basics. В него следует заносить текст, который будет появляется в броузере, пока изображение еще не загрузилось. Масштабирование изображения на закладке Basics корректно транслируется в HTML изменением значений атрибутов WIDTH и HEIGHT тега IMG. Прозрачный цвет, если он есть в изображении, не сохраняется при вставке с помощью Paste - используйте File/Import. Из анимированных изображений (GIF89a) вставляется только первый кадр (но в Notes версий 5.х анимация поддерживается). Domino генерирует URL для вставленных в форму или документ изображений как URL для обращения к элементу из поля типа Rich Text в базе. © InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 47 Пример 1. Тег, сгенерированный Domino для изображения, вставленного в форму. Здесь в URL: /site/discuss.nsf - путь к базе; 7171ddba9df5062cc325658d00458605 - UNID формы, в которую вставлено изображение; $Body - поле типа Rich Text, в котором Notes хранит изображения, вставленные в форму; 0.72e - указатель на начало элемента в поле. Имеет вид xx.yy , где xx - номер поля, уу - смещение в байтах в этом поле. Номер поля необходим ввиду того что Notes разбивает информацию в поле типа Rich Text на части по 15-20K, создавая ряд полей с таким же названием. ?OpenElement - производимая операция; FieldElemFormat - параметр операции OpenElement. Определяет графический формат, в который конвертируется изображение (gif или jpeg). Для URL, генерируемых Domino, его значение определяется параметром Image conversion format в секции HTTP Server в документе Server в общей адресной книге.
Следует учитывать, что если в форму или документ вставлены несколько совершенно одинаковых изображений, они все равно будут считываться с Web-сервера как разные, что замедлит загрузку страницы. Многие проблемы использования изображений в Notes решаются включением в форму или документ вставок на языке HTML со ссылками на графические файлы в файловой системе сервера или на присоединенные к документу файлы. Один из простых способов вставки HTMLкода в документ или форму - «заключение HTML-кода в квадратные скобки». Пример 2. Файлы из в каталога Domino для HTML (обычно notes\data\domino\html\). [ ] или [ ] Пример 3. Присоединенные к документу файлы. [ ] Здесь docidentifier - значение в первой сортированной колонке вида view или UNID документа; $File – поле типа Rich Text, в котором Notes хранит присоединенные файлы. Если к документу присоединено несколько файлов, они должны иметь разные имена.
5.2.3. Horisontal Rules Horizontal Rules - горизонтальные линии, используемые для визуального отделения частей документа. В Notes версии 4.6 такой элемент может быть создан с помощью команды меню Create/Horizontal Rule и имеет несколько свойств.
Рис. 5.6 Свойства элемента Horizontal Rule
© InterTrust Co. Тел. 956-7928
48
Разработка форм для Web-приложений Domino
Для элемента Horizontal Rule Domino генерирует следующий HTML-код: Автору не удалось добиться толщины линии менее 7 пикселей, а Netscape® Communicator 4.05, в отличие от MSIE 3.02, «остался равнодушен» к атрибуту COLOR. Если необходима более тонкая линия, можно явно вставить в форму или документ тег , «просто написав» [ ] там, где линия требуется. Тем не менее основное достоинство применения элемента Horizontal Rule состоит в том, что соответствующая ему линия «видна» не только в броузере, но и в клиенте Notes.
5.2.4. Кнопки в форме, кнопки в Action Bar и Hotspot-ы. Применение JavaScript Кнопки в форме При «выключенной» опции Web Access: Use JavaScript when generating pages в свойствах базы для документа, создаваемого или редактируемого в броузере, Domino транслирует в HTML только первую видимую кнопку из документа, причем всегда как кнопку типа Submit. Так, для кнопки в форме Notes с надписью "Сохранить" будет сгенерирован HTML-код
Если в редактируемом документе нет видимых кнопок, автоматически генерируется кнопка типа Submit с надписью "Submit". Для того, чтобы в документе броузера могли отображаться несколько кнопок, необходимо включить в свойствах базы опцию Web Access: Use JavaScript when generating pages. Во-первых, в этом случае все кнопки с @-формулой @Command([FileSave]) ; @Command([FileCloseWindow]);
будут транслироваться в HTML как кнопки типа Submit с соответствующим названием. Во-вторых, в этом случае Domino при трансляции добавит в HTML-документ функцию _doClick на JavaScript. Эта функция вызывается на событие onClick для всех кнопок в документе и выглядит в режиме чтения приблизительно так. <SCRIPT LANGUAGE="JavaScript">
URL, являющийся значением переменной location.href, определяет документ, «в котором была нажата кнопка», а так же, в параметре &Click, содержит информацию о «нажатой кнопке». Однако в режиме редактирования функция _doClick выглядит несколько иным образом. <SCRIPT LANGUAGE="JavaScript">
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 49 // -->
В этом случае _Seek - имя HTML-формы, содержащей скрытое поле __Click, в которое заносится информация о «нажатой кнопке», а submit() - метод, выполняющий передачу содержимого этой формы на сервер. В-третьих, сами другие кнопки будут представлены в HTML-документе в виде тэгов приблизительно следующим образом:
Таким образом, «нажатие» такой кнопки в броузере влечет вызов функции _doClick с передачей ей идентификатора нажатой кнопки, который и позволяет серверу отыскать в базе элемент дизайна, содержащий описание действия по этой кнопке. На Рис. 5.7 в документе, находящемся в режиме чтения, видны четыре кнопки. В них были использованы следующие формулы:
•
Редактировать (редактировать текущий документ)
@Command([EditDocument])
•
Удалить (удалить текущий документ)
@Command([EditClear])
•
Создать ответ (создать ответный документ к текущему по форме response)
@Command([Compose];"response")
•
Создать документ (создать документ по форме document)
@Command([Compose];"document")
Рис. 5.7 Включение опции Web Access: Use JavaScript when generating pages позволяет использовать кнопки на HTML-станицах
© InterTrust Co. Тел. 956-7928
50
Разработка форм для Web-приложений Domino
Кнопки в Action Bar Использование в Notes кнопок в Action Bar удобно тем, что эти кнопки имеют индивидуальные формулы скрытия и не скроллируются вместе с документом. При доступе броузером сам Action Bar транслируется в HTML как таблица, находящаяся в начале HTML-документа. Если действие, указанное в кнопке, выполнимо в броузере, кнопка транслируется, если не выполнимо - не транслируется.
Hotspot'ы Это наиболее универсальный инструмент для «прикрепления» действий на @-формулах Notes к участкам текста формы или документа (включая и HTML-код в квадратных скобках) и вставленной графике. Если Domino может оттранслировать формулу действия Hotspot'а в HTML-код, он «оформляет» Hotspot как активную область с соответствующим действием, если же не может игнорирует действие Hotspot'а. Например, Hotspot с командой @Command([ViewArrangeIcons]) будет проигнорирован при доступе броузером - аналога такой команде для броузера нет. Хорошим применением для Hotspot'ов в Web-приложениях являются пользовательские кнопки для навигации по виду: пролистать вперед - @DbCommand("Domino";"ViewNextPage"); пролистать назад - @DbCommand("Domino";"ViewPreviousPage"); раскрыть все категории - @Command([ViewExpandAll]); свернуть все категории - @Command([ViewCollapseAll]); поиск - @Command([ViewShowSearhBar]);
Применение JavaScript Помимо использования опции Web Access: Use JavaScript when generating pages можно просто вставлять в формы или документы Notes код на JavaScript как составляющую HTMLкода. Однако распространено мнение, что не следует применять новейшие достижения в области кодирования HTML-страниц по крайней мере непосредственно на Home Page, так как это может «отпугнуть» пользователей броузеров, не поддерживающих последние расширения HTML и JavaScript. Ниже приводится HTML-код с функциями на JavaScript для кнопки типа Rollover. Внешний вид этой кнопки изменяется «при наведении» на нее курсора мыши. Код работает в Netscape Communicator 4 и MSIE 4. Предполагается, что файлы изображений для кнопки находятся в подкаталоге roll и называются imgname0.gif (обычное состояние) и imgname1.gif («под курсором мыши»). Функция changeButton(x,'imgname') меняет изображение кнопки с именем name="imgname". Весь код размещается в форме Notes и «попадает» внутрь тега . <script language="JavaScript">
Можно также использовать JavaScript в поле $$Return, например, чтобы после нажатия на кнопку Submit «вернуться» в истории на два шага назад: "<script>history.go(-2);";
5.2.5. Псевдособытия HTML Attributes Псевдособытия HTML Attributes используются для вставки HTML-атрибутов в теги, генерируемые для соответствующих элементов дизайна Notes.
• • •
Информация из HTML Attributes для формы «попадает» в HTML-атрибуты тега . Информация из HTML Attributes для Java-апплета «попадает» тег для отображения в броузерах, не поддерживающих Java, в качестве «альтернативного текста». Она вставляется непосредственно перед закрывающим тегом . Информация из HTML Attributes для полей используется в основном для указания размеров поля для ввода текста (в режиме редактирования). • Для полей всех типов, кроме Rich Text и Keywords, она «попадает» в HTML-атрибуты соответствующего полю тега . • Для поля типа Rich Text она «попадает» в HTML-атрибуты соответствующего полю тега . • Для поля типа Keywords она «попадает» в HTML-атрибуты соответствующего полю тега <select>.
В Notes версии 4.5 HTML-атрибуты для полей можно было указывать в свойствах поля на закладке Options в поле Help description. Например, [<size=5>]. В Notes версии 4.6 эта информация игнорируется, если в событии HTML Attributes для данного поля что-то указано.
© InterTrust Co. Тел. 956-7928
52
Разработка форм для Web-приложений Domino
5.2.6. Поля и их HTML-аттрибуты. Обеспечение функционирования полей ключевых слов HTML-атрибуты для полей используются в основном для указания их размеров и свойств в режиме редактирования. В Notes версии 4.6 для полей имеется специальное событие для этих целей - HTML Attributes. В нем «в кавычках» указываются необходимые атрибуты. Для всех редактируемых полей Domino автоматически генерируются атрибуты "name=FieldName type=FieldType". Задание этих атрибутов «вручную» может привести к экзотическим последствиям. Для всех полей, кроме Rich Text и Keywords, могут использоваться атрибуты size и maxlength, например, "size=30 maxlength=40", где size - длина поля для ввода в символах, а maxlength - максимальная длина строки, которую можно ввести в это поле. Для полей типа Rich Text могут использоваться атрибуты rows, cols и wrap, например, "rows=5 cols=70 wrap=virtual", где rows - число строк в текстовой области (по умолчанию 7); cols - число колонок в текстовой области (в символах, по умолчанию 50); wrap=virtual - если указано, переводы строк будут вычисляться автоматически в зависимости от размеров окна, в противном случае сохраняются «авторские» переводы строки. Для полей типа Keywords (тип Dialog list, многозначное) может использоваться атрибут size, например, "size=3", где size - число вариантов значения, видимых одновременно. Поле такого типа транслируется в HTML как тег <select> (список значений для выбора), если только у него не включена опция Allow values not in list. Если же эта опция включена, получается обычное редактируемое текстовое поле. Для создания конструкции, позволяющей выбирать значения из списка и вносить новые, рекомендуется использовать пару полей - обычное и типа Keywords, где при сохранении значение обычного поля добавляется к списку значений поля типа Keywords. Примеры кода HTML, сгенерированного Domino для полей различных типов. Пример 1. HTML-код, сгенерированный Domino для поля existtopic (keywords/multivalue/Dialog list) размером 3 строки, по умолчанию выбрано значение "Проверка А". <SELECT
NAME="existtopic" MULTIPLE size=3> VALUE="_d0n1gbs05uc2vg1f8_">Груши VALUE="_d0n50bo05u02v41f80nmgbqg5t0_">Картинки VALUE="_20n6gbrg5s82us1fh0np0bq109514q_">Новости IBM VALUE="_40n6gbrg5s82us1fh0np0bq109hnn8tbj_">Новости Lotus SELECTED VALUE="_o0n7gbs05to2u41f50no0bqg5s0g0bg0_">Проверка А VALUE="_00nfgbo85tc2us1fa0nk0_">Яблоки
Пример 2. HTML-код, сгенерированный Domino для поля Header (text) длиной 40 символов, значение "test - updatedby". Пример 3. HTML-код, сгенерированный Domino для поля Body (Rich Text) высотой 5 строк и длиной 70 символов с виртуальным (динамическим) переносом строк. Это текст в поле Body
5.2.7. Поле $$Return Используется для замены стандартного подтверждающего сообщения, возникающего после нажатия на кнопку Submit. В этом поле может быть задан код HTML или формула для его вычисления. Если «написать URL в квадратных скобках», то он будет открываться немедленно после нажатия на кнопку Submit.
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 53
Применение поля $$Return часто необходимо в пользовательских формах запросов (в том числе и $$Search), так как в этом случае URL запроса вычисляется на основе данных, которые пользователь заносит в поля формы. Пример 1. Формирование своего подтверждающего сообщения (текст + ссылка). "Документ был успешно сохранен Переход на базу Дискуссии " Пример 2. Автоматическое возвращение в истории на два шага назад (JavaScript). "<script>history.go(-2);";
Отметим, что эффект, обеспечиваемый полем $$Return, может быть также достигнут "печатью HTML-кода" оператором Print из LotusScript в агенте, запускаемом по событию WebQuerySave (при сохранении).
5.2.8. Доступ к переменным CGI Имеется два способа получения значения CGI-переменной: 1. агентом на LotusScript, запускаемым «из броузера» (по URL типа ?OpenAgent или на события WebQueryOpen или WebQuerySave), с использованием свойства DocumentContext класса NotesSession; 2. созданием вычисляемого поля типа text с именем, совпадающим с именем нужной CGIпеременной, и именем этой переменной в качестве формулы. Однако для агентов, запускаемых на события WebQueryOpen или WebQuerySave, надежно работает только сочетание обоих способов: в документе должны присутствовать поля, имена которых совпадают с именами требуемых CGI-переменных, тогда с помощью агента на LotusScript можно работать с их значениями. Сказать точнее, автору известен единственный случай, когда в агенте, запускаемом на событие WebQueryOpen, удалось получить значение CGI-переменной Query_String, не имея в форме поля Query_String. Пример 1. Получение значения CGI-переменной REMOTE_USER и занесение ее значения в поле Effect агентом, запускаемым на событие WebQueryOpen (поле remote_user должно присутствовать в документе): Dim sess As New notessession Dim doc As notesdocument Set doc = sess.DocumentContext Dim remote As Variant remote = doc.remote_user(0) Call doc.ReplaceItemValue("Effect", remote) Call doc.Save(True, False)
Если Вы хотите только сохранить значение CGI-переменной в документе, не оперируя с ним (значением) до трансляции документа в HTML, то это можно сделать, создав поле с именем, совпадающим с именем нужной переменной (способ 2), например REMOTE_USER типа text/Computed со значением REMOTE_USER. Cписок CGI-переменных приведен в разделе 3.3.2. Пример 2. Агент на LotusScript (из журнала THE VIEW), который выводит все доступные во время его запуска CGI-переменные. Sub Initialize Dim sess As New NotesSession Set doc = sess.DocumentContext
© InterTrust Co. Тел. 956-7928
54
Разработка форм для Web-приложений Domino
Print "Display context variables " Forall item In doc.items Print "" & item.Name & ": " If Isempty(item.Text) Then Print "EMPTY" Else Print item.Text End If End Forall End Sub Результат его работы приводится на следующем рисунке.
Рис. 5.8 Результат работы агента, выводящего все доступные CGI-переменные.
5.2.9. События WebQueryOpen и WebQuerySave WebQueryOpen и WebQuerySave - единственные события, которые происходят в форме при работе из Web-броузера.
WebQueryOpen По умолчанию имеет значение @Command([ToolsRunMacro]; ""). В этом событии указывается один или несколько агентов, которые выполняются до того, как документ будет преобразован в HTML и отправлен в броузер. Изменения, вносимые в документ агентами на @формулах, не отображаются при первом открытии HTML-страницы, так как документ изменяется на сервере уже после того, как его HTML-версия была передана броузеру. Для того, чтобы произвести изменения в документе до его трансляции в HTML и передачи броузеру, нужно в агенте, написанном на LotusScript, воспользоваться свойством DocumentContext класса NotesSession. В Notes версии 4.5 вместо данного события использовалось специальное текстовое поле $$QueryOpenAgent. В качестве его значения указывается имя (одного) агента. В Notes версии 4.6 содержимое поля $$QueryOpenAgent игнорируется, если какие-то агенты указаны в событии WebQueryOpen. С помощью агента на LotusScript можно сформировать страницу для конкретного пользователя (или в зависимости от других доступных CGI-переменных), но при этом важно учесть, что для использования CGI-переменной в документе должно присутствовать поле с
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 55
совпадающим с ней именем. Агент же должен иметь установки Run Manually From Actions Menu и Run once. Domino игнорирует вывод (Print), совершаемый агентом, запускаемым по событию WebQueryOpen. Пример. Увеличение счетчика обращений к документу (counter) на 1 и запись в поле Effect значения CGI-переменной REMOTE_USER. Поле remote_user должно присутствовать в документе. Sub Initialize Dim sess As New notessession Dim doc As notesdocument Set doc = sess.DocumentContext Dim remote As Variant Dim c As Variant, d As Variant remote = doc.remote_user(0) c = doc.counter(0) d = c+1 Call doc.ReplaceItemValue("Effect", remote) Call doc.ReplaceItemValue("counter", d) Call doc.Save(True, False) End Sub
WebQuerySave По умолчанию имеет значение @Command([ToolsRunMacro]; ""). В этом событии указывается агент, который выполняются перед тем, как документ будет сохранен в базе. Впрочем, документ может и не быть сохранен, если в нем присутствует поле SaveOptions со значением "0". В версии Notes 4.5 вместо данного события использовалось специальное текстовое поле $$QuerySaveAgent, а в качестве его значения указывалось имя агента. Примером использования такого агента могло бы быть создание других документов на основе информации из данного. Кроме того, такой агент может использоваться вместо поля $$Return для формирования подтверждающего HTML-сообщения - оно создается с помощью операций Print на LotusScript.
5.2.10. Computed Text Computed Text (вычисляемый текст) - новая возможность Notes версии 4.6, позволяющая вычислять по @-формуле фрагменты статического текста в форме и фрагменты текста в полях типа Rich Text. Использование Computed Text как вычисляемого статического текста в форме эквивалентно использованию полей типа Computed for display. Однако Computed Text в форме удобно использовать для вставки HTML-кода (как текст, «заключенный в квадратные скобки» или «написанный» стилем HTML). При использовании Computed Text в поле типа Rich Text его формулу после создания можно вновь отредактировать, выбрав в меню Hotspot/Edit Hotspot, а также можно изменить внешние атрибуты: тип рамки вокруг текста и его параметры (шрифт, выравнивание и т.д.). Вероятно, основное «достижение» Computed Text в полях типа Rich Text состоит в том, что пользователь, имеющий к базе уровень доступа ниже Designer, может «придать тексту некоторую вычисляемость», используя формулы наподобие "Hello "+@UserName.
© InterTrust Co. Тел. 956-7928
56
Разработка форм для Web-приложений Domino
5.2.11. $$-поля В Domino существует ряд специальных «двухдолларовых» полей, предназначенных для выполнения функций, присущих только Web-приложениям. Обычно для этих полей используется тип Text/Computed for display.
$$ViewBody На месте этого поля в форме отображается вид или папка, имя которой указанно в значении поля. В версии 4.6 аналогичного результата можно достичь, используя команду меню Create/Web element/Embedded View.
$$ViewList На месте этого поля в форме отображается стандартный навигатор folders. Значение поля игнорируется. В версии 4.6 аналогичного результата можно достичь, используя команду меню Create/Web element/Embedded Folders Pane.
$$NavigatorBody, $$NavigatorBody_n В качестве значения поля указывается имя навигатора или формула, вычисляющая имя навигатора. На месте этого поля в форме отображается соответствующий навигатор. В документе может быть несколько таких полей, различающихся только числом n. В версии 4.6 аналогичного результата можно достичь, используя команду меню Create/Web element/Embedded Navigator.
$$Return Используется для замены стандартного подтверждающего сообщения, возникающего после нажатия на кнопку Submit. В этом поле может быть задан HTML-код или формула для его вычисления. Если в качестве значения поля «написать URL в квадратных скобках», то этот URL будет открываться немедленно после нажатия на Submit. Отметим, что эффект, обеспечиваемый полем $$Return, может быть также достигнут из LotusScript «печатью HTML-кода» оператором Print в агенте, запускаемом на событие WebQuerySave.
$$HTMLHead В этом поле задается HTML-код или формула для его вычисления, добавляемый в тег Head. В поле обычно указывается мета-информация, например: <META NAME="Author" CONTENT="Sergei V. Budylov"> <META NAME="description" CONTENT="InterTrust Corp. is DB developer under Lotus Notes."> <META NAME="keywords" CONTENT="InterTrust, Lotus, Notes, Domino, Database, developer, reseller, distributor">
Может также даваться изображение для фона страницы () и определение основного окна вывода ( ).
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 57
$$QueryOpenAgent В качестве значения поля указывается имя агента (в кавычках), который запускается перед открытием документа. Domino игнорирует вывод, генерируемый при этом агентом. В версии 4.6 для этих целей существует событие WebQueryOpen, в котором по умолчанию указана следующая формула: @Command([ToolsRunMacro]; ""). Имя агента задается вместо .
$$QuerySaveAgent В качестве значения указывается имя агента (в кавычках) который запускается «после нажатия кнопки Submit»: после проверки полей (validation), но перед сохранением документа. В версии 4.6 для этих целей существует событие WebQuerySave, в котором по умолчанию указана следующая формула: @Command([ToolsRunMacro]; ""). Имя агента задается вместо .
5.2.12. Способы внедрения HTML в конструкции Notes В продвинутых Web-приложениях в элементы дизайна Notes часто «напрямую» включают HTML-код. Чаще всего это делается для вставки графических изображений в формы, документы и виды, а также для конструирования страниц с фреймами.
Заключение HTML-кода в квадратные скобки Это наиболее удобный способ для вставки короткого HTML-кода. Он позволяет размещать в одной строке объекты Notes и код HTML. Пример 1. Указание размеров редактируемых полей. Код вставляется в Help description в свойствах поля на закладке Options. Пример 2. Для полей типа text (размер поля для ввода / максимальная длина вводимой строки). [<size=30 maxlenght=40>] Пример 3. Для полей типа keywords (число видимых одновременно вариантов выбора). [<size=5>] Пример 4. Для полей типа Rich Text (размеры поля для ввода / способ переноса строк). [] Пример 5. Ссылка на графический файл. [ ] Пример 6. Горизонтальная линия. [ ] Пример 7. Сочетание текста и HTML в одной строке. [] Bold text here [ ] Пример 8. Создание hotspot'ов «вокруг» кода HTML. Это может быть необходимо, например, при замене стандартных акций для управления видом. URL для них вычисляется динамически, поэтому нельзя использовать предопределенные [... ]. [ ]
© InterTrust Co. Тел. 956-7928
58
Разработка форм для Web-приложений Domino
Назначение абзацу стиля HTML Можно создать стиль текста с зарезервированным названием HTML. Абзацы, «написанные этим стилем», будут без интерпретации вставляться Domino в генерируемый HTML-код.
Назначение абзацу атрибута Pass-Thru HTML Абзацы с таким атрибутом будут без интерпретации вставляться Domino в генерируемый HTML-код. По сравнению с предыдущим способом основное неудобство данного заключается в том, что стиль текста «виден» в строке статуса, а чтобы «посмотреть», установлен ли атрибут Pass-Thru HTML, нужно открыть пункт меню Text.
Поле с именем HTML Если в документе присутствует поле с именем HTML, Domino передает в броузер только содержащийся в нем текст - все остальное игнорируется.
Включение в свойствах формы флага Treat document contents as HTML Во многом аналогично использованию поля HTML. Весь видимый текст из документа без обработки передается броузеру как HTML-код. Аналогичное свойство имеется для видов.
Поле $$HTMLHead Содержимое поля передается в броузер как HTML-код между тегами и .
Событие HTML Attributes Позволяет добавить HTML-аттрибуты в некоторые теги. Рассматривалось в разделе 5.2.5.
5.3.
Web-элементы для форм 5.3.1. Embedded Navigator
Embedded Navigator - навигатор Notes, встроенный в форму. Он создается командой меню Create/Web element/Embedded Navigator. В одну форму можно вставить несколько навигаторов, в том числе вычисляемых по @-формуле. В Notes версии 4.5 подобное было реализовано с помощью специальных полей $$NavigatorBody и $$NavigatorBody_n. В качестве значения поля указывается имя навигатора или @-формула, вычисляющая имя навигатора. На месте такого поля в форме отображался соответствующий навигатор. В документе можно быть создано несколько таких полей, различающихся только числом n. Такой способ тоже работает и в версии 4.6.
5.3.2. Embedded View Embedded View - вид Notes, встроенный в форму. Создается командой меню Create/Web element/Embedded View. В форме может быть только один Embedded View, содержащий вид, имя которого задано явно или вычислено по @-формуле. В Notes версии 4.5 для достижения подобного использовалось поле $$ViewBody. В качестве значения поля указывалось имя вида или @-формула, вычисляющая имя вида. На месте этого поля в форме отображался соответствующий вид. В версии 4.6 этот способ тоже работает.
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 59
5.3.3. Embedded Folder Pane Embedded Folder Pane - стандартный навигатор Folders, встроенный в форму. Создается командой меню Create/Web element/Embedded Folder Pane. В форме может быть только один Embedded Folder Pane. В Notes версии 4.5 для этих целей использовалось поле $$ViewList, на месте которого отображался навигатор Folders. В 4.6 этот способ тоже работает.
5.3.4. File Upload Control File Upload Control - элемент для присоединения файлов к документу в базе Notes из броузера. Для того, чтобы создать такой элемент, нужно выбрать из меню Create/Web Element/File Upload Control. В Notes версии 4.5 аналогичный результат достигался путем создания Action Hotspot с формулой @Command([EditInsertFileAttachment]). Для File Upload Control Domino генерирует тег , например:
В броузере элемент выглядит как поле с кнопкой Browse. В этом поле пользователь броузера выбирает или вводит путь к файлу. Чтобы удалить присоединенный файл из документа в базе Notes, используя броузер, нужно в режиме редактирования пометить его для удаления и сохранить документ.
5.4.
Формы-шаблоны
5.4.1. Формы-шаблоны для видов Такие формы должны иметь имена $$ViewTemplateDefault или "$$ViewTemplate for viewname", где viewname - имя вида. В каждой форме необходимо поле $$ViewBody. Наличие формы "$$ViewTemplate for viewname" перекрывает использование $$ViewTemplateDefault для вида viewname. Соответствующая форма будет открываться при обращении из броузера к виду данной базы, а тело вида будет отображаться на месте поля $$ViewBody. Используется этот прием в основном для замещения стандартных акций, которые Domino генерирует по умолчанию, а также для отображения на одной странице дополнительных навигаторов и ссылок. Применяя такую форму, удобно задать и фоновое изображение для вида. Заметим, что последнее можно достичь и «приписаванием» к названию вида текста наподобие [], но это «будет заметно» в Notes.
5.4.2. Формы-шаблоны для навигаторов Такие формы должны иметь имена $$NavigatorTemplateDefault или "$$NavigatorTemplate for navname", где navname - имя навигатора. В каждой форме необходимо поле $$NavigatorBody. Наличие формы "$$NavigatorTemplate for navname" перекрывает использование $$NavigatorTemplateDefault для навигатора navname. Соответствующая форма открывается при обращении к навигатору navname, а навигатор отображается на месте поля $$NavigatorBody. Формы-шаблоны для навигаторов обычно используются для отображения на одной странице вида и дополнительных ссылок.
5.4.3. Формы-шаблоны для поиска Форма с именем $$Search заменяет стандартную форму для формирования поисковых запросов по базе (search.htm). Использование «своей» поисковой формы может оказаться © InterTrust Co. Тел. 956-7928
60
Разработка форм для Web-приложений Domino
неудобным в базе, в которой незарегистрированный пользователь не имеет права создавать документы. Форма с именем $$SearchTemplateDefault или "$$SearchTemplate for viewname", где viewname - имя вида, применяется для изменения способа оформления результатов поиска. В форме необходимо наличие поля $$ViewBody. По сравнению со страницей, которая генерируется по умолчанию, у такой не будет показываться количество найденных документов и текст запроса, а так же будет отсутствовать конструктор уточняющего запроса. Форма с именем $$SearchSiteTemplate используется для изменения способа оформления результатов поиска в базе SearchSite. По сравнению со страницей, которая генерируется по умолчанию, у такой не будет показываться количество найденных документов и текст запроса, а так же будет отсутствовать конструктор уточняющего запроса.
5.4.4. Формы-шаблоны обработки ошибок в Domino Для оформления сообщений об ошибках в конкретной базе в соответствии с необходимым вам стилем применяются формы со следующими зарезервированными названиями.
• • • •
$$ReturnDocumentDeleted - подтверждение успешного удаления документа. $$ReturnAuthenticationFailure - сообщение о том, что такой пользователь с таким паролем не зарегистрирован на сайте. $$ReturnAuthorizationFailure - сообщение о том, что данный пользователь не имеет достаточно прав для выполнения данной операции. $$ReturnGeneralError - выдается на любую другую ошибку.
Однако следует земетить, что замена стандартных сообщений об ошибках часто делает эти сообщения менее информативными. Например, для следующей ошибки Error 500 HTTP Web Server: Lotus Notes Exception - Special database object cannot be located
будет известно только то, что она относится к типу General Error.
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 61
6. Разработка видов, навигаторов и карт-изображений для Web-приложений Domino 6.1.
Виды
Domino транслирует для броузера вид Notes в таблицу HTML, по умолчанию не более чем из 30 строк. Такое «количество строк по умолчанию» задается в общей адресной книге в документе Server в секции HTTP Server, в поле Lines per view page. Для конкретного URL, указывающего на вид, максимальное количество строк таблицы задается параметром Count в самом URL. Стандартные кнопки позволяют "пролистывать" вид в обоих направлениях, раскрывать/сворачивать все категории и создавать поисковый запрос для полнотекстового поиска по данной базе. Для стандартных операций со видом используются следующие формулы: пролистнуть вперед - @DbCommand("Domino";"ViewNextPage"); пролистнуть назад - @DbCommand("Domino";"ViewPreviousPage"); раскрыть все категории - @Command([ViewExpandAll]); свернуть все категории - @Command([ViewCollapseAll]); поиск - @Command([ViewShowSearhBar]). Следует отметить, что содержимое колонки с ответными документами (с «включенной» опцией Show responses only) отображается в том же столбце таблицы, в которую Domino преобразовал вид, что и следующая видимая колонка вида. При этом, несмотря на то, что на каждый ответный документ в виде выделяется отдельная строка, Domino не использует для HTML-аналога этой строки параметр colspan для объединения столбцов. В результате текст, соответствующий в виде ответному документу, может располагаться «в несколько строк узким столбцом», несмотря на то, что справа от него может быть свободное место. Бороться с таким эффектом можно путем размещения в виде сразу за колонкой с ответными документами одной широкой колонки, которая была бы последней видимой колонкой в виде.
6.2.
Навигаторы и карты-изображения
Карты-изображения (Image Map) позволяют получить эффектный (в смысле внешнего вида) набор гипертекстовых ссылок. Суть в том, что на одном графическом изображении выделяются несколько активных зон, каждая из которых является гипертекстовой ссылкой. Преимущество карты-изображения состоит в том, что один «большой» файл «скачивается» значительно быстрее, чем несколько «маленьких» с таким же суммарным размером. Недостатком карты-изображения для разработчика в первую очередь является неудобство внесения изменений в единый графический файл вместо замены «одного маленького». Использование векторно-объектной графики навигаторов Notes теоретически снимает эту проблему. Но поскольку редактор, используемый в Notes для создания навигаторов, достаточно примитивен, его возможностей может не хватить для создания чего-то «действительно красивого». А если вы хотите сделать так, чтобы графические кнопки «подсвечивались» при наведении на них курсора мыши, то и Image Map вам уже не подойдет. Недостатком карты-изображения для пользователя является невозможность воспользоваться ее встроенными ссылками до того, как изображение полностью загрузится в броузер. Кроме того, альтернативный текст для Image Map броузеры MSIE 3.02 и 4.0 не
© InterTrust Co. Тел. 956-7928
62
Разработка видов, навигаторов и карт-изображений для Web-приложений Domino
показывают вообще, а Netscape Communicator 4.04 показывает только при наведении курсора мыши на ссылку. Примером хорошего применения карты-изображения может быть интерактивная карта города, из которой можно открывать карты районов, «кликая» на них мышью. Генерируя HTML, Domino преобразует навигаторы Notes в карты-изображения, но при этом имеются три недостатка. 1. При обращении к навигатору некоторое время расходуется на преобразование его объектно-векторной графики в растровое изображение. 2. Если в используемом изображении больше 16 цветов, его палитра может заметно изменится при просмотре в броузере. Кроме того, «не сглаживается» текст (вероятно, ради быстроты преобразования) и не поддерживается анимация GIF89a. 3. В свойствах активной области навигатора нельзя указать для нее альтернативный текст. Если навигатор Notes имеет небольшие размеры и точная цветопередача вам не критична, навигатор можно рекомендовать к использованию. В том же случае, когда недостатки применения навигатора существенны, вам придется создать необходимый графический файл и фрагмент HTML-кода для карты-изображения. При подготовке HTML-кода для карты-изображения вам может сослужить «добрую службу» редактор, используемый в Notes для создания навигаторов. Технология такова. 1. Подготовленное изображение поместите в Graphic Background навигатора (можно с помощью File/Import). 2. Поверх изображения «расставьте» нужные активные области (hotspot'ы). 3. Выберите для hotspot'ов в качестве действия Simple action(s)/Open URL и укажите нужный URL. Если URL пока не неизвестен, вместо него можно указать любой идентификатор, позволяющий Вам опознать эту ссылку в HTML-коде и впоследствии заменить нужным URL. 4. Открыв после всего этого навигатор в броузере, остается получить и сохранить HTMLкод этой страницы. В нем будет присутствовать необходимый Image Map. Так значительно быстрее, чем «вручную вбивать» координаты областей в HTML-код. Остается привести пример HTML-кода для карты-изображения. <MAP NAME="main.map">
Выглядит же эта карта-изображение в броуэере следующим образом (фрейм слева).
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 63
Рис. 6.1 Набор ссылок, организованный в Image map (фрейм слева) Отметим, что в Notes версий 4.5 многие элементы навигаторов не работали в при просмотре броузером, а наличие у навигатора Graphic Background было для Domino обязательным.
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 65
7. Разработка агентов для Web-приложений Domino В Notes агенты используются для автоматизации выполнения многих задач, например создания документов, отправки почты, поиска, архивирования устаревших документов. Существует несколько способов активации (запуска) агентов: по расписанию, при «вставке» документов в базу из буфера обмена, при поступлении новой почты, при создании или модификации документов. Пользователь может также запустить агента, «кликнув» мышкой на кнопке, hotspot’у или акции формы или вида с формулой @Command([ToolsRunMacro]) или URL с операцией ?OpenAgent. Однако агенты Notes обычно ориентированы больше на работу с ними с клиентского места Notes, чем из Web-броузера. Поэтому для выполнения одной и той же задачи как из клиента Notes, так и из броузера, чаще приходится использовать два набора агентов, каждый из которых специализирован для одного интерфейса. Основная причина такого разделения - различия в способах взаимодействия агента с пользователем в разных средах. В Notes агент может запрашивать и получать информацию от пользователя в различных диалоговых окнах и изменять значения полей непосредственно в открытом в клиенте Notes документе. Единственный же способ передать информацию клиенту броузера (без применения JavaScript) создать и загрузить в броузер HTML-страницу. При этом разработчик Web-приложения может внести агентом изменения в текущий документ или перед тем, как по этому документу сервером будет сгенерирован и передан в броузер HTML-код (агент на событие WebQueryOpen), или после того, как данные HTML-формы будут переданы из броузера на сервер, но перед тем, как документ будет сохранен сервером (агент на событие WebQuerySave). Агенты для пользователей Web чаще всего пишутся на LotusScript или Java, поскольку «простые действия» Notes недоступны в Web-приложениях, а @-формулы не позволяют возвращать информацию пользователю.
7.1.
Агенты с опцией Run agent as Web User
Notes всегда осуществляет контроль прав доступа запускаемого и выполняемого агента. Агент, запускаемый пользователем Notes «вручную», имеет такие же права доступа, как и запустивший его пользователь. Права агента, выполняемого сервером по расписанию или событию, определяются правами создателя или последнего редактора этого агента (того, кем подписан агент). Один из вариантов агентов, доступных пользователям Web-броузеров - агенты с опцией Run agent as Web User.
Рис. 7.1 Свойства агента. Закладка Design
© InterTrust Co. Тел. 956-7928
66
Разработка агентов для Web-приложений Domino
Чтобы такой агент мог быть запущен сервером, создатель или последний редактор агента (тот, кем агент подписан) должен иметь на сервере права на выполнение агентов. Хотя пользователи броузеров не имеют ID-файлов, Domino способен аутентифицировать их. Поэтому при выполнении такой агент обладает правами не его создателя, а запустившего его пользователя броузера.
7.2.
Агенты - аналоги программ CGI
Поведение агента, запускаемого на сервере Domino из web-броузера, очень похоже на поведение CGI-програмы, запускаемой на «обычном» HTTP-сервере. Во-первых, такие агенты могут «печатать» операторами Print языка LotusScript HTML-код, который по завершении работы агента передается броузеру. Если же операторов Print в агенте нет, по окончании его работы в броузер посылается «подтверждающее сообщение» Agent done. Во-вторых, агентам, запускаемым из броузера, доступны переменные CGI. В данном разделе мы рассмотрим только агенты, запускаемые на сервере Domino из броузера «вручную» по команде @Command([ToolsRunMacro]) или по URL с операцией ?OpenAgent. Агенты, запускаемые по событиям WebQueryOpen и WebQuerySave будут рассмотрены в следуюших разделах главы. Пример 1. Агент AddBook, создающий по информации из CGI-переменных вспомогательный документ в базе и посылающий в броузер подтверждающее сообщение. Агент запускается по вычисляемому в hotspot’е URL наподобие http://host/DbName/AddBook?OpenAgent&UNID, где параметр UNID задает универсальный идентификатор документа, из которого запущен агент. Sub Initialize Dim sess As New NotesSession Dim doc,element As NotesDocument Dim dateTime As NotesDateTime Dim db As NotesDatabase Dim c,c1,d As Variant Set db=sess.CurrentDatabase Set dateTime = New NotesDateTime( "Today" ) Set element=New NotesDocument( db ) Set doc = sess.DocumentContext ‘Получение строки запроса (в данном случае вида ?OpenAgent&UNID) c = doc.Query_String(0) ‘Получение UNID документа из строки запроса c1 = Right(c, 32) ‘Получение IP-адреса пользователя d = doc.Remote_Addr(0) ‘Формирование полей документа и его сохранение Call element.ReplaceItemValue("Date", dateTime) element.UNID = c1 element.IP = d element.Form = "Element" Call element.Save(True, False) ‘Выдача подтверждающего сообщения в броузер Print "Книга добавлена в корзину " Print c1 Print " " Print d End Sub Пример 2. Агент для обработки данных, получаемых из формы методами POST и GET. HTML-код формы, использующейся для сбора информации. © InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 67 test page - post and get methods <SCRIPT LANGUAGE="JavaScript"> Агент WebQR получает информацию из формы и отправляет в броузер подтверждающее сообщение о полученной информации. Sub Initialize Dim s As New NotesSession Dim db As NotesDatabase Set db = s.CurrentDatabase Dim note As NotesDocument Set note = s.DocumentContext Dim RM As String Dim QS,QSD As String Dim CT As String Dim RC, RCD As String RM = note.Request_Method(0) Print "Request_Method="+RM+" " If ( 0 = Strcompare(RM, "GET", 1) ) Then ' Метод GET - аргументы в Query_String QS = note.Query_String(0) QSD = decode((QS)) Print "
Query_String="+QS+" " Print "
Decoded Query_String="+QSD+" " End If If ( 0 = Strcompare(RM, "POST", 1) ) Then ' Метод POST - аргументы в Query_String и REQUEST_CONTENT QS = note.Query_String(0)
© InterTrust Co. Тел. 956-7928
68
Разработка агентов для Web-приложений Domino
QSD = decode((QS)) Print "
Query_String="+QS+" " Print "
Decoded Query_String="+QSD+" " CT = note.Content_Type(0) Print "
Content_Type="+CT+" " RC = note.Request_Content(0) RCD = decode((RC)) Print "
Request_Content="+RC+" " Print "
Decoded Request_Content="+RCD+" " End If End Sub Функция decode, обрабатывающая получаемые строки. Function decode(content As String) As String ' Декодирование "URL-encoded" строки Dim answer, achar, hexdigits As String Dim pos, max, charval As Integer On Error Goto errhandle max = Len(content) pos = 1 answer = "" While ( pos <= max ) achar = Mid(content, pos, 1) pos = pos + 1 Select Case Asc(achar) ' "+" заменяется на пробел Case 43: answer = answer + " " ' "%ff" заменяется на символ с кодом &Hff Case 37: hexdigits = Mid(content, pos, 2 ) pos = pos+2 hexdigits = "&H" + hexdigits charval = Cint( hexdigits ) answer = answer + Chr( charval ) ' иначе никаких преобразований не выполняется Case Else: answer = answer + achar End Select Wend decode = answer On Error Resume Next errhandle: Exit Function Данный пример корректно работает при использовании для передачи информации метода POST. Но при использовании метода GET выдается ошибка Error 500 HTTP Web Server: Unknown Command Exception. Причина ошибки никак не связана с кодом самого агента WebQR. Дело в том, что броузер, формируя на основе строки document.forms[0].action = "http://mainint.inttrust.ru/WorkDatabases/Edication/eSuite.nsf/WebQR?OpenAgent"; окончательный URL запроса для метода GET, игнорирует необходимый для Domino параметр операцию ?OpenAgent. Вычисленный броузером URL имеет примерно следующий вид, но он недопустим как URL Domino, отчего сервер и возвращает приведенную выше ошибку. http://main-int.inttrust.ru/WorkDatabases/Edication/eSuite.nsf/WebQR? n1=v1&n2=v2&n3=%F0%F3%F1%F1%EA%E8%E9+%F2%E5%EA%F1%F2
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 69 Если же вместо агента используется подобная ему по функциональным возможностям CGIпрограмма или сервлет, то сформированный URL броузером будет воспринят корректно и передача данных по методу GET «отработает как положено».
7.3.
Агент на событие WebQueryOpen
По умолчанию событие WebQueryOpen имеет значение @Command([ToolsRunMacro]; ""). В этом событии указываются один или несколько агентов, которые выполняются до того, как этот документ будет преобразован сервером в HTML и отправлен в броузер web-клиента. В Notes версии 4.5 вместо данного события использовалось специальное текстовое поле $$QueryOpenAgent, а в качестве его значения указывается имя (одного) агента. В Notes версии 4.6 поле $$QueryOpenAgent игнорируется, если какие-то агенты указаны в событии WebQueryOpen. Для того, чтобы «убрать агент из WebQueryOpen», нужно удалить весь текст из окна формулы агента. Тогда при переключении на другое событие в WebQueryOpen восстановится стандартное @Command([ToolsRunMacro]; ""). Учтите, что изменения, вносимые в документ агентами события WebQueryOpen, «написанными» на @-формулах, не отображаются при первом просмотре этого документа в броузере. Поэтому агенты события WebQueryOpen обычно разрабатывают на языке LotusScript. Агент должен иметь опции When: Run Manually From Actions Menu и Run once. Такой агент может иметь доступ к CGI-переменным. Для агентов события WebQueryOpen (и WebQuerySave) при использовании CGI-переменных в документе должно присутствовать вычисляемое поле с именем, совпадающим с именем нужной CGI-переменной и именем этой же переменной в качестве формулы поля. Domino игнорирует вывод оператором Print, порождаемый агентом WebQueryOpen. Пример 1. Агент события WebQueryOpen (Run: Manually from action menu; Type: Run once) при каждом обращении к документу увеличивает на единицу счетчик обращений (поле counter). В документе присутствует поле сounter типа Number/Editable. Sub Initialize Dim sess As New notessession Dim doc As notesdocument Set doc = sess.DocumentContext Dim c As Variant, d As Variant c = doc.counter(0) d = c+1 Call doc.ReplaceItemValue("counter", d) Call doc.Save(True, False) End Sub Пример 2. Усовершенствованный вариант агента из предыдущего примера. Счетчик увеличивается только при запросах с операцией ?OpenDatabase, что выявляется анализом строки запроса query_string (содержит часть URL после знака "?"). Кроме того, агент используется для увеличения счетчиков в формах htmlstarterc. В форме присутствуют поля Counter типа Number/Editable и Query_string типа Text/Computed for display. Dim sess As New notessession Dim doc As notesdocument Set doc = sess.DocumentContext Dim c As Variant, d As Variant, q As Variant, f As Variant q=doc.query_string(0) f=doc.form(0) If q="OpenDatabase" Or f="htmlstarterc" Then c = doc.counter(0) d = c+1 Call doc.ReplaceItemValue("counter", d)
© InterTrust Co. Тел. 956-7928
70
Разработка агентов для Web-приложений Domino Call doc.Save(True, False) End If
Пример 3. Счетчик обращений можно «написать» и на @-формулах. Но такой счетчик «будет показывать в броузере» номер предыдущего обращения, поскольку значение поля counter увеличивается на единицу после того, как HTML-код документа был передан в броузер. Заметим, что для того, чтобы этот агент заработал, поле-счетчик counter должно содержать число. SELECT Form="HomePage"; (условие отбора) FIELD counter:=counter+1;
7.4.
Агент на событие WebQuerySave
По умолчанию событие WebQuerySave имеет значение @Command([ToolsRunMacro]; ""). В этом событии указывается агент, который выполняется сервером после нажатия пользователем броузера кнопки Submit в HTML-форме, соответствующей документу. Точнее, после того, как сервер выполнит проверку полей (Field’s validation) в уже измененном в виртуальной памяти сервера документе, но перед сохранением этого документа в базе. Впрочем, измененный документ может быть и не сохранен в базе, если в нем имеется поле SaveOptions со значением "0", а агент события WebQuerySave не производит принудительного сохранения методом Save на LotusScript. В Notes версии 4.5 вместо данного события использовалось специальное текстовое поле $$QuerySaveAgent, в качестве его значения указывалось имя агента. Агенты, выполняемые по событию WebQuerySave, можно применять для создания в базе документов на основе информации, переданной Web-клиентом. Например, агент из стандартной базы-примера domreg.nsf, создающий в адресной книге документ Person для Webклиента по заполненному клиентом документу-заявке на регистрацию. Другое применение - формирование новой или открытие существующей HTML-страницы «посредством печати» HTML-кода операторами Print на LotusScript. Пример. Агент выдает в броузер подтверждающее сообщение при сохранении документа. Для работы с CGI-переменной в документе присутствует поле remote_user типа text/Computed for display с формулой remote_user. Sub Initialize Dim sess As New notessession Dim doc As notesdocument Set doc = sess.DocumentContext Dim remote As Variant remote = doc.remote_user(0) Print "Документ был успешно сохранен " Print "Спасибо за участие в нашем форуме, "+remote+" " End Sub
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 71
8. Создание сайта на основе Lotus Domino 8.1.
Обзор примеров из каталога Sample (R4.6)
Прежде чем приступать к разработке собственного сайта, полезно ознакомиться с примерами сайтов, поставляемых в составе дистрибутива Lotus Domino 4.6 (каталог Sample). Вероятно, наибольшую практическую ценность из представленных примеров представляет Domino 4.6 Samples: Registration. Использование этой базы позволяет сразу решить непростую задачу online-регистрации пользователей на сайте. Domino 4.6 Samples: FAQ и Web Pages - относительно простые базы, типичные приложения для сайта на Domino. В базах Domino 4.6 Samples: Site1, Site2, Site3 и Frameset «есть на что посмотреть», но все они скорее напоминают инструмент «для штампования одинаковых сайтов», чем пример действующего сайта на Domino. Вряд ли вебмастеру, знакомому с HTML, «придет в голову» написать для себя средствами Notes достаточно сложную оболочку для конфигурирования фреймсета вместо того, чтобы «вручную вставить несколько строчек» нужного фреймсета.
8.1.1. Domino 4.6 Samples: FAQ База предназначена для использования на сайте в качестве зоны FAQ (часто задаваемые вопросы). Сделана просто и корректно. Каждый документ вычисляет собственный URL, по которому к нему можно обратиться. Специальный агент, запускающийся по событиям добавления или модификации документов, создает сводный документ с внутренними ссылками на материалы всех документов FAQ, чтобы содержимое базы было легко распечатать. База расчитана на заполнение из клиента Notes. Редактировать документы могут только пользователи, назначенные на роль FAQ Maintainer. При создании документов используется простой механизм workflow, управляемый полем Status. Предполагается, что вначале создается документ со статусом черновик (Draft), доступный всем редакторам для чтения и редактирования, но пока «невидимый для внешнего мира». Установка статуса документа в Reserved запрещает другим редакторам редактировать данный документ. Когда документ «готов увидеть мир», выставляется статус Public: теперь документ могут читать все, а редактировать по-прежнему FAQ Maintainer'ы.
8.1.2. Domino 4.6 Samples: Registration База реализует Online-регистрацию на сайте. Это требуется, например, когда пользователь создает документ на сайте, и нужно сделать так, чтобы только он и группа поддержки сайта могли редактировать этот документ. Пользователь сам заполняет регистрационную форму, данные из которой затем используются агентом для создания соответствующего документа Person в общей адресной книге. Но лучше «не засорять» корпоративную общую адресную книгу документами Person для Web-пользователей, а создавать эти документы в отдельной общей адресной книге, например, с названием WebNames.nsf. После создания такой адресной книги необходимо сделать ее доступной всем серверам домена: включением либо в список в базе Master Address Book, либо в список переменной Names в файле NOTES.INI серверов. Рекомендации по настройке базы. 1. Добавьте себя и ваш сервер в ACL базы WebNames.nsf в качестве менеджеров и назначьте на роль UserManager. Если эта база будет реплицироваться на несколько серверов, убедитесь, что все эти серверы назначены на роль UserManager.
© InterTrust Co. Тел. 956-7928
72
Создание сайта на основе Lotus Domino
2. Укажите в поле GroupsToJoin в форме New Account название группы из общей адресной книги, в которую будут включаться все регистрирующиеся Web-пользователи. По умолчанию значение этого поля . Группа с выбранным вами названием будет создана автоматически при регистрации первого пользователя. 3. Добавьте эту группу в ACL с доступом Author с правом создания документов и назначьте ее на роль Web Users. 4. Измените в библиотеке скриптов Modifiable Constants в объявлениях (Declarations) значения констант на соответствующие действительности (например, WebNames.nsf и Names.nsf). Учтите, что группа обязательно должна формироваться в основной адресной книге. 5. Убедитесь, что ваши агенты на LotusScript будут выполняться сервером - в документе Server в основной адресной книге в секции Agent Manager. Убедитесь, что в ACL основной адресной книги вы назначены на роли, позволяющие создавать и редактировать документы групп (GroupCreator, GroupModifier) и пользователей (UserCreator, UserModifier). 6. Пересохраните агенты Handle Change Password Request и Handle New Account Request под своим ID-файлом, чтобы они могли выполняться сервером и записывать изменения в основную адресную книгу. Для этого вставьте в текст агента пустую строку и пробел и сохраните его - это вызовет перекомпиляцию агента. 7. В ACL базы предоставьте Anonymous доступ автора с правом создания документов. Затем на закладке Advanced установите Maximum Internet name and password access = Author. Хотя Domino корректно регистрирует пользователя под русским именем, «слогиниться» потом под ним из броузера невозможно. В связи с этим не забудьте добавить в регистрационную форму соответствующее предупреждение. В данной базе имя пользователя (поле User Name в документе Person) вычисляется на основе информации из полей First Name, MiddleInitial и LastName, а не указывается отдельно. При желании такое поведение можно исправить: в поля First Name, MiddleInitial и LastName заносить русское имя, а в поле User Name - английское имя. Но при аутентификации все равно придется указывать то, что написано в User Name. Необходимо также скорректировать подтверждающие сообщения, генерируемые агентами Handle Change Password Request и Handle New Account Request по окончании их работы (подтверждение успешной регистрации, успешной смены пароля и т.д.). Для этого нужно просмотреть текст агентов и изметить информацию, выводимую операторами Print. Хорошо произвести и некоторые косметические изменения в дизайне базы.
8.1.3. Domino 4.6 Samples: Frameset На первый взгляд может показаться, что эта база представляет собой пример-оболочку для создания страниц с фреймами. Однако, скорее, это «самодостаточный сайт». Без сомнения, в этой базе «есть чему поучиться». В базе существуют 5 основных типов документов:
• • • • •
Frameset - страница с фреймами; Frame Content\Column of links to target frame - страница со столбцом текстовых ссылок; Frame Content\Site Map links to target frame - страница со встроенным видом Site Map; Frame Content\Web page - просто страница; Frame Content\Web page using HTML - HTML-страница.
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 73
При создании страницы с фреймами с помощью Frame Wizard выбирается одна из типичных конфигураций фреймов на странице, и далее в нескольких диалогах конфигурируются их параметры, включая URL для каждого фрейма. Способ генерации ссылок в документах типа Column of links to target frame может вызвать удивление: предполагается, что вводимые URL являются содержимым первой колонки скрытого вида (Lookup). Описание используемого «спецсинтаксиса» можно получить при нажатии соответствующей кнопки подсказки. Например, для указания абсолютного URL используются два слэша вначале: //www.lotus.com. В базе использованы два основных приема. 1. Формирование HTML-кода в скрытом вычисляемом поле на основании значений конфигурационных полей. 2. Использование разных форм для просмотра документов из Notes и из броузера. Способ для отображения фреймов: комментирование автоматически генерируемого Domino тега . Это достигается следующим образом. В самом начале формы находится поле $$HTMLHead, у которого в конце формулы «включено» начало комментария: "", а за ним поле с текстом фреймсета. Таким образом, тег оказывается «закомментированным», и ничто не мешает отображению фреймсета. В базе реализован механизм для работы с присоединенными графическими файлами, которые могут использоваться в качестве линков (графических кнопок). Также дается совет, как формировать HTML-ссылки на эти файлы.
8.1.4. Domino 4.6 Samples: Web Pages, Site1, Site 2, Site 3 Domino 4.6 Samples: Web Pages Данную базу рекомендуется изучать в качестве самого простого примера - это пример готового сайта в одной базе. Используются документы-аналоги HTML-страниц. Один из них назначается в качестве Home Page и открывается первым при открытии базы броузером. Кроме назначения Home Page, остальное похоже на часть базы Domino 4.6 Samples: Frameset.
Domino 4.6 Samples: Site 1 Еще один пример готового сайта в одной базе. По сравнению с Web Pages добавлена возможность формировать линки на каждой странице (в виде текста или картинок), а также Site Map.
Domino 4.6 Samples: Site 2 Очередной пример готового сайта. На этот раз текстовые линки «в строчку» были жестоко заменены на столбец встроенных в форму навигаторов.
Domino 4.6 Samples: Site 3 Последний пример готового сайта. Однако 10 вычисляемых линков заменены встроенным в форму навигатором. В результате дизайн базы стал проще, чем у Site1 и Site2.
© InterTrust Co. Тел. 956-7928
74
Создание сайта на основе Lotus Domino
8.2.
Планирование сайта
Вначале стоит сказать несколько слов о продукте Domino.Action 1.0, предназначенном для «быстрого и простого» создания полноценного web-сайта. Продукт поставляется в виде двух шаблонов (NTF) баз Notes. На основе этих шаблонов создаются две базы, одна из которых является библиотекой элементов (изображений), а вторая - конфигурационной программой и инсталлятором сайта. В процессе конфигурирования вам в первую очередь будет предложено выбрать, из каких зон должен состоять ваш сайт, т.е. фактически какие функции он будет выполнять. Предлагаемый список зон очень обширен, а в случае Domino.Merchant 1.0 в нем имеются еще и возможности электронной торговли. Конфигурированием будущего сайта можно заниматься долго, особенно если заносить собственные изображения в базу-библиотеку элементов Domino.Action. Когда все сконфигурировано, запускается AppAssembler, который и создает соответствующие выбранным зонам базы. Результаты его работы удивительны… Так, выбрав из зон только Home Page, Registration и Order Processing Area, автор получил базу HomePage размером 4MB с 285 документами, хотя ожидал одного, который открывается «как HomePage». Количество полей в формах этой базы может «привести в ужас» даже опытного разработчика. Но самое интересное, что некоторые линки при этом работали неправильно, а найти и исправить их оказалось далеко не простым делом… Имелись и другие случаи, подтверждающие это. Один из знакомых автора успешно установил у себя Domino.Action и был чрезвычайно доволен этим продуктом, однако хотел кое-что изменить: добавить в Home Page линк на новую базу. В ходе разговора выяснилось, что он не знает, где же собственно находится Home Page и как ее можно редактировать. По мнению автора, пользоваться этим сложным продуктом могут или трудолюбивые специалисты высокого класса, или те, кто не знает даже в общих чертах, как работает Domino и что такое HTML, и считает, что такие знания и не нужны вовсе… Если вы не остановили свой выбор на Domino.Action, давайте рассмотрим типичный набор компонент (зон) сайта. 1. Home Page - страница, которая открывается первой при обращении к Web-серверу. На ней размещаются ссылки на различные области сайта и служебные элементы, например, счетчик обращений. Для упрощения структуры сайта для «хранения этой страницы» можно использовать отдельную базу. В дальнейшем вам скорее всего понадобится создать в этой базе как минимум еще и английскую версию странички Home Page. 2. Информация о компании - краткое описание компании. Для него обычно хватает одной странички. Если у вас уже имеется такая страничка в формате HTML, можно использовать и ее. Но документ Notes предпочтительнее в том плане, что в будущем его будет проще редактировать человеку, не желающему иметь дело с HTML-редакторами. Такую базу тоже можно создать одну для всех версий About Our Company. 3. Продукция/услуги. Конечно, это уже база Notes. Она может быть предназначена только для чтения (каталог) или предоставлять возможность создавать в ней заказы на продукты/услуги. Если классификация продукции имеет сложную структуру, возможно, следует создать даже несколько таких баз, чтобы уменьшить число уровней документов и облегчить поиск. 4. Новости. База типа «библиотека документов», открытая для web-клиентов только на чтение. В ней публикуются корпоративные новости, анонсы выхода новых продуктов/услуг и пресс-релизы, касающиеся области деятельности фирмы или самой фирмы. 5. Свежие новости (Hot News). Линк на этот раздел должен быть хорошо заметен на Home Page. Там размещаются «самые свежие новости». Физически же это удобно организовать в базе «Новости» как папку (folder), в которую «одним нажатием на кнопку» можно поместить любой документ из базы.
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 75
6. Дискуссии. Все могут задавать вопросы или отвечать на них, «работая» в этой базе. База организуется для того, чтобы уменьшить количество консультаций по телефону. Общедоступность базы повышает эффективность размещения в ней вопросов. Рекомендуется разрешать создавать документы в этой базе только пользователям, зарегистрированным на сайте. 7. Прайс-листы. Они могут пригодится, если в вашу компанию часто звонят и интересуются ценами. Физически это может быть специальный вид в базе «Новости» или отдельная база. 8. Работа. Если ваша компания часто набирает сотрудников, разумно сделать на сайте раздел с описанием имеющихся вакансий. 9. Регистрация. Важна для поддержания баз, в которых web-клиенты могут создавать документы. База хранит свои внутренние документы на пользователей и «автоматически создает» документы Person в адресной книге Notes. Чтобы потенциально большое число зарегистрированных Web-пользователей «не замусорило» общую адресную книгу, можно выделить для них отдельную адресную книгу. Для удобства организации управления доступом в общей адресной книге создается группа, в которую автоматически включаются все регистрирующиеся Web-клиенты. 10. Поиск. Позволяет осуществлять полнотекстовый поиск на сайте. Для этого используется конфигурационная база, создаваемая по шаблону Sarch Site.
8.3.
Разработка сайта
8.3.1. Общие рекомендации Чтобы иметь минимум проблем с безопасностью, рекомендуется выделить для Web-сервера отдельный компьютер. Если же Web-сервером «по совместительству» является внутрикорпоративный сервер Notes, а на нем находятся базы, не предназначенные «для широкой общественности», администратору придется более внимательно следить за их ACL. Всегда полезно «посмотреть» на созданный элемент сайта из разных броузеров, так как каждый из них интерпретирует HTML «несколько по-своему». Так как по умолчанию броузер использует для отображения документа свои шрифты, имеет смысл использовать один шрифт, изменяя лишь его атрибуты (размер, цвет, начертание). Поскольку при трансляции текста из Notes в HTML игнорируются табуляции и дополнительные пробелы, используйте для выравнивания текста таблицы. В HTML линии таблицы либо все видны, либо все скрыты. Соблюдение регистра букв в названиях баз, видов, и т.д. необходимо для систем отличных от Windows, а для русских букв необходимо и в Windows. Не пренебрегайте регистрами в ссылках. Использование длинных имен файлов может причинить некоторые неудобства пользователю системы, не поддерживающей длинных имен. Теги (tag) HTML рекомендуется писать заглавными буквами. Полезно указывать размеры картинок использующихся в тегах .
1.1.2. Home Page Страница Home Page - лицо вашего сайта. Как правило она должна содержать логотип, название компании и в краткое описание рода ее деятельности. Основная сложность здесь совместить высокую скорость считывания страницы и ее красивый внешний вид. Удовлетворить все пожелания невозможно, однако, скорее всего, главное - это удобство и функциональность.
© InterTrust Co. Тел. 956-7928
76
Создание сайта на основе Lotus Domino
Создайте базу с названием Home Page и именем файла HomePage.nsf в каталоге Site (физически в подкаталоге Site каталога данных Notes). Установите в ACL базы доступ Reader для -Default- и Manager для себя. Наиболее удобно было бы создать форму (form) со всем необходимым содержанием, затем создать по этой форме единственный документ и открывать этот документ при обращении к базе. Но есть одна небольшая проблема - если вставлять изображения в базу Notes операциями Paste или Import, то Domino будет генерировать для них URL с операцией ?OpenElement. Это может помешать устаревшим web-броузерам локально кэшировать такие изображения. Более того, если одно и то же изображение используется на странице 10 раз, оно будет «скачиваться» 10 раз, так как для броузера это 10 разных элементов. В таких случаях логичнее использовать ссылки на один файл формата GIF или JPEG. Это можно реализовать, используя вставки HTML-кода наподобие [ ]. При этом сам файл помещается в каталог для HTML (обычно notes\data\domino\html\) или присоединяется (attach) к документу Notes. Учитывая это, логично будет сделать страницу на HTML и «внедрить» ее код в форму. Создадим форму Russian в базе Home Page и по ней один документ, затем вид с названием homestarter, в первой сортированной колонке которого будет отображаться поле Form. Сразу после этого можно указать Launch first document in view в Database Properties/Launch/On Web Open и выбрать «свежесозданный» вид homestarter. Поскольку с этой базой будут работать только из броузера, можно выбрать любой способ Launch, лишь бы при этом открывался созданный нами документ по форме Russian. Теперь сделаем счетчик обращений в форме Russian. Для этого нужно открыть в форме событие WebQueryOpen. По умолчанию формула, содержащаяся в нем, имеет вид: @Command([ToolsRunMacro]; "")
Вместо указывается имя агента, который запустится на сервере перед открытием документа (в данном случае IncRussianCounter). В версии 4.5 имя агента, запускаемого перед открытием документа, указывалось в поле $$QueryOpenAgent (типа Text/Computed for display). Это поле можно поместить в самом верху формы и скрыть. Следует заметить, что в версии 4.6 продолжают работать поля с $$-именами, хотя для них появились «более наглядные заменители». Пропустив несколько строк, создадим поле counter типа Number/Editable, в котором будет вестись счетчик числа обращений. После этого нужно открыть созданный нами ранее документ, указать в поле counter 1 и сохранить его. Создадим shared-агента с названием IncRussianCounter с опциями Run Manually From Actions Menu и Act on All documents in database, который будет увеличивать значение счетчика в документе, созданном по форме Russian. В окне Formula нужно указать: SELECT Form="Russian"; FIELD counter:=counter+1
Теперь можно проверить, как это работает. Обратитесь к сайту из броузера. Когда документ откроется, убедитесь, что счетчик увеличивается на 1 при каждой перезагрузке этого документа. Если так оно и есть, можно считать, что счетчик сделан. Как уже говорилось, можно вставлять графику непосредственно в элементы Notes или помещать в файлы (например, в каталоге для HTML) и ссылаться на них. Вообще говоря, самое сложное - «нарисовать красивые картинки и красиво расположить их», а метод, которым они будут выводиться в броузере, уже второстепенен. Если вы не хотите заниматься кодированием на HTML, в Notes есть достаточно удобные инструменты для вставки изображений и создания карт-изображений. Прозрачный цвет в GIF89a сохраняется, если картинка вставляется с помощью операции File/Import, но не Paste. Однако в настоящее время только использование
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 77
ссылок на HTML позволяет использовать все возможности графического формата изображения. Eсли Вы захотите использовать анимацию в формате GIF89a, то «ее придется вставлять» с помощью ссылок на HTML. Рассмотрим вначале страницу с комбинированием HTML и Notes, а затем сделаем то же самое только средствами Notes. В базе Home Page в форме Russian после поля $$QueryOpenAgent (если оно используется) вставим примерно следующий текст (комментарии даны курсивом): <META NAME="Author" CONTENT="Sergei V. Budylov"> <META NAME="description" CONTENT="InterTrust Corp. is leading DB developer under Lotus Domino in Russia."> <META NAME="keywords" CONTENT="InterTrust, Lotus, Notes, Domino, Database, developer, reseller, distributor">
SRC="/news.gif" hspace=10 SRC="/news.gif" hspace=10 SRC="/news.gif" hspace=10 SRC="/news.gif" hspace=10 SRC="/news.gif" hspace=10
Весь этот текст нужно выделить и создать для него стиль HTML - это один из способов вставить HTML-код в Notes. Желательно добавить заголовок окна. Для этого в форме в Window Title нужно задать необходимую формулу, к примеру, "InterTrust HomePage". Результат приведен на Рис. 8.1. В Notes аналогичную страницу сделать тоже просто. В свойствах формы на закладке Background с помощью кнопки Import Graphic можно назначить для формы фон из файла hicontrast.gif. Лого фирмы можно импортировать из файла mainlogo.gif с помощью команды меню File/Import, аналогично и изображения для ссылок (news.gif). Желательно всегда указывать в свойствах изображения текст, который будет показан вместо изображения, когда оно само еще не загрузилось (Alternate text for Web...). Чтобы сделать гипертекстовую ссылку на изображении, нужно выделить это изображение и выбрать в меню Create/Hotspot/Action
© InterTrust Co. Тел. 956-7928
78
Создание сайта на основе Lotus Domino
Hotspot, а затем указать формулу, которая будет открывать то, что надо. Например, если нужно открыть базу news.nsf в каталоге Site, то @Command([FileOpenDatabase];"":"Site\\news.nsf").
Рис. 8.1 Пример Home Page сайта Что касается счетчика, то он у нас с самого начала был сделан средствами Notes. Напомним еще раз, что вставленные непосредственно в документы Notes растровые изображения будут открываться несколько медленнее готовых файлов, так как некоторое время будет расходоваться их на конвертацию в форматы gif или jpeg. Кроме того, и при импорте и при конвертации возможны некоторые искажения в палитре изображений («больше всего обычно достается фотографиям людей»). И последние замечания. 1. Не рекомендуется использовать фреймы на Home Page, так как это может усложнить как навигацию (особенно при низком разрешении) так и разработку сайта. К тому же фреймы «будут неприятным сюрпризом» для пользователей броузеров, не поддерживающих эту возможность (например, Notes 4.5). 2. При помощи навигатора в Notes можно легко создать карту-изображение (Image Map). 3. С помощью небольшой функции на JavaScript можно сделать кнопки типа rollover (изменяющиеся при наведении на них курсора мыши).
8.3.3. Информация о компании Обычно это всего одна страничка (документ), поэтому возникает желание реализовать ее в какой-нибудь уже существующей базе, например Home Page. Однако это сделает структуру сайта менее понятной, так как название такого важного элемента не будет фигурировать отдельным блоком в Notes Workspace. Поэтому создадим базу About.nsf в каталоге Site с названием About. В отличие от Home Page, здесь нет необходимости в жесткой оптимизации скорости вывода графики, если только эта страница не будет открываться по умолчанию при обращении к сайту (например, в другом фрейме). Создадим форму RusAbout, в которой в виде статического текста и импортированных изображений будет содержаться информация о компании. В Window Title формы можно указать «Информация о компании». Для выравнивания и размещения объектов на странице © InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 79
удобно использовать таблицы, так как дополнительные пробелы и табуляции игнорируются при трансляции текста в HTML-код. Кроме того, если необходимо разделить текст или часть страницы, можно использовать следующие простые HTML-теги: [] - начало параграфа; [ ] - перевод строки; [
] - горизонтальная линия (в версии 4.6 можно использовать Create/Horizontal Rule). Создадим вид view, у которого в первой сортированной колонке будет отображаться поле Form. Затем создадим документ по форме RusAbout и сохраним его. Теперь к нему можно будет обращаться по ссылке /site/about.nsf/view/RusAbout?OpenDocument.
Рис. 8.2 Документ «О компании»
8.3.4. «Новости/Свежие новости» Информация в эту базу заносится только из Notes. В ней сотрудниками фирмы публикуются корпоративные новости, анонсы выхода новых продуктов/услуг и пресс-релизы, касающиеся области деятельности фирмы или самой фирмы. Создадим базу News с именем файла news.nsf в каталоге Site. Целесообразно сразу установить в ACL базы уровень доступа Reader для -Default- и назначить группу редакторов, которые будут заносить информацию в базу. Наш план таков: вначале сделаем рабочую часть базы, а затем добавим специальные детали для оптимизации Web-доступа. Создадим форму с названием document, оформленную примерно так, как показано на Рис. 8.3. В начале формы «напишем» тег для фона [], скрытый от пользователей Notes, а на следующей строке курсивом выровненную вправо надпись Новости ИнтерТраст. Затем вставим таблицу 1х1 без обрамления с белым фоном (светлый шрифт на темном фоне не удается корректно распечатать). В таблице создадим полe topic типа text/editable/multivalue, в которое будет вносится тема (категория), к которой относится «новость». Под таблицей создадим поле Header типа text/editable, в котором будет заноситься заголовок документа. Чуть ниже создадим еще одно поле типа Rich Text/editable с названием Body, в котором будет содержаться само сообщение. © InterTrust Co. Тел. 956-7928
80
Создание сайта на основе Lotus Domino
Примечание. Domino 4.6 по умолчанию использует тег FACE для отображения шрифтов в генерируемых им страницах HTML. Добавьте переменную DominoNoFace=1 в файл NOTES.INI сервера, чтобы отключить эту возможность (только версия 4.6a) или используйте шрифты Helv и Courier. В нижней части формы можно добавить автоматически вычисляемую информацию о создании документа и его последнем изменении. В Window Title формы можно указать формулу наподобие "Новости ИнтерТраст - "+Header.
Рис. 8.3 Дизайн формы document для базы "Новости" Еще можно сделать «полезную кнопку» для выбора темы из списка уже существующих. Ее использование предотвратит «размножение похожих тем» и ускорит работу оператора. Теперь создадим необходимые виды.
•
• •
По датам (Alias: ByDate) - наиболее полезный вид в базе. Документы должны быть отсортированы по дате модификации (новые вверху - descending). Рекомендуемые колонки - дата модификации (отсортированная по убыванию, категоризированная), категория (topic), название документа (header). По категориям (Alias: ByTopic) - второй по полезности вид. По авторам (Alias: ByAuthor) - необязателен, но может быть полезен.
Обычно имеются документы, в общем случае относящиеся к разным категориям, которые должны быть «показаны в первую очередь». Их можно условно назвать "Свежие новости" (Hot News). Удобным способом формирования подборки «свежих новостей» является копирование помеченных документов в папку (folder). Создадим в базе Новости папку с названием hot. Поскольку в ней не ожидается большого количества документов, категоризировать их не имеет смысла. Сортировать документы лучше по дате последней модификации (новые вверху). Для этой папки и для видов разумно будет установить в свойствах вида (или папки) параметр Lines per row больше 1. Тогда, если информация в колонке не поместится в одной строке, она будет переноситься на следующую строку. Еще полезно сделать для папки hot действие (action) «удалить из папки», которое реализуется с помощью Simple Action: Remove from folder, а в каждый из видов, напротив,
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 81
добавить действие типа «Make it HOT!» с Simple Action: Copy to folder (hot). Все эти действия следует «скрыть от web-броузеров». После того, как проверено, что в клиенте Notes все работает, можно заняться добавлением специальных элементов для Web-доступа. Прежде всего, добавим универсальную «маску» для видов. Для этого создадим форму с названием $$ViewTemplateDefault, примерно как, показано на картинке ниже.
Рис. 8.4 Дизайн формы-шаблона для отображения видов При доступе броузером в базе с помощью этой формы будут открываться все виды, кроме тех, для которых указана персональная «маска» (форма $$ViewTemplate for viewname). Обязательным элементом этой формы является поле с названием $$ViewBody, причем его содержание неважно (можно сделать поле типа text/computed for display со значением ""). На месте этого поля в форме будет отображаться вид. Основной целью использования таких форм обычно является замена стандартных кнопок, которые автоматически генерируются Domino для вида. Однако это также удобно для назначения фоновой картинки, цвета и оформления вообще. Кроме того, в эту же форму можно встроить навигатор Notes или просто набор дополнительных линков. Domino транслирует вид Notes для броузера в HTML-таблицу, по умолчанию размером не более чем из 30 строк. Это значение (30 строк) задается в общей адресной книге в документе Server в поле Lines per view page из секции HTTP Server. Для конкретного URL, открывающего вид, максимальное количество строк таблицы задается параметром Count в самом URL. Стандартные кнопки позволяют "пролистывать" вид в обоих направлениях, «раскрывать/сворачивать» все категории и создавать поисковый запрос для полнотекстового поиска по данной базе. Для этих стандартных операций со видом используются следующие формулы:
• • • • •
пролистнуть вперед - @DbCommand("Domino";"ViewNextPage"); пролистнуть назад - @DbCommand("Domino";"ViewPreviousPage"); раскрыть все категории - @Command([ViewExpandAll]); свернуть все категории - @Command([ViewCollapseAll]); поиск - @Command([ViewShowSearhBar]).
Для папки hot ("Свежие новости") можно создать персональную форму $$ViewTemplate for hot с несколько отличающимся фоном и персональным заголовком.
© InterTrust Co. Тел. 956-7928
82
Создание сайта на основе Lotus Domino
Теперь сделаем для базы «стандартный интерфейс», упрощающий как работу с ней, так и навигацию по сайту. Он будет представлять собой страничку, разделенную на три части (фрейма), в одной из которых будут располагаться ссылки на разные базы сайта, в другой ссылки на разные виды в этой базе, а в третьей (самой большой) будет отображаться текущий вид базы или документ. Для этого нам понадобятся специальные документы, которые можно будет открывать по ключу из специального вида. Практика показывает, что такой вид и документы более разумно сделать в базе HomePage, чем в каждой отдельной базе. Создадим в базе HomePage форму htmlstarter с двумя текстовыми полями: id и HTML. В поле id будет указываться ключ, а в поле HTML - HTML-код. Создадим также вид starter с формулой отбора документов SELECT Form="htmlstarter" и единственной отсортированной колонкой, в которой будет отображаться значение поля id. Теперь создадим 3 документа, которые и будут использоваться для отображения базы «Новости». Документ 1. Этот документ описывает фреймы на странице. Поле id: news. Поле HTML: <TITLE>news - Новости ИнтерТраст THIS PAGE CONTAINS FRAMES - USE BROWSER WHICH SUPPORT FRAMES GO TO NOFRAMES NEWS
Документ 2. Этот документ описывает левый фрейм, выполняющий роль навигатора по данной базе. Поле id: newsleft. Поле HTML:
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 83
Документ 3. Этот документ описывает нижний фрейм, выполняющий роль навигатора по сайту. Зарезервированное имя цели _top обозначает, что документы, открывающиеся по ссылкам из этого фрейма, будут открываться «на все окно». Поле id: newsbottom Поле HTML:
Результат получается примерно такой.
Рис. 8.5 Законченный вид интерфейса для базы «Новости»
8.3.5. «Продукция/услуги» База может быть предназначена только для просмотра (как «каталог») или предоставлять возможность создавать в ней заказы на продукты/услуги. Если классификация продукции имеет сложную структуру, возможно, следует создать несколько таких баз, чтобы уменьшить число уровней в иерархии документов и облегчить поиск. Если база предназначена только для просмотра, то она может быть очень похожа на базу «Новости». Только в ней «наиболее важным» будет вид по категориям товаров, причем сложную цепь категорий можно задавать в одном поле, например, "аудио\hi-fi\cdпроигрыватель". Если же в базе можно создавать заказы, но заказ создается только на один вид товара, то этого легко достичь, используя наследование информации из текущего документа (описания товара) в новый (заказ). Связанный с этим способом вопрос создания форм, заполняемых клиентом из броузера, будет рассмотрен нами ниже в описании базы "Дискуссии".
© InterTrust Co. Тел. 956-7928
84
Создание сайта на основе Lotus Domino
Возможен и более сложный способ построения заказа: пользователь сначала помечает документы (описания товара), на которые он хочет оформить заказ, а потом получает один документ со списком того, что он заказывал. В принципе такой вполне логичен и реализуем, а главное, что удобно для электронных платежей - уменьшает число транзакций. Поэтому именно такой подход применен в Domino.Merchant. В данном разделе мы рассмотрим процесс создания достаточно простого и симпатичного, но не ориентированного на заказы, каталога товаров. В каталоге Site создадим базу Products с именем файла prod.nsf как копию базы «Новости». Основная форма document после доработки выглядит примерно следующим образом (показана наиболее важная часть).
Рис. 8.6 Дизайн основной формы document в базе «Продукция/Услуги» Верхняя часть формы почти такая же, как в базе «Новости». Но в поле topic (категория) теперь лучше указывать только одну категорию. В поле Header (заголовок) будет задаваться наименование продукта. Далее следует поле Pic (типа text/computed for display), в котором с помощью формулы @If(filename="";"[нет фото]";"[ ]")
формируется HTML-код для отображения фотографии товара. Далее следует поле Short с кратким описанием товара и поле Body (типа Rich Text) с подробным описанием. В поле Price указывается цена, а поле Present (типа Keyword с интерфейсом Checkbox) предназначено для того, чтобы помечать, имеется ли сейчас этот продукт в продаже. В разделе «Служебная информация для вида типа Каталог» расположены три поля, которые используются для вывода изображений в виде «иллюстрированный каталог». В поле File (типа Rich Text) присоединяется (attach) файл формата GIF или JPEG с изображением товара. Поле filename (типа text/computed) с формулой @AttachmentNames используется в качестве идентификатора документа и имени файла. «Альтернативный текст» также используется в качестве одной из составляющих тега IMG. В этой форме реализован, вообще говоря, спорный подход к выводу изображений товаров. Для показа как в виде, так и в документе используется один и тот же присоединенный графический файл, масшабируемый броузером. Недостатками этого подхода являются, вопервых, увеличение времени работы с видом «иллюстрированный каталог» (броузер «скачивает большие картинки» и затем их масштабирует, вместо того, чтобы «скачивать маленькие»), и во-вторых, снижение наглядности при работе в Notes (отсутствует изображение из присоединенного файла). Все остальное можно рассматривать только как преимущества © InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 85
этого подхода. Значимость первого недостатка снижается при уменьшении разницы в размере (в байтах) файлов «большого» и «маленького» изображения. Но если необходимо выводить в документах по-настоящему большие изображения (например, 800х600 и более), то рациональнее использовать для вида и для документа два разные изображения. Однако обращаться к графике, импортированной или вставленной в поле документа, можно с помощью URL конструкции http://Host/Database/View/Doc/FieldName/FieldOffset?OpenElement &FieldElemFormat=ImageFormat
Здесь ImageFormat - GIF или JPEG (по умолчанию GIF), а FieldOffset - указатель на начало элемента в поле. FieldOffset имеет формат xx.yy , где xx - номер поля-«пункта», уу - смещение в байтах в этом поле. Номер поля-«пункта» необходим, поскольку Notes «разбивает» информацию в поле типа Rich Text на части по 15-20 Kб, создавая ряд полей-«пунктов» с таким же названием. Величина FieldOffset «достаточно загадочна», поэтому лучше всего «узнать ее», посмотрев в броузере HTML-код для документа, в который вставлено изображение. После этого «полученное выражение» FieldOffset можно с успехом использовать для всех изображений, вставленных в это поле в документах по этой же форме. Применение таких URL решает проблему наглядности при работе из Notes. Создадим скрытый вид (filelib) с алиасом filelib и формулой отбора SELECT Form="document". В первой отсортированной колонке этого вида отобразим имя присоединенного к документу файла. Данный вид будет использоваться для обращения к присоединенному графическому файлу. Создадим вид catalog с формулой отбора SELECT Form="document" | Form="add". В его первой категоризированной колонке будет отображаться информация из поля topic. Во второй колонке будут отображаться документы с дополнительными материалами о продукте (созданные по форме add). У этой колонке в свойствах на закладке Basic должен быть включен флаг Show responses only. Следующая колонка будет использоваться для вывода изображения из документа, ее формула: @If(form="document"&filename=""; "[нет фото]"; form="document"; "[ ]"; "")
Примечание. В данном случае можно обойтись и без обращения к вспомогательному виду filelib, использовав вместо ключа UNID документа: @If(form="document"&filename=""; "[нет фото]"; form="document"; "[ ]"; "")
Затем в виде идут колонки с полями Header (название товара), Price (цена), Short (краткое описание). Кроме того, полезно указать в свойствах этого вида значение Lines per row > 1, чтобы длинный текст в колонках занимал несколько строк. Можно также порекомендовать создать подобный, но «более быстрый» вид, отличающийся только отсутствием колонки с изображениями. В качестве тематики для «своего» каталога автор использовал аудиотехнику, а поскольку о различных продуктах (моделях) выходят обзорные статьи в тематических журналах, то можно добавить форму Additional Info | add типа response специально для этих целей. Следует отметить, что содержимое колонки с ответными документами (с включенной опцией show responses only) отображается в том же столбце таблицы (в которую Domino преобразует вид), что и следующая видимая колонка вида. При этом, несмотря на то, что на
© InterTrust Co. Тел. 956-7928
86
Создание сайта на основе Lotus Domino
каждый ответный документ в виде выделяется отдельная строка, Domino не использует для HTML-аналога этой строки параметр colspan для объединения столбцов. В результате текст, соответствующий в виде ответному документу, может располагаться в несколько строк «узким столбцом», несмотря на то, что справа от него может быть «свободное место». «Бороться» с этим эффектом можно, размещая в виде сразу вслед за колонкой с ответными документами одну широкую колонку, которая должна быть последней видимой колонкой в этом виде. Последний штрих - добавление стандартного интерфейса, выражающееся в создании трех документов starter в базе HomePage. Этого легко достичь копированием аналогичных документов, как и для базы «Новости», с их последующей незначительной корректировкой. В броузере база Products с открытым видом "Иллюстрированный каталог" выглядит следующим образом.
Рис. 8.7 Интерфейс базы «Продукция/Услуги»
8.3.6. «Дискуссии» Дискуссии организуются для обмена информацией между заинтересованными клиентами, так как все могут «в одном месте» задавать вопросы или отвечать на них. В общем, такая база может уменьшить количество консультаций по телефону. Для организации технической поддержки разумно сделать отдельную базу, вопросы в которой будут создавать web-клиенты, а отвечать на них будут только специалисты вашей фирмы. «Жаждущие ответов» могут размещать свои вопросы в обоих базах. Рекомендуется разрешать создавать документы-вопросы только пользователям, зарегистрированным на сайте (база «Регистрация» будет описана ниже). С точки зрения разработчика в этой базе есть новый элемент: форма, которую web-клиент заполняет в броузере. Создадим базу discuss.nsf в каталоге Site «копированием» базы «Новости». На время отладки можно установить в ее ACL доступ Editor для -Default-, чтобы Domino «не докучал» запросами ввода имени и пароля, когда вы будете открывать документы на редактирование. В принципе же для -Default- следует предоставлять доступ Author с правами на создание и удаление документов. В этой базе будет две формы: документ (document) и ответ (response), логически связанный с документом или другим ответом. Форма document в режиме дизайна выглядит примерно следующим образом.
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 87
Рис. 8.8 Дизайн формы document базы «Дискуссии» В начале формы находится поле $$HTMLHead (типа text/computed for display) со следующим значением ""
В данном случае оно используется исключительно для отображения фонового изображения. Поле пришлость использовать, потому что MSIE 4.0 «не показывал» фон документа в режиме редактирования, если фон задавался тегом [] в теле документа. Задать фоновое изображение для формы можно и с помощью свойств формы Notes, но поскольку документы, созданные по этой форме, будут открываться весьма часто, то нежелательно, чтобы фоновое изображение «скачивалось» в броузер каждый раз заново при открытии документа. Далее в форме имеется поле A типа Authors/Computed when composed со значением "[SiteManager]":@UserName, предназначенное для того, чтобы документ мог редактировать только его автор или человек, назначенный на роль SiteManager. Для этого создайте в ACL базы роль SiteManager и назначьте на нее себя. Далее в форме встречается тройка полей для работы с категориями документа.
•
• •
existtopic - поле типа keyword с формулой для выбора категорий из списка уже существующих. Можно регулировать количество одновременно видимых строк поля с помощью тега типа [<size=3>], помещаемого в Help description на закладке Options в свойствах поля или в псевдособытие HTML Attributes поля. Выбор опции Allow values not in list приводит к тому, что при редактировании документа из броузера поле выглядит, как и обычное редактируемое поле. Это поле следует «скрыть» в режиме чтения. newtopic - обычное текстовое поле, предназначенное для указания новой категории. Можно регулировать длину поля ввода таким же способом, например [<size=70>]. Это поле тоже нужно «скрыть» в режиме чтения. topic - текстовое поле типа computed с формулой @Trim(@Unique(existtopic:newtopic)), объединяющей значения из двух предыдущих полей. Это поле, напротив, нужно скрывать в режиме редактирования. Ниже в форме находятся три Action Hotspot'а:
• •
редактировать - @Command([EditDocument]); удалить - @Command([EditClear]);
© InterTrust Co. Тел. 956-7928
88
•
Создание сайта на основе Lotus Domino
создать ответ - @Command([Compose];"response").
Для того, чтобы такие «кнопки» размещались «в одну строку», а для каждой из них можно было указать свою формулу скрытия, используйте таблицу с несколькими столбцами. Скрыть «кнопку» «редактировать» от тех, кто не имеет права редактировать данный документ, можно с помощью формулы !@IsMember(@UserName;A) & !@IsMember("[SiteManager]";@UserRoles)
Если эта «кнопка» не будет скрыта, и пользователь, не являющийся редактором, «нажмет на нее», Domino запросит имя и пароль. У поля Body типа Rich Text можно указать «побольше» атрибутов, например: []. В данном случае cols - длина, rows - высота, wrap=virtual означает, что переносы строк будут формироваться динамически, а не сохраняться с текстом. Затем в форму можно вставить элемент для присоединения файлов из броузера. Для этого нужно выбрать из меню Create/Web Element/File Upload Control. В Notes версий 4.5 аналогичный результат достигался путем создания Action Hotspot c формулой @Command([EditInsertFileAttachment]). Далее в форме создается кнопка «Сохранить» с формулой @Command([FileSave]) ; @Command([FileCloseWindow])
Если в свойствах базы на закладке Basic не выбрана опция Web access: Use JavaScript when generating pages, то в качестве кнопки Submit ("Сохранить") Domino выбирает первую кнопку в форме или создает новую, если в нем нет видимых кнопок. При этом формула кнопки игнорируется. Если же вышеуказанная опция выбрана, Domino «принимает за Submit» каждую кнопку с формулой @Command([FileSave]) ; @Command([FileCloseWindow])
При этом «надпись на кнопке» может быть любой. После нажатия на кнопку Submit Domino по умолчанию «показывает страницу с надписью» Form Processed. Однако появление этой страницы совсем не означает, что документ был сохранен, а лишь то, что он был обработан Domino. «Молчаливое» запрещение сохранения реализуется помещением в форму поля с именем SaveOptions (типа text) со значением "0". Такая возможность часто используется для реализации «диалога на HTML». Сообщение после нажатия кнопки Submit можно настраивать в форме с помощью поля $$Return (обычно типа text/computed for display). Самый простой способ - указать в поле набор HTML-тегов, формирующих сообщение и ссылки, например: "Документ был успешно сохранен Переход на базу Дискуссии "
Если в поле $$Return указан «URL в квадратных скобках», то соответствующая страница откроется сразу после нажатия Submit. Этот же способ используется для запуска CGI-скриптов. Однако при использовании фреймов может оказаться затруднительно направить вывод этой страницы в нужный фрейм. В поле $$Return можно использовать и JavaScript. Например, чтобы вернуться «в истории» броузера на два шага назад, достаточно указать следующее "<script>history.go(-2);";
Форма response очень похожа на форму document. Самое важное отличие - тип формы Response to response. Для большей наглядности привязки в форме response хорошо наследовать
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 89
в специальное поле заголовок родительского документа. Ссылку на родительский документ можно сделать, создав поле типа text/computed со значением $Ref. В этом случае после сохранения в документе появится «линк на родителя». На следующем рисунке показан ответный документ, открытый на редактирование. Внизу виден элемент File Upload.
Рис. 8.9 Редактирование ответного документа в базе «Дискуссии»
8.3.7. Прайс-листы Каталог товаров не всегда удобно использовать в качестве прайс-листа, поскольку каждому товару в каталоге соответствует отдельный документ с его описанием. Цены же на некоторые классы товаров (например, гвозди) могут быть стандартными. В этом случае, по-видимому, следует создать таблицу с ценами на целый класс товаров внутри одного документа. Это можно реализовать в виде отдельной базы по образцу «Новости» или папки (folder) в той же базе, помещая в папку документы, имеющие отношение к прайс-листам.
8.3.8. «Работа» Обычно зона «Работа» создается фирмой для публикации имеющихся вакансий. Если создается крупный сайт, можно также создать базу типа «Биржа труда», в которой web-клиенты смогут создавать как документы типа «вакансия», так и документы типа «ищу работу». Эта база, скорее всего, будет очень похожа на «Каталог с возможностью оставлять заявки».
8.3.9. Регистрация Существует по крайней мере два способа регистрировать web-пользователей на сервере. 1. Администратор сам создает документы Person для пользователей в общей адресной книге (например, на основании запросов, поступающих к нему по электронной почте). 2. Online-регистрация: пользователь сам заполняет регистрационную форму, а данные из формы затем используются агентом для создания соответствующего документа Person в общей адресной книге. Второй способ позволяет пользователю зарегистрироваться намного быстрее, чем первый, а так как для создания документов в базе типа «Дискуссии» требуется, чтобы пользователь был
© InterTrust Co. Тел. 956-7928
90
Создание сайта на основе Lotus Domino
зарегистрирован на сайте, то чем проще и быстрее регистрация, тем вероятнее, что пользователь «не поленится» зарегистрироваться и примет участие в дискуссии. В комплекте с Domino версии 4.6 поставляется пример такой базы для регистрации пользователей под названием Domino 4.6 Samples: Registration. Имеет смысл сохранить в неприкосновенности исходную базу, создав ее новую копию в каталоге Site с названием regzone.nsf, и выполнив доработки, уже рассмотренные нами в разделе 8.1.2.
8.3.10. Полнотекстовый поиск В Domino существует возможность производить полнотекстовый поиск по определенному виду в базе или по нескольким базам. Поиск документов можно производить по отдельным словам, содержащимся в них, или по значениям конкретных полей. ASCII-текст, содержащийся в присоединенных файлах, также может быть проиндексирован. Можно порекомендовать сделать «кнопку» для создания поискового запроса для поиска по всем информационным базам на сайте. «Кнопки» же для создания поискового запроса по конкретному виду входят «в стандартную поставку» к каждому виду. Для того, чтобы реализовать на сайте поиск по нескольким базам, создадим по шаблону Search Site в каталоге Site базу данных, и в ней документ Search Scope Configuration. В таком документе указывается «область» для поиска баз, которые должны быть включены в Multi Database Index или отдельная база. В простом случае достаточно одного документа Search Scope Configuration со следующими значениями полей:
• • • •
Scope - directory («область» для поиска баз - каталог); Server - serg/itsertifier (полное имя сервера Notes); Directory - Site (каталог, в котором находятся нужные базы); Full Text Index Options - Index Full Document (опция индексирования - индексировать весь документ).
У баз, информация из которых будет включаться в Multi Database Index, на закладке Design в свойствах базы должна быть выбрана опция Include in multi database index. Перед тем, как начинать поиск с использованием этой базы, для нее нужно создать полнотекстовый индекс. В руководстве по Domino настоятельно рекомендуется после любого изменения конфигурации этой базы (документов Search Scope Configuration) удалять индекс и создавать заново. Поскольку распространено мнение, что в формах поисковых запросов на русском сайте вспомогательный текст тоже должен быть русским, рассмотрим способы изменения внешнего облика поисковых форм. По умолчанию по команде @Command([ViewShowSearchBar]) открывается файл search.htm из каталога domino\icons. Этот способ хорош тем, что даже пользователь, имеющий к базе доступ Reader, сможет пользоваться этой поисковой формой для составления запроса, ибо создания документа в базе при этом не происходит. Для замены поисковой формы в пределах одной базы создается форма с именем или алиасом $$Search. Лучше всего «позаимствовать» профессионально выполненные формы Web Search Simple и Web Search Advanced из базы Search Site и затем подкорректировать их. Особое внимание следует уделить формуле в поле $$Return. Так как форма была предназначена для поиска по базе Search Site, эта формула имеет примерно следующий вид: DBName:=@Subset(@DbName;-1); "[[/"+DBName+"?SearchSite&Query="+Query+"&Search...
Для поиска в базе по виду формируемый URL следует подправить: "[[/"+DBName+"/ViewName/?SearchView&Query="+Query+"&Search...,
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 91
где ViewName - имя вида, по которому будет производится поиск. Однако тогда, уже по команде @Command([ViewShowSearchBar]), будет создаваться документ, и если пользователь имеет к базе доступ Reader, то Domino запросит его имя и пароль, так как доступа читателя недостаточно для создания документов. Такое поведение особенно неприятно для баз типа «Новости», в которых web-клиенты не должны иметь возможности создавать документы. Однако эту проблему можно решить, указав для «содержательных» форм в свойствах на закладке Access список пользователей, которые могут создавать документы с помощью этих форм, а доступ к базе для web-пользователей «поставить» как Author. Радикальным способом является редактирование упоминавшегося ранее файла search.htm, но перед этим надо убедиться, что старая поисковая форма никому не понадобится. Другой способ заключается в том, чтобы создавать форму для поискового запроса (назовем ее RemoteSearch) в другой базе, в которой web-клиент имеет по умолчанию доступ Author. Задача поисковой формы - упростить формирование URL поискового запроса. Этот URL помещается в поле $$Return (text/computed) в двойных квадратных скобках. URL запроса в общем случае имеет вид: http://Host/NotesDatabase/View/?SearchView&Arguments. Возникает естественное желание использовать одну универсальную поисковую форму и передавать ей в качестве параметров для поиска имя базы и вида. Попытки реализации этого плана часто наводили автора на мысль о простоте редактирования файла search.htm, но тем не менее и без этого удалось добиться некоторых результатов. Как уже говорилось, в базе, в которой Anonymous имеет доступ Author с возможностью создавать документы, создадим форму на основе Web Search Simple и назовем ее RemoteSearch. Добавим поле «для захвата аргументов» с зарезервированным названием Query_String типа text/editable. Аргументы будут передаваться вместе с URL, открывающим поисковую форму, который формируется формулой (для базы news.nsf): @URLOpen("/site/homepage.nsf/RemoteSearch?OpenForm&"+ @ViewTitle+"&news.nsf")
Первый аргумент - имя вида (возвращается как UNID), а второй - файл базы. Часть формулы из поля $$Return в форме RemoteSearch: "[["+"/site/"+@Right(@Right(Query_String;"&" );"&")+"/"+@Left(@Right(Query_String;"&" );"&")+"/?SearchView&Query=... "
Самое интересное здесь в том, что поле $$Return получало информацию из поля Query_String только в том случае, когда последнее не было скрыто, то есть присутствовало в форме, и в него можно было при желании что-нибудь ввести. Все это создавало впечатление некоторой «недоделанности» формы, а потому вряд ли можно было рекомендовать оставить все в таком виде. Менее красивый, но более надежный путь - отказаться от передачи параметров и создать для каждого вида, в котором нужно искать, свою форму типа RemoteSearch, где в поле $$Return прямо указать файл базы и вид, например: "[[/site/news.nsf/ByTopic/?SearchView&Query=... "
Если учесть, что обычно требуется поиск только по одному специально для этого предназначенному виду для каждой базы, то работы будет не так уж много. И последнее из того, что автор хотел сказать о поисковых запросах - возможность поиска по значениям полей. Поисковый URL выглядит в этом случае примерно так: http://serg/site/news.nsf/ByAuthor/?SearchView&Query=FIELD+Creator=Sergei+B udylov+AND+FIELD+Form=document+AND+FIELD+DateModifyed>=15.01.98
© InterTrust Co. Тел. 956-7928
92
Создание сайта на основе Lotus Domino
Существует также возможность изменять оформление списка результатов поиска путем создания формы с названием $$SearchTemplate for viewname или $$SearchTemplateDefault. В обоих формах должно присутствовать поле $$ViewBody (его значение игнорируется), которое по сути только обозначает место, где в форме будет расположен список результатов. Для базы типа Search Site такая форма будет называться $$SearchSiteTemplate. Рекомендуется использовать эту возможность только в том случае, если пользователи «чрезвычайно плохо» относятся к английскому тексту. Дело в том, что при использовании этих форм имеются две «неприятности»: 1) пропадает заголовок результатов, содержащий запрос и число найденных документов; 2) пропадает поле для ввода уточняющего поискового запроса.
8.4.
Развитие и обслуживание сайта
Взявшись однажды за разработку сайта, остановиться уже практически невозможно. С каждым днем растет число людей, желающих получать нужную для себя информацию с сайта. Информация должна часто обновляться и всегда быть актуальной. Чем более эффективно размещение информации на сайте, тем больше различной информации о компании хочется «туда выложить», а это неминуемо приведет к появлению новых зон. Прежде всего может появиться потребность создать зону линков на другие сайты. Держать несколько лишних картинок на home page «накладно» - они замедляют открытие страницы. Скорее всего, это будут линки на компании-партнеры (с которыми всегда полезно обменяться линками), а также на крупные компании-поставщики продукции. Использование электронной почты часто может оказаться более эффективным, чем телефонный звонок в компанию. Страница или зона (в зависимости от количества информации) «Контактные лица компании», на которой перечислены соответствующие сотрудники с описанием, какими вопросами они занимаются и указаны их адреса е-mail, поможет пользователю точно адресовать вопрос и получить обдуманный и компетентный ответ. Действительно, такой способ не вынуждает сотрудника компании что-то «лихорадочно вспоминать» - он найдет нужную информацию и ответит более компетентно. Иногда возникает необходимость в зоне «ОЧЕНЬ ГОРЯЧИЕ НОВОСТИ!». К этому разряду можно отнести объявление о крупных скидках, которые действуют только несколько дней, или объявление о проведении какого-либо крупного мероприятия (семинара, выставки). Подробная информация, как правило, заносится в документ базы «Новости», но дополнительно на Home Page помещается «красочный плакат» с линком на этот документ. Хороший способ получить такой линк - открыть броузером вид, в котором отображается документ, и скопировать ссылку на него (copy link location). Если изображение вставлено в документ (Import, Paste) или ссылка на изображение «написана» способом [ ], то «вокруг нее» можно создать hotspot типа link hotspot, предварительно скопировав документ как doclink. В Notes версии 4.6, в отличие от версии 4.5, hotspot'ы, «сделанные вокруг» текста стиля HTML, не работают. Что же касается именно обслуживания сайта, то полезно делать следующее. 1. Периодически проверять, «отвечает ли» сайт и насколько быстро он работает. 2. Следить за регистрацией Web-пользователей (некоторые регистрируются по несколько раз из-за того, что забывают свои имена или пароли). Наиболее «настойчивым» можно послать письмо по е-mail и объяснить, как осуществляется регистрация. 3. Быть в курсе изменений в ACL баз на сайте, включая изменения в составе групп. 4. Добавляя на сайт новые базы, не забывайть включать их в список баз, по которым производится поиск на сайте (Multi database search). Поисковая база «вяло реагирует» на изменение списка баз, так что может понадобиться удалить ее полнотекстовый индекс и затем построить заново.
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 93
9. Конфигурирование Web-сервера Domino версий 4.6.x Web-сервер Domino представляет собой задачу с именем HTTP, запускаемую на сервере Notes и позволяющую клиентам, оснащенным Web-броузерами, получать доступ как к информации из баз данных, находящихся на сервере Notes, так и к HTML-файлам, CGIпрограммам и сервлетам, находящимся в каталогах компьютера сервера Notes Задача HTTP загружается командой Load http, a завершается командой Tell http quit. Чтобы задача автоматически запускалась при старте сервера, ее имя следует внести в список задач в переменной ServerTasks в файле NOTES.INI. Статистика работы сервера Domino может быть получена командой консоли Show stat domino. Основные настройки для задачи HTTP задаются в секциях Internet Port and Security Configuration и HTTP Server документа Server из общей адресной книги.
9.1.
Настройки в документе Server
9.1.1. Секция Internet Port and Security Configuration документа Server В этой секции задаются номера и статус портов TCP/IP, по которым задача HTTP должна ожидать обращений клиентов, а так же возможность «анонимного» доступа и (или) применяемые варианты аутентификации клиентов.
Рис. 9.1 Секция Internet Port and Security Configuration в документе Server TCP/IP port number (по умолчанию 80). Задает номер порта, на котором сервер Domino должен «ожидать» запросы по «обыкновенному» протоколу HTTP. Стандартно для протокола HTTP используется порт 80. Не используйте значений, меньших чем 1024 (кроме стандартного 80), поскольку они зарезервированы для других прикладных программ TCP/IP. Если задается нестандартный номер порта, клиенты будут вынуждены явно указывать этот номер порта в URL. Например, URL http://domino.lotus.com:8080/ «запрашивает» начальную страницу с хоста domino.lotus.com, который «ожидает» запросы по протоколу HTTP на порту 8080. После изменения номера порта, чтобы эти изменения «вступили в силу», сервер Notes следует перезапустить.
© InterTrust Co. Тел. 956-7928
94
Конфигурирование Web-сервера Domino версий 4.6.x
TCP/IP port status (по умолчанию Enabled). Выбор Enabled разрешает серверу Domino обслуживать запросы по «обыкновенному» протоколу HTTP, выбор Disabled - запрещает обслуживать запросы по «обыкновенному» протоколу HTTP, а выбор Redirect to SSL требует «перенаправлять» запросы на порт с поддеркой SSL (по тому же URL, но c «префиксом протокола» https://). Должно быть разрешено обслуживание запросов хотя бы по одному из двух возможных портов: «обыкновенному» (TCP/IP port status) или с поддержкой SSL (SSL port status). Если обслуживание запрещено по обоим портам, Domino не сможет функционировать. SSL port number (по умолчанию 443). Задает номер порта, на котором сервер Domino должен «ожидать» запросы по протоколу HTTP с поддержкой SSL. После изменения номера порта, чтобы изменения «вступили в силу», сервер Notes следует перезапустить. SSL port status (по умолчанию Disabled). Выбор Enabled разрешает серверу Domino обслуживать запросы по протоколу HTTP с поддержкой SSL, а выбор Disabled - запрещает. Бессмысленно «разрешать» поддерку SSL, если для сервера не создан KeyRing-файл (его имя должно задаваться в поле SSL key file). Вопросы поддержки SSL подробно рассматриваются в следующей главе. При работе по «обыкновенному» протоколу HTTP возможен как «анонимный» доступ (Yes в поле в строке Anonymous в верхней половине таблицы), так и аутентификация клиента по введенным им имени и паролю (Yes в поле в строке Name & password в верхней половине таблицы). Если разрешен «анонимный» доступ, обратившийся к серверу HTTP-клиент «будет фигурировать на сервере» под именем Anonymous. Доступ такого клиента в каждой базе Notes определяется прежде всего списком управления доступом этой базы: как Anonymous или, если в ACL отсутствует имя Anonymous, как -Default-, но не выше максимального уровня доступа для HTTP-клиентов (поле Maximum Internet name & password access в ACL базы). Чтобы стала возможной аутентификация клиента по введенным им имени и паролю, для клиента в любой из доступных серверу адресных книг необходимо создать документ Person с именами в полях User name и Short name и паролем в поле Internet password.
Рис. 9.2 Фрагмент документа Person Когда клиент получает в броузере запрос на ввод имени и пароля, он может ввести любое из имен, присутствующих в полях User name или Short name его документа Person. Если по полученному от клиента имени сервер находит в доступных ему адресных книгах единственный документ Person, то, после успешного сравнения паролей, данный HTTP-клиент «станет фигурировать на сервере» под именем, которое «записано первым» в поле User name его документа Person. Именно это «Notes-имя HTTP-клиента» - первый элемент из поля-списка
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 95
User name - администратор сервера должен использовать в ACL баз Notes или в группах в общей адресной книге сервера. Доступ HTTP-клиента к базе Notes определяется доступом к базе «Notes-имени этого HTTP-клиента», но не будет превышать максимального уровня доступа для HTTP-клиентов (поле Maximum Internet name & password access в ACL базы). Если на сервере разрешена аутентификация клиента по введенным им имени и паролю (Yes в поле в строке Name & password в верхней половине таблицы на Рис. 9.1), но «анонимный» доступ запрещен (No в поле в строке Anonymous в верхней половине таблицы), все HTTPклиенты при обращении к серверу Domino «сразу» получают запрос на ввод имени и пароля. Если же на сервере разрешены как аутентификация клиента по введенным им имени и паролю (Yes в поле в строке Name & password в верхней половине таблицы), так и «анонимный» доступ (No в поле в строке Anonymous в верхней половине таблицы), все зависит от списка управления доступом базы, к которой обращается HTTP-клиент. Если к этой базе возможен «анонимный» доступ, то запроса на ввод имени и пароля не последует. Если же Anonymous и -Default- не имеют доступа к базе, клиенту придется ввести имя и пароль. При работе по протоколу HTTP с поддержкой SSL возможны «анонимный» доступ (Yes в поле в строке Anonymous в нижней половине таблицы на Рис. 9.1), аутентификация клиента по введенным им имени и паролю (Yes в поле в строке Name & password в нижней половине таблицы) и аутентификация клиента по информации из его сертификата стандарта X.509 (Yes в поле в строке Client certificate в нижней половине таблицы). Последний вариант аутентификации возможен только с версии 4.6 и удобен тем, что клиенту не требуется вводить имя и пароль.
9.1.2. Секция HTTP Server документа Server Рассмотрим, группа за группой, многочисленные поля этой секции.
Рис. 9.3 «Начало» секции HTTP Server
Группа полей Basics Host name (по умолчанию пусто). Поле должно содержать хост-имя компьютера, на котором установлен сервер Domino. Это может быть любое из хост-имен, определеных для вашего компьютера на DNS-сервере. Если ваш компьютер не имеет зарегистрированного на сервере DNS хост-имени, можно задать в этом поле IP-адрес вашего компьютера. Но при этом случае клиенты будут вынуждены задавать в URL его IP-адрес, например, http://194.220.133.11/.
© InterTrust Co. Тел. 956-7928
96
Конфигурирование Web-сервера Domino версий 4.6.x
Если вы оставите поле Host name пустым, Domino будет использовать хост-имя, определенное в стеке протокола TCP/IP операционной системы. Bind to host name (по умолчанию Disabled). Выбирать в этом поле значение Enabled следует только в том редком случае, когда на вашем компьютере установлены несколько серверов Domino (partitioned server), поддерживающих более одной задачи HTTP. В такой ситуации нужно «уточнить», по какому IP-адресу должно производиться обращение к задаче HTTP на конкретном сервере Domino. Это и достигается указанием в поле Host name IP-адреса или имени хоста (что определяет IP-адрес) и выбором Enabled в поле Bind to host name. Например, на одном компьютере, имеющем IP-адреса 194.220.133.11 (www1.acme.com) и 194.220.133.12 (www2.acme.com), установлены два сервера Domino (NotesServer1/Acme/US и NotesServer2/Acme/US). В документе Server для NotesServer1/Acme/US в поле Host name содержится www1.acme.com, а в документе Server для NotesServer2/Acme/US соответственно www2.acme.com. В обоих документах Server в поле Bind to host name выбрано Enabled. В результате обращения по URL http://www1.acme.com/… обрабатываются задачей HTTP сервера NotesServer1/Acme/US, а обращения по URL http://www2.acme.com/… обрабатываются задачей HTTP сервера NotesServer2/Acme/US. Если же на компьютере установлен один сервер Domino, и вы хотите поддерживать на нем одной задачей HTTP несколько виртуальных Web-серверов, то в поле Bind to host name должно быть выбрано Disabled. DNS lookup (по умолчанию Disabled). Выберите Enabled, если требуется, чтобы сервер Domino выполнял поиск хост-имени каждого своего клиента по его IP-адресу, обращаясь к серверам DNS. Выбор Enabled несколько ухудшает эффективность работы сервера Domino, однако в протоколах работы сервера Domino будут содержаться хост-имена клиентов, а не IPадреса, и в фильтрах протоколирования вы сможете использовать как маски на основе хостимен клиентов, так и маски на основе IP-адресов клиентов. Если же выбрано Disabled, сервер Domino не обращается к серверам DNS для определения хост-имени клиента. Выбор Disabled улучшает эффективность работы сервера Domino, однако в протоколах работы Domino будут содержаться только IP-адреса клиентов и в фильтрах протоколирования вы сможете использовать маски только на основе IP-адресов клиентов. Default home page (по умолчанию default.htm). Если в качестве начальной страницы (home page) должен использоваться обычный файл в формате HTML, укажите в этом поле имя файла и «очистите» поле Home URL в группе полей Mapping. Тогда, если в URL запроса клиента не указана конкретная страница (http://host-name/), сервер Domino, «обнаружив», что поле Home URL «пусто», будет загружать клиенту этот файл из каталога, указанного в поле HTML directory (обычно, domino\HTML). Если же в качестве начальной страницы должен использоваться какой-то элемент из базы данных Notes (например, документ About или навигатор), оставьте в поле Default home page его значение по умолчанию, а в поле Home URL укажите соответствующий «относительный» URL, например, что-то подобное /home.nsf?OpenDatabase для документа About или /home.nsf/Main+Navigator?OpenNavigator для навигатора. Allow HTTP clients to browse databases (по умолчанию Yes). Если в поле выбрано Yes, клиенты, указав URL http://host-name/?OpenServer, смогут получить список баз данных на сервере Notes, а из него, «переходя по ссылкам», предпринимать попытки открыть и сами базы. Когда же выбрано No, клиенты не смогут получить список имеющихся на сервере баз, но смогут открывать конкретные базы данных, если знают их имена файлов и имеют к ним доступ. Maximum requests over a single connection (по умолчанию 5). Максимальное число HTTPзапросов за одно соединение. Number active threads (по умолчанию 40). Задает максимально возможное количество параллельно работающих подпроцессов (thread's), порождаемых задачей HTTP. Если заданный максимум достигнут, сервер Domino «отказывается отвечать» на новые запросы, пока уже принятые им запросы не будут обслужены и исполнявшие их подпроцессы не освободятся. Чем
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 97
более мощный компьютер используется в качестве сервера, тем и большее максимально возможное количество подпроцессов должно задаваться в этом поле. Однако выбор слишком большого значения может привести к излишней трате ресурсов компьютера на «прокачку страниц» между оперативной памятью и файлом страниц. На платформе Windows NT рекомендуется экспериментально исследовать этот вопрос с применением приложения Performance Monitor. Minimum active threads (по умолчанию 20). В версиях «ниже» 4.6 задает минимальное количество подпроцессов, всегда поддерживаемых задачей HTTP. Сервер Domino не должен закрывать подпроцессы «ниже этого минимума», даже если они неактивны, т.е. не обслуживают запросы. Подпроцессы же «сверх этого минимума» при переходе в неактивное состояние должны закрываться задачей HTTP и открываться снова, когда это требуется. Начиная с версии 4.6 поле Minimum active threads не используется.
Группа полей Mapping Группа полей Mapping задает реальное местоположение каталогов HTML-файлов, пиктограмм и CGI-программ и определяет URL для доступа к ним. Учтите, что на одном компьютере «под одним сервером Notes» может функционировать несколько виртуальных серверов Domino (рассматривается в 9.2). В этом случае для каждого виртуального сервера Domino информация из группы полей Mapping «перекрывается» аналогичной информацией из документов Virtual Server базы данных DOMCFG.NSF. Home URL (по умолчанию /?Open). Относительный URL элемента из базы данных Notes (например, документа About или навигатора), HTML-образ которого Domino должен возвращать, когда клиенты «входят на сервер», не указывая в URL требуемый им каталог или страницу (http://host-name/). Использование значения по умолчанию /?Open влечет отображение списка баз данных, имеющихся на сервере (как по File - Database - Open в клиенте Notes). Если же вы используете начальную страницу (home page) непосредственно в формате HTML, «очистите» поле Home URL и укажите имя HTML-файла в поле Default home page. HTML directory (по умолчанию domino\html). Каталог для HTML-файлов. Если указан не полный путь, он «отсчитывается» относительно каталога данных Notes. Icon directory (по умолчанию domino\icons). Каталог пиктограмм Domino. Если указан не полный путь, он «отсчитывается» относительно каталога данных Notes. Icon URL Path (по умолчанию /icons). Относительный URL для каталога пиктограмм Domino. Например, чтобы «открыть в броузере» файл abook.gif или форму search.htm, находящиеся в подкаталоге domino\icons каталога данных Notes, необходимы URL http://hostname/icons/abook.gif или http://host-name/icons/search.htm. В большинстве случаев не следует изменять исходное значение этого поля. CGI directory (по умолчанию domino\cgi-bin). Каталог для программ CGI. Если указан не полный путь, он «отсчитывается» относительно каталога данных Notes. CGI URL path (по умолчанию /cgi-bin). Относительный URL для каталога программ CGI на сервере Domino. Например, для запуска CGI-программы CGITest.exe, находящейся в подкаталоге domino\cgi-bin каталога данных Notes, необходим URL http://host-name/cgibin/CGITest.
Группа полей Disk Cache for Images and Files Эта группа полей (Рис. 9.4) «отвечает» за управление файловым кэшем. Файловый кэш содержит файлы изображений и присоединенные файлы. Cache directory (по умолчанию domino\cache). Определяет каталог, который сервер Domino должен использовать для сохранения графических и присоединенных файлов. Когда клиент запрашивает страницу с элементами графики, Domino преобразует каждый графический
© InterTrust Co. Тел. 956-7928
98
Конфигурирование Web-сервера Domino версий 4.6.x
элемент в файл соответствующего графического формата, передает файл клиенту и сохраняет копию файла в каталоге кэша. Если Domino получает другой запрос на ту же самую страницу, он уже передает клиенту соответствующие файлы непосредственно из кэша. То же самое происходит и с присоединенными файлами - будучи «отсоединенными» из документа Notes для передачи клиенту, они «попадают» в кэш, а откуда в течение некоторого времени могут повторно использоваться Domino. Если в поле указывается не полный путь, то считается, что он был задан относительно каталога данных Notes. Garbage collection (по умолчанию Enabled) и Garbage collection interval (по умолчанию 60 минут). Чтобы не допустить «разрастания» кэша сверх максимального размера, рекомендуется разрешить (выбором значения Enabled в поле Garbage collection) периодическое выполнение сервером Domino процесса «уборки мусора». Процесс «уборки мусора» удаляет файлы из кэша, начиная с наименее часто используемых. Период, с которым запускается процесс «уборки мусора», запускается в поле Garbage collection interval.
Рис. 9.4 Продолжение секции HTTP Maximum cache size (по умолчанию 50 MB). Максимальное количество дискового пространства, доступного для кэша (в МБ). Размер кэша обычно остается ниже заданного максимума, но может иногда становиться и немного большим. Когда максимальный размер кэша достигнут, автоматически запускается процесс «уборки мусора». Если никакое значение не задано (поле Maximum cache size пустое), сервер Domino вообще не применяет кэширование файлов. Delete cache on shutdown (по умолчанию Disabled). Если выбрано Enabled, Domino будет «очищать кэш» при остановке сервера Notes. Если же выбрано Disabled, при перезапусках сервера Notes кэш будет сохраняться.
Группа полей Memory Caches В дополнение к файловому кэшу для повышения производительности HTTP-сервера с версии 4.6 введены три кэша в виртуальной памяти.
•
Кэш HTML-страниц. На генерацию кода HTML-страницы по информации из базы данных Notes, в отличие от обращения к «уже готовому» HTML-файлу, затрачивается некоторое
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 99
время. Чтобы способствовать уменьшению времени отклика для клиента, задача HTTP предпринимает попытку кэшировать генерируемый ею по запросам клиентов HTML-код. Поэтому последующие обращения клиентов по URL, соответствующему имеющейся в кэше HTML-странице, могут отрабатываться быстрее, если только «прообраз» кэшируемой страницы в базе Notes не успел измениться. В поле Maximum cached HTTP commands задается максимальный размер этого кэша. Кэширование выполняется не для всех страниц, а только для тех, которые являются «достаточно статическими». «Потенциальными кандидатами» для кэширования выступают лишь страницы, в URL которых имеются «операции» ?OpenDatabase, ?OpenView, ?OpenDocument, ?OpenForm и ?ReadForm. Прочие страницы (например, ?EditDocument) вообще никогда не заносятся в кэш. В версии 4.6 факт присутствия @-функций в «прообразе» страницы безусловно означал исключение этой страницы из числа «кандидатов для кэширования». С версии 4.6.1 страницы, «прообразы» которых содержат @-функции, могут кэшироваться. В Domino 4.6.1 в состав задачи HTTP включен анализатор @-формул (Formula Analyzer). Анализируя @-формулы «прообраза страницы», он «дает заключение» об уровне изменчивости страницы, стратегии для кэширования этой страницы и условиях, при возникновении которых кэшируемая страница должна считаться «устаревшей». Однако «по умолчанию» для совместимости с версией 4.6 анализатор формул не функционирует, т.е. страницы с @-формулами не кэшируются. Чтобы «включить» анализатор формул, нужно добавить в файл NOTES.INI сервера переменную DominoAnalyzeFormulas=1. Прежде всего анализатор формул вычисляет по «прообразу» страницы набор флагов:
• • • • • • • • • • •
OffDb - используются данные, получаемые не из текущей базы, например, переменные CGI; TimeVariant - зависит от времени, например, используется @Now; HadEffect - имеет посторонние эффекты, например, используется @DialogBox; UsedEnv - используются переменные из файла NOTES.INI; UserVariant - зависит от имени пользователя, например, в данных или элементах дизайна используются обращения к ACL, поля типа Readers или Authors, секции с управляемым доступом…; DesignUserVariant - используются «закрытые» элементы дизайна; DbData - используются данные не только из конкретного документа, например, в форме применены Embedded View, Embedded Folder Pane…; UsedDocId - используются идентификаторы документов; UsedNewDoc - «прообраз» страницы создан в виртуальной памяти и не сохранен в базе; Unknown - используется такое, что анализатор формул «не способен понять», например, LotusScript; Error - имеются ошибки.
Затем анализатор формул вычисляет стратегию кэширования данной страницы. Выбранная стратегия описывается набором из следующих:
• • • • •
DontCache - не кэшируется; Document - кэшируется, устаревает при изменении документа; DbDesign - кэшируется, устаревает при изменении документа; DbData - кэшируется, устаревает при любых изменениях в базе; OnlyAnonymous - кэшируется, но берется из кэша только для передачи анонимным пользователям.
© InterTrust Co. Тел. 956-7928
100
Конфигурирование Web-сервера Domino версий 4.6.x
Страницы с флагами OffDb, TimeVariant, HadEffect, UsedEnv, Error, Unknown, UserVariant и DesignUserVariant не кэшируются - «используется стратегия» DontCache. Поскольку анализатор формул в принципе не может быть настолько совершенным, чтобы всегда давать правильное заключение о необходимой стратегии кэширования, предусмотрены и средства, позволяющие разработчику управлять стратегией кэширования конкретных страниц «вручную». Для этого в документах и формах применяются следующие поля.
• •
$CacheOptions - если значение текстового поля равно "0", то кэширование не должно выполняться. $CacheValid - текстовое поле содержит количество секунд "N", в течении которых механизму кэширования «запрещается проверять», не устарела ли страница. Аналогичное значение по умолчанию «для всего сервера» может задаваться переменной DominoDefaultCacheValid=N в файле NOTES.INI. Например, имеется страница, соответствующая в базе документу со «статическими» @-формулами. Эту страницу регулярно и часто, пусть, раз в минуту, «читают» HTTPклиенты. К тому же содержание документа регулярно изменяется, но частота его изменения в несколько, допустим, в 10 раз, превышает частоту обращений к странице. Скорее всего, анализатор формул предложит для этой страницы стратегию Document. В результате задача HTTP каждую минуту будет проверять, не изменился ли документ. Можно поменять стратегию кэширования, добавив в документ поле $CacheValid со значением "300". Это означает, что в течении 300 секунд (5 минут) после обновления HTML-образа документа в кэше при очередных 4-5 обращениях HTTP-клиентов страница будет возвращается им из кэша без проверки, не изменился ли документ. По прошествии 5 минут будет восстановлена предложенная анализатором стратегия, и при каждом последующем обращении станут выполняться проверки изменения документа.
Заметим, что если в файл NOTES.INI добавить переменную DominoTraceCmdCache=1, то информация о стратегии кэширования будет помещаться в HTML-заголовок страницы. Описания добавляемых в заголовок атрибутов и способы наблюдения за изменениями этих атрибутов имеются в статье Andrew Wharton «Expanded Command Caching in Domino 4.61», которую можно найти «в базе» http://www.notes.net/home.nsf/.
•
Кэш с информацией для быстрого доступа к элементам дизайна баз данных. Когда клиент броузера «впервые открывает» базу данных, задача HTTP просматривает все элементы дизайна базы (формы, виды, агенты…) и создает таблицу, сопоставляющую имени каждого элемента дизайна его идентификатор. Эта таблица позволяет по идентификаторам более быстро извлекать из базы те элементы дизайна, которые нужны для генерации HTML-страницы, запрошенной клиентом (например, форму «для показа» документа). Кэширование таких таблиц в виртуальной памяти способствует уменьшению времени отклика для клиентов. В поле Maximum cached designs задается максимальный размер этого кэша.
•
Кэш с информацией об именах и паролях аутентифицированных пользователей и их принадлежности к группам. Когда клиент броузера впервые обращается в базе, «требующей» аутентификации клиента, ему приходится ввести свое имя и пароль. По завершении процесса аутентификации имя, пароль и информация о принадлежности этого имени к группам из адресной книги помещается в кэш и содержится в нем в течении указанного в поле Cached users expiration interval количества секунд. Если клиент вновь обращается к базе данных, «требующей» аутентификации, но информацию об этом клиенте удается найти в кэше, клиенту не требуется в очередной раз вводить имя и пароль, а серверу – выяснять принадлежность клиента к группам. В поле Maximum cached users задается максимальный размер этого кэша.
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 101
Протоколирование обращений к серверу Domino По каждому HTTP-запросу, выполняемому броузером, сервер Domino способен протоколировать следующую информацию: с какого IP-адреса (или DNS-имени) поступил запрос, какой броузер использует клиент, какой URL использовался для доступа, сколько байт передано, какие ошибки (если были) сгенерированны программами CGI. Протоколируемая информация может быть сохранена или в текстовом файле, или в базе данных Notes с именем DOMLOG.NSF, или в обоих местах сразу. Протоколирование в текстовые файлы «включается» в поле Log files, а протоколирование в базу данных DOMLOG.NSF – в поле Domlog.nsf. База данных DOMLOG.NSF создается в каталоге данных Notes по шаблону Domino Web Server Log (DOMLOG.NTF). Протоколирование в базу данных Notes обычно более удобно, но оно требует привлечения несколько больших ресурсов компьютера, чем протоколирование в текстовый файл. При протоколировании в текстовые файлы в поле Access log format можно выбрать менее подробный (Common) или более подробный (Extended Common) формат файла Access log (ACCESS-LOG). Поле Time format определяет формат, в котором записывается время обращения. Файлы ежедневных протоколов создаются в каталоге, указанном в поле Directory for log files, причем в день создается пять файлов: Access log (ACCESS-LOG), Agent log (AGENT-LOG), Error log (ERROR-LOG), CGI error log (CGI-ERROR-LOG), Referer log (REFERER-LOG). В скобках указаны «имена по умолчанию» для этих файлов. Имена файлов могут быть изменены в «одноименных» полях. В качестве расширения для файлов выбирается дата их создания. В группе полей Exclude From Logging определяются «исключения из протоколирования»:
• • • • • •
URLs – список URL или «шаблонов» URL, например *.gif. Methods – список запросов, например, POST и DELETE. MIME types – список MIME-типов, например image/gif. User agents – список броузеров, например Mozilla. Return codes – список кодов возврата, например 300. Hosts or domains – список IP-адресов, имен хостов или их «шаблонов», например 130.333.* или *.edu.
Кроме того, имеется возможность протоколировать информацию об обращениях к серверу из броузеров с помощью серверной задачи Billing. Для этого в файле NOTES.INI сервера в список переменной BillingClass нужно добавить протоколирование HTTP-запросов, например: BillingClass=Session, Database, Document, Replication, Mail, Agent, HttpRequest . К сожалению, при всем богатстве выбора протоколы обычно имеют большой размер и не удобны для анализа.
Группа полей Timeouts Группа полей Timeouts задает временные ограничения для контактов между сервером Domino и клиентом. Input timeout (по умолчанию 2 минуты). Максимальное время в минутах с момента установления клиентом HTTP-соединения с сервером Domino до посылки клиентом запроса на ресурс (GET URL). Если клиент не посылает запрос за заданное время, сервер Domino разрывает HTTP-соединение с ним. Output timeout (по умолчанию 20 минут). Максимальное время в минутах, отводимое на передачу данных сервером Domino (но не запущенной им CGI-программой) клиенту. По истечении этого времени сервер Domino «разрывает» HTTP-соединение с клиентом. Ограничение касается запросов на получение локальных файлов и информации из баз данных Notes, но не касается запросов, выполнение которых влечет запуск программ CGI.
© InterTrust Co. Тел. 956-7928
102
Конфигурирование Web-сервера Domino версий 4.6.x
CGI timeout (по умолчанию 5 минут). Максимальное время в минутах, отводимое на работу программе CGI, запущенной сервером Domino. Когда отведенное время истекает, сервер Domino посылает программе CGI сообщение. Затем, еще через пять минут, сервер Domino «снимает» эту программу. Idle thread timeout (по умолчанию 0 минут). С версии 4.6 поле не используется. В версиях до 4.6 задавало интервал времени в минутах, в течение которого сервер Domino не должен был закрывать неактивный подпроцесс. Подпроцесс становился неактивным после того, как он выполнял свой последний запрос. Если текущее количество подпроцессов было больше, чем указано в поле Minimum active threads, и сервер Domino не использовал некоторый подпроцесс в течение заданного интервала времени, сервер закрывал этот подпроцесс. Чтобы Domino вообще не закрывал неактивные подпроцессы, в поле задавалось значение 0.
Рис. 9.5 «Окончание» секции HTTP
Группа полей Conversion/Display Определяет формат и стиль отображения графики, а так же отображение информации из видов. Image conversion format (по умолчанию GIF). Domino может преобразовывать графические элементы из форм и документов Notes или в формат GIF, или в формат JPEG. В зависимости от того, какой из форматов был выбран вами в данном поле, будут присутствовать или отсутствовать следующие поля. (Выбран GIF) Interlaced rendering (по умолчанию Enabled). Если выбрано Enabled, Domino создает GIF-файлы в «чередуемом» формате. В GIF-файле «чередуемого» формата строки изображения сохранены не в обычной последовательности (строка за строкой от первой до последней), а, например, вначале каждая восьмая строка изображения, затем каждая четвертая строка изображения, затем каждая вторая строка... Поэтому GIF-файл «чередуемого» формата в процессе загрузки в броузер отображается в окне броузера, как бы «приобретая все более и более четкие очертания». Поскольку глаз человека обладает свойством «восстанавливать» отсутствующие части изображения, у клиента создается впечатление, что загрузка изображения происходит быстро. Если же выбрано Disabled, Domino создает файлы GIF в обычном формате - такое изображение в окне броузера появляется «сверху вниз строка за строкой». (Выбран JPEG) Progressive rendering (по умолчанию Enabled). Если выбрано Enabled, Domino создает JPEG-файлы в «прогрессирующем» формате. Броузеры обычно загружают и отображают JPEG-файл обычного формата за один проход. JPEG-файл в «прогрессирующем» формате загружается и отображается за несколько проходов: изображение в окне броузера с каждым проходом приобретает «все более и более четкие очертания». В результате клиент может «идентифицировать» возникающее изображение прежде, чем оно полностью загружено в броузер. (Выбран JPEG) JPEG image quality (по умолчанию 75). Целое число в диапазоне от 5 до 100 (процентов), определяющее «качество изображения» в создаваемом Domino JPEG-файле.
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 103
Большие значения - больший по размеру файл и лучшее качество изображения, малые значения - меньший по размеру файл, меньшее количество времени на загрузку, но более низкое качество изображения. Default lines per view (по умолчанию 30). Количество строк из вида в базе данных Notes, возвращаемое сервером Domino в броузер за один запрос. Это лишь «значение по умолчанию», но оно касается всех баз на сервере. Клиент броузера в каждом конкретном случае может изменить получаемое им количество строк из вида, указав в URL параметр &Count наподобие http://host-name/db-name.nsf/view-name?OpenView&Start=1&Count=999&ExpandView.
Группа полей Character Set Mapping Default character set group (по умолчанию Western). Набор символов, в котором HTMLтекст будет предоставляться клиенту. Возможные варианты: Western, Central European, Japanese, Traditional Chinese, Simplified Chinese, Korean, Cyrillic, Greek, Turkish, Thai и Multilingual. Чтобы обеспечить поддержку «русских букв», выбирают Cyrillic. Character set mapping (по умолчанию Latin1). Сервер Domino использует заданный в поле Default character set group набор символов и заданную в поле Character set mapping (Рис. 9.7) таблицу кодов символов при создании HTML-текста для броузера. Выбор в поле Character set mapping зависит от выбора в поле Default character set group. Если Default character set group = Cyrillic, в поле Character set mapping можно выбрать таблицы кодов символов ISO-8859-5, CP1251 или KOI8-R. Имеется возможность выбирать нужный набор символов (например, Western, Cyrillic, Greek…) при создании из броузера новых документов. Для этого в поле Default character set group должно быть выбрано Multilingual (Native Code Page) или Multilingual (ISO10646). Только тогда появится возможность выбрать для каждого набора символов необходимую кодовую страницу (но только по одной для каждого набора!).
Рис. 9.6 Группа полей Character Set Mapping при выборе Multilingual (Native Code Page)
Рис. 9.7 «Выпадающий список» для выбора нужного набора символов при создании документа из броузера © InterTrust Co. Тел. 956-7928
104
Конфигурирование Web-сервера Domino версий 4.6.x
Пользователь броузера, создавая «в базе» новый документ, обнаружит «в конце» этого документа поле типа «выпадающий список» с меткой Select Encoding, позволяющее выбрать желательный ему набор символов. Возможность же выбирать в рамках одного набора символов несколько кодовых страниц, например KOI8-R или Windows-1251 для Cyrillic, отсутствует.
9.2.
База данных Domino Web Server Configuration
1.1.1. Виртуальные серверы Domino (hosting multiple sites on one server) На одном компьютере, «несущем» один сервер Notes и одну задачу HTTP, может функционировать несколько виртуальных серверов Domino. Каждый виртуальный сервер Domino имеет собственные имя хоста, «начальную» страницу и каталоги HTML, CGI и Icons, но при этом структура каталога данных Notes для всех виртуальных серверов Domino остается одинаковой. Наличие собственного IP-адреса для каждого виртуального сервера совсем не обязательно. На сервере Notes создается база данных DOMCFG.NSF по шаблону Domino Configuration (DOMCFG.NTF). В этой базе для каждого «очередного» виртуального сервера Domino создается документ Virtual Server. Чтобы выполненные изменения «вступили в силу», перезапускают задачу HTTP. Таким образом, настройки для «первого» сервера Domino задаются в секции HTTP Server из документа Server, а настройки «очередных» получаются из настроек «первого» сервера Domino заменой значений «одноименных» полей на значения из соответствующего документа Virtual Server.
Рис. 9.8 Документ Virtual Server Поясним это на примере. Предположим, что имена хостов www.inttrust.ru и main.inttrust.ru имеют один и тот же IP-адрес 195.208.68.130 (main.inttrust.ru – имя хоста, а www.inttrust.ru – его алиас), а имя хоста main-int.inttrust.ru имеет IP-адрес 195.208.68.1. Пусть в секции HTTP Server документа Server в поле Host name указано main-int.inttrust.ru, а в поле Bind to host name выбрано Disabled. В базе DOMCFG.NSF создадим два документа Virtual Server, указав в поле с меткой IP Address (не обращайте внимания на семантику метки поля!) для одного «текст» main.inttrust.ru, а для другого - «текст» www.inttrust.ru, а в полях с меткой Home URL соответствующие «начальные» страницы. Перезапустим задачу HTTP. Клиент, обращающийся к HTTP-серверу по URL http://main-int.inttrust.ru, будет «попадать» на указанную в секции HTTP Server документа Server «начальную» страницу. «Получив» URL http://main.inttrust.ru или http://www.inttrust.ru, задача HTTP «решает вопрос», какому же виртуальному серверу
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 105
соответствует этот URL, непосредственно по содержащемуся в URL имени хоста (main.inttrust.ru или www.inttrust.ru) и «отправляет клиента» на указанную в соответствующем документе Virtual Server «начальную страницу». Теперь добавим в базу DOMCFG.NSF третий документ Virtual Server, указав в поле IP Address «текстовую строку» «195.208.68.130» и соответствующую ей «начальную» страницу. И после перезапуска задачи HTTP ее поведение может показаться … совершенно необъяснимым. По мнению автора, все зависит от того, в каком порядке оказались расположенными наши документы Virtual Server в «скрытом несортированном» виде ($Virtual Servers). Обратите внимание, что в рассматриваемом случае www.inttrust.ru и main.inttrust.ru имеют IP-адрес 195.208.68.130. Если порядок «сверху вниз по виду» 195.208.68.130 ! www.inttrust.ru ! main.inttrust.ru, то «два последних» документа вообще не будут функционировать, т.е. обращаясь по URL http://main.inttrust.ru или http://www.inttrust.ru, вы будете попадать на начальную страницу, указанную в документе для 195.208.68.130. Если порядок www.inttrust.ru ! 195.208.68.130 ! main.inttrust.ru, не будут функционировать «последний» документ. Вероятно, причина «столь замысловатого поведения» объясняется тем, что в Domino версий 4.5x для каждого виртуального сервера требовался свой собственный IP-адрес, а в версиях 4.6x, как показывает практика, это не обязательно. Поэтому, чтобы «не попадать в зону неопределенности», можно порекомендовать указывать в документах Virtual Server и в поле Host name документа Server или только имена хостов, или только IP-адреса, а не то и другое вместе. Обратите также внимание, что в базе DOMCFG.NSF имеются другие могущие оказаться полезными формы для создания документов:
• • •
Mapping URL → Directory - для перемещения каталогов HTML, CGI, images и других в новое местоположение без изменения URL, используемых клиентами для доступа к ним; Mapping URL → URL - для автоматической замены входящего URL на другой, соответствующий реальному местоположению на этом же HTTP-сервере; Redirection URL → URL - для автоматической замены входящего URL на другой, в том числе и расположенный на другом HTTP-сервере.
9.2.2. Собственные страницы «в ответ» на ошибочные ситуации Начиная с версии 4.6 имеется возможность создавать собственные страницы «в ответ» на ошибочные ситуации. Допустимы четыре категории «ответных» страниц:
• • • •
Authentication failure – задаче HTTP не удалось аутентифицировать клиента (неправильные имя или пароль); Authorization failure – согласно списку управления доступом базы клиент не имеет необходимого уровня доступа для выполнения запрошенной им операции; Document successfully deleted – «в ответ» на успешное удаление документа по запросу клиента; General error – «в ответ» на все остальные ошибки.
Во первых, такие ответные страницы могут быть определены в конкретной базе данных. Для этого в базе нужно создать четыре формы с предопределенными именами (или алиасами) $$ReturnAuthenticationFailure, $$ReturnAuthorizationFailure, $$ReturnDocumentDeleted, $$ReturnGeneralError. Если при работе с такой базой из броузера возникает ошибка соответствующей категории, клиент получает в ответ HTML-код, сгенерированный по соответствующей форме. Пример такой доработки базы можно найти в шаблоне Combined Mail (MAILC46.NTF), поставляемом с Domino 4.6. Во-вторых, для всех остальных баз, которые не имеют собственных форм «для ответа на ошибки», «типовые ответные» формы можно определить в базе данных Domino Configuration (DOMCFG.NSF). Для этого в базе DOMCFG.NSF необходимо создать один документ Mapping Error Messages для «всего» HTTP-сервера или по одному такому документу для каждого из его © InterTrust Co. Тел. 956-7928
106
Конфигурирование Web-сервера Domino версий 4.6.x
виртуальных серверов. В документе для каждой категории задается имя базы данных и название формы, в соответствии с которой должен генерироваться HTML-код «в ответ» на ошибку. Естественно, что вам также потребуется создать в указанных в документе Mapping Error Messages базах формы с указанными именами (рекомендуется создавать их непосредственно в DOMCFG.NSF). Тогда, если при работе с базой из броузера возникает ошибка, но в этой базе не определены собственные «ответные» формы, для генерации HTMLкода будут использоваться «типовые ответные» формы.
Рис. 9.9 Документ Mapping Error Messages
9.3.
Поддержка сервлетов на Web-сервере Domino 9.3.1. Что такое «сервлет»
Сервлет (servlet) представляет собой специальное приложение, написанное на языке Java и выполняющееся на Web-сервере, обеспечивающем поддержку сервлетов. Когда Web-сервер принимает от клиента запрос, URL которого «указывает на» сервлет, сервер выполняет сервлет, и вывод сервлета отправляется клиенту. Поведение сервлета во многом подобно поведению CGI-программы. Одно из основных отличий состоит в том, что сервлет не нуждается в загрузке при каждом обращении к нему - загрузка сервлета выполняется только один раз, при первом обращении. Сервлеты должны реализовывать интерфейс javax.servlet.Servlet. Обычно этого достигают, создавая класс-потомок javax.servlet.GenericServlet или javax.servlet.HttpServlet. Оба эти базовых класса реализуют интерфейс Servlet, причем HttpServlet сам является потомком GenericServlet. Когда сервлет загружается сервером, в сервлете происходит вызов метода init(). Метод init() вызывается только один раз. После того, как сервер загрузит и «инициализирует» сервлет, последний становится способен обрабатывать запросы клиентов. Каждый запрос клиента приводит к вызову в сервлете метода service(). Метод service() должен быть написан с учетом параллельного выполнения потоков (thread-safe manner), поскольку каждый новый запрос порождает новый поток, выполняющий в себе метод service(). Например, если метод service() изменяет значение некоторого поля в объекте сервлета, доступ к
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 107
этому полю должен быть синхронизирован. Если же по каким-то соображениям метод service() не должен выполняться в разных потоках, то сервлет должен реализовать интерфейс SingleThreadModel. import javax.servlet.* import java.io.* public class MyServlet1 extends HttpServlet { /* метод service() будет вызываться из многих потоков */ } import javax.servlet.* import java.io.* public class MyServlet2 extends HttpServlet implements SingleThreadModel { /* метод service() может вызываться только в одном потоке */ }
Сервлет обычно функционирует на сервере до тех пор, пока функционирует сервер или пока его не выгрузит администратор. В этом случае в сервлете вызывается метод destroy(). Метод destroy() вызывается только один раз, и должен «дождаться» завершения или принудительно завершить все потоки, выполняющие метод service(), и освободить все выделенные сервлету ресурсы. Только после этого сервлет может быть вновь загружен и инициализирован. Еще одним стандартным методом сервлета является getServletInfo(). Он должен возвращать строку (String), содержащую описание сервлета. Возвращаемый текст обычно используется средствами управления сервлетами на сервере. «Неперегруженный» метод getServletInfo() возвращает пустую строку. Если сервлет является наследником класса HttpServlet, часто перегружают не сам метод service(), а другие методы, вызываемые «родным» методом service() в зависимости от запросов клиента:
• • •
doGet() - вызывается для обработки запросов GET, условный GET и HEAD (клиент запрашивает необходимые ему данные, а сервер (сервлет) возвращает клиенту запрошенную им информацию); getLastModified() - вызывается при обработке запросов GET, условный GET и HEAD и возвращает время последней модификации запрошенного клиентом ресурса; doPost() - вызывается для обработки запроса POST (клиент заполняет форму и передает введенные данные на сервер, сервер (сервлет) принимает и обрабатывает данные и обычно отвечает клиенту подтверждением приеме данных).
«Неперегруженные» методы doGet() и doPost() возвращают код ошибки 400 (BAD_REQUEST - «Плохой» запрос от клиента), а «неперегруженный» getLastModified() отрицательное число, означающее, что время последней модификации неизвестно, а потому не должно применяться в запросе условный GET и при кэшировании. Методы service(), doGet() и doPost() получают два аргумента: объекты классов HttpServletRequest и HttpServletResponse, метод getLastModified() - один аргумент: объект класса HttpServletRequest. Эти объекты поддерживают соответственно интерфейсы javax.servlet.http.HttpServletRequest и javax.servlet.http.HttpServletResponse, которые в свою javax.servlet.ServletRequest очередь «расширяют базовые» интерфейсы и javax.servlet.ServletResponse. Класс HttpServletRequest инкапсулирует передачу информации от клиента к сервлету. Методы и свойства ServletRequest позволяет сервлету получать такую информацию, как имена параметров, переданных клиентом серверу, схему, использованную клиентом, имена хостов клиента и сервера, а также входной поток ServletInputStream, «из которого» сервлет получает данные, переданные клиентом при использовании метода POST. Класс HttpServletResponse инкапсулирует передачу информации от сервлета к клиенту. Методы и свойства ServletResponse позволяет сервлету «отвечать» клиенту: задать MIME-тип
© InterTrust Co. Тел. 956-7928
108
Конфигурирование Web-сервера Domino версий 4.6.x
«ответа» и длину содержимого (content length), а так же получить выходной поток ServletOutputStream, в который сервлет должен записывать передаваемые клиенту данные. Пример 1. Сервлет возвращает броузеру страницу, содержащую текст «Hello World». /* * @(#)HelloWorldServlet.java 1.9 97/05/22 * Copyright (c) 1995-1997 Sun Microsystems, Inc. All Rights Reserved. * CopyrightVersion 1.0 * * Перекомпилирован VisualAge for Java (Enterpise) Version 1 Patch Set 2 * Обращение: http://main.inttrust.ru/Servlet/Hello */ import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloWorldServlet extends HttpServlet { public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); ServletOutputStream out = res.getOutputStream(); out.println(""); out.println("
Hello World "); out.println(""); out.println("Hello World "); out.println(""); } public String getServletInfo() { return "Create a page that says Hello World and send it back"; } } Пример 2. Сервлет принимает запрос клиента, определяет параметры запроса, распознает тип запроса (GET или PUT), выбирает данные запроса и возвращает в броузер сгенерированный в строке msg HTML-код, по смыслу являющийся протоколом запроса. /* * @(#) EchoFormServlet.java * Copyright (c) Elliotte Rusty Harold * From Book: Java Network Programming * * Перекомпилирован VisualAge for Java (Enterpise) Version 1 Patch Set 2 * Обращение: http://main.inttrust.ru/Servlet/EchoForm */ import import import import
java.servlet.*; java.servlet.http.*; java.io.*; java.util.*;
public class EchoFormServlet extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response)
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 109 { String msg = "<TITLE>\r\n"; msg += "Form ResponseForm Response \r\n"; // Основные параметры запроса msg += "Method: " + request.getMethod() msg += "URI: " + request.getRequestURI() msg += "Protocol: " + request.getProtocol() msg += "Path Info: " + request.getPathInfo()
+ + + +
" \r\n"; " \r\n"; " \r\n"; " \r\n";
// Получение пар «имя-значение» из MIME-заголовка Enumeration e = request.getHeaderNames(); while (e.hasMoreElements()) { String header = (String) e.nextElement(); msg += header + ": " + request.getHeader(header) + " \r\n"; } msg += ""; // Получение данных формы String qs = ""; if (request.getMethod().equals("GET")) { qs = request.getQueryString(); } else if (request.getMethod().equals("POST")) { try { DataInputStream dis = new DataInputStream(request.getInputStream()); String s; while ((s = dis.readLine()) != null) { qs += s + "\r\n"; } } catch (IOException ie) { } } else { msg += "I can't handle the " + request.getMethod() + " method. "; } // Разбор данных на пары «имя-значение», URL decoding отсутствует if (qs != null) { StringTokenizer st = new StringTokenizer(qs, "&"); while (st.hasMoreTokens()) { String temp = st.nextToken(); String name = temp.substring(0, temp.indexOf('=')); String value = temp.substring(temp.indexOf('=') + 1, temp.length()); msg += name + ": " + value + " \r\n"; } } // Возвращаемый клиенту HTML сгенерирован msg += "\r\n"; // Отправка его клиенту response.setContentLength(msg.length()); response.setContentType("text/html"); try {
© InterTrust Co. Тел. 956-7928
110
Конфигурирование Web-сервера Domino версий 4.6.x DataOutputStream rs = new DataOutputStream(response.getOutputStream()); rs.writeBytes("\r\n" + msg); } catch (IOException ie) { }
} } Для тестирования этого сервлета удобно использовать следующую HTML-форму с применением языка JavaScript. Форма содержит три текстовых поля и две кнопки. Одна из кнопок передает сервлету данные из полей формы методом GET («в составе URL»), а вторая - методом POST («в теле запроса»). <SCRIPT LANGUAGE="JavaScript"> В случае запроса GET сервлет возвращает броузеру приблизительно следующее. Form Response Method: GET URI: /Servlet/EchoForm?n1=v1&n2=v2&n3=v3 Protocol: http Path Info: null ACCEPT-LANGUAGE: ru,en;q=0.5 CONNECTION: Keep-Alive REFERER: http://main.inttrust.ru/eSuite.nsf/byKeys/01-xx-001?OpenDocument ACCEPT: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, */* ACCEPT-ENCODING: gzip, deflate USER-AGENT: Mozilla/4.0 (compatible; MSIE 4.01; Windows NT) HOST: main.inttrust.ru n1: v1 n2: v2 n3: v3 В случае запроса POST сервлет возвращает броузеру приблизительно следующее. Form Response Method: POST URI: /Servlet/EchoForm Protocol: http Path Info: null CONTENT-LENGTH: 17 CONTENT-TYPE: application/x-www-form-urlencoded ACCEPT-LANGUAGE: ru,en;q=0.5 CONNECTION: Keep-Alive
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 111 REFERER: http://main.inttrust.ru/eSuite.nsf/byKeys/01-xx-001?OpenDocument ACCEPT: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, */* ACCEPT-ENCODING: gzip, deflate USER-AGENT: Mozilla/4.0 (compatible; MSIE 4.01; Windows NT) HOST: main.inttrust.ru n1: v1 n2: v2 n3: v3
Завершая экскурс в сервлеты, необходимо заметить, что данное рассмотрение преследовало лишь цель облегчить понимание вопросов конфигурирования поддержки сервлетов Webсервером Domino, и ни в коей мере не претендует на полноту освещения всех возможностей и вопросов разработки сервлетов. В частности, не следует из приведенного материала делать вывод, что «общение» между клиентом (броузером или апплетом на странице броузера) и сервлетом ограничиваются только методами протокола HTTP. Полную информацию о сервлетах и комплект разработчика сервлетов JSDK можно получить на http://jserv.javasoft.com/products/java-server/servlets/index.html. В поисках разнообразных примеров сервлетов можно обратиться на http://javashareware.com.
9.3.2. Конфигурирование поддержки сервлетов сервером Domino В настоящее время поддержка сервлетов осуществляется только сервером Domino 4.6х на платформе Windows NT/Intel. Поддерживаются сервлеты, реализующие интерфейсы JavaSoft. По умолчанию поддержка сервлетов сервером Domino «запрещена». Чтобы разрешить ее:
• •
убедитесь, что в каталоге программ сервера присутствуют файлы servlet.dll и icsclass.jar; добавьте в файл NOTES.INI сервера две переменные: • DominoEnableJavaServlets=1 - разрешает поддержку сервлетов задачей HTTP, • JavaUserClasses=c:\notes\data\domino\servlets - задает полные пути к каталогам, в которых вы будете хранить сервлеты, а так же им необходимые JAR-файлы.
Признаком того, что поддержка сервлетов разрешена, будет «автоматическое» появление в файле DOMINO.CNF (находится в каталоге данных сервера) следующих строк. #Java Servlet Settings EnableJavaServletSupport
yes
ServerInit servlet:ServletInit c:\notes\data\servlet.cnf Service /Servlet/* servlet:ServletService* ServerTerm servlet:ServletTerm
В результате этого при очередном запуске задачи HTTP будет автоматически загружаться виртуальная машина Java, которая будет пытаться найти и загрузить класс ServletManager. Этот класс, а так же прочие необходимые для поддержки сервлетов классы находятся в файле icsclass.jar. Если все успешно, вы обнаружите на консоли сервера приблизительно следующие сообщения. 25.03.98 13:48:33 25.03.98 13:48:43 25.03.98 13:48:44
HTTP Web Server started JVM: Java Virtual Machine initialized. Java Servlet Manager initialized
Сервлеты, которые должен загружать ServletManager, должны быть определены вами в файле SERVLET.CNF. Этот текстовый файл вы должны создать в каталоге данных. Например, файл может содержать следующее: #Servlet configuration settings Servlet HelloWorldServlet { }
© InterTrust Co. Тел. 956-7928
112
Конфигурирование Web-сервера Domino версий 4.6.x
Servlet EchoFormServlet { } Servlet SnoopServlet { } Servlet DateServlet { } Service Service Service Service
HelloWorldServlet /Servlet/Hello HelloWorldServlet /Servlet/EchoForm SnoopServlet /Servlet/Snoop DateServlet /Servlet/Now
В данном файле перечислены 4 сервлета: HelloWorldServlet, EchoFormServlet, SnoopServlet и DateServlet. Их файлы .class должны находиться в каталоге, указанном в переменной JavaUserClasses. Обращения же к этим сервлетам из броузера должны выполняться соотвественно по URL http://hostname/Servlet/Hello, http://hostname/Servlet/EchoForm, http://hostname/Servlet/Snoop и http://hostname/Servlet/Now. ServletManager определяет местоположение всех перечисленных в файле SERVLET.CNF сервлетов, когда запускается задача HTTP. При первом обращении к сервлету из броузера ServletManager выполняет загрузку кода этого сервлета и вызывает его метод init() с параметрами, указанными в файле SERVLET.CNF. При каждом обращении к сервлету из броузера для сервлета вызывается его метод service(). Методу service() передаются два параметра: ServletRequest - объект, представляющий запрос пользователя, и ServletResponse объект, представляющий «ответ» сервлета пользователю. Код сервлета должен быть многопоточным. При завершении задачи HTTP ServletManager вызывает для всех загруженных сервлетов их методы destroy(). Во время «первичной» загрузки сервлета приблизительно следующие сообщения:
вы
обнаружите
на
консоли
сервера
25.03.98 13:50:44 25.03.98 13:50:44 25.03.98 13:50:44 25.03.98 13:50:44 25.03.98 13:50:44 25.03.98 13:50:44 25.03.98 13:50:45 25.03.98 13:50:45 25.03.98 13:50:45
Addin: Agent printing: HelloWorldServlet: init Addin: Agent printing: Addin: Agent printing: Loaded servlet: HelloWorldServlet Addin: Agent printing: -----Servlet Information----Addin: Agent printing: Servlet Name: HelloWorldServlet Addin: Agent printing: Servlet Base Class: HelloWorldServlet Addin: Agent printing: Servlet State: READY Addin: Agent printing: Servlet configuration parameters: <none> Addin: Agent printing: Servlet Info [Servlet.toString()]: HelloWorldServlet@7d87b1
26.03.98 12:49:55 26.03.98 12:49:56 26.03.98 12:49:56 26.03.98 12:49:56 26.03.98 12:49:56 26.03.98 12:49:56 26.03.98 12:49:56 26.03.98 12:49:56 26.03.98 12:49:57
Addin: Agent printing: EchoFormServlet: init Addin: Agent printing: Addin: Agent printing: Loaded servlet: EchoFormServlet Addin: Agent printing: -----Servlet Information----Addin: Agent printing: Servlet Name: EchoFormServlet Addin: Agent printing: Servlet Base Class: EchoFormServlet Addin: Agent printing: Servlet State: READY Addin: Agent printing: Servlet configuration parameters: <none> Addin: Agent printing: Servlet Info [Servlet.toString()]: EchoFormServlet@9108bb
Средства для принудительной выгрузки сервлетов в Domino пока отсутствуют. Чтобы заменить загруженный сервлет, изменить параметры его запуска или добавить загрузку нового сервлета, вам всякий раз придется перезапускать задачу HTTP. Рассмотрим подробнее синтаксис файла SERVLET.CNF. Для каждого сервлета в файле обычно должны присутствовать две директивы. © InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 113
Директива Servlet | AdminServlet задает имя сервлета, а так же имена и значения передаваемых его методу init() параметров. В отличие от «обыкновенного» сервлета (Servlet) сервлет администратора (AdminServlet) имеет доступ к конфигурации ServletManager и может изменять ее.
{ Servlet | AdminServlet } <имя сервлета>
{
<имя параметра> = <значение параметра> . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . <имя параметра> = <значение параметра> } Директивы отображения определяет URL для обращения к сервлету. В принципе для каждой точки входа Go WebServer Application Programming Interface (GWAPI) должна указываться своя директива и свой URL. При обращении клиента по этому URL управление должно передаваться Web-сервером на однозначно связанную с директивой точку входа GWAPI. Однако в Domino версий 4.6x все эти директивы «отображаются» на метод service() сервлета. Поэтому достаточно одной директивы отображения
Service <имя сервлета> Что касается упоминания GWAPI, то, с учетом имевших место высказываний разработчиков компании IBM/Lotus, это означает планируемое в будущем слияние продуктов Go WebServer и Domino Web Server. Однако в настоящее время это пока «разные» продукты. Документацию по GWAPI можно получить с http://www.lotus.com/dominogowebserver.
9.4.
Кластеры из Web-серверов Domino: реалии и перспектива
Кластеры из серверов Notes/Domino обеспечивают балансировку загрузки (load balancing) и автоматическое перенаправление запросов, адресованных на «сильнозагруженный или неработающий» сервер-член кластера, на другой сервер-член кластера, способный обслужить этот запрос (failover). Однако полнофункционально это поддерживается в настоящее время только для клиентов Notes. Подробнее познакомиться с принципом функционирования и вопросами настройки кластеров из серверов Notes/Domino можно, например, в [3]. Простейшая попытка приблизиться к достижению подобного поведения для Web-клиентов может состоять в использовании т.н. round-robin DNS. Суть подхода состоит в том, что несколько серверов Notes/Domino, функционирующих в составе одного кластера и имеющих реплики всех доступных Web-клиентам баз данных, «назначаются на сервере DNS на одно и то же имя». Например, следующие 4 записи из файла DNS зоны inttrust.ru означают, что mainext.inttrust.ru и second-ext.inttrust.ru - имена хостов, а www.inttrust.ru - алиас для имен обоих этих хостов. main-ext second-ext www
IN IN IN IN
A A CNAME CNAME
195.208.68.130 195.208.68.132 main-ext second-ext
В этом случае «обыкновенный» DNS на запрос на имя www.inttrust.ru всегда будет возвращать IP-адрес хоста main-ext.inttrust.ru, тогда как round-robin DNS на «каждый нечетный» запрос будет возвращать IP-адрес хоста main-ext.inttrust.ru, а на «каждый нечетный» - IP-адрес second-ext.inttrust.ru. В результате поток запросов Web-клиентов может «распределяться» сервером DNS на два «синхронных» Web-сервера. Более продвинутым и интересным примером реализации «балансировки нагрузки» на основе round-robin DNS является кластер из трех Web-серверов Domino в домене Notes.Net http://www.notes.net. Серверы Domino Net1 и Net2 установлены на компьютерах с двумя процессорами Pentium II 266 МГц и оперативной памятью 512 Мб. Серверы Domino Net3 и Net4 установлены на компьютерах с двумя процессорами Pentium Pro 200 МГц и оперативной памятью 256 Мб. В состав кластера входят только серверы Net2, Net3 и Net4, и на каждом из них функционирует задача HTTP. Сервер Net1 не входит в состав кластера, но между ним и
© InterTrust Co. Тел. 956-7928
114
Конфигурирование Web-сервера Domino версий 4.6.x
одним из серверов-членов кластера осуществляются «обычные» репликации с частотой 1 минута. Люботпытно, что с сервера Net1 на серверы-члены кластера выполняются селективные репликации предоставляемых Web-клиентам баз - в репликах на серверах Net2, Net3 и Net4 присутствуют только индексы видов, необходимые Web-клиентам, но нет индексов видов, применяемых при доступе к базам из клиентов Notes. «Перед сервером управления» Net1 «находится» достаточно большое количество внутрикорпоративных серверов Notes, в репликах базах данных на которых «из клиентов Notes» и создается информация, «помещаемая затем на сайт». Настройка же round-robin DNS очевидна из Рис. 9.10.
Рис. 9.10 Схема организации кластера из трех Web-серверов в домене Notes.Net Однако в подходе на основе round-robin DNS имеются три существенных недостатка. Вопервых, сервер DNS «распределяет запросы» без всякого учета текущей рабочей загрузки Webсерверов. Во-вторых, другие DNS-серверы обычно кэшируют «удачно разрешенные ими» IPадреса и могут «не быть» round-robin DNS. В-третьих, Proxy-серверы, выполняя кэширование страниц, обычно оперируют IP-адресами в URL этих страниц, а не именами «исходных» Webсерверов. Другой подход к решению проблемы балансировки загрузки может состоять в использовании продукта IBM's Network Dispatcher (http://www.entmag.com/archive/1997/ march19/031912.html), который с учетом времени отклика обслуживаемых им Web-серверов перенаправляет «поступающие на него» запросы Web-клиентов на «наиболее быстро отвечающий» Web-сервер. Однако в настоящее время IBM's Network Dispatcher при перенаправлении запросов «принимает во внимание» только время отклика, но не реальную загрузку Domino Web-сервера или наличие на нем реплик баз данных. Но тем не менее вторая и третья проблемы, присущие варианту с применением «round-robin DNS», при использовании IBM's Network Dispatcher отсутствуют, поскольку все запросы клиентов «поступают в адрес» Network Dispatcher, а далее распределяются уже им по обслуживаемых Web-серверам. Кардинального решения проблемы распределения нагрузки между Web-серверами Domino, входящими в состав кластера, следует ожидать только в Domino версии 5.0. В его состав будет входить спецально предназначенная для этих целей задача Internet Cluster Manager (ICM). Эта
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 115
задача устанавливается на одном из серверов-членов кластера, «принимает на себя», подобно IBM's Network Dispatcher, запросы Web-клиентов, и затем, с учетом возможности исполнения запроса (наличия реплик) и реальной загрузки, перенаправляет их задачам HTTP на других серверах-членах кластера. ICM поддерживает запросы как по «обычному» протоколу HTTP, так и по протоколу HTTP с поддержкой SSL. В подтверждение сказанного на Рис. 9.11 дается внешний вид секции ICM из документа Server адресной книги Domino версии 5.0 (Developer Test Build 2).
Рис. 9.11 Внешний вид секции ICM из документа Server адресной книги Domino версии 5.0
© InterTrust Co. Тел. 956-7928
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 117
10. Secure Sockets Layer в Lotus Domino 4.6.1 Материал этой главы поможет вам понять, что такое SSL, как в Domino реализована его поддержка и что необходимо проделать на сервере Domino и в броузере клиента для обеспечения поддержки SSL.
10.1. Основы SSL Фундаментом коммуникаций по Internet является протокол TCP/IP. Поскольку протокол открыт и относительно прост, существует множество людей, хорошо осведомленных во всех его тонкостях. Когда вы устанавливаете соединение с кем-нибудь в Internet, передаваемые между вами пакеты могут быть «перехвачены» на пути их следования третьими лицами, записаны и исследованы. Чтобы получать копии всех пакетов, которыми вы обменивались в течение сеанса, в простейшем случае могут использоваться программы, известные как IP sniffers. Более того, вы даже не знаете наверняка, с кем вы в действительности установили соединение и не искажают ли третьи лица информацию, передаваемую между вами и тем, с кем вы установили соединение. Более подробную информацию по этим вопросам можно найти, например, в главе 4 «Анализ способов нарушения информационной безопасности» из книги «Теория и практика обеспечения информационной безопасности» 1). Однако использование SSL вместе с протоколами прикладного уровня поверх TCP/IP обеспечивает в условиях априорно небезопасной сети приемлемую защиту первого уровня. SSL (Secure Sockets Layer – «слой защищенных сокетов») был первоначально создан компанией Netscape, чтобы обеспечить поверх обычного протокола HTTP дополнительный «слой», включающий аутентификацию клиентом и сервером друг друга на основе сертификатов, шифрование передаваемых по соединению данных и проверку того, что передача осуществляется без искажений. В настоящее время SSL утвержден и становится основным стандартом первого уровня для защиты всех протоколов Internet и трафика прикладных программ, работающих поверх TCP/IP. Его следует понимать как простое, общее и полезное соглашение (спецификацию), которому должны следовать разработчики программного обеспечения, чтобы защитить любое двунаправленное соединение по сети. Отметим, что SSL вовсе не единственный из применяемых стандартов защиты передаваемых по сети данных. Например, в настоящее время в состоянии утверждения находится стандарт SET (Secure Electronic Transaction), возможности которого в мире электронной торговли многие оценивают выше SSL. Рассмотрим основные моменты, позволяющие уяснить принцип функционирования SSL 2). Реализация SSL компании Netscape использует систему шифрования RSA. В этой системе шифрования каждому субъекту (пользователю или серверу) предоставляется пара ключей для шифрования и дешифрирования данных. Пара состоит из открытого ключа (public key) и секретного ключа (private key). Данные, которые зашифрованы открытым ключом, могут быть дешифрированы только секретным ключом. Наоборот, данные, зашифрованные секретным ключом, могут быть дешифрированы только открытым ключом. Обозначим данные, зашифрованные ключом «ключ», как {данные} ключ . Тогда справедливы соотношения
1)
Под ред. П. Д. Зегжды. М.: Издательство агентства «Яхтсмен», - 1996, 192 с.
2)
Более подробное изложение этих вопросов на русском языке имеется, например, в книге Сергея Баричева «Kpиптогpафия без секpетов», электронную версию которой можно попытаться найти по ссылке http://infoart.sinaps.ru/it/talk/crypto/index.htm. Наиболее полную информацию о SSL на английском языке можно найти по ссылкам http://home.netscape.com/info/security-doc.html и http://www.consensus.com/security/ssl-talkfaq.html, а об алгоритме RSA – по ссылке http://www.rsa.com/.
© InterTrust Co. Тел. 956-7928, 956-7929
118
Secure Sockets Layer в Lotus Domino 4.6.1
{ {данные} public-key} private-key = данные { {данные} private-key} public-key = данные Открытый ключ передается владельцем любому желающему его иметь, и, следовательно, известен многим. Секретный ключ, напротив, доступен только его владельцу и никогда не должен передаваться другим. Хотя секретный и открытый ключи находятся в известной математической зависимости, попытка подбора одного ключа при известном другом ключе требует значительной вычислительной работы, причем количество этой работы возрастает экспоненциально в зависимости от используемой длины ключей.
Аутентификация (установление подлинности) Установление подлинности - процесс проверки, позволяющий одному субъекту убедиться в том, что другой субъект именно тот, «кем он представился» первому субъекту. Предположим, что субъект A хочет аутентифицировать субъекта B. B имеет пару ключей – секретный и открытый, и уже сообщил свой открытый ключ субъекту A. Способ, которым B сообщил A свой открытый ключ, мы обсудим ниже. Субъект A генерирует «случайным образом» сообщение и посылает его B: A → B: Произвольное сообщение Приняв это сообщение, B шифрует его своим секретным ключом и возвращает зашифрованную версию A: B → A: {Произвольное сообщение} B-private-key A получает это сообщение и дешифрирует его, используя открытый ключ B, а затем сравнивает полученный результат с первоначально отправленным сообщением: { {Произвольное сообщение} B-private-key } B-public-key =?= Произвольное сообщение Если обнаружено совпадение, А считает, что соединение установлено действительно с B. Любой другой субъект C, представившийся A под именем B, не смог бы пройти такую проверку, поскольку он не знает секретного ключа B.
Постоянная проверка источника принятых данных Функция (алгоритм) хеширования по данным Д произвольной длины вычисляет некоторое значение, обычно, длиной в 128 бит. Будем обозначать это значение digest[Д]. Поскольку такая операция не сохраняет количество информации, очевидно, существует множество данных Д', что digest[Д'] = digest[Д], но Д' ≠ Д. Может показаться, что в качестве алгоритма хеширования можно использовать практически любой алгоритм, например, сумму по модулю 2 каждых очередных 16-и байтов данных. Но для рассматриваемого нами применения подходит лишь такой алгоритм, который гарантирует, что попытка подбора Д' ≠ Д, чтобы digest[Д'] = digest[Д], потребует значительной вычислительной работы. Например, алгоритм MD5, разработанный компанией RSA. В случае «не заслуживающего доверия» соединения необходимо обеспечить, чтобы субъект A, принимая данные от субъекта B, был всегда уверен, что эти данные были переданы именно B, а не некоторым другим субъектом C, «вмешавшимся в разговор». Для этого B «приходится» передавать A «вслед» за данными значение функции хеширования от этих данных, зашифрованное секретным ключом B: B → A: Сообщение + { digest[Сообщение] } B-private-key Тогда A, «зная» открытый ключ B, сможет вычислить значение функции хеширования по принятому сообщению и сравнить это значение со значением функции хеширования, вычисленным B по отправленному сообщению и в зашифрованном виде переданным A:
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 119
digest[Сообщение] =?= { { digest[Сообщение] } B-private-key } B-public-key Если обнаружено совпадение, А считает, что им было принято сообщение от B, причем в точности такое, какое отправлял B. Любой другой субъект C, во-первых, не может создать подобное сообщение, поскольку он не знает секретного ключа B, а во-вторых, не может «незаметно» для A внести изменения в «перехваченное» им «в пути» от B к A сообщение, поскольку подбор Д' ≠ Д с digest[Д'] = digest[Д] потребует значительной вычислительной работы. Описанная методика широко известна как «цифровая подпись». Говорят, что B «подписал» отправленное им сообщение, а A «проверил цифровую подпись B под принятым им сообщением».
Распространение открытых ключей Рассмотренное выше предполагает, что каждый из субъектов уже знает открытый ключ другого. Чтобы решить проблему «первичной передачи» открытого ключа, используется объект, именуемый сертификатом. Каждый из субъектов (A и B) имеет свой сертификат. Сертификат содержит имя своего владельца, его открытый ключ и дополнительную информацию, обычно дату истечения срока действия сертификата. Сертификат имеет также цифровую подпись 3-ей стороны – субъекта, выдавшего этот сертификат. Чтобы проверить «подпись под сертификатом», необходимо заранее знать открытый ключ выдавшего сертификат субъекта. Процесс «первичной передачи» открытого ключа напоминает следующее. A → B: «Передай свой сертификат» B → A: Cертификат-B Получив сертификат субъекта B, субъект A проверяет «подпись под сертификатом», используя открытый ключ выдавшего этот сертификат субъекта. Способ, которым A получает открытый ключ субъекта, выдавшего сертификат B, мы обсудим ниже. Если проверка подписи прошла успешно, A «извлекает» из полученного сертификата имя и открытый ключ B. Затем «диалог» продолжается. A → B: «Докажи это» B → A: «Я действительно B» + { digest[«Я действительно B»] } B-private-key Субъект A проверяет «подпись под» принятым сообщением, используя открытый ключ B. Если проверка успешна, A «считает», что он «уверенно знает» открытый ключ B, а В «знает» свой секретный ключ. Предположим, что другой субъект C, имеющий сертификат субъекта B, «перехватывает» сообщения, передаваемые между A и В, и пытается имитировать поведение B. A → С: «Передай свой сертификат» С → A: Cертификат-B A → С: «Докажи это» С → A: «Я действительно B» + { digest[«Я действительно B»] } ??? Попытка завершится неуспехом, поскольку С не знает секретного ключа B. Однако такая попытка могла быть успешной, если бы С знал секретный ключ B. Поэтому B должен хранить свой секретный ключ «в надежном хранилище» и никогда не передавать его другим субъектам.
Обмен секретной информацией После того, как A аутентифицировал B, он может передавать B информацию в
© InterTrust Co. Тел. 956-7928, 956-7929
120
Secure Sockets Layer в Lotus Domino 4.6.1
зашифрованном виде. Это могло бы происходить следующим образом: A → B: { «секрет» } B-public-key + { digest[{ «секрет» } B-public-key] } B-public-key «Извлечь информацию» из этого сообщения может только субъект В, поскольку только он должен знать свой секретный ключ. После успешной проверки цифровой подписи B выполняет над принятыми им данными операцию {{ «секрет» } B-public-key} B-private-key =«секрет» Однако имеются два мотива, чтобы усовершенствовать этот процесс. Во-первых, в алгоритмах семейства RSA с двумя ключами используют обычно ключи длиной 512 бит, а при таких длинах ключей затраты на шифрование-дешифрирование относительно велики. Вовторых, хотя смена пары «секретный/открытый ключи» и возможна, на практике она выполняется относительно нечасто, например, один раз в год. А это уже срок из разряда теоретически достаточных для подбора «перехватчиком сообщений» C секретного ключа В и дешифрирования переданной A информации. Проблема решается при использовании криптографических алгоритмов с одним и тем же ключом для шифрования и дешифрирования - типа DES, RC4 или IDEA. Во-первых, эти алгоритмы «работают быстрее», а во-вторых, ключ шифрования субъекты могут сгенерировать случайным образом, обменяться им, а затем использовать его только в течении некоторого непродолжительного времени. Обмен ключом шифрования может происходить следующим образом. A выбирает алгоритм шифрования с одним ключом (из числа поддерживаемых А и B), генерирует случайным образом ключ шифрования для этого алгоритма и передает B название алгоритма и ключ. A → B: {RC4,ключ-RC4}B-public-key+{digest[{RC4, ключ-RC4}B-public-key]}B-public-key B → A: «Ok RC4» + {digest[«Ok RC4»]}A-public-key A → B: {«секрет»}ключ-RC4 + {digest[«секрет»]}ключ-RC4 В результате «хакеру» C остается возможность «перехватывать» передаваемую между А и В информацию, «не понимая ее смысла». Попытки же со стороны C «искажать» передаваемую информацию сразу же будут обнаружены субъектом B – для таких сообщений попытка «проверить подпись» закончится неуспешно. Обнаружив вмешательство, В может запросить от А повторную передачу «искаженных» сообщений. Таким образом, C не может получать или изменять передаваемую между А и В информацию, однако может мешать нормальной передаче и даже, искажая все передаваемые сообщения, сделать передачу совершенно невозможной. Самоподписанные сертификаты Самоподписанный сертификат представляет собой сертификат, выданный для субъекта «за подписью» этого же субъекта. Один из примеров самоподписанных сертификатов сертификаты, которые организации, специализирующиеся на выпуске сертификатов для других субъектов (например, VeriSign, Inc.), используют для того, чтобы сообщать свои открытые ключи всем субъектам, которым приходится проверять выданные этими организациями сертификаты. Для субъекта, получившего самоподписанный сертификат, последний означает приблизительно следующее: "Вот тебе сертификат. Я (тот, кто выдал) выдал его и только я могу проверять его непосредственно, ибо «уверенно» знаю свой открытый ключ. Ты же можешь этому сертификату «доверять» (т.е. извлекать «без проверки» из него мой открытый ключ и использовать при проверке других сертификатов, выданных мною) или «не доверять»". Уровень доверия самоподписанному сертификату выбирается его потребителем в соответствии с уровнем доверия к тому пути, которым сертификат был доставлен от издателя к потребителю. Самоподписанный сертификат, переданный лично вам на дискете лицом, представляющим выдавшую сертификат организацию, непосредственно известным вам и заслуживающим вашего доверия, вероятно, тоже заслуживает доверие. Самоподписанный © InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 121
сертификат, которое вы получаете по Internet от, вообще говоря, «неизвестного» субъекта и по «неизвестному» каналу (от него до вас), вообще говоря, не заслуживает доверия.
10.2. Обзор реализации SSL в Domino Пользователи, работающие из клиентов Notes с серверами Notes, имеют и автоматически используют собственные механизмы аутентификации и защиты информации. Эти механизмы появились в Notes за несколько лет до появления первых версий SSL, однако во многом оказались похожими на сегодняшние версии SSL. Однако с сервером Domino можно также работать из самых различных броузеров и почтовых клиентов по стандартным протоколам прикладного уровня поверх TCP/IP: Hyper Text Transfer Protocol (HTTP), Post Office Protocol v. 3 (POP3), Internet Message Access Protocol (IMAP), Lightweight Directory Access Protocol (LDAP), Network News Transport Protocol (NNTP). При работе по этим протоколам без использования SSL аутентификация обычно осуществляется «в форме cleartext» – по запросу сервера пользователь вводит имя и пароль, они передаются серверу в общеизвестном формате name:password с применением способа кодирования символов Base64, а передача данных в ходе сеанса – в незашифрованном виде. В этом случае аутентификация сторон и защита передаваемой информации, которые пользователь Notes считает само собою разумеющимися, почти полностью отсутствуют. Сравнимый с «обычным Notes» уровень безопасности при работе с сервером Domino из броузеров и почтовых клиентов (например, Netscape Navigator, MS Internet Explorer, Netscape Messenger, MS Outlook Express…) можно обеспечить только при работе по вешеупомянутым протоколам прикладного уровня с применением SSL. Первая и основная функция SSL – шифрование передаваемых сообщений. Хакеры могут получать копии всех пакетов, которыми обменивались пользователь и сервер в течение сеанса. Если бы информация передавалась в незашифрованном виде, хакер имел бы возможность исследовать эту информацию. При использовании SSL вся информация после «SSLрукопожатия» передается в зашифрованном виде, так что перехват пакетов не дает возможности «понять» их содержимое. Чтобы гарантировать секретность передаваемых сообщений, совместно используются две различные схемы шифрования: шифрование с применением двух (открытого и секретного) ключей (RSA) и шифрование с одним ключом (обычно, RC4). При инициализации сеанса в процессе «SSL-рукопожатия», стороны, используя схему шифрования с двумя ключами, договариваются об алгоритме шифрования с одним ключем и его ключе, которыми и будет шифроваться последующая часть трафика между SSL-сервером и SSL-клиентом. Во-вторых, SSL гарантирует, что сообщения не были изменены каким-либо способом в процессе их передачи между сервером и клиентом. Чтобы обеспечить это, SSL-сервер и SSLклиент используют механизм цифровой подписи. Если в ходе сеанса обнаружено «поврежденное» или «непонятное» сообщение, предполагается, что имело место вмешательство. Постоянно проверяя целостность сообщений, SSL-сервер и SSL-клиент способны поддерживается целостность сеанса и гарантировать непрерывную безопасную передачу. Последняя и наиболее важная функция SSL - взаимное установление подлинности (аутентификация). Это процесс, в ходе которого клиент и сервер могут убедиться в подлинности друг друга. Процесс включает обмен сертификатами стандарта X. 509 и проверку этих сертификатов.
«SSL-рукопожатие» (SSL Handshake) SSL в меру возможности «скрывает свое присутствие» от конечного пользователя. Обычно, пользователь броузера просто «переходит по ссылке» на необходимую ему HTML-страницу, а при этом броузер автоматически соединяется по протоколу HTTP с поддержкой SSL (HTTPS) с
© InterTrust Co. Тел. 956-7928, 956-7929
122
Secure Sockets Layer в Lotus Domino 4.6.1
поддерживающим SSL сервером. Обычно HTTP-серверы, поддерживающие SSL, открывают такое соединение не по порту для обычных HTTP-запросов (по умолчанию порт 80), а по другому порту (по умолчанию порт 443). Другим протоколам для использования с SSL тоже назначены соответствующие порты по умолчанию. Когда прикладная программа пользователя устанавливает соединение с сервером, начинается процедура «SSL-рукопожатия», по завершении которой открывается SSL-сессия. С этого момента и до тех пор, пока SSL-сессия поддерживается, весь трафик между пользователем и сервером шифруется и выполняются проверки целостности передаваемых пакетов. На одну SSL-сессию «SSL-рукопожатие» выполняется только один раз. «SSL-рукопожатие» выполняется в три этапа.
•
•
•
Сначала, пользователь и сервер (или сервер и сервер) обмениваются своими сертификатами X.509. Сертификаты проверяются как на предмет возможной подделки цифровой подписи выдавшего их «третьего лица», так и на предмет даты окончания срока их действия. После этого каждая из сторон «знает» открытый ключ другой. Затем клиент и сервер обмениваются случайными сообщениями с применением шифрования по схеме с двумя ключами, что позволяет им убедиться, что каждая из сторон «знает» свой секретный ключ. Если все прошло успешно, «рукопожатие» продолжается, но с этого момента передаваемые между сторонами сообщения шифруются по схеме с двумя ключами. Если же что-то было некорректно, соединение разрывается. Клиент и сервер «договариваются» о функции хеширования, и с этого момента каждая сторона, передавая сообщение, «подписывает» его, а другая сторона, приняв сообщение, «проверяет стоящую под ним» цифровую подпись. Затем клиент и сервер «договариваются» о алгоритме шифрования с одним ключом, который будет использоваться в открываемой сессии. Сначала сервер «просит», чтобы броузер клиента сообщил список всех доступных ему алгоритмов шифрования с одним ключом. Затем сервер выбирает «самый сильный» алгоритм шифрования с одним ключом из тех, которые поддерживаются сервером и клиентом. Однако, по опыту автора, при использовании International Release Domino этим «самым сильным» алгоритмом всегда оказывается RC4 с ключами по 40 бит. На последнем этапе «рукопожатия» одна из сторон (обычно, сервер) случайным образом генерирует ключ, который должен использоваться для шифрования сообщений по схеме с одним ключом, и передает его другой стороне. В данный момент каждая сторона «имеет в своих руках» по четыре ключа: свои секретный и открытый ключи, открытый ключ другой стороны и ключ шифрования по схеме с одним ключом, который будет использоваться в течении открываемой сессии. С этого момента вся передаваемая между сторонами информация шифруется по схеме с одним ключом.
Как реализация SSL встроена в Domino Реализация SSL встроена в архитектуру Domino на уровне сетевой абстракции. Поэтому один и тот же набор подпрограмм отвечает в Domino за реализацию SSL как на разных платформах, так и для разных типов сетей. Кроме того, подпрограммы, реализующие SSL в Domino, «знают только», что по данному порту SSL должен поддерживаться, но «не знают», для какого именно протокола прикладного уровня с поддержкой SSL (HTTP, IMAP…) данный порт используется. Все это существенно сокращает затраты на сопровождение кода Domino SSL и гарантирует его одинаковые функциональные возможности на разных платформах. Подпрограммы, реализующие SSL в Domino, в основном «привязаны» к подпрограммам отправки-получения сообщений сетевого уровня. Основную работу по реализации SSL выполняет подпрограмма ICT. После завершения первой фазы «SSL-рукопожатия» эта подпрограмма «активизируется на перехват» и начинает «перехватывать» каждую операцию отправки-получения сообщений. При отправке сообщения ICT выполняет над подготовленным к отправке сообщением соответствующие алгоритмы шифрования и цифровой подписи, а затем передает результат обработки подпрограммам отправки сетевого уровня. Для полученных от
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 123
подпрограмм сетевого уровня «входящих» зашифрованных и подписанных сообщений ICT выполняет соответствующие алгоритмы расшифровки и проверки подписи. По завершении SSL-сессии подпрограмма ICT прекращает «перехват» операций отправки-получения сообщений и освобождает «захваченные» ею память и другие ресурсы.
10.3. Сертификаты X.509, Certificate Authority, Trusted Roots и KeyRing-файлы Cертификаты стандарта X.509 содержат:
• • • •
«Различаемое» (distinguished) имя владельца сертификата. Открытый ключ владельца сертификата. Он необходим для осуществления шифрования по схеме с двумя ключами. Прочее наполнение (серийный номер; дата, до наступления которой сертификат имеет силу; название организации, выдавшей сертификат...) Цифровая подпись (fingerprint) по имеющейся в сертификате информации «от имени» выдавшей сертификат организации, которую обобщенно называют Certificate Authority.
Рис. 10.1 Так выглядит в Netscape Navigator сертификат пользователя, выпущенный VeriSign Class 1 CA (из меню Communicator - Security Info – Certificates\Yours - View) Certificate Authority (CA) – 3-я сторона, выдающая сертификаты для пользователей и серверов по их запросам. Она может быть «общеизвестной» (например, VeriSign, Inc.) или «внутрикорпоративной» (например, любая организация, использующая Notes Domino). Роль CA состоит в расширении взаимного доверия. Говоря упрощенно, CA выступает как посредник (третье лицо) между двумя сторонами, чтобы стало возможным проверить, не пытается ли одна из сторон предоставить другой «поддельный» сертификат. Подробнее же происходит следующий процесс.
• • •
CA «подписывает» сертификат (будем предполагать, ваш), используя для этого свой (CA) секретный ключ. На первом этапе «SSL-рукопожатия» вы посылаете мне ваш сертификат. Я использую открытый ключ CA, сообщенный мне CA, «подписавшей» ваш сертификат, чтобы проверить, что ваш сертификат был действительно выдан ими и что в него не было внесено изменений с тех тор, как этот сертификат был выдан. Чтобы сделать это, я должен быть способен найти открытый ключ для вашей CA в своем «хранилище ключей».
© InterTrust Co. Тел. 956-7928, 956-7929
124
Secure Sockets Layer в Lotus Domino 4.6.1
Для того, чтобы пользователь и сервер могли взаимно проверить сертификаты друг друга, каждый из них, проверяя сертификат другого, должен найти в своем «хранилище ключей» открытый ключ той CA, которая этот сертификат выпустила, т.е. «подписала». Открытый ключ CA содержится в «хранилище ключей» «не сам по себе», а в составе сертификата, выпущенного этой CA «для своего имени за своей же подписью» - так называемого «самоподписанного» сертификата. Причем просто факта наличия самоподписанного сертификата CA в «хранилище ключей» обычно недостаточно – необходимо, чтобы владелец «хранилища ключей» явным образом «заявил о своем доверии этой CA», т.е. о том, что он уверен, что открытый ключ этой CA именно таков, как указано в самоподписанном сертификате этой CA, находящемся в «хранилище ключей» этого владельца. В зависимости от того, находитесь ли вы в среде Netscape Navigator, MS Internet Explorer или клиента Notes, запущенного на сервере Notes, такое «заявление о доверии CA» выглядит, называется и настраивается немного по разному. В среде клиента Notes, запущенного на сервере Notes, администратор сервера выбирает самоподписанные сертификаты некоторых CA в качестве "доверяемых корней" ("Trusted Roots").
Рис. 10.2 Самоподписанные сертификаты CA, которые администратор сервера Notes выбрал в качестве Trusted Roots Пользователь Netscape Navigator автоматически «доверяет» всем имеющимся в его «хранилище» самоподписанным сертификатам CA, но имеет возможность удалить из «хранилища» самоподписанные сертификаты некоторых CA или добавить в него новые.
Рис. 10.3 Список CA, сертификаты которых «разрешил проверять» пользователь Netscape Navigator (из меню Communicator – Security Info – Certificates\Signers) © InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 125
Пользователь MS Internet Explorer «отмечает галочкой» самоподписанные сертификаты тех CA, «которым он доверяет».
Рис. 10.4 Список CA, сертификаты которых «разрешил проверять» пользователь MS Internet Explorer Но суть «заявления о доверии» везде одна и та же – сторона «разрешает» своему программному обеспечению без всякой проверки извлекать открытый ключ CA из самоподписанного сертификата данной CA в своем «хранилище ключей» и использовать этот открытый ключ при проверке сертификата, выпущенного данной CA для другой стороны.
Рис. 10.5 Так выглядит самоподписанный сертификат VeriSign Class 1 CA в среде Netscape Navigator Заметим, что самоподписанные сертификаты «общеизвестных» CA обычно изготавливаются этими CA заблаговременно, передаются компаниям-разработчикам программного обеспечения, и уже компаниями-разработчиками «включаются» в производимое ими программное обеспечение. Но в то же время клиент обычно имеет возможность обратиться непосредственно на Web-сервер компании, выполняющей роль CA, получить с него самоподписанный сертификат этой CA и «поместить» его в свое «хранилище ключей».
© InterTrust Co. Тел. 956-7928, 956-7929
126
Secure Sockets Layer в Lotus Domino 4.6.1
В качестве «хранилища ключей» обычно выступает KeyRing-файл (Key Ring File). Наиболее подходящие по смыслу в нашем контексте переводы термина «Key Ring» - «кольцо с ключами», «связка ключей», «хранилище ключей». KeyRing-файл представляет собой двоичный файл, дополнительно защищенный паролем. Злоумышленнику недостаточно просто скопировать этот файл – чтобы воспользоваться файлом, необходимо знать его пароль. В «обычном» Notes аналогом KeyRing-файла является ID-файл. KeyRing-файлы используются в Domino в качестве контейнеров для хранения:
• • •
открытых и секретных ключей владельца файла; сертификатов для владельца файла, «подписанных» CA; самоподписанных сертификатов для Trusted Root CA – тех, которые «подписали» сертификаты владельца файла и иных, которым владелец файла «доверяет».
Каждый субъект, поддерживающий SSL, имеет свой KeyRing-файл. Сервер Domino, поддерживающий SSL, имеет KeyRing-файл сервера. Cервер Domino, выполняющий функции внутрикорпоративной CA, имеет два KeyRing-файла: для Certificate Authority и для сервера. Клиент броузера тоже хранит свои ключи и сертификаты в KeyRing-файле, только этот файл «управляется» специфическим для броузера способом.
10.4. Обеспечение поддержки SSL серверами Domino Процесс начинается созданием необходимых KeyRing-файлов: для «внутрикорпоративной» Certificate Authority и для серверов Domino. В качестве сервера Certificate Authority выбирается один из серверов, на котором функционирует задача HTTP. На этом сервере создается база Certificate Authority CERTCA.NSF. Оперируя в этой базе, можно создать KeyRing-файл для «внутрикорпоративной» Certificate Authority. Этот KeyRing-файл (обычно он имеет имя CAKey.kyr) будет помещен в каталог данных сервера, а все «управление» файлом осуществляется из базы CERTCA.NSF. С этого момента становится возможным создать KeyRing-файл для этого сервера. Этот KeyRingфайл (на Рис. 10.6 он имеет имя KeyFile1.kyr) будет помещен в каталог данных сервера, а все «управление» файлом осуществляется из базы Server Certificate Administration - CERTSRV.NSF. KeyRing-файл сервера «напрямую» необходим серверным задачам (например, HTTP) для поддержки SSL. Сервер Certificate Authority
HTTP
Сервер 2
Сервер 3
HTTP
IMAP
CERTCA.NSF
CERTSRV.NSF
CERTSRV.NSF
CERTSRV.NSF
CAKey.kyr
KeyFile1.kyr
KeyFile2.kyr
KeyFile3.kyr
Рис. 10.6 Создание KeyRing-файлов и управление ими
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 127
Все последующие «текущие» работы по поддержке SSL - выпуск сертификатов для клиентов и других серверов, передача самоподписанного сертификата CA всем нуждающимся и т.п. - выполняются в базе CERTCA.NSF администратором «внутрикорпоративной» Certificate Authority по запросам от клиентов или администраторов других серверов. На других серверах домена, где функционирует задача HTTP или другие задачи, допускающие работу с применением SSL (POP3, IMAP, LDAP, NNTP…), создается только база Server Certificate Administration - CERTSRV.NSF. Оперируя в этой базе, можно создать KeyRing-файл для данного сервера. Этот KeyRing-файл (на Рис. 10.6 он имеет имя KeyFileX.kyr) будет помещен в каталог данных сервера и станет «напрямую» использоваться его серверными задачами для поддержки SSL.
10.4.1. База Certificate Authority Выберите сервер для этой роли и создайте на нем базу CERTCA.NSF - Certificate Authority по шаблону CCA461.NTF.
Рис. 10.7 Создание базы Certificate Authority из клиента, запущенного на сервере Notes В списке управления доступом созданной базы «назначьте» себя и тех лиц, которые будут выполнять функции администраторов CA, на роль CAPrivlegedUser. Остается выполнить три действия: создать KeyRing-файл и самоподписанный сертификат для Certificate Authority, «заполнить профиль» и создать KeyRing-файл для сервера Domino. Все прочие операции с данной базой будут носить «текущий» характер.
Создание KeyRing-файла и самоподписанного сертификата для Certificate Authority KeyRing-файл для CA содержит секретный и открытый ключи и самоподписанный сертификат этой CA. Файл необходим, чтобы было возможным «подписывать» сертификаты для ваших серверов Domino и клиентов «от имени» CA. Кроме того, копия самоподписанного сертификата CA помещается в текстовое поле в документе, создаваемом по форме CACert в базе CERTCA.NSF. Этот документ необходим, чтобы удобно экспортировать из него самоподписанный сертификат CA любому желающему «установить» этот сертификат в качестве Trusted Root. Из клиента Notes, запущенного на компьютере сервера, откройте локально базу Certificate Authority и выберите в навигаторе пункт "1. Create Certificate Authority Key Ring & Certificate".
© InterTrust Co. Тел. 956-7928, 956-7929
128
Secure Sockets Layer в Lotus Domino 4.6.1
Рис. 10.8 Навигатор базы Certificate Authority Заполните появившуюся форму.
Рис. 10.9 Форма для создания KeyRing-файла CA В поле Key Ring File Name укажите имя для создаваемого KeyRing-файла. По умолчанию предлагается имя CAKEY.KYR. Если в поле не указан полный путь, файл создается в каталоге данных сервера. Обратите внимание, что в одной базе Certificate Authority может быть создан только один такой файл - при попытке создать в базе второй файл вы получите соответствующее предупреждение (Рис. 10.10). В поле Key Ring Password задайте пароль, необходимый для использования этого файла (не менее 6 символов). Информация, которую вы введете в следующих полях, определяет различаемое (distinguished) имя вашей CA.
•
Common Name – общее (common) имя CA, например, InterTrustCorp.
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 129
• • • • •
Organizational Unit (необязательно) – оргединица, в состав которой входит CA. Organization - название вашей организации, например, InterTrust Co. City or Locality (необязательно) – местоположение CA (например, город). State or Province – штат или провинция (область). Country – двухсимвольный код страны.
Рис. 10.10 В одной базе CERTCA.NSF можно создать только один KeyRing-файл для CA По заполнении полей в форме нажмите кнопку Create Certificate Authority Key Ring, затем кнопку Ok в окне-подтверждении.
Рис. 10.11 Подтверждение о создании KeyRing-файла По завершении операции рекомендуется сделать копию созданного KeyRing-файла CA и сохранить ее в безопасном месте. К оригиналу файла должны иметь доступ (знать пароль файла) только лица, выполняющие функции администраторов CA.
Заполнение профиля Certificate Authority Выбрав в навигаторе пункт "2. Configure Certificate Authority Profile", вы получите форму (Рис. 10.12), в которой необходимо уточнить местоположение KeyRing-файла (чтобы не
© InterTrust Co. Тел. 956-7928, 956-7929
130
Secure Sockets Layer в Lotus Domino 4.6.1
вводить его при каждой операции «текущего» характера) и задать имя хоста, по которому доступен ваш сервер Domino (используется при генерации URL «на документы» в данной базе).
Рис. 10.12 Форма «Профиль CA»
Создание KeyRing-файла для сервера Domino, одновременно выполняющего функцию сервера Certificate Authority Выбрав в навигаторе пункт «3. Create Server Key Ring & Certificate», вы получите следующую форму.
Рис. 10.13 Форма для создания KeyRing-файла сервера в базе CERTCA.NSF
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 131
В поле Key Ring File Name задайте имя создаваемого файла, включая путь. По умолчанию предлагается имя KeyFile.KYR. В поле Key Ring Password укажите пароль, который должен будет использоваться для доступа к этому файлу (не менее 6 символов). В поле CA Certificate Label введите общее (common) имя вашей CA. В поле Common Name следует задать имя хоста, по которому доступен этот сервер Domino. Обратите внимание, что SSL может поддерживаться вашим сервером Domino только при обращении к нему из броузера по заданному в этом поле имени хоста. К серверу, сконфигурированному для поддержки нескольких виртуальных серверов Domino, обращение с использованием SSL возможно только по одному имени хоста. Остальные поля подобны соответствующим полям в рассмотренной ранее форме для создания KeyRing-файла CA. Остается нажать кнопку Create Server Key Ring, ввести в появившемся диалоговом окне пароль для обращения к KeyRing-файлу вашей CA и нажать кнопку Ok в окне-подтверждении о создании KeyRing-файла сервера.
Рис. 10.14 Подтверждение о создании KeyRing-файла сервера Созданный KeyRing-файл содержит все, что необходимо:
• • •
секретный и открытый ключи сервера, сертификат для этого сервера, «подписанный» вашей CA, самоподписанные сертификаты вашей CA и ряда «общеизвестных» CA, уже установленные как Trusted Root.
После этого вам, по-сути дела, остается лишь выполнить действия по завершению настройки SSL на данном сервере Domino (см. 10.4.3). Отметим, что в Domino версии 4.6 при выборе в навигаторе аналогичного «3. Create Server Key Ring & Certificate» пункта выдавалось только описание последовательности действий для создания KeyRing-файла сервера. Выполнять же эти действия приходилось в базе CERTSRV.NSF – Server Certificate Administration.
Смена пароля и анализ содержимого KeyRing-файла Certificate Authority Выбрав в навигаторе базы Certificate Authority пункт View Certificate Authority Key Ring, можно «перечитать» в базу информацию из KeyRing-файла (кнопка Display CA Key Ring), сменить пароль KeyRing-файла (кнопка Change CA Key Ring Password), и просмотреть имеющийся в нем самоподписанный сертификат «как документ» (в категории CA Certificate).
Доступ к базе Certificate Authority через броузер При обращении к базе Certificate Authority через броузер клиенты и администраторы серверов Notes могут выполнить следующие операции:
• •
Request Server Certificate - создание запроса на получение подписанного сертификата для сервера, Pick Up Server Certificate - вставка подписанного сертификата в KeyRing-файл сервера, © InterTrust Co. Тел. 956-7928, 956-7929
132
• • • •
Secure Sockets Layer в Lotus Domino 4.6.1
Accept This Authority In Your Server/Browser - вставка самоподписанного сертификата CA в KeyRing-файл сервера или в броузер клиента в качестве Trusted Root, Request Client Certificate - создание запроса на получение подписанного сертификата для броузера, Pick Up Client Certificate - вставка подписанного «клиентского» сертификата в броузер, Register Browser Certificate In Address Book - регистрация сертификата броузера в адресной книге сервера.
Рис. 10.15 База Certificate Authority в окне броузера
10.4.2. База Server Certificate Administration Прежде всего убедитесь в наличии на сервере базы CERTSRV.NSF – Server Certificate Administration. Эта база автоматически создается при установке сервера Domino: в версии 4.6 по шаблону CERTSRV.NTF, а в версии 4.6.1 - по шаблону CSRV461.NTF. Однако ваш сервер «мог претерперь» целую серию обновлений версий… Так что, если база CERTSRV.NSF по каким-то причинам отсутствует, просто создайте новую шаблону CSRV461.NTF.
Рис. 10.16 Создание базы Server Certificate Admin из клиента, запущенного на сервере Notes © InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 133
Далее возможны два случая.
•
•
Если KeyRing-файл для вашего сервера уже подготовлен, по-видимому, база будет использоваться вами только для анализа содержимого KeyRing-файла сервера, управления «доверием» самоподписанным сертификатам и смены пароля KeyRing-файла. Рассмотрите ниже только эти возможности базы и переходите к 10.4.3. Маловероятно, что в этом случае вам понадобится «весь функционал» базы CERTSRV.NSF. Если же KeyRing-файл для вашего сервера отсутствует, вам придется познать все возможности базы CERTSRV.NSF. Предстоит выполнить довольно утомительную цепочку действий по созданию KeyRing-файл для сервера: создать KeyRing-файл с «неподписанным» сертификатом, создать запрос на получение подписанного сертификата от CA, установить самоподписанный сертификат CA в качестве Trusted Root, дождаться, пока администратор CA создаст «подписанный» сертификат для вашего сервера, и, наконец, поместить этот сертификат KeyRing-файл вашего сервера. Без всего этого действительно никак не обойтись по крайней мере в двух случаях: если ваш сервер Domino версии 4.6, но не 4.6.1, или если сервер должен получить сертификат от «не Domino» Certificate Authority.
Смена паролей, анализ содержимого KeyRing-файлов и управление «доверием» самоподписанным сертификатам из базы Server Certificate Administration Выбрав в навигаторе базы Server Certificate Administration пункт View & Edit Key Rings, можно:
• • •
Выбрать KeyRing-файл для смены пароля или изучения его содержимого (кнопка Select Key Ring to Display). Изменить пароль для доступа к выбранному KeyRing-файлу (кнопка Change Key Ring Password). Изучить содержимое выбранного KeyRing-файла: • Документы в категории Site Categories соответствуют имеющиеся в KeyRing-файле сертификатам. • Документы в категории Certificate Authorites соответствуют имеющимся в KeyRingфайле «самоподписанным» сертификатам. Если такой сертификат установлен как Trusted Root, открыв соответствующий ему документ, вы обнаружите в документе кнопку Do Not Trust This Certificate, нажатием которой можно «лишить сертификат доверия». Напротив, если сертификат не установлен как Trusted Root, открыв соответствующий ему документ, вы обнаружите в последнем кнопку Trust This Certificate, нажатием которой можно «вернуть доверие сертификату».
Шаг 1. Создание KeyRing-файла сервера с «неподписанным» сертификатом Для создания KeyRing-файла сервера в навигаторе базы Server Certificate Administration выберите пункт «1. Create KeyRing» (Рис. 10.17). Заполните появившуюся форму (Рис. 10.18). В поле Key Ring File Name задайте имя создаваемого файла, включая путь. По умолчанию предлагается имя KeyFile.KYR. В поле Key Ring Password укажите пароль, который должен будет использоваться для доступа к этому файлу (не менее 6 символов). В поле Common Name следует задать имя хоста, по которому доступен этот сервер Domino. Обратите внимание, что SSL может поддерживаться вашим сервером Domino только при обращении к нему из броузера по заданному в этом поле имени хоста. К серверу, сконфигурированному для поддержки нескольких виртуальных серверов Domino, обращение с использованием SSL возможно только по одному имени хоста. Остальные поля подобны соответствующим полям в рассмотренной ранее форме для создания KeyRing-файла CA.
© InterTrust Co. Тел. 956-7928, 956-7929
134
Secure Sockets Layer в Lotus Domino 4.6.1
Рис. 10.17 Навигатор базы Server Certificate Administration
Рис. 10.18 Форма для создания KeyRing-файла сервера После нажатия кнопки Create Key Ring появится диалоговое окно, подтверждающее создание файла и поясняющее следующий шаг – создание запроса на получение сертификата от CA.
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 135
Рис. 10.19 Подтверждение о создании KeyRing-файла сервера Созданный KeyRing-файл содержит секретный и открытый ключи сервера, «неподписанный» сертификат для этого сервера и достаточно большое количество самоподписанных сертификатов «общеизвестных» CA, уже установленных как Trusted Root. Поскольку сертификат сервера еще «не подписан», он пока и не может быть никем «проверен». Поэтому все последующие шаги направлены на получение «подписи под этим сертификатом от имени» какой-либо CA. «Подписать» сертификат сервера может как «общеизвестная» CA (однако обычно это влечет денежные расходы), так и ваша «внутрикорпоративная» CA.
Шаг 2. Запрос на получение подписанного сертификата от CA Из навигатора в базе Server Certificate Administration выберите пункт «2. Create Certificate Request». В появившейся форме введите имя и пароль для KeyRing-файла сервера, а так же способ передачи запроса на сертификат: либо «вставкой» через буфер обмена в форму в базе или на Web-сервере Certificate Authority, либо «отправкой по почте».
Рис. 10.20 Форма для создания запроса на получение сертификата с передачей через буфер обмена в форму в базе Certificate Authority © InterTrust Co. Тел. 956-7928, 956-7929
136
Secure Sockets Layer в Lotus Domino 4.6.1
Если была выбрана передача через буфер обмена, после нажатия кнопки Create Certificate Request появится диалоговое окно, в котором необходимо «выделить» запрос на сертификат и скопировать его в буфер обмена.
Рис. 10.21 Запрос на сертификат в формате PKCS копируется в буфер обмена Обратите внимание, что запрос на сертификат создается в стандартном формате PKCS (Public Key Cryptography Standards), который распознается как Domino, так и большинством других известных CA. Способ создания запроса «вставкой в поле формы на Web-сервере CA» тоже довольно распространен. Затем нужно открыть базу Certificate Authority на сервере CA (из клиента Notes или через броузер) и, выбрав в ее «главном» навигаторе Submit Server Certificate Request (из клиента Notes) или Request Server Certificate (через броузер), создать в ней документ-запрос (Рис. 10.22 Рис. 10.23).
Рис. 10.22 «Голова» формы запроса на сертификат в базе Certificate Authority © InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 137
Рис. 10.23 «Хвост» формы запроса на сертификат в базе Certificate Authority В создаваемом документе в поле Certificate необходимо вставить из буфера обмена запрос на сертификат в формате PKCS, а так же заполнить остальные поля информацией об авторе запроса. После нажатия кнопки вы получите диалоговое окно - подтверждение о создании запроса.
Рис. 10.24 Подтверждение о создании запроса на сертификат в базе Certificate Authority При передаче запроса на сертификат «по почте» в форме базы базе Server Certificate Administration «появятся» дополнительные поля, в которых потребуется ввести адрес CA, куда отправляется запрос (обычно, адрес администратора этой CA), а так же свой адрес для получения «ответа» и информацию о себе.
Рис. 10.25 Фрагмент формы для создания запроса на получение сертификата с передачей по почте администратору CA © InterTrust Co. Тел. 956-7928, 956-7929
138
Secure Sockets Layer в Lotus Domino 4.6.1
После нажатия кнопки Create Certificate Request появится окно-подтверждение, а в указанный в поле CA’s E-Mail Address адрес будет отправлено письмо с запросом на сертификат в формате PKCS.
Рис. 10.26 Подтверждение об отправке почтой запроса на сертификат Администратор CA получит письмо с запросом (Рис. 10.27) на сертификат, и ему придется создать по полученному письму в базе Certificate Authority такой же документ, который бы вы создали сами при передаче запроса в базу Certificate Authority «методом вставки в поле формы через буфер обмена».
Рис. 10.27 Письмо с запросом на сертификат
Шаг 3. Установка самоподписанного сертификата CA в качестве Trusted Root Просмотрите список Trusted Root в KeyRing-файле сервера (Рис. 10.2). Если необходимая CA в нем отсутствует, обратитесь на Web-сервер этой CA и получите с него самоподписанный
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 139
сертификат этой CA. В большинстве случаев его можно получить в виде файла или скопировать в буфер обмена. Затем в навигаторе базы Server Certificate Administration выберите пункт «3. Install Trusted Root Certificate into Key Ring». Введите в появившейся форме (Рис. 10.28) имя вашего KeyRingфайла и пароль для доступа к нему. Поле Certificate Label не должно оставаться пустым – в него «для идентификации сертификата» в KeyRing-файле нужно поместить общее (common) имя CA. Если самоподписанный сертификат уже скопирован в ваш буфер обмена, выберите Clipboard в поле Certificate Source и вставьте сертификат в следующее поле. Если же сертификат получен в виде файла, выберите File в поле Certificate Source и укажите в поле File Name имя этого файла.
Рис. 10.28 Форма для установки самоподписанного сертификата CA как Trusted Root Нажмите кнопку Merge Trusted Root Certificate into Key Ring и затем дважды Ok.
Рис. 10.29 Информация о самоподписанном сертификате CA, устанавливаемом в качестве Trusted Root © InterTrust Co. Тел. 956-7928, 956-7929
140
Secure Sockets Layer в Lotus Domino 4.6.1
Рис. 10.30 Подтверждение об установке сертификата в качестве Trusted Root
Шаг 4. Администратор CA создает «подписанный» сертификат Следующий шаг выполняется администратором CA по получении запроса на сертификат в стандартном формате PKCS. Если это «внутрикорпоративная» CA в базе Certificate Authority на сервере Domino, то, как будут выглядеть действия администратора CA, описывается ниже. Если же это CA «иной природы», сохранится только семантика выполняемых действий, внешний же вид, скорее всего, будет совершенно другим. Запрос «обнаруживается» администратором CA в виде базы Certificate Authority, открываемом из навигатора выбором в левой части «Server Certificate Requests». При этом кнопками на полосе вида можно просмотреть запросы, ожидающие выпуска сертификата (Certificate Requests\Waiting for Approval), запросы, на которые уже был выпущен сертификат (Certificate Requests\Approved for Pickup), и запросы, в выпуске сертификатов на которые было отказано (Certificate Requests\Denied). Запрос, ожидающий выпуска сертификата, «как документ» выглядит примерно следующим образом.
Рис. 10.31 Администратор CA «подписывает» сертификат © InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 141
Если администратор CA согласен с запросом, то после ввода пароля для KeyRing-файла CA и нажатия кнопки Approve необходимый сертификат будет выпущен. Если была выбрана опция Send a notification email to the requestor, то лицо, запросившее сертификат, получит уведомление почтой. Обратите внимание, что в этом письме-уведомлении содержится «ссылка», указывающая на документ в базе Certificate Authority, из которого нужно «извлечь уже подписанный» сертификат и «поместить» его в KeyRing-файл сервера.
Рис. 10.32 Лицо, запросившее сертификат, получает уведомление о его выпуске
Шаг 5. «Помещение» подписанного сертификата в KeyRing-файл сервера После того, как администратор CA выпустил («подписал») сертификат для вашего сервера, остается поместить этот сертификат в KeyRing-файл сервера. Документ, содержащий сертификат, можно найти в базе Certificate Authority либо из броузера обращением по ссылке из письма, либо выбором из броузера в «главном» навигаторе базы Certificate Authority пункта Pick Up Certificate с последующим вводом идентификатора (Pickup ID) необходимого сертификата. Из этого документа администратор сервера должен получить «подписанный» сертификат либо копированием в буфер обмена, либо как присоединенный файл.
Рис. 10.33 Форма для «помещения» подписанного сертификата в KeyRing-файл сервера © InterTrust Co. Тел. 956-7928, 956-7929
142
Secure Sockets Layer в Lotus Domino 4.6.1
Затем в базе Server Certificate Administration необходимо выбрать в навигаторе пункт «4. Install Certificate into Key Ring». В появившейся форме (Рис. 10.33) следует указать местоположение и пароль вашего KeyRing-файла, а в поле Certificate Source - способ передачи «подписанного» сертификата:
• •
Clipboard – вставка сертификата из буфера обмена в следующее поле, File – ввод имени файла с сертификатом в поле File Name. Остается нажать кнопку Merge Certificate into Key Ring и затем дважды Ok.
Рис. 10.34 Информация о подписанном сертификате, помещаемом в KeyRing-файл сервера
Рис. 10.35 Подтверждение о добавлении сертификата в KeyRing-файл сервера
10.4.3. Настройка SSL на сервере Domino Нам остается «разрешить поддержку» SSL сервером Notes в его документе Server, обеспечить клиентам необходимый доступ к базам, находящимся на сервере, и «вынудить» клиентов пользоваться SSL. Cервер Domino может поддерживать SSL в двух вариантах.
•
Без аутентификации клиента по сертификату X.509. Обеспечивается шифрование и проверка передаваемой между клиентом и сервером информации, выполняется аутентификация сервера клиентом по сертификату сервера, но не выполняется аутентификация клиента сервером по сертификату клиента. При выборе этого варианта: • сервер должен иметь сертификат от «внутрикорпоративной» или внешней CA; • клиент должен иметь сертификат от «внутрикорпоративной» или внешней CA и установить самоподписанный сертификат CA сервера как свой Trusted Root;
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 143
• •
если для клиента создан документ Person с именем и Internet-паролем, сервер может выполнять аутентификацию клиента, но не по его сертификату X.509, а по вводимым клиентом имени и паролю (Name & Password).
С аутентификацией клиента и сервера по сертификатам X.509. В дополнение к предыдущему варианту выполняется и аутентификация клиента сервером по сертификату X.509 клиента. При выборе этого варианта: • сервер должен иметь сертификат от «внутрикорпоративной» или внешней CA; • клиент должен иметь сертификат от «внутрикорпоративной» или внешней CA и установить самоподписанный сертификат CA сервера как свой Trusted Root; • на сервере самоподписанный сертификат CA клиента должен быть установлен как Trusted Root; • для клиента должен иметься документ Person, содержащий его сертификат X.509.
Если вы выбрали вариант «без аутентификации клиента по сертификату X.509», обеспечьте правильную информацию в следующих полях из секции Internet Port and Security Configuration документа Server.
• •
SSL key file – KeyRing-файл сервера. SSL protocol version (только для задач NNTP, IMAP, POP3, LDAP) – версия SSL. • V2.0 only – разрешены только соединения с использованием SSL 2.0. • V3.0 handshake – предпринимается попытка установить соединение с использованием SSL 3.0. Если SSL 3.0 handshake заканчивается неудачей, но клиент поддерживает SSL 2.0, предпринимается попытка установить соединение с использованием SSL 2.0. • V3.0 only – разрешены только соединения с использованием SSL 3.0. • V3.0 and V2.0 handshake - предпринимается попытка установить соединение с использованием SSL 3.0, но вначале выполняется SSL 2.0 handshake.
•
•
Negotiated (по умолчанию) - предпринимается попытка установить соединение с использованием SSL 3.0. При неуспехе предпринимается попытка установить соединение с использованием SSL 2.0. Пока не возникают проблемы установления соединения между клиентом и сервером из-за несовместимых версий SSL, рекомендуется выбирать эту установку. Accept expires SSL certificates – должна (Yes) или не должна (No) игнорироваться дата истечения срока действия сертификата.
Далее в секции Internet Port and Security Configuration располагается таблица, состоящая из двух подтаблиц. «Верхняя» подтаблица содержит настройки для обычных (без применения SSL) портов TCP/IP разных задач, а «нижняя» – для портов TCP/IP с применением SSL. Естественно, что настройки в обоих подтаблицах должны быть согласованы – ситуацию на Рис. 10.36, когда к серверу Domino возможен доступ как по протоколу HTTP (без применения SSL), так и по протоколу HTTPS (с применением SSL), скорее всего следует считать «проколом в защите». Перейдем к заполнению «нижней» подтаблицы.
• • • •
В полях строки SSL port number при необходимости можно изменить используемые по умолчанию номера портов для необходимых вам задач. В полях строки SSL port status выберите Enabled для необходимых вам задач. В полях строки Client certificate выберите No для необходимых вам задач. Этим вы запрещаете аутентификацию сервером клиентов по их сертификатам X.509. Если нужно, чтобы клиент аутентифицировался сервером по введенным клиентом имени и паролю, выберите Yes в полях из строки Name & Password для необходимых вам задач и обеспечьте необходимые документы Person с именами и паролями. Обратите внимание, что клиент при такой «аутентификации» может вводить любое из своих имен – элементов
© InterTrust Co. Тел. 956-7928, 956-7929
144
•
Secure Sockets Layer в Lotus Domino 4.6.1
списка в поле User Name или Short Name, но в списках управления доступом баз необходимо использовать только первый элемент из списка в поле User Name. Если нужно, чтобы клиент мог получать и анонимный доступ к серверным задачам HTTP, LDAP и NNTP, выберите Yes в соответствующем поле в строке Anonymous.
Рис. 10.36 Секция Internet Port and Security Configuration в документе Server Если вы выбрали вариант «Аутентификация клиента и сервера по сертификатам X.509», то в дополнение к предыдущему варианту проделайте следующее.
• • •
•
•
Убедитесь, что клиент имеет сертификат от внешней CA, и эта CA установлена для вашего сервера как Trusted Root. В полях в строке Client certificate выберите Yes для необходимых вам задач. Этим вы разрешаете аутентификацию сервером клиентов по их сертификатам X.509. Для клиента обязательно должен иметься документ Person, причем в поле User Name одним из элементов списка обязательно должно присутствовать общее (Common) имя клиента, в точности так, как оно указано в его сертификате X.509. В то же время в списках управления доступом баз для этого клиента необходимо использовать только первый элемент из списка в поле User Name. Клиент должен «представить свой сертификат» администратору «внутрикорпоративной» CA. Для этого клиент из своего броузера должен открыть базу Certificate Authority (по URL наподобие http://main.inttrust.ru/certca.nsf), выбрать «во фрейме слева» Register Browser Certificate in Address Book, ввести «во фрейме справа» свое имя, адрес электронной почты, телефон и комментарии, и нажать кнопку Submit Certificate. При этом в базе Certificate Authority будет создан документ-запрос. Администратор CA должен «поместить сертификат пользователя в документ Person этого пользователя». Для этого он открывает базу Certificate Authority «локально», выбирает в навигаторе «слева» Client Registration Requests, открывает соответствующий документзапрос и «соглашается» (кнопки Accept и OK) или «отказывается» (кнопка Reject) от помещения сертификата пользователя в его документ Person. Если выбрана опция Send a notification email to the requestor, клиент получит уведомление почтой. Обратите внимание, что изменение в документе Person выполняется «не непосредственно», а с использованием задачи Administration Process. В результате в документе Person пользователя будет создано
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 145
поле UserCertificate, содержащее сертификат X.509 пользователя. Признак наличия этого поля – появление «Present» в поле с меткой X.509 certificate в секции Public Keys.
Рис. 10.37 Сертификат X.509 пользователя помещен в документ Person Когда пользователь устанавливает соединение с сервером, Domino ищет общее (common) имя пользователя, полученное в сертификате X.509, «по полям» User Name документов Person в общей адресной книге. Если соответствие найдено, первый элемент из списка User Name используется при проверке в списках управления доступом баз. Если имя из сертификата X.509 не позволяет однозначно определить документ Person, «уточнение» выполняется по совпадению открытых ключей из сертификата X.509 пользователя и сертификатов X.509 в документах Person. Если в таблице выбраны одновременно только Client certificate и Name & Password, Domino сначала пытается определить документ Person по информации из сертификата X.509. Если сертификат отсутствует в адресной книге, клиент получает запрос на ввод имени и пароля, и затем соответствующий документ Person определяется по имени и паролю. Аналогично, если в таблице выбраны одновременно только Client certificate и Anonymous, Domino сначала пытается определить документ Person по информации из сертификата X.509. Если это не удается, клиент получает «анонимный доступ». Если в таблице выбраны одновременно Client certificate, Name & Password и Anonymous, Domino сначала пытается определить документ Person по информации из сертификата X.509. Если сертификат отсутствует в адресной книге, дальнейшее зависит от того, к какой базе данных обращается клиент. Если список управления доступом базы допускает анонимный доступ, клиент получает «анонимный доступ». Если не допускает, клиент получает запрос на ввод имени и пароля.
Обеспечение SSL-клиентам необходимого уровня доступа к базам на сервере К базам, в окне свойств которых на закладке Basics выбрана опция Force SSL Connection on the Web, доступ через броузер возможен только с использованием SSL. Если сервер поддерживает аутентификацию клиентов с использованием сертификатов X.509, он сразу же предпринимает попытку аутентифицировать обратившегося к нему клиента. Если аутентификация успешна, клиент «получает имя» - первый элемент из списка в поле User Name своего документа Person. Далее такой клиент получает доступ к базе данных подобно обычному пользователю Notes - в соответствии с тем, какой доступ имеет имя клиента в списке управления доступом базы. Поле Maximum Internet name & password access на закладке Advanced в списке управления доступом базы не играет при аутентификации с использованием сертификатов X.509 никакой роли.
© InterTrust Co. Тел. 956-7928, 956-7929
146
Secure Sockets Layer в Lotus Domino 4.6.1
Если сервер поддерживает аутентификацию клиентов «по вводу имени и пароля», но «анонимный доступ» к нему запрещен, сервер сразу же предпринимает попытку аутентифицировать обратившегося к нему клиента, «выдавая ему» окно для ввода имени и пароля. Если аутентификация успешна, клиент «получает имя» - первый элемент из списка в поле User Name. Далее такой клиент получает доступ к базе данных в соответствии с тем, какой доступ имеет имя клиента в списке управления доступом базы, но не выше указанного в поле Maximum Internet name & password access из списка управления доступом базы. Если сервер поддерживает аутентификацию клиентов «по вводу имени и пароля», однако к нему разрешен и «анонимный доступ», сервер по возможности не предпринимает попытки аутентифицировать обратившегося к нему клиента, а «присваивает» ему имя Anonymous. Далее все зависит состояния списка управления доступом той базы данных, к которой обращается клиент. Если имя Anonymous имеет доступ к базе данных (явно как Anonymous, как член группы или -Default-), клиент получает соответствующий доступ к базе данных, но не выше указанного в поле Maximum Internet name & password access. Только когда клиент обращается к базе данных, к которой нет доступа для Anonymous или -Default-, сервер предпринимает попытку аутентифицировать клиента, «выдавая» ему окно для ввода имени и пароля. Если аутентификация успешна, клиент «получает имя» - первый элемент из списка в поле User Name. Далее клиент получает доступ к базе данных в соответствии с тем, какой доступ имеет его имя в списке управления доступом базы, но не выше указанного в поле Maximum Internet name & password access из списка управления доступом базы. Однако при необходимости клиент может «заставить» сервер осуществить его аутентификацию, даже если к базе возможен и анонимный доступ. Для этого в передаваемый серверу URL «после команды» следует добавить аргумент &Login (например, http://main-int.inttrust.ru/mab45.nsf?OpenDatabase&Login).
Как «вынудить» клиентов использовать SSL Чтобы клиенты использовали SSL для доступа из броузеров ко всем базам на сервере Domino, нужно в документе Server в секции Internet Port and Security Configuration выбрать Redirect to SSL в полях из строки TCP/IP port status. Такая возможность не поддерживается только для задач NNTP и POP3. Для того, чтобы «вынудить» клиентов использовать SSL для доступа из броузеров только к некоторым базам на сервере, нужно в окне свойств этих баз на закладке Basics выбрать опцию Force SSL Connection on the Web.
Рис. 10.38 К этой базе доступ через броузер возможен только с использованием SSL и только в случае аутентификации клиента по его сертификату X.509
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 147
10.5. Настройка клиентского броузера Клиент может получить сертификат X.509 для своего броузера как от любой «общеизвестной» Certificate Authority (например, VeriSign, Inc.), так и от Domino Certificate Authority (только для Domino версии не ниже 4.6.1).
Действия при получении сертификата X.509 от «общеизвестной» CA В этом случае клиенту необходимо проделать следующее.
•
• •
Получить сертификат от «общеизвестной» CA. Для этого клиенту обычно придется «посетить» Web-сервер выбранной CA (например, http://www.verisign.com/ для VeriSign, Inc.) и выполнить специфическую для этой CA процедуру. Выпущенный в результате этого «клиентский» сертификат будет помещен в KeyRing-файл броузера. Убедиться, что в броузере имеется самоподписанный сертификат для CA, выпустившей «клиентский» сертификат. При отсутствии получить самоподписанный сертификат этой CA. Установить самоподписанный сертификат CA в качестве Trusted Root. Если сервер Domino тоже сертифицирован «общеизвестной» CA, установить самоподписанный сертификат этой CA в качестве Trusted Root броузера. Если сервер Domino сертифицирован Domino Certificate Authority, получить ее самоподписанный сертификат и установить в качестве Trusted Root. Рис. 10.39 - Рис. 10.43 демонстрируют процесс получения и установки самоподписанного сертификата Domino Certificate Authority в качестве Trusted Root для MS Internet Explorer 4.0. При использовании Netscape Communicator 4.0 этот процесс начинается аналогично, но завершается «проще» - за меньшее количество шагов.
Рис. 10.39 На странице базы Certificate Authority «выбрано» Accept This Authority In Your Browser
© InterTrust Co. Тел. 956-7928, 956-7929
148
Secure Sockets Layer в Lotus Domino 4.6.1
Рис. 10.40 Появляется окно для получения файла с самоподписанным сертификатом, в нем необходимо выбрать Open this file from its current location
Рис. 10.41 Уточнение, в каких случаях должен использоваться этот сертификат
Рис. 10.42 Информация о сертификате
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 149
Рис. 10.43 Проверка – сертификат Domino Certificate Authority «добавлен» в броузер
•
• •
Если требуется аутентификация клиента по его сертификату X.509, зарегистрировать свой сертификат в адресной книге сервера Domino. Для этого необходимо обратиться из броузера к базе Certificate Authority, выбрать Register Browser Certificate in Address Book, заполнить появившуюся форму и нажать в ней кнопку Submit Certificate. Дождаться, пока администратор CA подтвердит регистрацию и сертификат X.509 будет добавлен в документ Person этого пользователя. Проверить работоспособность SSL, обратившись из броузера к какой-либо базе на сервере, доступ к которой возможен только с применением SSL (см. Рис. 10.38), указав URL наподобие https:///.nsf/.
Получение клиентом сертификата X.509 от Domino Certificate Authority В Domino версии не ниже 4.6.1 имеется возможность выпускать сертификаты X.509 для клиентов от имени "самой" Domino CA, причем с одновременной регистрацией их в общей адресной книге. Во-первых, при этом в принципе отпадает необходимость в услугах «общеизвестных» CA все эти услуги предоставляет ваша «внутрикорпоративная» Domino CA. Во-вторых, снимается пусть небольшая, но все-таки забота слежения за тем, чтобы сервер «доверял» самоподписанному сертификату CA, сертифицировавшей клиента, а клиент «доверял» самоподписанному сертификату CA, сертифицировавшей сервер. В-третьих, при этом для обеспечения аутентификации по сертификату клиента последнему нет необходимости предварительно регистрировать свой сертификат в адресной книге сервера - это может происходить автоматически. Рассмотрим последовательность администратором CA.
•
действий,
выполняемых
для
этого
клиентом
и
Клиент из в броузера открывает базу CERTCA.NSF, выбирает левом фрейме Request Client Certificate, заполняет форму в правом фрейме и нажимает кнопку Submit Certificate Request.
© InterTrust Co. Тел. 956-7928, 956-7929
150
Secure Sockets Layer в Lotus Domino 4.6.1
Рис. 10.44 Заполнение формы-запроса на получение сертификата
•
«В ответ» клиент получает подтверждение о приеме запроса на сертификат.
Рис. 10.45 Подтверждение о принятии запроса
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 151
•
Администратор CA обнаруживает запрос клиента «как документ» в виде Client Certificate Requests\Waiting for Approval базы CERTCA.NSF.
Рис. 10.46 Администратор CA «обнаружил» запрос на сертификат
•
Администратор CA открывает этот документ, выбирает в его полях регистрацию сертификата X.509 в адресной книге, уведомление клиента по почте, срок действия сертификата (например, 2 года) и «выпускает» сертификат, нажав кнопку Approve.
Рис. 10.47 «Заголовок» клиентского запроса на регистрацию сертификата X.509
© InterTrust Co. Тел. 956-7928, 956-7929
152
Secure Sockets Layer в Lotus Domino 4.6.1
Рис. 10.48 Администратор CA «подтверждает» выпуск сертификата для клиента
•
Чтобы «подписать» сертификат, необходим секретный ключ CA. Он находится в KeyRingфайле CA на этом сервере. Поэтому администратору CA «для обращения» к KeyRing-файлу приходится ввести соответствующий пароль.
Рис. 10.49 Ввод пароля KeyRing-файла CA
• •
Клиенту автоматически отправляется письмо с уведомлением о выпуске сертификата. Серверная задача Administration Process (ADMINP) автоматически получает «соответствующее задание» и через некоторое время создает для клиента документ Person (если его не существовало ранее) и добавляет в этот документ Person сертификат X.509.
Рис. 10.50 «Следы» работы задачи ADMINP в базе ADMIN4.NSF © InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 153
•
Клиент получает письмо-уведомление о выпуске сертификата. В письме имеется ссылка, по которой этот сертификат можно получить (URL). Клиент "переходит по ссылке"...
Рис. 10.51 Письмо-уведомление о выпуске сертификата
•
Открывается соответствующая страница из базы CERTCA.NSF. Клиент нажимает на этой странице кнопку Accept Certificate, инициирующую процесс передачи сертификата в его броузер.
Рис. 10.52 Кнопка Accept Certificate инициирует процесс передачи сертификата в броузер © InterTrust Co. Тел. 956-7928, 956-7929
154
•
Secure Sockets Layer в Lotus Domino 4.6.1
Клиент получает подтверждение о помещении сертификата KeyRing-файл его броузера.
Рис. 10.53 Броузер принял сертификат
•
Клиент исследует свойства этого сертификата и убеждается, что сертификат действительно выпущен Domino СА.
Рис. 10.54 Свойства сертификата
•
Клиент предпринимает попытку открыть на сервере Domino базу, доступ к которой возможен только с использованием SSL и только при аутентификации клиента по его сертификату X.509 (Рис. 10.38). Попытка завершается успехом.
Рис. 10.55 База, доступ к которой возможен только с использованием SSL и только при аутентификации клиента по его сертификату, открылась
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 155
10.6. SSL, Domino и Notes SSL поддерживается как сервером Domino, так и броузером, входящим в состав клиента Notes (Personal Web Navigator). Реализация SSL в Notes полностью соответствует стандарту SSL 3.0, поддерживаются промышленные стандарты шифрования RSA и CA (Certificate Authorities). За все приходится платить. Если вы применяете SSL, производительность сети несколько снижается (примерно 10-20%). Но снижение производительности сети относительно невелико, а выгоды от использования «защищенного соединения» вполне реальны. Поэтому имеет смысл широко применять SSL для контактов между «не Notes»-клиентом и Domino-сервером. Тем более, что при работе через Internet какой-либо иной способ создания и поддержки соединения, обеспечивающего аутентификацию сторон, шифрование передаваемых данных и контроль того, что передача происходит без искажений, между «не Notes»-клиентом и Domino-сервером в настоящее время попросту отсутствует. Ответы на неизбежные российские вопросы «Законно ли применение SSL?» и «Какова криптоустойчивость алгоритмов шифрования с ключами длиной 40 бит (в связи с экспортными ограничениями правительства США)?» вы сами cможете найти соответственно в Указе Президента Российской Федерации от 3 апреля 1995 года N 334 (например, http://win.www.osp.ru/law/law0013.html) и в статье Павла Семьянова «Почему криптосистемы не надежны?» (http://www.hackzone.ru/articles/ieindex.html). Поддержка SSL сервером Domino ни каким образом не заменяет собственной системы защиты Notes – это лишь предназначенное для специфических нужд (контакт из «не Notes»клиента с сервером Domino и контакт из броузера Notes с «не Domino»-сервером) подмножество из всего множества имеющихся в Notes средств защиты.
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 157
11. Применение eSuite DevPack 1.0 eSuite DevPack - это набор апплетов для размещения в HTML-документах и набор классов, созданных в соответствии со спецификацией JavaBeans, для построения собственных апплетов и приложений. Апплеты eSuite DevPack можно условно разделить на две группы: апплеты доступа к данным и апплеты презентации данных.
Апплеты доступа к данным Апплеты доступа к данным отличаются тем, что обычно не имеют пользовательского интерфейса и применяются разработчиками для получения данных с Web-серверов или JDBCисточников и помещения их в InfoBus, откуда эти данные становятся доступны апплетам презентации данных, или наоборот, для получения данных из InfoBus и помещения их на Webсерверы или в JDBC-источники. В eSuite DevPack 1.0 включены следующие апплеты доступа к данным:
• • • • • •
SQL/JDBC - обмен данными с JDBC-источниками CGI Gateway - обмен данными с CGI-программами TableReader - выборка данных из таблиц в HTML-документе FormReader - выборка данных из форм в HTML-документе FileReader - выборка данных из HTML-документов ScriptHelper - расширяет возможности языков скриптов (JavaScript).
Апплеты презентации данных Апплеты презентации данных предназначены для отображения полученных из InfoBus данных в броузере, а так же для работы с этими данными. В eSuite DevPack 1.0 включены следующие апплеты презентации данных:
• • • • • •
Sheet - электронная таблица Chart - построитель графиков и диаграмм WordProcessor - текстовый редактор Presentation - редактор презентационной графики Scheduler - планировщик проектов AppletContainer - контейнер апплетов.
Приложения eSuite На базе апплетов eSuite DevPack разработчики могут создавать мощные интерактивные кроссплатформные приложения. Основные подходы к их созданию:
• •
включение необходимых апплетов eSuite DevPack в документ HTML (используется HTML и JavaScript); «сборка» собственных апплетов из Bean-компонентов, каковыми являются классы eSuite DevPack (обычно используются визуальные среды разработки Java-приложений).
InfoBus InfoBus - технология обмена данными между апплетами, одновременно выполняемыми одной виртуальной машиной Java. Эта технология была разработана Lotus Development Corporation и в настоящее время включена Sun Microsystems в JDK как стандартное расширение.
© InterTrust Co. Тел. 956-7928, 956-7929
158
Применение eSuite DevPack 1.0
InfoBus c точки зрения разработчика HTML-страниц Необходимые апплеты eSuite DevPack (т.е. соответствующие теги <APPLET>) помещаются в один HTML-документ. Настройка апплетов осуществляется заданием их параметров (теги в тегах <APPLET>) или вызовом методов и свойств апплетов из JavaScript. Поскольку апплеты, содержащиеся в одном HTML-документе, одновременно выполняются в одной виртуальной машиной Java, они имеют возможность обмениваться информацией друг с другом по технологии InfoBus. При этом сам объект InfoBus воспринимается разработчиком как «шина данных», объединяющая данные всех апплетов HTML-документа и позволяющая управлять потоками данных между этими апплетами. Поясним это на «абстрактном» примере Рис. 11.1.
Рис. 11.1 Апплеты eSuite DevPack, «соединенные InfoBus», в одном документе HTML Апплет SQL/JDBC получает данные из JDBC-источника и «публикует» их в InfoBus. Опубликованный в InfoBus элемент данных имеет имя и характеризуется интерфейсом, применяемым для доступа к содержащимся в нем данным. Пусть это будет элемент данных с именем TableData c интерфейсом ArrayAccess. Апплет Sheet «настроен» так, что ожидает появления в InfoBus элемента данных с именем TableData, и, как только он появляется, извлекает содержащиеся в нем данные и отображает их в своем окне «как электронную таблицу». Далее «за дело принимается» пользователь броузера. Предположим, он изменяет данные в электронной таблице. Когда изменения выполнены, данные необходимо отобразить в виде диаграммы в апплете Chart. Чтобы сообщить апплету Chart о факте готовности данных для отображения, пользователь нажимает кнопку в форме. Эта кнопка, «написанная на JavaScript», инициирует публикацию апплетом Sheet элемента данных с именем SheetData и интерфейсом ArrayAccess. Апплет Chart «ожидает» этого события. Как только элемент данных с именем SheetData появляется в InfoBus, апплет Chart извлекает и отображает в виде диаграммы содержащиеся в нем данные. А зачем здесь апплет ScriptHelper? Он не отображается броузером и выполняет вспомогательные функции, расширяя возможности языка JavaScript методами для непосредственной работы с InfoBus и для создания специфических объектов, передаваемых другим апплетам. Приблизительно таковы представления о InfoBus, необходимые для разработчика HTMLстраниц с апплетами eSuite. И, поверьте, ему нет никаких причин изучать устройство InfoBus более подробно, оставаясь в своих рамках.
InfoBus c точки зрения разработчика апплетов, использующего Java Builder Подобным образом воспринимает InfoBus и разработчик прикладных апплетов, когда он «собирает» свой апплет в визуальной среде разработки из готовых Bean-компонентов (классов, © InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 159
которые удовлетворяют спецификации JavaBeans), в том числе из Bean-компонентов, входящих в eSuite DevPack. Пусть в приложении, собранном из Bean-компонентов, «объединенных» InfoBus, один компонент обеспечивает ввод некоторой информации, для простоты, «строки запроса». Когда эта строка введена пользователем приложения, она публикуется в InfoBus. Следующий компонент, допустим, компонент SQL/JDBC, получив «ожидаемую» «строку запроса» из InfoBus, обращается к JDBC-источнику, связанному с внешней базой данных, извлекает откуда соответствующие запросу данные и «через InfoBus» передает их третьему компоненту, допустим, компоненту Chart, который и строит график на основе этих данных. Однако реалии использования eSuite DevPack на таком поприще в настоящее время более скромны.
• •
Хотя классы eSuite DevPack 1.0 и удовлетворяют спецификации JavaBeans, но использование их как Bean-компонентов в визуальных средах разработки не сертифицировано Lotus. Ожидается, что Lotus сертифицирует использование классов eSuite DevPack 1.5 как Beanкомпонентов. По крайней мере классы из версии eSuite DevPack 1.5 Preview (была доступна, когда писались эти строки) были протестированы Lotus в качестве Beanкомпонентов в визуальной среде разработки Symantec Visual Cafe 2.5 for Java.
InfoBus для профессионального разработчика на Java Необходимость в более подробной информации об InfoBus возникает, если нужно создать собственный «InfoBus-совместимый» апплет. Получить InfoBus 1.1 (документация, классы, примеры…) можно с сайта JavaSoft http://java.sun.com/beans/infobus/index.html.
Элементы данных InfoBus, используемые в eSuite DevPack Апплеты eSuite DevPack «работают» с элементами данных следующих интерфейсов.
• • • • • •
ImmediateAccess - содержит одно значение или один объект. ArrayAccess - содержит многомерный массив значений, в eSuite применяются двумерные «массивы». RowsetAccess - содержит набор записей из базы данных, создается апплетом SQL/JDBC. Collection - всевозможные коллекции, реализующие любой из интерфейсов Java Collection, например, Collection, Map, Set и List (см. Java Development Kit, Version 1.2, from Sun Microsystems, Inc.). MinimalMap - eSuite-подмножество интерфейса Map из Java Collection. Например, апплет FormReader публикует элемент данных с интерфейсом MinimalMap, и этот элемент данных может быть использован апплетами Presentation и CGI Gateway. MinimalCollection - eSuite-подмножество интерфейса Java Collection. Объект MinimalCollection может возвращать объект MinimalIterator, который реализует eSuiteподмножество интерфейса Java Collection Iterator для последовательного доступа к элементам объекта MinimalCollection.
Броузеры, в которых работают апплеты eSuite DevPack 1.0 Апплеты eSuite DevPack 1.0 работают только в броузерах Netscape Navigator версии не ниже 4.04 c установленным Netscape patch for Java 1.1.4 или Microsoft Internet Explorer версии не ниже 4.01. Работоспособность всех примеров, приводимых в данной главе, проверялась авторами в Microsoft Internet Explorer 4.01. Только немногие из этих примеров были дополнительно проверены в Netscape Navigator 4.04.
© InterTrust Co. Тел. 956-7928, 956-7929
160
Применение eSuite DevPack 1.0
Размещение апплетов eSuite DevPack Сами апплеты eSuite DevPack могут располагаться на любых стандартных HTTP-серверах, включая Domino, Domino Go WebServer, Microsoft Internet Information Server, Netscape Enterprise Server и др. Обычно все, что относится к eSuite DevPack, помещается на HTTP-сервер в каталог eSuiteDP. Классы для апплетов eSuite DevPack «упакованы» в файлы-архивы двумя методами: JAR и CAB, и расположены соответственно в подкаталогах jars и cabs каталога eSuiteDP. Архивы JAR поддерживаются как броузером Netscape Navigator, так и Microsoft Internet Explorer (но если отсутствуют архивы CAB). Netscape Navigator может «проверять электронную подпись» только для одного файла-архива JAR. Поэтому в случае, если в HTML-документе применяется несколько апплетов eSuite, в броузер должен загружаться один JAR-архив, содержащий классы для всех используемых на странице апплетов eSuite. Microsoft Internet Explorer вообще не «проверяет электронную подпись» для архивов JAR. Архивы CAB поддерживаются броузером Microsoft Internet Explorer, но не поддерживаются Netscape Navigator. Internet Explorer может «проверять электронную подпись» для нескольких файлов-архивов CAB. Поэтому в случае, если в HTML-документе применяется несколько апплетов eSuite, в броузер можно загружать несколько CAB-архивов, каждый из которых содержит классы, относящиеся к одному апплету.
11.1. Апплет ScriptHelper Апплет ScriptHelper (ранее известный как InfoBusBridge), пользовательского интерфейса не имеет. Как и следует из названия апплета, он «добавляется» в HTML-документ исключительно для того, чтобы «в JavaScript этого документа» стали доступны некоторые дополнительные методы. Методы апплета позволяет из JavaScript, содержащегося в HTML-документе, публиковать в InfoBus строки и массивы строк, а так же создавать некоторые специфические Java-объекты (Color, Date, TimeZone, InfoBusVector, DataInputStream, OutputBuffer, DataItemReader), которые необходимы для передачи в качестве аргументов методам и свойствам других апплетов eSuite. Для публикации строк и массивов строк в InfoBus апплет использует объект класса lotus.scripthelper.InfoBusVector, а для получения данных из InfoBus - объект класса lotus.scripthelper.DataItemReader.
Метод createInfoBusVector lotus.scripthelper.InfoBusVector InfoBusVector = ScriptHelper.createInfoBusVector() Создает пустой объект класса InfoBusVector. Для «занесения» данных в объект InfoBusVector используются методы addValue(), appendRow() и appendColumnValue() объекта InfoBusVector. После того, как все необходимые данные занесены в объект InfoBusVector, он передается методу publishVectorToInfoBus() для публикации в InfoBus.
Метод addValue класса InfoBusVector InfoBusVector.addValue(int row, int column, String value) Присваивает новое значение value «элементу массива» InfoBusVector «с индексами» row (номер строки) и col (номер столбца). Нумерация строк и столбцов «начинается с нуля». Если указаны строка или столбец вне текущих границ объекта InfoBusVector, объект автоматически создает необходимое число «пустых» строк или столбцов, чтобы стало возможным добавить этот элемент.
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 161
Метод appendRow класса InfoBusVector int row = InfoBusVector.appendRow() Добавляет новую пустую строку в InfoBusVector и возвращает ее номер.
Метод appendColumnValue класса InfoBusVector InfoBusVector.appendColumnValue(int row, String value) Добавляет новый элемент «вслед за последним имеющимся» в строке row. Если происходит «выход за текущие границы» InfoBusVector, его границы автоматически расширяются.
Метод publishVectorToInfoBus ScriptHelper.publishVectorToInfoBus(String itemName, InfoBusVector InfoBusVector) Публикует объект InfoBusVector, содержащий двумерный массив строк, в InfoBus «под именем» itemName как элемент данных с интерфейсом ArrayAccess. Если для элемента данных было указано «новое» имя (ранее не существовавшее в InfoBus), соответствующий элемент данных будет добавлен в InfoBus. Если же было указано имя, совпадающее с именем уже имеющегося в InfoBus элемента данных, прежний элемент будет удален и заменен новым, имеющим то же имя.
Метод publishStringToInfoBus ScriptHelper.publishStringToInfoBus(String itemName, String itemValue) Публикует в InfoBus «одну строку» itemValue под именем itemName как элемент данных с интерфейсом ImmediateAccess. Если указано «новое» (ранее не существовавшее в InfoBus) имя элемента данных, элемент будет добавлен в InfoBus. Если указано имя элемента данных, который уже был ранее опубликован методом publishStringToInfoBus() этого же экземпляра апплета ScriptHelper, новое значение заменяет старое в существующем в InfoBus элементе данных. Если указано имя элемента данных, которое было ранее опубликовано методом publishVectorToInfoBus(), старый элемент данных удаляется и затем публикуется новый.
Метод readStringFromInfoBus String datastring = ScriptHelper.readStringFromInfoBus(String itemName) Выбирает данные из элемента данных InfoBus с именем itemName и возвращает их как строку, если элемент данных с указанным именем существует в InfoBus и поддерживает интерфейс для получения значения в форме строки (presentation string) или имеет строковое значение (value string). В противном случае возвращается null. Для элементов данных с интерфейсом ImmediateAccess возвращается presentation string, форматируемая в соответствии с текущей местностью пользователя (current locale).
Метод findInfoBusItem lotus.scripthelper.DataItemReader DataItemReader = ScriptHelper.findInfoBusItem(String itemName) Возвращает новый объект класса DataItemReader, позволяющий получить доступ к данным из содержащегося в InfoBus элемента данных с именем itemName, или null, если этот элемент данных не доступен. Методы класса DataItemReader позволяют определить, какой интерфейс поддерживает элемент данных, а так же извлечь данные из элемента данных с интерфейсом ArrayAccess или ImmediateAccess.
© InterTrust Co. Тел. 956-7928, 956-7929
162
Применение eSuite DevPack 1.0
Метод isImmediateAccess класса DataItemReader boolean flag = DataItemReader.isImmediateAccess() Если элемент данных поддерживает интерфейс ImmediateAccess, возвращает true, иначе false.
Метод readImmediateValueAsString класса DataItemReader String value = DataItemReader.readImmediateValueAsString() Если элемент данных поддерживает интерфейс ImmediateAccess, возвращается его значение как строка. Возвращаемая строка вычисляется как presentation string, если элемент данных поддерживает эту функцию, иначе как value string. Если же элемент данных не поддерживает интерфейс ImmediateAccess, или поддерживает, но значение не может быть получено, возвращается null.
Метод readImmediateValueAsObject класса DataItemReader Object objRef = DataItemReader.readImmediateValueAsObject() Если элемент данных поддерживает интерфейс ImmediateAccess, возвращается ссылка на объект, представляющий его значение. В противном случае возвращается null.
Метод isArrayAccess класса DataItemReader boolean flag = DataItemReader.isArrayAccess() Если элемент данных поддерживает интерфейс ArrayAccess, возвращает true, иначе false.
Метод getDimensionCount класса DataItemReader int dimCount = DataItemReader.getDimensionCount() Возвращает количество измерений элемента данных ArrayAccess или 0, если элемент данных не поддерживает интерфейс ArrayAccess.
Метод getDimensionSize класса DataItemReader int indexCount = DataItemReader.getDimensionSize(int dimension) Возвращает размерность (количество элементов) элемента данных ArrayAccess по измерению dimension. Измерения «номеруются с нуля» - двумерный массив имеет измерения с номерами 0 и 1. Если элемент данных не поддерживает интерфейс ArrayAccess или поддерживает, но указано несуществующее измерение, возвращается -1.
Метод readArrayValueAsString класса DataItemReader String value = DataItemReader.readArrayValueAsString(String coords) Для содержащегося в «массиве ArrayAccess» элемента, определенного «строкой индексов» coords, возвращает строку, содержащую значение этого элемента. Например, «строка индексов» "1,0,8" определяет «элемент трехмерного массива» с индексом [1][0][8]. Если элемент InfoBus не поддерживает интерфейс ArrayAccess, возвращается null. Если поддерживает, но «строка индексов» указывает на несуществующий «элемент массива», возвращается пустая строка ("").
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 163
Метод dispose класса DataItemReader DataItemReader.dispose() Освобождает ссылку на объект DataItemReader. Должен вызываться после того, как объект DataItemReader «стал более не нужен». Пример 1. В приведенном ниже фрагменте HTML-документа демонстрируются основные приемы «ручного» занесения информации в InfoBus и «ручного» получения информации из InfoBus. Кнопка Fields as myOutput (см. Рис. 11.2) создает объект InfoBusVector, заносит в него информацию из полей формы и затем публикует ее как элемент данных ArrayAccess с именем myOutput. Кнопка MyString as myOutput1 публикует строку «MyString» как элемент данных ImmediateAccess с именем myOutput1. Кнопки Read myOutput1 и Read myOutput «исследуют свойства и получают значения» опубликованных в InfoBus элементов данных.
Рис. 11.2 Внешний вид HTML-документа в броузере <APPLET CODEBASE="/eSuiteDP" CODE="lotus.scripthelper.ScriptHelper" NAME="scrHelper" ARCHIVE="/eSuite/jars/devpack_scripthelper_app.jar" WIDTH=0 HEIGHT=0> <SCRIPT LANGUAGE="JavaScript">
© InterTrust Co. Тел. 956-7928, 956-7929
164
Применение eSuite DevPack 1.0
vector.appendColumnValue( row, document.forms[0].ec1.value ); vector.appendColumnValue( row, document.forms[0].ed1.value ); row = vector.appendRow(); vector.appendColumnValue( row, document.forms[0].ea2.value ); vector.appendColumnValue( row, document.forms[0].eb2.value ); vector.appendColumnValue( row, document.forms[0].ec2.value ); vector.appendColumnValue( row, document.forms[0].ed2.value ); row = vector.appendRow(); vector.appendColumnValue( row, document.forms[0].ea3.value ); vector.appendColumnValue( row, document.forms[0].eb3.value ); vector.appendColumnValue( row, document.forms[0].ec3.value ); vector.appendColumnValue( row, document.forms[0].ed3.value ); // Публикация объекта класса InfoBusVector document.scrHelper.publishVectorToInfoBus( "myOutput", vector ); alert("Вектор myOutput опубликован"); // // // // // // // // // // // // // }
Обратите внимание, что при таком порядке заполнения будет получен двумерный массив размера 5 Х 4, в котором первый индекс (индекс строки ) меняется от 0 до 4 (5 строк), а второй индекс (индекс столбца) меняется от 0 до 3 (4 столбца). "***" обозначает незаполненный элемент, а "eXY" - имя поля, из которого заполняется элемент 0 1 2 3 ..................... 0 . *** *** *** *** 1 . ea0 *** *** *** 2 . ea1 eb1 ec1 ed1 3 . ea2 eb2 ec2 ed2 4 . ea2 eb2 ec2 ed2
// Публикация в InfoBus одной строки function doClick2(n) { document.scrHelper.publishStringToInfoBus( "myOutput1", "MyString" ); alert("Строка myOutput1 опубликована"); } // Чтение строки из InfoBus function doClick3(n) { itemName = "myOutput1"; alert(itemName + " = \"" + document.scrHelper.readStringFromInfoBus(itemName) +"\""); reader = document.scrHelper.findInfoBusItem(itemName); if (reader == null) alert("Элемент " + itemName + " не найден"); if (reader.isImmediateAccess()) alert("Это элемент с интерфейсом ImmediateAccess"); alert("Он имеет " + reader.getDimensionCount() + " измерений"); // Он имеет 0 измерений alert("Его значение как строка " + reader.readImmediateValueAsString()); // Его значение как строка MyString alert("Его значение как объект " + reader.readImmediateValueAsObject()); // Его значение как объект MyString alert("Val[0][0] = \"" + reader.readArrayValueAsString("0,0") + "\""); // Val[0][0] = "null" reader.dispose(); }
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 165 // Получение информации о векторе, имеющемся в InfoBus function doClick4(n) { itemName = "myOutput"; alert(itemName + " = \"" + document.scrHelper.readStringFromInfoBus(itemName) + "\""); // myOutput = "null" reader = document.scrHelper.findInfoBusItem(itemName); if (reader == null) alert("Элемент не найден"); if (reader.isArrayAccess()) alert("Элемент с интерфейсом ArrayAccess"); alert("Он имеет " + reader.getDimensionCount() + " измерения"); // Он имеет 2 измерения n0 = reader.getDimensionSize(0); alert("Dim[0] = " + n0); // Dim[0] = 5 n1 = reader.getDimensionSize(1); alert("Dim[1] = " + n1); // Dim[1] = 4 alert("Dim[2] = " + reader.getDimensionSize(2)); // Dim[2] = -1 for (i0 = 0; i0 < n0; i0++) for (i1 = 0; i1 < n1; i1++) alert("Val["+i0+"]["+i1+"] = \"" + reader.readArrayValueAsString(i0+","+i1) + "\""); // Val[i0][i1]= | i1 = 0 i1 = 1 i1 = 2 i1 = 3 // _____________|__________________________________________________ // i0 = 0 | "" "" "" "" // i0 = 1 | "Strategic data" "" "" "" // i0 = 2 | " " "Point 1" "Point 2" "Point 3" // i0 = 3 | "Strategy 1" "1." "5." "9." // i0 = 4 | "Strategy 2" "2." "6." "10." reader.dispose(); } //--> Кнопка публикует в InfoBus вектор данных из расположенных выше полей
Кнопка публикует в InfoBus строку "MyString"
Кнопка читает из InfoBus строку MyString
Кнопка получает из InfoBus информацию о векторе
© InterTrust Co. Тел. 956-7928, 956-7929
166
Применение eSuite DevPack 1.0
Метод createColor java.awt.Color Color = ScriptHelper.createColor(String colorSpecifier) Преобразует заданное строкой название или 16-ричное RGB-значение цвета в объект класса java.awt.Color.
Метод createDate java.util.Date Date = ScriptHelper.createDate(String datestring) Преобразует строку, содержащую «дата-временное» значение, в объект класса java.util.Date. Строка анализируется согласно соглашению о локализации (настройка приложения на работу в определенной местности и на определенном языке) в части формата записи даты и времени в соответствии с текущей местностью пользователя (user's current locale). Информация о времени игнорируется. Вначале предпринимается попытка «разобрать» строку с использованием стиля FULL (см. класс java.text.DateFormat), при неуспехе - стиля LONG, затем MEDIUM и, наконец, SHORT. Если все попытки завершились неуспешно, возвращается null.
Метод createTimeZone java.util.TimeZone TimeZone = ScriptHelper.createTimeZone(String zoneName) Создает объект класса java.util.TimeZone, соответствующий временной зоне, название которой задано строкой zoneName (например, "EST"). Если указанная строка не может быть «понята» пользовательской виртуальной машиной Java, возвращается null.
Метод createOutputBuffer lotus.scripthelper.OutputBuffer OutputBuffer = ScriptHelper.createOutputBuffer() Создает «пустой» объект класса lotus.scripthelper.OutputBuffer. Во-первых, объект OutputBuffer содержит метод, позволяющий разработчику создать поток вывода данных java.io.DataOutput для записи в объект OutputBuffer любой информации в форме строк. Во-вторых, ряд апплетов eSuite содержат методы для «выгрузки» содержащихся в них документов в поток вывода данных. Наконец, объект OutputBuffer содержит метод, позволяющий извлечь всю информацию, уже записанную в объект OutputBuffer через поток вывода данных, как одну строку символов, с применением по желанию нужного кодирования символов.
Метод getOutputStream класса OutputBuffer java.io.DataOutput DataOutput = OutputBuffer.getOutputStream() Возвращает поток вывода данных (объект класса java.io.DataOutput), связанный с объектом OutputBuffer.
Метод saveDocumentToStream ряда апплетов eSuite boolean isSaved = myApplet.saveDocumentToStream(java.io.DataOutput outputStream) Сохраняет документ, содержащийся в апплете, в указанном потоке вывода данных (объекте класса java.io.DataOutput), используя при этом «формат по умолчанию» для соответствующего документа. Метод применим к апплетам AppletContainer, Chart, Presentation, Scheduler, Sheet и WordProcessor. Если сохранение завершилось успешно, возвращается true, иначе false.
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 167
Метод getString класса OutputBuffer String contents = OutputBuffer.getString(String encoding) Возвращает все данные, содержащиеся в объекте OutputBuffer, в форме строки. Аргумент encoding позволяет задать кодировку символов для возвращаемой строки. По умолчанию применяется кодировка "PSUU16" (pseudo-uuencoding, 16 values or 4 bits per character). Любые нераспознанные кодировки интерпретируются как «отсутствие перекодировки».
Метод createInputStream java.io.DataInput DataInput = ScriptHelper.createInputStream(String contents, String encoding) Создает поток ввода данных (объект класса java.io.DataInput) для доступа к содержимому строки contents. Аргумент encoding позволяет указать кодировку символов в строке contents. По умолчанию предполагается кодировка "PSUU16". Любые нераспознанные кодировки интерпретируются как «отсутствие перекодировки». Содержимое строки contents впоследствии будет извлекаться из объекта java.io.DataInput как unencoded или plain text. Кроме того, ряд апплетов eSuite содержат методы для «загрузки» в них документов из потока ввода данных.
Метод openDocumentFromStream ряда апплетов eSuite boolean isOpened = myApplet.openDocumentFromStream(java.io.DataInput inputStream, boolean promptToSave) Открывает в апплете новый документ и заносит в него данные из потока ввода данных (объекта класса java.io.DataInput). Применим к апплетам AppletContainer, Chart, Presentation, Scheduler, Sheet и WordProcessor. Апплет, который «загружает» данные из потока, интерпретирует их в своем «формате по умолчанию». Если аргумент promptToSave равен true, и пользователь сделал изменения в «текущем» документе апплета, то при закрытии «текущего» документа будет появляться диалоговое окно с запросом о его сохранении или отмене внесенных изменений. Если же аргумент promptToSave равен false, такое диалоговое окно не появляется и «текущий» документ не сохраняется. Метод возвращает true, если «загружаемый» документ был успешно открыт, или false, если если документ не удалось загрузить или если пользователь выбрал Cancel в диалоговом окне при сохранении «текущего» документа. Applet1
Документ
java.io.DataOutput
OutputBuffer
Applet2 Документ
java.io.DataInput
Java String
Рис. 11.3 Логика передачи документа из одного апплета в другой Таким образом, использование объекта OutputBuffer дает возможность из JavaScript преобразовать выходной поток апплета в строку символов, по желанию с применением
© InterTrust Co. Тел. 956-7928, 956-7929
168
Применение eSuite DevPack 1.0
нужного кодирования, а затем передавать эту строку другому апплету или «на сервер», CGIпрограмме «по заданному URL». Пример 2. Приведенный ниже фрагмент на JavaScript демонстрирует передачу документа из одного апплета eSuite в другой (см. Рис. 11.3). Документ, загруженный в апплет Applet1, выгружается в поток вывода данных, связанный с объектом OutputBuffer. Затем содержимое объекта OutputBuffer (документ) без перекодировки преобразуется в строку. Далее создается поток ввода данных, содержащий информацию из этой строки. Наконец, информация из потока ввода данных загружается в апплет Applet2. Подобный же прием будет продемонстрирован позже, при рассмотрении апплета Sheet, для передачи «документа-таблицы» на Web-сервер и последующей загрузки с Web-сервера в апплет. // Создаем объект OutputBuffer, // scrhlp - имя экземпляра апплета ScriptHelper ob = scrhlp.createOutputBuffer(); // В связанный с объектом OutputBuffer поток вывода данных // записываем документ из апплета applet1 applet1.saveDocumentToStream(ob.getOutputStream()); // Теперь этот документ без перекодировки извлекаем в строку docString = ob.getString(""); // Создаем поток ввода данных, содержащий эту строку (без перекодировки) // и загружаем "информацию из строки" в апплет applet2 applet2.openDocumentFromStream(scrhlp.createInputStream(docString, ""));
11.2. Апплет FileReader Публикует в InfoBus данные из восьми-битного ASCII последовательного файла как двухмерный элемент данных с интерфейсом ArrayAccess. Байт-код апплета - Filereader.class. Для работы апплета в броузер должен быть загружен JAR-архив devpack_filereader_app.jar или CAB-архив devpack_filereader_app.cab. Апплет разбирает входной файл на лексемы (токены), используя в пределах строки пробелы в качестве символа-разделителя. При этом апплетом используется класс java.io.StreamTokenizer. Каждая лексема из строки входного файла заносится в отдельный элемент в строке выходного массива, а каждая строка входного файла - в отдельную строку выходного массива.
Параметр и свойство OutputItemName FileReader.setOutputItemName(String name) String name = FileReader.getOutputItemName() Имя публикуемого в InfoBus элемента данных, который будет содержать информацию из входного файла апплета. По умолчанию используется имя экземпляра апплета (из атрибута NAME в теге <APPLET>), а если его нет, то "FileReaderOutput".
Параметр и свойство DocumentName FileReader.setDocumentName(String fileName) String fileName = FileReader.getDocumentName() URL входного файла для апплета. Для доступа к локальным файлам используется конструкция "file:///c:\/filename.extension", например,
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 169
Параметр и свойство DocumentNameItemName FileReader.setDocumentNameItemName(String dinFileIn) String dinFileIn = FileReader.getDocumentNameItemName() Игнорируется, если был задан параметр documentName. Сообщает имя элемента данных с интерфейсом ImmediateAccess, который должен содержать URL для получения входного файла апплета. Апплет ожидает этот элемент данных, а по его появлении выполняет разбор указанного в нем файла и публикацию в InfoBus содержащихся в файле данных. При использовании параметра одним экземпляром апплета можно последовательно «загрузить в InfoBus несколько файлов». При каждом изменении имени файла в элементе данных dinFileIn соответствующий файл «разбирается и публикуется, заменяя в InfoBus старый».
Параметр debug Значение true разрешает протоколирование в System.out основных событий при работе апплета, а значение false (по умолчанию) - запрещает протоколирование. Если выбрано true, апплет также выполняет протоколирование основных событий при работе InfoBus.
Параметр verbose Значение true разрешает протоколирование в System.out публикуемых в InfoBus данных (содержимого массива, полученного из файла), а значение false (по умолчанию) - запрещает. Если выбрано true, апплет также выполняет протоколирование основных событий при работе InfoBus. Пример 1. Приведенный фрагмент HTML-кода «минимально-необходим» для запуска апплета FileReader. HTML-документ, содержащий апплет, имеет URL http://main.inttrust.ru/eSuite.nsf/byKeys/0102-001?OpenDocument. Апплет при своей инициализации читает входной файл "../Images/FileReader/$File/FileReader.txt?OpenElement" (присоединенный файл FileReader.txt из документа «с ключем» FileReader в виде Images этой же базы) и публикует его содержимое в InfoBus под именем «dinFileOut». <APPLET CODEBASE="/eSuiteDP" CODE="lotus.filereader.FileReader" NAME="fileReader" ARCHIVE="/eSuiteDP/jars/devpack_filereader_app.jar" WIDTH=400 HEIGHT=100> Содержимое файла FileReader.txt выглядит следующим образом. "Row "Row "Row "Row
0" 1" 2" 3"
" Col 1 " " Col 2 " " Col 3 " " Col 4 " " Col 5 " ab bc cd de ef 1 2 3 4 5 2.07 3.31 4. 5.11 6.21
Далее приведен фрагмент протокола апплета, выводимого в System.out (Java Console).
© InterTrust Co. Тел. 956-7928, 956-7929
170
Применение eSuite DevPack 1.0
URL(../Images/FileReader/$FILE/FileReader.txt?OpenElement) URL.openStream() addElement [0][0]=Row 0 addElement [0][1]= Col 1 addElement [0][2]= Col 2 addElement [0][3]= Col 3 addElement [0][4]= Col 4 addElement [0][5]= Col 5 addElement [1][0]=Row 1 addElement [1][1]=ab addElement [1][2]=bc addElement [1][3]=cd addElement [1][4]=de addElement [1][5]=ef addElement [2][0]=Row 2 addElement [2][1]=1.0 addElement [2][2]=2.0 addElement [2][3]=3.0 addElement [2][4]=4.0 addElement [2][5]=5.0 addElement [3][0]=Row 3 addElement [3][1]=2.07 addElement [3][2]=3.31 addElement [3][3]=4.0 addElement [3][4]=5.11 addElement [3][5]=6.21 ib.fireItemAvailable(dinFileOut, null, this) Пример 2. Апплет ожидает появления URL входного файла в InfoBus. URL вводится пользователем в поле и публикуется в InfoBus кнопкой, «вызывающей» функцию на JavaScript. Для реализации этого действия используется метод апплета ScriptHelper. Когда URL входного файла опубликован, апплет читает этот файл и загружает информацию из него в InfoBus под именем «dinFileOut1». <APPLET CODEBASE="/eSuiteDP" CODE="lotus.filereader.FileReader" NAME="fileReader1" ARCHIVE="/eSuiteDP/jars/devpack_filereader_app.jar" WIDTH=400 HEIGHT=100> <APPLET CODEBASE="/eSuiteDP" CODE="lotus.scripthelper.ScriptHelper" ARCHIVE="jars/devpack_chart_app.jar" NAME="ibBridge" WIDTH=1 HEIGHT=1>
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 171 VALUE="/eSuiteDP/cabs/devpack_scripthelper_app.cab, /eSuiteDP/cabs/devpack_infobus.cab, /eSuiteDP/cabs/devpack_shared.cab, /eSuiteDP/cabs/devpack_filereader_app.cab"> <SCRIPT LANGUAGE="JavaScript"> Введите URL публикуемого файла и нажмите OK.
11.3. Апплет TableReader Апплет получает HTML-код (обычно по заданному URL), находит в нем нужную таблицу (тег
в HTML-коде), анализирует и выбирает из нее данные, а затем публикует их в InfoBus. Байт-код апплета - TableReader.class. Для работы апплета в броузер должен быть загружен JAR-архив devpack_htmlparse_app.jar или CAB-архив devpack_htmlparse_app.cab. Апплет может иметь «видимый» пользовательский интерфейс.
Рис. 11.4 Внешний вид «пользовательского интерфейса» апплета TableReader
© InterTrust Co. Тел. 956-7928, 956-7929
172
Применение eSuite DevPack 1.0
Параметр и свойство OutputItemName TableReader.setOutputItemName(String datasetName) String datasetName = TableReader.getOutputItemName() Задает имя элемента данных, публикуемого апплетом в InfoBus. По умолчанию "ReaderOutput". Этот двухмерный элемент данных с интерфейсом ArrayAccess содержит информацию из таблицы.
Параметр и свойство URL TableReader.setURL(String tableURL) String tableURL = TableReader.getURL() Задает URL документа, содержащего нужную таблицу. Необходим, если апплет не имеет «видимого» пользовательского интерфейса. Если же «видимый» интерфейс имеется, то URL можно ввести в соответствующем текстовом поле аплета. Если во время загрузки текущей таблицы происходит изменение URL, текущая операция загрузки прерывается и запускается операция загрузки новой таблицы.
Параметр и свойство SearchIndex TableReader.setSearchIndex(int tableNumber) int tableNumber = TableReader.getSearchIndex() Номер таблицы (тега в HTML-коде), из которой должны выбираться данные. Должен быть целым числом. Первая таблица имеет номер 1. Значение по умолчанию 1. Свойство getSearchIndex() возвращает -1, если таблица задается не своим номером, а строкой для поиска. Если во время загрузки текущей таблицы происходит изменение номера таблицы, текущая операция загрузки прерывается и запускается операция загрузки новой таблицы.
Параметр и свойство SearchString TableReader.setSearchString(String searchString) String searchString = TableReader.getSearchString() Задает строку для поиска в HTML-коде. Данные будут выбираться из первой таблицы (тег ), в которой эта строка будет обнаружена. Если во время загрузки текущей таблицы происходит изменение поисковой строки, текущая операция загрузки прерывается и запускается операция загрузки новой таблицы.
Параметр и свойство CharacterEncoding TableReader.setCharacterEncoding(String encoding) String encoding = TableReader.getCharacterEncoding()
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 173
Сообщает метод кодирования символов в HTML-документе. Например, "8859_1" для ISO Latin-1, "8859_7" для ISO Latin/Greek или "UTF8" для Standard UTF-8. Если параметр задан, он должен содержать правильное имя метода кодирования, если не задан - предполагается метод кодирования по умолчанию.
Параметр и свойство paramInputItemName TableReader.setParamInputItemName(String dataItemName) String dataItemName = TableReader.getParamInputItemName() Определяет имя элемента данных, ожидаемого апплетом в InfoBus, и, в зависимости от имени, интерпретацию значения этого элемента данных. Значение dataItemName может быть одним из следующих: "URL" - элемент данных с именем URL содержит URL документа, из таблицы в котором должны выбираться данные; "SearchIndex" - элемент данных с именем SearchIndex содержит номер таблицы, выбираемой из HTML-документа; "SearchString" - элемент данных с именем SearchString содержит строку для поиска в таблице из HTML-документа; "Charset" - элемент данных с именем Charset содержит название набора символов для документа, из таблицы в котором выбираются данные. Эти имена элементов данных «подобны» параметрам и свойствам URL, SearchIndex, SearchString и CharacterEncoding, рассмотренным выше. Как только элемент данных с именем dataItemName появляется в InfoBus, он выбирается апплетом, апплет завершает «текущий разбор» (если он выполняется) и начинает «новый разбор».
Параметр и свойство HTMLInputItemName TableReader.setHTMLInputItemName(String datasetName) String datasetName = TableReader.getHTMLInputItemName() Если параметр задан, то апплет будет «прослушивать InfoBus» до появления в ней элемента данных с указанным в этом параметре именем. Предполагается, что этот элемент данных содержит HTML-код. Когда элемент данных появится, апплет начнет его разбор. Параметр позволяет апплету извлекать HTML-код не по заданному URL, а динамически создаваемый CGI-программой и помещаемый в InfoBus апплетом CGI Gateway.
Параметр и свойство AllowUI TableReader.setAllowUI(boolean uiSetting) boolean uiSetting = TableReader.getAllowUI() Если указано true (значение по умолчанию), апплет будет иметь «видимый» пользовательский интерфейс, если же указано false - пользовательский интерфейс будет «скрыт». Однако, поскольку для апплета всегда должны быть заданы ширина и высота (WIDTH и HEIGHT в теге APPLET), установка этого параметра в false недостаточна для создания «невидимого» апплета. Если параметр был задан, можно указать WIDTH=0 и HEIGHT=0, чтобы «скрыть» апплет. © InterTrust Co. Тел. 956-7928, 956-7929
174
Применение eSuite DevPack 1.0
При наличии пользовательского интерфейса URL может быть введен в соответствующем поле интерфейса, а процесс выборки таблицы может быть запущен нажатием кнопки Submit это удобно при отладке. При отсутствии интерфейса URL должен быть задан, а процесс выборки таблицы начинается при старте апплета.
Параметр и свойство Debug TableReader.setDebug(boolean setting) boolean setting = TableReader.getDebug() Если указано true, апплет выводит отладочные сообщения, если указано false (значение по умолчанию) - не выводит.
Методы abort и parse TableReader.abort() TableReader.parse() Метод abort() прерывает обработку текущей таблицы. В «пользовательском интерфейсе» это аналогично нажатию кнопки Cancel (см. Рис. 11.4). Метод parse() инициирует процесс обработки таблицы. В «пользовательском интерфейсе» это аналогично нажатию кнопки Read Data. Если вызов метода или нажатие кнопки происходят во время загрузки текущей таблицы, текущая операция загрузки прерывается и запускается новая. Пример 1. Приведенный фрагмент HTML-кода «минимально-необходим» для запуска апплета TableReader. HTML-документ, содержащий апплет, имеет URL http://main.inttrust.ru/eSuite.nsf/byKeys/0103-001?OpenDocument. Апплет при своей инициализации читает HTML-документ "../AllExs?OpenView&Start=1&Count=999&ExpandView" («раскрытый» вид с именем AllExs из этой же базы) и публикует содержимое второй таблицы «из этого вида» в InfoBus под стандартным именем «ReaderOutput». <APPLET NAME="tableParse" CODEBASE="/eSuiteDP" CODE="lotus.htmlparse.TableReader" ARCHIVE="/eSuiteDP/jars/devpack_htmlparse_app.jar" WIDTH=450 HEIGHT=250> Пример 2. Фрагмент HTML-кода демонстрирует выборку второй таблицы из HTML-образа вида базы данных Notes, загрузку информации из этой таблицы в InfoBus как элемента данных с интерфейсом ImmediateAccess с именем «tableItem» и последующее помещение этого элемента данных в апплет электронную таблицу eSuite. На Рис. 11.5 показано, как выглядит этот HTML-код в броузере. На Рис. 11.6 показано, как выглядит соответствующий вид в базе данных Notes. Несоответствие данных в первом столбце электронной таблицы eSuite и вида из базы Notes объясняется очень просто - электронная таблица «производит вычисления» над переданными ей данными.
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 175 <APPLET NAME="tableParse" CODEBASE="/eSuiteDP" CODE="lotus.htmlparse.TableReader" ARCHIVE="/eSuiteDP/jars/devpack_htmlparse_app.jar" WIDTH=0 HEIGHT=0> <APPLET CODEBASE="/eSuiteDP" CODE="lotus.sheet.Sheet" ARCHIVE="/eSuiteDP/jars/devpack_sheet_app.jar" WIDTH=600 HEIGHT=300 NAME=sheet>
<SCRIPT LANGUAGE="JavaScript"> Введите URL и номер публикуемой таблицы и нажмите OK.
© InterTrust Co. Тел. 956-7928, 956-7929
176
Применение eSuite DevPack 1.0
Рис. 11.5 Внешний вид HTML-кода в броузере
Рис. 11.6 «Исходный» вид в клиенте Notes
11.4. Апплет FormReader Апплет FormReader предназначен для чтения содержимого формы (тега FORM) из HTMLдокумента и публикации имеющихся в форме данных в InfoBus. Байт-код апплета - FormReader.class. Для работы апплета в броузер должен быть загружен JAR-архив devpack_htmlparse_app.jar или CAB-архив devpack_htmlparse_app.cab. По умолчанию апплет делает следующее:
• • • •
обращается к HTML-документу по заданному URL, «просматривает» документ до нахождения данных формы, извлекает данные из формы, публикует эти данные в InfoBus как двумерный элемент данных с интерфейсом ArrayAccess, в первой строке которого содержатся имена элементов ввода формы, а во второй строке - соответствующие им значения. Элементы ввода формы, которые «понимает» апплет, даны в следующей таблице.
Элемент ввода формы
Его интерпретация апплетом
как «MyName = MyValue»
© InterTrust Co. Тел. 956-7928, 956-7929
как «MyName = MyValue» только при наличии атрибута CHECKED как «MyName = CHECKED»
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 177
<SELECT NAME="MyName"> Variant1 Variant2 Variant3 My text
только при наличии атрибута SELECTED как «MyName = Variant2»
как «RESET = Reset form!»
как «MyName = My text»
как «SUBMIT = Submit form!»
В текущей версии апплета не поддерживаются «радиокнопки» ( ), списки с множественным выбором (<SELECT MULTIPLE>…) и, к сожалению, элементы ввода без явного указания типа ( ), которые по умолчанию должны иметь тип TEXT. Поэтому не удивляйтесь, что «читая апплетом» FormReader HTML-образ документа в режиме редактирования из базы Notes, вы не обнаружите информации из «текстовых» полей документа - ведь Domino генерирует для них тег без явного указания типа. Обычно при применении апплета нет потребности в интерфейсе пользователя - все параметры передаются апплету «через HTML». Однако при отладке приложения апплет может использоваться и с интерфейсом пользователя.
Рис. 11.7 Внешний вид «пользовательского интерфейса» апплета FormReader Апплет FormReader сразу после инициализации создает отдельный поток для получения HTML-кода документа по заданному URL. Благодаря этому всегда можно прервать поток «скачивания» документа. Затем документ анализируется лексема за лексемой. Данные из формы публикуются в InfoBus как элемент данных с интерфейсом KeyedDataSet, с ключами, являющимися именами полей формы. Если задан тег , апплет будет динамически отвечать на запросы о выборке данных из форм, посылаемые ему из других апплетов через InfoBus.
Параметр и свойство OutputItemName FormReader.setOutputItemName(String datasetName)
© InterTrust Co. Тел. 956-7928, 956-7929
178
Применение eSuite DevPack 1.0
String datasetName = FormReader.getOutputItemName() Имя элемента данных, содержащего данные из формы и публикуемого апплетом в InfoBus. По умолчанию "ReaderOutput".
Параметр и свойство URL FormReader.setURL(String formURL) String formURL = FormReader.getURL() Задает URL документа, содержащего нужную форму. Необходим, если апплет не имеет «видимого» пользовательского интерфейса. Если же «видимый» интерфейс имеется, URL можно ввести и в текстовом поле апплета.
Параметр и свойство SearchIndex FormReader.setSearchIndex(int formNumber) int formNumber = FormReader.getSearchIndex() Номер формы (тега в HTML-коде), из которой должны выбираться данные. Должен быть целым числом. Первая форма имеет номер 1. Значение по умолчанию 1. Свойство getSearchIndex() возвращает -1, если форма задается не своим номером, а строкой для поиска. Если во время загрузки текущей формы происходит изменение номера формы, текущая операция загрузки прерывается и запускается операция загрузки новой формы.
Параметр и свойство SearchString PARAM NAME = "searchString" VALUE = "string"> FormReader.setSearchString(String newString) String newString = FormReader.getSearchString() Задает строку для поиска в HTML-коде. Данные будут выбираться из первой формы (тег ), в которой эта строка была обнаружена. Если во время загрузки текущей формы происходит изменение поисковой строки, текущая операция загрузки прерывается и запускается операция загрузки новой формы.
Параметр и свойство CharacterEncoding FormReader.setCharacterEncoding(String encoding) String encoding = FormReader.getCharacterEncoding() Сообщает метод кодирования символов в HTML-документе. Например, "8859_1" для ISO Latin-1, "8859_7" для ISO Latin/Greek или "UTF8" для Standard UTF-8. Если параметр задан, он должен содержать правильное имя метода кодирования, если не задан - предполагается метод кодирования по умолчанию.
Параметр и свойство paramInputItemName
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 179
FormReader.setParamInputItemName(String dataItemName) String dataItemName = FormReader.getParamInputItemName() Определяет имя элемента данных, ожидаемого апплетом в InfoBus, и, в зависимости от имени, как должно интерпретироваться значение этого элемента. Значение dataItemName может быть одним из следующих: "URL" - элемент данных с именем URL содержит URL документа, из формы в котором выбираются данные; "SearchIndex" - элемент данных с именем SearchIndex содержит номер формы, выбираемой из HTML-документа; "SearchString" - элемент данных с именем SearchString содержит строку для поиска в форме из HTML-документа; "Charset" - элемент данных с именем Charset содержит название набора символов для документа, из формы в котором выбираются данные. Эти имена элементов данных «подобны» параметрам и свойствам URL, SearchIndex, SearchString и CharacterEncoding, рассмотренным выше. Как только элемент данных с именем dataItemName появляется в InfoBus, он выбирается апплетом, апплет завершает «текущий разбор» (если он выполняется) и начинает «новый разбор».
Параметр и свойство HTMLInputName FormReader.setHTMLInputItemName(String databusItemName) String databusItemName = FormReader.getHTMLInputItemName() Если параметр или свойство установлены, то апплет будет «прослушивать InfoBus» до появления в ней элемента данных с именем databusItemName. Предполагается, что этот элемент данных содержит HTML-код. Когда элемент данных появится, апплет начнет разбор содержащихся в нем данных. Параметр позволяет апплету извлекать HTML-код не по заданному URL, а динамически создаваемый CGI-программой и помещаемый в InfoBus апплетом CGI Gateway.
Параметр и свойство AllowUI FormReader.setAllowUI(boolean uiSetting) boolean uiSetting = FormReader.getAllowUI() Если указано true (значение по умолчанию), апплет будет иметь «видимый» пользовательский интерфейс, если же указано false - пользовательский интерфейс будет «скрыт». Однако, поскольку для апплета всегда должны быть заданы ширина и высота (WIDTH и HEIGHT в теге APPLET), установка этого параметра в false недостаточна для создания "невидимого" апплета. Если параметр был задан, можно указать WIDTH=0 и HEIGHT=0, чтобы "скрыть" апплет. При наличии пользовательского интерфейса URL может быть введен в соответствующем поле интерфейса, а процесс выборки данных из формы может быть запущен нажатием кнопки Submit - это удобно при отладке. При отсутствии интерфейса URL должен быть задан, а процесс выборки таблицы начинается при старте апплета.
© InterTrust Co. Тел. 956-7928, 956-7929
180
Применение eSuite DevPack 1.0
Параметр и свойство Debug FormReader.setDebug(boolean setting) boolean setting = FormReader.getDebug() Если указано true, апплет выводит отладочные сообщения, если указано false (значение по умолчанию) - не выводит.
Методы abort и parse FormReader.abort() FormReader.parse() Метод abort() прерывает обработку текущей таблицы. В «пользовательском интерфейсе» это аналогично нажатию кнопки Cancel (см. Рис. 11.7). Метод parse() инициирует процесс обработки таблицы. В «пользовательском интерфейсе» это аналогично нажатию кнопки Read Data. Если вызов метода или нажатие кнопки происходят во время загрузки текущей таблицы, текущая операция загрузки прерывается и запускается новая. Пример 1. Приведенный фрагмент HTML-кода «минимально-необходим» для запуска апплета FormReader. HTML-документ, содержащий апплет, имеет URL http://main.inttrust.ru/eSuite.nsf/byKeys/0104-001?OpenDocument. Апплет при своей инициализации читает HTML-документ "../byKeys/01-04001?EditDocument" (этот же документ, но в «режиме редактирования») и публикует содержимое его единственной формы в InfoBus под стандартным именем «ReaderOutput». <APPLET NAME="formParse" CODEBASE="/eSuiteDP" CODE="lotus.htmlparse.FormReader" ARCHIVE="/eSuiteDP/jars/devpack_htmlparse_app.jar" WIDTH=450 HEIGHT=250> Пример 2. Фрагмент HTML-кода демонстрирует выборку данных формы из HTML-документа, загрузку информации из этой формы в InfoBus как элемента данных с интерфейсом ImmediateAccess с именем «formItem» и последующее помещение этого элемента данных в апплет - электронную таблицу eSuite. На Рис. 11.8 показано, как выглядит этот HTML-код в броузере. <APPLET NAME="formParse" CODEBASE="/eSuiteDP" CODE="lotus.htmlparse.FormReader" ARCHIVE="/eSuiteDP/jars/devpack_htmlparse_app.jar" WIDTH=0 HEIGHT=0>
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 181 <APPLET CODEBASE="/eSuiteDP" CODE="lotus.sheet.Sheet" ARCHIVE="/eSuiteDP/jars/devpack_sheet_app.jar" WIDTH=600 HEIGHT=100 NAME=sheet> <SCRIPT LANGUAGE="JavaScript"> Введите URL и номер публикуемой формы и нажмите OK.
Рис. 11.8 Внешний вид HTML-кода в броузере
© InterTrust Co. Тел. 956-7928, 956-7929
182
Применение eSuite DevPack 1.0
11.5.
Апплет CGI Gateway
Апплет CGI Gateway стандартно выполняет следующее:
• • • •
получает из InfoBus данные, которые необходимо передать CGI-программе; соединяется с сервером по URL CGI-программы; посылает данные CGI-программе и принимает возвращаемые CGI-программой данные; публикует возвращенные CGI-программой данные в InfoBus, делая их доступными другим апплетам. Документ в броузере HTTP-Сервер Апплет CGI Gateway InfoBus
InterNet
CGI-программа (CGI-скрипт, сервлет, http://host/dbase.nsf/ FormName?Create Document…)
Интерфейс пользователя
Рис. 11.9 Схема функционирования апплета CGI Gateway Для облегчения процесса отладки приложений апплет обеспечивает минимальный пользовательский интерфейс.
Рис. 11.10 Внешний вид «пользовательского интерфейса» апплета CGI Gateway Данные выбираются из InfoBus согласно описанию, обеспеченному через параметры апплета. Описание содержит имена элементов данных, получаемых из InfoBus, или, альтернативно, список самих данных.
Параметр inputType Определяет способ получения данных апплетом. Возможны три варианта "Direct", "NameValuePair" и "Value".
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 183
"Direct" подразумевает, что данные даются «непосредственно», т.е. значением параметра inputValue. "NameValuePair" означает, что данные должны быть получены из InfoBus, из элемента данных, имя которого задано параметром inputName. Этот элемент данных должен быть массивом (таблицей), в первом столбце которого содержатся имена, а в последующих столбцах - значения отправляемых на сервер данных. Если «этих последующих» столбцов несколько, данные из них перед отправкой на сервер «конкатенируются». "Value" указывает, что данные должны быть выбраны из InfoBus, из элемента данных, имя которого задано параметром inputName. При этом имя элемента данных определяет имя отправляемых на сервер данных, а его значение - значение отправляемых на сервер данных. Используйте "Value", если должно передаваться только одно значение. Если должен передаваться список значений, используйте "NameValuePair".
Параметр inputValue Задает сами данные, если был выбран вариант "Direct". Отсутствие параметра при inputType = "Direct" влечет сообщение об ошибке. Если же inputType = "NameValuePair" или "Value", напротив, сам факт наличия параметра влечет сообщение об ошибке.
Параметр inputName Имя входного элемента данных для апплета. Этот параметр необходим, если inputType = "NameValuePair" или "Value".
Параметр и свойство InputParameterString Gateway.setInputParameterString(String paramItems) String paramItems = Gateway.getInputParameterString() Задает параметризованную входную строку, содержащую имена фактических входных пунктов, отделенные друг от друга символом "%". Элементы этой строки считаются именами полей. Параметризованная строка используется как «шаблон» при передаче серверу. Пунктам, указанным в шаблоне, сопоставляются значения из элемента данных, определенного параметром InputType. Затем все передается на сервер. Апплет поддерживает CGI 1.1. В данной реализации обеспечен только метод POST, метод GET не поддерживается. Пока апплет способен передавать на сервер только данные MIMEтипа text/plain, однако эти данные по выбору могут быть URL-кодированы.
Параметр и свойство URL Gateway.setURL(String prgrmURL) String prgrmURL = Gateway.getURL() Задает URL CGI-программы, которая должна быть запущена HTTP-сервером. Необходим, если апплет не имеет «видимого» пользовательского интерфейса. Если же «видимый» интерфейс имеется, то URL можно ввести в текстовом поле аплета.
© InterTrust Co. Тел. 956-7928, 956-7929
184
Применение eSuite DevPack 1.0
Параметр и свойство URLEncode Gateway.setURLEncode(boolean setting) boolean setting = Gateway.getURLEncode() Если задано значение true, апплет будет выполнять URL-кодирование данных перед передачей их CGI-программе (MIME-тип отправляемых данных будет application/x-www-formurlencoded). URL-кодирование сводится к замене в данных пробелов, символов "/" и иных специальных символов, применение которых в URL не допускается, их 16-ричными эквивалентами. Например, дата рождения "11/05/73" будет представлена как "11%2F05%2F73". Без этого параметра данные передаются "как есть" (MIME-тип отправляемых данных будет text/plain). Ваш выбор, естественно, должен быть согласован с возможностями конкретной CGIпрограммы. Процесс установления соединения и обмен данными с серверам в «пользовательском интерфейсе» инициируется нажатием кнопки Submit. Этот процесс в апплете реализуется отдельным потоком - что позволяет асинхронно завершать этот поток. Например, если сервер или CGI-программа не отвечает, можно нажать кнопку Cancel.
Методы submit и cancelPost boolean Gateway.submit() Gateway.cancelPost() Метод submit() начинает операцию POST, только и если только все необходимые для этого данные уже получены. Когда операция запущена, метод блокируется до того момента, пока не будут приняты данные с сервера, или не произойдет разрыв соединения по таймауту. Если не было указано имя публикуемого в InfoBus элемента данных (параметром или свойством OutputItemName), используется имя "Gateway". Возвращаемое значение сигнализирует о приеме данных от CGI-программы. Метод cancelPost() принудительно завершает операцию POST, выполняемую апплетом. Данные, получаемые апплетом от CGI-программы, автоматически анализируются, публикуются «как текст» в InfoBus и, по выбору, в окне броузера, если они имеют MIME-тип text/plain или text/html. Другие же MIME-типы, возвращенные CGI-программой, помещаются в InfoBus как generic Object data (объект InfoBus-класса SimpleDataItem). Разработчику приложения, чтобы преобразовывать такие данные, придется написать свой InfoBusсовместимый апплет.
Параметр и свойство UILevel Gateway.setUILevel(int intType) int intType = Gateway.getUILevel() Тип пользовательского интерфейса. Может быть одним из следующих: "Full" (1) - полный: включает поле для ввода URL, кнопки Submit и Cancel, а также область сообщений о состоянии. используется по умолчанию. "Button" (2) - включает только кнопку Submit. В обоих уже рассмотренных случаях данные отправляются на сервер только после нажатия кнопки Submit. "Automatic" (3) - апплет не имеет пользовательского интерфейса, данные отправляются на сервер сразу после того, как они готовы. © InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 185
"Manual" (4) - апплет не имеет пользовательского интерфейса, но данные отправляются на сервер после того, как они готовы и «явно» вызван метод submit(). В этом случае игнорируется параметр Trigger и изменения, произошедшие в элементах данных, не влекут передачи данных на сервер.
Параметр и свойство Trigger Gateway.setTrigger(String itemName) String itemName = Gateway.getTrigger() Имя элемента данных, при появлении которого в InfoBus автоматически начинается операция POST.
Параметр и свойство ButtonLabel Gateway.setButtonLabel(String label) String label = Gateway.getButtonLabel() Текст на кнопке Submit.
Параметр и свойство Debug Gateway.setDebug(boolean setting) boolean setting = Gateway.getDebug() Значение true требует выводить отладочные сообщения в область сообщений о состоянии, значение false (по умолчанию) отменяет вывод отладочной информации. Данные, возвращенные сервером, публикуются в InfoBus или, по выбору, отображаются в окне броузера. Элементы данных публикуются в InfoBus методом writeObject. Ссылки на элементы данных сохраняются в hashtable. Если элемент данных не был ранее представлен в таблице, он регистрируется, и генерируется событие DATAAVAILABLE. Если же элемент данных уже имеется в таблице, заменяется его значение и генерируется событие DATACHANGED.
Параметр и свойство outputFormat Gateway.setoutputFormat(String dsFormat) String dsFormat = Gateway.getoutputFormat() В JAR-архивах getOutputFormat() и getOutputFormat() ! Задает MIME-тип данных, возвращаемых сервером (CGI-программой). Если задано значение "Infobus" (по умолчанию), «ответ сервера» разбирается на строки и публикуется в InfoBus (подразумевается, что эти данные имеют MIME-тип text/plain). Если задано значение "Browser", «ответ сервера» будет передан апплетом броузеру для отображения (подразумевается, что эти данные имеют MIME-тип text/html). Однако, если при
© InterTrust Co. Тел. 956-7928, 956-7929
186
Применение eSuite DevPack 1.0
этом броузер не поддерживает JavaScript, то «ответ сервера» будет опубликован в InfoBus (как в случае outputFormat = "Infobus"). Если возвращаемые сервером данные имеют MIME-тип, отличный от text/html или text/plain, «ответ сервера» публикуется в InfoBus как generic Object (объект InfoBus-класса SimpleDataItem). В этом случае другой апплет, ожидающий эти данные в InfoBus, должен сам преобразовать их в необходимый ему формат.
Параметр и свойство outputItemName Gateway.setOutputItemName(String itemName) String itemName = Gateway.getOutputItemName() Если outputFormat = "Infobus", параметр или свойство задает имя публикуемого в InfoBus элемента данных, который будет содержать данные, полученные от CGI-программы. По умолчанию "GatewayOutput". Если же outputFormat = "Browser", значение параметра или свойства игнорируются (за исключением случая, когда броузер не поддерживает JavaScript).
Параметр и свойство inputCharacterEncoding Gateway.setInputCharacterEncoding(String encoding) String encoding = Gateway.getInputCharacterEncoding() Кодировка символов в получаемом апплетом с сервера потоке данных.
Параметр и свойство outputCharacterEncoding Gateway.setOutputCharacterEncoding(String encoding) String encoding = Gateway.getOutputCharacterEncoding() Кодировка символов в отправляемом апплетом на сервер потоке данных. Пример 1. Приведенный ниже фрагмент HTML-кода демонстрирует работу апплета CGI Gateway «по варианту Value». Вариант Value подразумевает, что апплету посредством его параметров сообщены имена элементов данных из InfoBus, содержащих те данные, которые апплет должен передать на сервер. Это элементы данных с именами Name1, Name2 и Name3. Они создаются в функции doSubmit() методом publishStringToInfoBus() апплета ScriptHelper и имеют соответственно значения "Value 1", "Value 2" и "Value 3". В качестве CGI-программы используется агент WebQR (см. пример 2 в разделе 7.2) в базе данных Notes. Этот агент принимает передаваемые апплетом CGI Gateway данные и «отвечает» апплету подтверждением об их приеме. Данные, передаваемые апплетом (метод POST) агенту, агент извлекает из CGI-переменной Request_Content. После URL-декодирования они имеют вид "Name3= Value 3& Name2= Value 2& Name1= Value 1". Данные, принятые апплетом от агента (сгенерированный агентом HTMLкод), помещаются в InfoBus в элемент данных со стандартным именем GatewayOutput. Функция doSubmit() в отладочных целях выводит содержимое этого элемента данных в диалоговое окно, приведенное на Рис. 11.11. <SCRIPT LANGUAGE="JavaScript"> function doSubmit(n) { // Создаем в InfoBus три элемента данных ImmediateAccess document.ibBridge.publishStringToInfoBus("Name1", "Value 1");
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 187 document.ibBridge.publishStringToInfoBus("Name2", "Value 2"); document.ibBridge.publishStringToInfoBus("Name3", "Value 3"); // Передаем информацию на сервер и принимаем ответ сервера document.myGateway.submit(); // Визуально проверяем ответ сервера alert(document.ibBridge.readStringFromInfoBus("GatewayOutput")); }
<APPLET CODEBASE="/eSuiteDP" CODE="lotus.scripthelper.ScriptHelper" ARCHIVE="jars/devpack_chart_app.jar" NAME="ibBridge" WIDTH=1 HEIGHT=1> <APPLET NAME="myGateway" CODEBASE="/eSuiteDP" CODE="lotus.gateway.Gateway" ARCHIVE="/eSuiteDP/jars/devpack_gateway_app.jar" WIDTH=750 HEIGHT=200>
NAME="inputType1" NAME="inputName1" NAME="inputType2" NAME="inputName2" NAME="inputType3" NAME="inputName3"
VALUE="Value"> VALUE="Name1"> VALUE="Value"> VALUE="Name2"> VALUE="Value"> VALUE="Name3">
В отладочных целях апплет CGI Gateway имеет «видимый» пользовательский интерфейс, подобный приведенному на Рис. 11.10. Ниже дается информация из области сообщений о состоянии апплета CGI Gateway. Info: Info: Info: Info:
Waiting for data Data item found: Data item found: Data item found:
items. Name1 Name2 Name3
© InterTrust Co. Тел. 956-7928, 956-7929
188
Применение eSuite DevPack 1.0
Info: Info: Info: Info: Info: Info: Info: Info: Info: Info: Info: Info: Info: Info:
All data items have been found. submit() all data found; submitting... starting thread for posting... outputCharacterEncoding= Connecting to server... Writing to server =>>>Name3%3dValue+3%26Name2%3dValue+2%26Name1%3dValue+1<<< Reading from server... Connection content=com.ms.net.wininet.http.HttpInputStream@21d Content type=text/html Content length=466 Output format=Browser inputCharacterEncoding= WINDOWS1251 Writing string to browser, stream=java.io.BufferedReader@18e Writing string=>>> javascript:'
Request_Method=POST
Query_String=OpenAgent
Decoded Query_String=OpenAgent
Content_Type=application/x-www-form-urlencoded
Request_Content=Name3%3dValue+3%26Name2%3dValue+2%26Name1%3dValue+1
Decoded Request_Content=Name3=Value 3&Name2=Value 2&Name1=Value 1 '<<< Warning: Client does not support Javascript protocol MalformedURLException). Output sent to Infobus Info: Writing Object to Infobus, dataset=GatewayOutput Value=
Request_Method=POST
Query_String=OpenAgent
Decoded Query_String=OpenAgent
Content_Type=application/x-www-form-urlencoded
Request_Content=Name3%3dValue+3%26Name2%3dValue+2%26Name1%3dValue+1
Decoded Request_Content=Name3=Value 3&Name2=Value 2&Name1=Value 1 Info: Ready to send (readResponse)
Рис. 11.11 «Ответ» агента WebQR апплету CGI Gateway
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 189
11.6. Апплет SQL/JDBC Апплет SQL/JDBC используется для взаимодействия с СУБД. Он выполняет три важные функции:
• • •
чтение данных из баз данных; изменение данных в базах данных; публикация полученных данных в InfoBus, чтобы ими могли воспользоваться другие апплеты.
Байт-код апплета – lotus.jdbc.JDBCSources. Для работы апплета в броузер должен быть загружен один из JAR-архивов devpack_jdbc_app.jar или devpack_chart_sheet_jdbc_app.jar и CAB-архив devpack_jdbc_app.cab. Апплет SQL/JDBC использует механизм JDBC (Java DataBase Connections) для доступа к базам данных. Обычно этот апплет не виден пользователю, но для облегчения отладки содержит простой интерфейс. Один экземпляр апплета SQL/JDBC устанавливает соединение с одним источником данных. Для каждого из источников данных необходимо создать отдельный экземпляр апплета.
Параметр и свойство AllowUI boolean uiStatus = JDBCSource.getAllowUI() JDBCSource.setAllowUI(boolean uiStatus) Определяет, будет ли показан интерфейс пользователя, используемый для отладки.
Параметр и свойство AutoConnect boolean setting =JDBCSource.getAutoConnect() JDBCSource.setAutoConnect(boolean setting) Если значение равно true, то связь с источником данных будет установлена при загрузке апплета, в противном случае соединение необходимо будет инициировать вручную. Имя источника данных, имя пользователя и пароль должны быть определены в свойствах и параметрах апплета.
Параметр и свойство Autoload boolean setting =JDBCSource.getAutoload() JDBCSource.setAutoload(boolean setting) Если значение равно true, то JDBC драйвер будет загружен в момент старта апплета.
Параметр и свойство CharacterEncoding String type = JDBCSource.getCharacterEncoding() JDBCSource.setCharacterEncoding (String type)
© InterTrust Co. Тел. 956-7928, 956-7929
190
Применение eSuite DevPack 1.0
Определяет тип кодировки для символов. Используются стандартные значения для определения кодировок, например “CP1251” для кодовой страницы 1251 в Windows, “UTF8” для Standard UTF-8, “8859_1” для ISO Latin-1.
Параметр Command Задает один SQL-запрос для выборки данных (SELECT) или несколько SQL-запросов, разделенных точками с запятой “;” для изменения данных (INSERT, DELETE, UPDATE).
Параметр и свойство Database String dbIdentifier = JDBCSource.getDatabase() JDBCSource.setDatabase(String dbIdentifier) Задает имя источника данных, которое определяется в формате JDBC protocol:dbId:driverArguments. Protocol определяет протокол, по которому происходит обращение к источнику данных. Protocol всегда равен jdbc. dbId задает имя драйвера (например, db2, JdbcOdbc, oracle). driverArguments содержит сведения об источнике данных. Для каждого драйвера существует собственный метод именования источников данных.
Параметр и свойство Debug boolean setting = JDBCSource.getDebug() JDBCSource.setDebug(boolean setting) Если значение равно true, то апплет будет генерировать отладочные сообщения. Данный параметр имеет смысл, если AllowUI установлен в true, то есть интерфейс пользователя виден.
Параметр и свойство Driver String driverName = JDBCSource.getDriver() JDBCSource.setDriver(String driverName) Задает имя класса драйвера JDBC в формате Java. Например, COM.ibm.db2.jdbc.app.DB2Driver.
Параметр и свойство Host String hostName = JDBCSource.getHost() JDBCSource.setHost(String hostName) Задает имя компьютера в сети, на котором размещен источник данных. Переменная %HOST% в URL, будет заменена на значение заданное в Host.
Параметр и свойство Password
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 191
String dbPassword = JDBCSource.getPassword() JDBCSource.setPassword(String dbPassword) Определяет пароль для доступа к источнику данных, если он необходим.
Параметр и свойство Proxy String proxytName = JDBCSource.getProxy() JDBCSource.setProxy(String proxyName) Определяет прокси-сервер, используемый для соединения с источником данных. Значение proxyName задается в формате "host:port".
Параметр и свойство User String userName = JDBCSource.getUser() JDBCSource.setUser(String userName) Определяет имя пользователя, который получает доступа к источнику данных.
Параметр Retrievals Задает одну или несколько выборок данных из источников данных. Если выборок несколько, то они должны быть разделены точкой с запятой “;”. Каждая выборка должна быть конкретизирована в соответствующем теге . Например.
11.7. Апплеты InfoCenter и AppletContainer Апплет InfoCenter реализует интерфейс пользователя для изменения свойств других апплетов (например, цвет фона или шрифт) и выполнения операций (например, операции с буфером обмена, сохранение, печать). InfoCenter состоит из трех основных элементов:
• • •
Панель операций (action bar), на которой можно выбрать основные команды и некоторых из их наиболее часто используемых опций. Всплывающие окна (Quick Picks), появляющиеся при выборе опций команды. В них можно выбрать значение опции (например, цвет или способ выравнивания текста). Прочие панели, подобные диалоговым окнам, появляющиеся взаимосвязанных групп свойств или выполнении некоторых операций.
при
изменении
Можно настраивать InfoCenter для апплетов с помощью eSuite Template Builder. При этом создается файл настроек для InfoCenter (обычно тип файла ICC-*, где * определяет апплет). Для использования апплета с таким «нестандартным» InfoCenter нужно указать необходимый файл настроек - параметром или свойством InfoCenterProfileName апплета.
© InterTrust Co. Тел. 956-7928, 956-7929
192
Применение eSuite DevPack 1.0
Не следует пытаться включить тег <APPLET> для InfoCenter в HTML-код, поскольку механизм для отображения InfoCenter реализует апплет AppletContainer. В состав AppletContainer - «контейнера для других апплетов» - может входить до четырех апплетов (не считая InfoCenter). Каждый апплет в составе AppletContainer идентифицируется своим номером (нумерация с 0) и имеет свое имя экземпляра. Номера апплетов определяет порядок, в котором эти апплеты отображаются один относительно другого во фрейме AppletContainer. Значение параметра layoutStyle определяет расположение апплетов во фрейме. Например, если в состав AppletContainer входят апплеты applet0, applet1 и applet2, а layoutStyle = "TopToBottom" («сверху вниз»), applet0 появляется в верхней части фрейма, applet1 появляется ниже applet0 слева, и applet2 появляется ниже applet0 справа.
Параметр appletn Задает имя (файла байт-кода) n-того апплета в контейнере AppletContainer. Например, .
Параметр namen Задает имя экземпляра для n-того апплета в контейнере AppletContainer. Например, .
Свойство AppletIndex (только чтение) int index = AppletContainer.getAppletIndex(String name) По имени экземпляра апплета возвращает его номер.
Параметр appletName.PARAM Задает значение paramValue для параметра с именем PARAM в апплете с именем экземпляра appletName, содержащемся в AppletContainer. Например, третий тег
задает значение "mysheettemplate.html" для параметра fileName в апплете с именем экземпляра mySheet. Как следует из двух предшествующих тегов, это апплет lotus.sheet.Sheet, входящий в состав AppletContainer под номером 0.
Метод getContainedAppletCount int numOfApplets = AppletContainer.getContainedAppletCount() Возвращает количество апплетов, содержащихся в контейнере AppletContainer.
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 193
Метод findContainedAppletByIndex Applet = AppletContainer.findContainedAppletByIndex(int index) Возвращает ссылку на объект, связанный с апплетом, содержащимся в объекте AppletContainer под номером index.
Метод findContainedApplet Applet = AppletContainer.findContainedApplet(String name) Возвращает ссылку на объект, связанный с апплетом, содержащимся в объекте AppletContainer под именем экземпляра name.
Параметр и свойство infoCenterVisible AppletContainer.setInfoCenterVisible(boolean visible) boolean visible = AppletContainer.getInfoCenterVisible() Если значение равно true, то апплет InfoCenter будет «видимым», если false - «невидимым». Значение по умолчанию false.
Параметр и свойство compactInfoCenter AppletContainer.setCompactInfoCenter(boolean isCIC) boolean isCIC = AppletContainer.getCompactInfoCenter() Если значение равно true, «нижняя строка» в InfoCenter не отображается, если false отображается. «Компактный» InfoCenter занимает столько же места и имеет те же функциональные возможности, что и «некомпактный». Отличие лишь в том, что в своем «штатном» состоянии «компактный» InfoCenter менее информационно загружен.
Рис. 11.12 «Некомпактный» InfoCenter
Рис. 11.13 «Компактный» InfoCenter
Параметр height Задает в пикселях высоту области, занимаемой фреймом AppletContainer во время выполнения. Когда AppletContainer содержит более чем один апплет, значения высот областей содержащихся в нем апплетов, располагающихся один под другим, в сумме не должны превышать значения этого параметра.
Параметр width
© InterTrust Co. Тел. 956-7928, 956-7929
194
Применение eSuite DevPack 1.0
Задает в пикселях ширину области, занимаемой фреймом AppletContainer во время выполнения. Когда AppletContainer содержит более чем один апплет, значения «ширин» областей содержащихся в нем апплетов, располагающихся один вслед за другим по горизонтали, в сумме не должны превышать значения этого параметра.
Параметр и свойство layoutStyle AppletContainer.setLayoutStyle(String layoutStyle) String layoutStyle = AppletContainer.getLayoutStyle() Определяет стиль размещения апплетов, входящих в состав AppletContainer, в области, отведенной фрейму AppletContainer. Возможные значения layoutStyle и соответствующие им примеры размещения апплетов в области AppletContainer приведены в следующей таблице. LayoutStyle
Пример размещения в случае 2-х, 3-х и 4-х апплетов
TopToBottom (по умолчанию)
BottomToTop
LeftToRight
RightToLeft
Параметр propertyBagn Имя файла, в котором заданы значения свойств для апплета с номером n, содержащегося в AppletContainer. Файл - «чемодан свойств» - должен располагаться в том же каталоге, что и HTMLстраница, содержащая апплет AppletContainer. Это текстовый ASCII-файл, содержащий список пар "имяСвойства=значениеСвойства". Например, для апплета Sheet мог быть подготовлен файл ehv.pbg, содержащий значения трех свойств: editline=false
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 195 hscroll=false vscroll=false
При этом HTML-код для апплета AppletContainer, содержащего аппплет Sheet, мог бы выглядеть следующим образом:
11.8. Апплет Chart - построитель графиков и диаграмм Апплет Chart применяется для графического представления данных. Он позволяет:
•
• •
создавать вертикальные или горизонтальные двухмерные («плоские») или трехмерные (проекция с изменением углов поворота) диаграммы и графики - прямоугольные, прямоугольные «с накоплением», круговые, «множественные круговые», «линейчатые» и др.; применять многострочные с выбором шрифта, выравнивания и цвета заголовки, сноски и «легенды», выбирать фоновый цвет или фоновое изображение для области изображения; сохранять и впоследствии использовать «стили» диаграмм. Заголовок (Title) Область изображения (Plot)
«Легенда» (Legend)
«Серии» (Series) Ось X (X-axis) Сноска (Note) Ось Y (Y-axis)
Рис. 11.14 Основные элементы («вложенные» объекты) диаграммы (объекта Chart) Байт-код апплета - Chart.class. Для работы апплета в броузер должен быть загружен один из JAR-архивов devpack_chart_app.jar, devpack_chart_sheet_jdbc_app.jar, devpack_chart_lite.jar или три CAB-архива devpack_infobus.cab, devpack_shared.cab и devpack_chart_app.cab.
11.8.1. Методы для получения ссылок на «вложенные» объекты Логически объект Chart «как контейнер содержит в себе» следующие объекты:
• •
Plot - представляет область изображения и может быть получен методом findPlot() объекта Chart; TextElement - представляет текст, содержащийся в заголовке, «легенде», сноске или наименованиях осей и может быть получен соответственно методами findTitle(), findNote, findLegend(), findXAxisTitle() и findYAxisTitle() объекта Chart;
© InterTrust Co. Тел. 956-7928, 956-7929
196
• •
Применение eSuite DevPack 1.0
Axis - представляет ось (линия оси, масштабы, метки…) и может быть получен методами findXAxis() или findYAxis() объекта Chart; Series - представляет одну «серию» (ее данные, способ отображения, цветовое оформление…) и может быть получен методом findSeries() объекта Chart.
Метод findPlot lotus.chart.Plot plot = document.Chart.findPlot() Возвращает ссылку на объект Plot, содержащийся в объекте Chart.
Метод findTitle lotus.chart.TextElement title = document.Chart.findTitle() Возвращает ссылку на объект класса TextElement, представляющий текст, содержащийся в заголовке объекта Chart.
Метод findLegend lotus.chart.TextElement legend = document.Chart.findLegend() Возвращает ссылку на объект класса TextElement, представляющий текст, содержащийся в «легенде» объекта Chart.
Метод findNote lotus.chart.TextElement note = document.Chart.findNote() Возвращает ссылку на объект класса TextElement, представляющий текст, содержащийся в сноске объекта Chart.
Методы findXAxisTitle и findYAxisTitle lotus.chart.TextElement xAxisTitle = document.Chart.findXAxisTitle() lotus.chart.TextElement yAxisTitle = document.Chart.findYAxisTitle() Возвращает ссылку на объект класса TextElement, представляющий текст, содержащийся в названии оси X или Y объекта Chart.
Методы findXAxis и findYAxis lotus.chart.Axis xAxis = document.Chart.findXAxis() lotus.chart.Axis yAxis = document.Chart.findYAxis() Возвращает ссылку на объект класса Axis, представляющий ось X или Y объекта Chart.
Метод findSeries lotus.chart.Series series = document.Chart.findSeries(int seriesID) Возвращает ссылку на объект класса Series, представляющий серию с номером seriesID объекта Chart. Нумерация серий начинается «с нуля». Если указанный номер серии меньше 0, возвращается null.
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 197
Свойство SeriesCount int numSeries = document.Chart.getSeriesCount() Текущее количество серий в диаграмме. Обычно используется, чтобы затем в цикле получать методом findSeries() ссылку на каждый объект Series в объекте Chart.
Метод createSeries Series newSeries = Chart.createSeries() Возвращает ссылку на новый «пустой» объект класса Series. Если перед вызовом метода в объекте Chart имелось n серий, возвращаемый объект Series будет представлять серию с номером n+1. Этот объект можно «заполнить» данными, например, воспользовавшись его свойством setData().
11.8.2. Параметры, методы и свойства объекта Chart Параметр и свойство AppletLocale Chart.setAppletLocale(String locale) String locale = Chart.getAppletLocale() Код языка и страны. Например, "ru_RU" (русский язык/Россия) или "en_GB" (английский язык/Великобритания).
Параметр и свойство CharacterEncoding Chart.setCharacterEncoding(String module) String module = Chart.getCharacterEncoding() Модуль из JDK 1.1.x, используемый апплетом при перекодировании символов. Например, "Cp1251", "KOI8_R" или "MacCyrillic".
Параметр и свойство UserInterfaceLanguage Chart.setUserInterfaceLanguage(String languageCode) String languageCode = Chart.getUserInterfaceLanguage() Двухсимвольный код языка, применяемого в пользовательском интерфейсе апплета. Например, "ru" или "en".
Параметр и свойство UserTimeZone Chart.setUserTimeZone(String timeZone) String timeZone = Chart.getUserTimeZone() Временная зона, в которой работает пользователь. Может задаваться одним из следующих обозначений JDK 1.1.x: "GMT", "ECT", "EET", "ART", "EAT", "MET", "NET", "PLT", "IST",
© InterTrust Co. Тел. 956-7928, 956-7929
198
Применение eSuite DevPack 1.0
"BST", "VST", "CCT", "JST", "ACT", "AET", "SST", "NST", "MIT", "HST", "AST", "PST", "PNT", "MST", "CST", "EST", "IET", "PRT", "CNT", "AGT", "BET".
Параметр height Задает в пикселях высоту области, которую апплет Chart занимает во время выполнения. Когда апплет AppletContainer обслуживает более чем один апплет, то значения высот для обслуживаемых им апплетов, которые вы хотите иметь расположенными один над другим, в сумме должны быть не менее значения параметра height апплета AppletContainer.
Параметр width Задает в пикселях ширину области, которую апплет Chart занимает во время выполнения. Когда апплет AppletContainer обслуживает более чем один апплет, то значения «ширин» для обслуживаемых им апплетов, которые вы хотите иметь расположенными один за другим, в сумме должны быть не менее значения параметра width апплета AppletContainer.
Параметр dataInputItemName и свойства DataInputItemName и DataInputIndirectItemName myObject.setDataInputItemName(String strSource) String strSource = myObject.getDataInputItemName() Chart.setDataInputIndirectItemName(String strSource) String strSource = Chart.getDataInputIndirectItemName() Параметр и свойство DataInputIndirectItemName относятся к объекту Chart, свойство DataInputItemName - к объекту Chart или содержащемуся в нем объекту Series. Параметр задает имя элемента данных, который апплет (объект Chart) должен получить из InfoBus и отобразить на диаграмме. Возможны два варианта. Если задано «непосредственно имя», например, "DataItemName", то апплет рассматривает его как имя двумерного элемента данных с интерфейсом ArrayAccess, RowsetAccess или MinimalMap, получает этот элемент данных из InfoBus и отображает содержащиеся в нем данные. Если заданное имя начинается символом «%», например, "%dataItemName", то апплет рассматривает "dataItemName" как имя элемента данных с интерфейсом ImmediateAccess или ArrayAccess, который должен содержать, в случае ArrayAccess «в первой ячейке», имя элемента данных с интерфейсом ArrayAccess, RowsetAccess или MinimalMap, получает это имя из InfoBus, затем получает из InfoBus соответствующий элемент данных и отображает его данные. По умолчанию в качестве значения параметра используется имя апплета (из атрибута NAME в теге <APPLET>). Свойство DataInputItemName аналогично использованию параметра в варианте «непосредственно имя» и применимо как к объекту Chart, так и к содержащемуся в нем объекту Series. Свойство DataInputIndirectItemName аналогично использованию параметра со значением, начинающимся символом «%» и применимо к объекту Chart. После изменения значения этих свойств для «перерисовки» данных на диаграмме необходимо вызвать метод refresh().
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 199
Параметр legends и свойство LegendItemName Chart.setLegendItemName(String strSource) String strSource = Chart.getLegendItemName() Определяет данные для «легенды». Параметр может задаваться в двух вариантах:
• •
string1,string2,. . .,stringN - перечисленные через запятую названия в «легенде», в порядке «сверху вниз»; %strSource , где strSource - имя одномерного элемента данных с интерфейсом ArrayAccess, содержащего список названий в «легенде».
Свойство, подобно второму варианту параметра, дает имя одномерного элемента данных с интерфейсом ArrayAccess, содержащего список названий в «легенде». После изменения значения свойства для «перерисовки» данных на диаграмме необходимо вызвать метод refresh().
Параметры note и title Текст или источник текста сноски (note) или заголовка (title) диаграммы. Если первый символ в строке string не «%», то string должна содержать непосредственно текст для сноски или заголовка. Вариант %string задает имя элемента данных (string) с интерфейсом ImmediateAccess или ArrayAccess, данные которого, в случае ArrayAccess в первой ячейке, содержат текст сноски или заголовка.
Параметр xAxisLabels и свойство XAxisLabelsItemName Chart.setXAxisLabelsItemName(String strSource) String strSource = Chart.getXAxisLabelsItemName() «Метки» отсчетов на оси X. Параметр может задаваться в двух вариантах:
• •
string1,string2,. . .,stringN - перечисленные через запятую метки отсчетов, по оси в порядке слева направо; %strSource , где strSource - имя одномерного элемента данных с интерфейсом ArrayAccess, содержащего список меток отсчетов.
Свойство, подобно второму варианту параметра, дает имя одномерного элемента данных с интерфейсом ArrayAccess, содержащего список меток отсчетов. После изменения значения свойства для «перерисовки» данных на диаграмме необходимо вызвать метод refresh().
Параметр и свойство Perspective Chart.setPerspective(String dims) String dims = Chart.getPerspective()
© InterTrust Co. Тел. 956-7928, 956-7929
200
Применение eSuite DevPack 1.0
Если задано значение "3D", диаграмма должна быть «трехмерной», если "2D" «двухмерной». По умолчанию принимается "3D".
Параметр и свойство Elevation Chart.setElevation(double angle) double angle = Chart.getElevation() Угол (в градусах, от 0 до 90), на который «трехмерная» диаграмма должна быть повернута вокруг горизонтальной оси, «сверху вниз». Значение по умолчанию - 15. Если Perspective = "2D" (двухмерная диаграмма), то по умолчанию Elevation и Rotation устанавливаются равными 0. Если Perspective = "3D", то по умолчанию Elevation устанавливается равным 15, а Rotation равным 20. Наоборот, если Elevation и Rotation установлены равными 0, то по умолчанию Perspective принимается равным "2D".
Параметр и свойство Rotation Chart.setRotation(double angle) double angle = Chart.getRotation() Угол (в градусах, от 0 до 90), на который «трехмерная» диаграмма должна быть повернута вокруг вертикальной оси, «слева направо». Значение по умолчанию - 20. Если Perspective = "2D" (двухмерная диаграмма), то по умолчанию Elevation и Rotation устанавливаются равными 0. Если Perspective = "3D", то по умолчанию Elevation устанавливается равным 15, а Rotation равным 20. Наоборот, если Elevation и Rotation установлены равными 0, то по умолчанию Perspective принимается равным "2D".
Параметр и свойство PlotLayout Chart.setPlotLayout(string pStyle) string pStyle = Chart.getPlotLayout() Стиль области изображения диаграммы: "vertical" - вертикальная (значение по умолчанию) - данные изображаются вертикальными полосами, "horizontal" - горизонтальная - данные изображаются горизонтальными полосами, "pie" - круговая - данные изображаются секторами круга.
Параметр и свойство ParseDirection Chart.setParseDirection(String pDirection) String pDirection = Chart.getParseDirection() Данные, которые апплет получает из источника данных, можно представлять себе как матрицу. По умолчанию диаграмма строится по этой матрице «в таком направлении», которое минимизирует количество серий. Например, если в источнике данных содержится «матрица 3 строки x 4 столбца», диаграмма строится по строкам - в 3 серии по 4 элемента в каждой из серий. Как только апплет, обрабатывая первый источник данных, «выбрал» направление построения диаграммы по умолчанию, он «будет применять» это направление и ко всем последующим источникам данных. Вы же можете изменить это направление, используя
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 201
параметр или свойство ParseDirection. Возможные значения: "column" - по столбцам, и "row" по строкам.
Параметр и свойство SeriesLayout Chart.setSeriesLayout(String sLayout) String sLayout = Chart.getSeriesLayout() Расположение «полос», отображающих данные серии, относительно друг друга. Возможные варианты: "behind" (значение по умолчанию) - «полосы серии» отображаются одна позади другой, "beside" - «полосы серии» располагаются одна около другой, "stacked" - «с накоплением» («полосы серии» располагаются «в столбик» одна над другой, см. Рис. 11.16). Игнорируется для круговой диаграммы.
Параметр и свойство PieMultiple Chart.setPieMultiple(boolean isMultiple) boolean isMultiple = Chart.getPieMultiple() Для круговой диаграммы при значении true данные из каждой серии данных изображаются на отдельном (этой серии) «круге», при значении false изображается только один «круг», представляющий данные из первой серии. Значение по умолчанию true.
Параметр и свойство PieSliceDirection Chart.setPieSliceDirection(String direction) String direction = Chart.getPieSliceDirection() Направление, в котором рисуются секторы на круговой диаграмме: "clockwise" - по часовой стрелке, "counter-clockwise" или "counterclockwise" (по умолчанию) - против часовой.
Параметр и свойство backgroundColor myObject.setBackgroundColor(java.awt.Color fColor) java.awt.Color fColor = myObject.getBackgroundColor() Параметр определяет цвет фона для каждого объекта в составе объекта Chart, например, «легенды», области изображения (plot) и серий данных. В качестве значения параметра могут задаваться названия цветов: "aqua", "black", "blue", "cyan", "darkGray", "fuchsia", "gray", "green", "grey", "lightGray" (значение по умолчанию), "lime", "magenta", "maroon", "navy", "olive", "orange", "pink", "purple", "red", "silver", "teal", "white", "yellow", или «строковые шестнадцатеричные RGB-значения» цветов, например "FF00FF". Для задания цвета фона конкретного объекта диаграммы необходимо использовать подобный параметр для этого объекта. Свойство определяет цвет фона для диаграммы (объект Chart), серии данных (объект Series) или области изображения (объект Plot). Значение по умолчанию Color.lightGray. В качестве аргумента и возвращаемого значения свойства используется объект класса java.awt.Color, а для его создания в JavaScript может применяться метод createColor() апплета ScriptHelper.
© InterTrust Co. Тел. 956-7928, 956-7929
202
Применение eSuite DevPack 1.0
Как параметр, так и свойство имеют смысл только тогда, когда для соответствующего объекта свойство BackgroundTransparent равно false.
Параметры legendBackgroundColor, noteBackgroundColor и titleBackgroundColor Цвет фона для «легенды» (legend), сноски (note) или заголовка (title). Задается названием или RGB- значением цвета.
Параметр и свойство BackgroundTransparent myObject.setBackgroundTransparent(boolean isTransparent) boolean isTransparent = myObject.getBackgroundTransparent() Если задано значение true, будет установлен «прозрачный» режим фона, если false «сплошной». Параметр относится ко всему объекту Chart, включая содержащиеся в нем объекты. Свойство применяется к конкретному объекту: Chart, Series, Plot и TextElement (заголовок, «легенда», сноска, наименования осей).
Параметры legendBackgroundTransparent, noteBackgroundTransparent и titleBackgroundTransparent Режим фона для «легенды» (legend), сноски (note) или заголовка (title): true (по умолчанию) - «прозрачный» (transparent), false - «сплошной» (solid).
Параметр и свойство BackgroundImageName Chart.setBackgroundImageName(String URL) String URL = Chart.getBackgroundImageName() Фоновое изображение для окна апплета: URL файла в формате GIF.
Свойство BackgroundImage Chart.setBackgroundImage(jawa.awt.Image theImage) jawa.awt.Image theImage = Chart.getBackgroundImage() Объект java.awt.Image, используемый в качестве фонового изображения для окна апплета.
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 203
Параметр и свойство backgroundImageOptions Chart.setBackgroundImageOptions(String format) String format = Chart.getBackgroundImageOptions() Способ вывода фонового изображения в окне апплета. Может быть одним из следующих: "scaled" - изображение масштабируется в размеры окна апплета, "Unscaled" - изображение выводится в окно апплета без масштабирования, в натуральную величину, "tiled" - изображение выводится в натуральную величину и «мозаикой» заполняет все окно апплета.
Параметр и свойство LegendVisible Chart.setLegendVisible(boolean isVisible) boolean isVisible = Chart.getLegendVisible() При значении true (по умолчанию) «легенда» отображается, при значении false она не видима.
Параметр и свойство NoteVisible Chart.setNoteVisible(boolean isVisible) boolean isVisible = Chart.getNoteVisible() Если значение равно true (по умолчанию), сноска «отображается», иначе (false) - нет.
Параметр и свойство TitleVisible myObject.setTitleVisible(boolean isVisible) boolean isVisible = myObject.getTitleVisible() Если значение равно true, заголовок «отображается», иначе (false) - нет. Параметр относится к заголовку диаграммы (title), свойство же может применяться как к объекту Chart (как заголовок диаграммы), так и к объекту Axis (как название оси). По умолчанию заголовок диаграммы отображается, а название оси - нет.
Параметр и свойство PieLabelsVisible Chart.setPieLabelsVisible(boolean isVisible) boolean isVisible = Chart.getPieLabelsVisible() При значении true (по умолчанию) на секторах круговой диаграммы должны отображаться метки отсчетов, при значении false - не должны.
Параметр legendPosition
© InterTrust Co. Тел. 956-7928, 956-7929
204
Применение eSuite DevPack 1.0
Местоположение «легенды» на диаграмме: east (по умолчанию) - справа от области изображения («восточнее»), south - под областью изображения («южнее»).
Свойство Position ChartElement.setPosition(String position) String position = ChartElement.getPosition() Применимо только к объекту legend. Определяет местоположение «легенды» на диаграмме: "east" - справа от области изображения («восточнее»), "south" - ниже области изображения («южнее»).
Параметр и свойство XAxisLabelsPosition Chart.setXAxisLabelsPosition(String position) String position = Chart.getXAxisLabelsPosition() Для «вертикально-ориентированной» диаграммы расположение меток отсчетов на оси X: "Beside" - на одной линии, "Stagger" - поочередно на двух линиях, "Bestfit" (значение по умолчанию) - лучшее «по мнению апплета» расположение.
Параметры noteAlignment и titleAlignment Выравнивание для текста в сноске (note) или заголовке (title): left (по умолчанию) - по левому краю, center - «центрирование», right - по правому краю.
Параметры legendBorderVisible, noteBorderVisible и titleBorderVisible Отображается ли бордюр «легенды» (legend), сноски (note) или заголовка (title): true (по умолчанию) - да, false - нет.
Свойство BorderColor myObject.setBorderColor(java.awt.Color eColor) java.awt.Color eColor = myObject.getBorderColor() Цвет серии данных (для объекта Series) или бордюра диаграммы (для объекта Plot). По умолчанию Color.black.
Параметры legendBorderLineColor, noteBorderLineColor и titleBorderLineColor
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 205
Цвет бордюра для «легенды» (legend), сноски (note) или заголовка (title). Задается названием или RGB- значением цвета.
Свойство BorderLineWidth myObject.setBorderLineWidth(integer lWidth) integer lWidth = myObject.getBorderLineWidth() Толщина линий, образующих бордюр объектов Series или Plot. Допустимы следующие значения: 0 - толщиной в один пиксель (по умолчанию), 1 - «очень тонкая», 2 - тонкая, 3 «толще тонкой», 4 - средней толщины, 5 - «толще средней толщины», 6 - «толстая», 7 - «более толстая», 8 - «очень толстая».
Свойство LineWidth myObject.setLineWidth(integer width) integer width = myObject.getLineWidth() Толщина линии, изображающей ось объекта Axis или «соединительную линию» между отсчетами объекта Series на двумерной линейчатой диаграмме. Допустимы те же значения, что и для свойства BorderLineWidth.
Параметры legendBorderLineWidth, noteBorderLineWidth и titleBorderLineWidth Толщина линий, образующих бордюр «легенды» (legend), сноски (note) или заголовка (title). Значение lWidth может быть одним из следующих: onepixel - толщиной в один пиксель (по умолчанию), verythin - «очень тонкая», thin - тонкая, moderatelythin - «умеренно тонкая, толще тонкой», medium - средней толщины, moderatelythick - «умеренно толстая, толще средней толщины», thick - «толстая», verythick - «более толстая», extremelythick - «очень толстая».
Параметр и свойство TextColor myObject.setTextColor(java.awt.Color tColor) java.awt.Color tColor = myObject.getTextColor() Параметр назначает цвет текста во всех «текстосодержащих» объектах диаграммы, например, заголовке, сноске, «легенде». В качестве значения параметра могут задаваться названия цветов: "aqua", "black" (значение по умолчанию), "blue", "cyan", "darkGray", "fuchsia", "gray", "green", "grey", "lightGray", "lime", "magenta", "maroon", "navy", "olive", "orange", "pink", "purple", "red", "silver", "teal", "white", "yellow", или «строковые шестнадцатеричные RGBзначения» цветов, например "FF00FF". Для задания цвета текста конкретного объекта диаграммы необходимо использовать подобный параметр для этого объекта. Свойство определяет цвет текста для конкретного объекта: серии данных (объект Series), «текстосодержащего» элемента (объект TextElement) или названий осей (объект Axis). Значение по умолчанию Color.black. В качестве аргумента и возвращаемого значения свойства используется объект класса java.awt.Color, а для его создания в JavaScript может применяться метод createColor() апплета ScriptHelper.
© InterTrust Co. Тел. 956-7928, 956-7929
206
Применение eSuite DevPack 1.0
Параметры legendTextColor, noteTextColor и TitleTextColor Цвет текста в «легенде» (legend), сноске (note) или заголовке (Title). Задается названием или RGB- значением цвета.
Параметр и свойство Font myObject.setFont(jawa.awt.Font font) jawa.awt.Font font = myObject.getFont() Параметр задает имя, размер и стиль шрифта для всего объекта Chart. Значение fName может быть одним из следующих: helvetica, timesroman (по умолчанию), courier, dialog или zapfdingbats. Размер шрифта задает fSize (число). Стиль fStyle может быть PLAIN (по умолчанию), BOLD, ITALIC или BOLD|ITALIC. Свойство же применяется к объектам Series, TextElement или Axis и использует для определения шрифта объект jawa.awt.Font. После изменения значения свойства для объекта Chart следует вызывать метод refresh().
Свойство FontName Chart.setFontName(String fName) String fName = Chart.getFontName() Название шрифта, применяемого для вывода текста в объектах Series, TextElement и Axis. После изменения значения свойства для диаграммы следует вызывать метод refresh().
Свойство FontSize Chart.setFontSize(integer fSize) integer fSize = Chart.getFontSize() Размер шрифта в пунктах для текста в объектах Series, TextElement и Axis. Значение по умолчанию 12.
Свойство Bold myObject.setBold(boolean isBold) boolean isBold = myObject.getBold() Применяется к объектам Series, TextElement и Axis. При значении true текст отображается как «жирный», при значении false (по умолчанию) - как «обычный».
Свойство Italic myObject.setItalic(boolean isItalic) boolean isItalic = myObject.getItalic() При значении true текст в объектах Series, TextElement или Axis выводится курсивом, при значении false (по умолчанию) - «обычным начертанием». © InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 207
Параметры и свойства LegendFont, NoteFont и TitleFont Chart.setLegendFont(java.awt.Font font) java.awt.Font font = Chart.getLegendFont() Chart.setNoteFont(java.awt.Font font) java.awt.Font font = Chart.getNoteFont() Chart.setTitleFont(java.awt.Font font) java.awt.Font font = Chart.getTitleFont() Шрифт, используемый для вывода текста «легенды» (legend), сноски (note) или заголовка (title). Параметр задает название, размер и стиль шрифта для текста. Значения fName, fSize, fStyle такие же, как для параметра font. В свойстве для определения шрифта применяется объект класса java.awt.Font. После изменения значения свойства для диаграммы следует вызвать метод redraw().
Метод setRefreshEnabled Chart.setRefreshEnabled(boolean isEnabled) Вызов метода со значением true «включает» режим автоматической «перерисовки» диаграммы при изменении любого из ее свойств, а со значением false - «выключает». По умолчанию режим автоматической «перерисовки» выключен, поэтому после изменения свойств диаграммы для ее «перерисовки» апплетом приходится явно вызывать метод refresh().
Метод isRefreshEnabled isEnabled = Chart.isRefreshEnabled() Возвращает true, если режим автоматической «перерисовки» диаграммы включен, или false, если нет.
Метод refresh Chart.refresh() Вынуждает апплет «перерисовать» диаграмму.
Метод newDocument boolean success = Chart.newDocument(String templateURL, boolean promptToSave) Загружает в апплет документ-шаблон, созданный в eSuite Template Builder (обычно тип файла ECHART), или пустой документ-шаблон. Аргумент templateURL задает URL загружаемого документа. Он может быть абсолютным или относительным (относительно URL документа, содержащего апплет). Если templateURL = null, загружается пустой документ. Если promptToSave равен true, то если текущий документ апплета был изменен, пользователю перед загрузкой нового документа будет выдано диалоговое окно с запросом о сохранении текущего документа. Если же promptToSave равен false, то если запрос о сохранении не выдается и измененный текущий документ не сохраняется. Метод возвращает true, если документ был успешно загружен, или false, если не был или пользователь нажал кнопку Cancel в окне запроса о сохранении текущего. © InterTrust Co. Тел. 956-7928, 956-7929
208
Применение eSuite DevPack 1.0
Свойство getDocumentName String URL = Chart.getDocumentName() Возвращает полный URL текущего документа-шаблона.
Метод openDocument boolean success = Chart.openDocument(String URL, boolean promptToSave) Открывает в апплете документ-шаблон, URL которого задан в строке URL. Если аргумент promptToSave равен true, а пользователь выполнил изменения в документе, то при попытке закрыть документ появится диалоговое окно с запросом о сохранении документа или отказе от изменений. Если promptToSave равен false, такое диалоговое окно не появляется и документ не сохраняется. Возвращается true, если документ был успешно открыт, или false, если документ не удалось загрузить или пользователь выбрал Cancel в запросе о сохранении документа.
Метод openDocumentFromStream boolean success = Chart.openDocumentFromStream(java.io.DataInput inputStream, boolean promptToSave) Аналогичен методу openDocument, но документ-шаблон загружается из потока ввода данных (объекта класса java.io.DataInput) и применяется формат по умолчанию. Подробности в описании апплета ScriptHelper.
Метод isChanged boolean changed = Chart.isChanged() Возвращает true, если в документ-шаблон были внесены изменения, и они могут быть потеряны, если документ не будет сохранен, или false, если никаких изменений не было. Метод saveDocument boolean success = Chart.saveDocument(String URL) Сохраняет документ-шаблон по текущему (если URL == null) или по указанному URL. Если расширение файла, заданное в строке URL, не распознается апплетом, документ сохраняется в формате по умолчанию. Возвращает true, если документ был успешно сохранен, или false, если нет.
Метод saveDocumentToStream boolean success = Chart.saveDocumentToStream(java.io.DataOutput outputStream) Аналогично предыдущему, но документ-шаблон сохраняется в потоке ввода данных (объекте класса java.io.DataOutput). Используется формат по умолчанию. Подробности в описании апплета ScriptHelper.
Параметр и свойство InfoCenterProfileName Chart.setInfoCenterProfileName(String fileName) String fileName = Chart.getInfoCenterProfileName()
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 209
URL файла, созданного в eSuite Template Builder и содержащего настройки для InfoCenter. Файл должен соответствовать апплету (обычно тип файла ICC-ECHART) и должен располагаться или в каталоге, в котором находится содержащий апплет документ, или задаваться URL относительно документа, содержащего апплет.
11.8.3. Свойства объекта Plot и соответствующие им параметры Объект Plot имеет свойства BackgroundTransparent, BackgroundColor, BorderColor, BorderLineWidth и Visible. Все они, кроме свойства Visible, уже были рассмотрены выше, а потому в данном разделе даются только параметры, соответствующие этим свойствам.
Параметр plotBackgroundTransparent и свойство BackgroundTransparent Если задано true, фон области изображения диаграммы прозрачный (transparent), если false (по умолчанию) - сплошной (solid).
Параметр plotBackgroundColor и свойство BackgroundColor Фоновый цвет области изображения диаграммы. Игнорируется, если фон области изображения прозрачный (transparent). Задается названием цвета или «шестнадцатеричным» RGB-значением наподобие "FF00FF".
Параметр plotBorderLineColor и свойство BorderColor Цвет линий, образующих бордюр области изображения диаграммы. Задается названием цвета или «шестнадцатеричным» RGB-значением наподобие "FF00FF".
Параметр plotBorderLineWidth и свойство BorderLineWidth Толщина линий, образующих бордюр области изображения диаграммы. Значение lWidth может быть одним из следующих: onepixel - толщиной в один пиксель (по умолчанию), verythin - «очень тонкая», thin - тонкая, moderatelythin - «умеренно тонкая, толще тонкой», medium средней толщины, moderatelythick - «умеренно толстая, толще средней толщины», thick «толстая», verythick - «более толстая», extremelythick - «очень толстая».
Параметр plotBorderVisible Если задано true (по умолчанию), бордюр области изображения «видим», если false - не видим.
Cвойство Visible myObject.setVisible(boolean isVisible) boolean isVisible = myObject.getVisible() Область изображения «видима» при значении true (по умолчанию), и не отображается при значении false.
© InterTrust Co. Тел. 956-7928, 956-7929
210
Применение eSuite DevPack 1.0
Кроме того, это свойство применяется к конкретной серии.
11.8.4. Свойства объекта TextElement Кроме перечисленных в данном разделе, объект TextElement имеет рассмотренные выше свойства TextColor, Font, FontName, FontSize, Bold, Italic.
Свойство TextItemName TextElement.setTextItemName(String dataItem) String dataItem = TextElement.getTextItemName() Имя элемента данных с интерфейсом ImmediateAccess или ArrayAccess, который должен содержать, в случае ArrayAccess «в первой ячейке», имя элемента данных, содержащего текст для объекта TextElement, представляющего заголовок или сноску, но не «легенду».
Свойство Text TextElement.setText(String str) String str = TextElement.getText() Текст для объекта TextElement, представляющего заголовок, сноску или название оси, но не «легенду».
Свойство BorderVisible TextElement.setBorderVisible(boolean isVisible) boolean isVisible = TextElement.getBorderVisible() При значении true объект TextElement имеет бордюр, при значении false - не имеет.
11.8.5. Свойства объекта Axis и соответствующие им параметры При кажущейся простоте объект Axis содержит достаточно много элементов: название оси (видимость, цвет, шрифт); линия, изображающая ось (видимость, цвет, толщина); основные и вспомогательные линии сетки, перпендикулярные оси (видимость, цвет, толщина); изображение делений шкалы на оси (видимость, цвет, толщина); видимость, местоположение, цвет, шрифт и формат представления числовых значений, соответствующих делениям шкалы; непосредственно сама шкала (тип, максимум, минимум, шаг).
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 211 Основная линия сетки для оси Y Вспомогательная линия сетки для оси Y
Основная линия сетки для оси X
Рис. 11.15 Основные и вспомогательные линии сетки Поскольку свойства TitleVisible, TextColor, Font, FontName, FontSize, Bold, Italic уже были рассмотрены, в данном разделе даются только описания соответствующих им параметров.
Параметры xAxisTitleVisible, yAxisTitleVisible и свойство TitleVisible True означает, что название оси X или Y отображается, а false - нет. Значение по умолчанию false.
Параметры xAxisTitle и yAxisTitle Определяет название оси X или Y. Параметр может задаваться в двух вариантах:
• •
string - непосредственно текст названия оси; %strSource - имя элемента данных с интерфейсом ImmediateAccess или ArrayAccess, содержащего, в случае ArrayAccess в «первой ячейке», текст названия оси.
Параметры xAxisTitleTextColor, yAxisTitleTextColor и свойство TextColor Цвет, которым выводится название для оси X или Y. Значением параметра может быть название или RGB-значение цвета.
Параметры xAxisTitleFont, yAxisTitleFont и свойства Font, FontName, FontSize, Bold, Italic
© InterTrust Co. Тел. 956-7928, 956-7929
212
Применение eSuite DevPack 1.0
Название, размер и стиль шрифта, которым выводится название для оси X или Y.
Параметры xAxisLineVisible, yAxisLineVisible и свойство AxisLineVisible Axis.setAxisLineVisible(boolean isVisible) boolean isVisible = Axis.getAxisLineVisible() True (по умолчанию) означает, что линия оси видима, false - не видима.
Параметры xAxisLineWidth, yAxisLineWidth и свойство LineWidth myObject.setLineWidth(integer width) integer width = myObject.getLineWidth() Толщина линии, изображающей ось X или Y. Значение lWidth может быть одним из следующих: onepixel - толщиной в один пиксель (по умолчанию), verythin - «очень тонкая», thin - тонкая, moderatelythin - «умеренно тонкая, толще тонкой», medium - средней толщины, moderatelythick - «умеренно толстая, толще средней толщины», thick - «толстая», verythick - «более толстая», extremelythick - «очень толстая». Свойство применимо для объекта Axis (толщина линии, изображающей ось) или объекта Series (толщина «соединительной линии» между отсчетами на двумерной линейчатой диаграмме). Допустимы следующие значения: 0 - толщиной в один пиксель (по умолчанию), 1 «очень тонкая», 2 - тонкая, 3 - «толще тонкой», 4 - средней толщины, 5 - «толще средней толщины», 6 - «толстая», 7 - «более толстая», 8 - «очень толстая».
Параметры xAxisLineColor, yAxisLineColor и cвойство LineColor Axis.setLineColor(java.awt.Color axisColor) java.awt.Color axisColor = Axis.getLineColor() Цвет линии, изображающей ось X или Y. Значением параметра может быть название или RGB-значение цвета. Значение свойства задается объектом класса java.awt.Color (по умолчанию Color.black), который в JavaScript можно получить методом creareColor() апплета ScriptHelper.
Параметры xAxisMajorGridsVisible, yAxisMajorGridsVisible, yAxisMinorGridsVisible и свойства MajorGridVisible, MinorGridVisible Axis.setMajorGridVisible(boolean isVisible) boolean isVisible = Axis.getMajorGridVisible()
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 213
Axis.setMinorGridVisible(boolean isVisible) boolean isVisible = Axis.getMinorGridVisible() Сетка на области изображения диаграммы (см. Рис. 11.15) образуется горизонтальным (для оси Y) и вертикальным (для оси X) наборами линий. Набор линий может включать линии двух типов: основные линии (Major) и вспомогательные (Minor). Вспомогательные линии сетки допустимы только для оси Y. По умолчанию видимы только основные линии сетки оси Y. True означает, что основные или вспомогательные линии сетки соответствующей оси «видимы», false - не видимы. После изменения значения свойства для диаграммы следует вызывать метод refresh().
Параметры xAxisMajorGridColor, yAxisMajorGridColor, yAxisMinorGridColor и свойства MajorGridColor, MinorGridColor Axis.setMajorGridColor(java.awt.Color gridColor) java.awt.Color gridColor = Axis.getMajorGridColor() Axis.setMinorGridColor(java.awt.Color gridColor) java.awt.Color gridColor = Axis.getMinorGridColor() Цвет линии, изображающей основные (Major) линии сетки оси X и основные (Major) или вспомогательные (Minor) линии сетки оси Y. Значением параметра может быть название или RGB-значение цвета. Для свойства цвет задается объектом класса java.awt.Color (по умолчанию Color.black), который в JavaScript можно получить методом creareColor() апплета ScriptHelper. Свойство MinorGridColor применимо только для оси Y.
Параметры xAxisMajorGridWidth, yAxisMajorGridWidth, yAxisMinorGridWidth и свойства MajorGridWidth, MinorGridWidth Axis.setMajorGridWidth(integer width) integer width = Axis.getMajorGridWidth() Axis.setMinirGridWidth(integer width) integer width = Axis.getMinirGridWidth() Толщина линий, которыми изображаются основные (Major) линии сетки оси X и основные (Major) или вспомогательные (Minor) линии сетки оси Y. Допустимые значения параметров xAxisMajorGridWidth, yAxisMajorGridWidth и такие же, как у параметров AxisLineWidth и yAxisLineWidth. Допустимые значения свойств MajorTickWidth и MinorGridWidth такие же, как у свойства LineWidth. Свойство MinorGridWidth применимо только к оси Y.
© InterTrust Co. Тел. 956-7928, 956-7929
214
Применение eSuite DevPack 1.0
Параметры xAxisMajorTicksVisible, yAxisMajorTicksVisible, yAxisMinorTicksVisible и свойства MajorTicksVisible, MinorTicksVisible Axis.setMajorTicksVisible(boolean isVisible) boolean isVisible = Axis.getMajorTicksVisible() Axis.setMinorTicksVisible(boolean isVisible) boolean isVisible = Axis.getMinorTicksVisible() На осях обычно присутствуют шкалы, деления которых изображаются короткими отрезками, «переходящими» в линии сетки, если последние «видимы». Данные параметры и свойства определяют «видимость» основных и вспомогательных «осевых делений». Свойство MinorTickVisible применимо только для оси Y. По умолчанию основные деления оси Y видимы (true), а вспомогательные деления оси Y и основные деления оси X - нет (false).
Параметры xAxisMajorTickColor, yAxisMajorTickColor, yAxisMinorTickColor и свойства MajorTickColor, MinorTickColor Axis.setMajorTickColor(java.awt.Color tickColor) java.awt.Color tickColor = Axis.getMajorTickColor() Axis.setMinorTickColor(java.awt.Color tickColor) java.awt.Color tickColor = Axis.getMinorTickColor() Цвет линии, которой изображается основное или вспомогательное деление на оси. Значением параметра может быть название или RGB-значение цвета. Свойство MinorTickColor применимо только для оси Y. Для свойства цвет задается объектом класса java.awt.Color (по умолчанию Color.black), который в JavaScript можно получить методом creareColor() апплета ScriptHelper.
Параметры xAxisMajorTickWidth, yAxisMajorTickWidth, yAxisMinorTickWidth и свойства MajorTickWidth, MinorGridWidth Axis.setMajorTickWidth(integer width) integer width = Axis.getMajorTickWidth() Axis.setMinorTickWidth(integer width) integer width = Axis.getMinorTickWidth() Толщина линии, которой изображается основное или вспомогательное деление на оси.
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 215
Допустимые значения параметров xAxisMajorTickWidth, yAxisMajorTickWidth yAxisMinorTickWidth такие же, как у параметров AxisLineWidth и yAxisLineWidth.
и
Допустимые значения свойств MajorTickWidth и MinorTickWidth такие же, как у свойства LineWidth. Свойство MinorGridWidth применимо только к оси Y.
Свойства Maximum, Minimum, MajorStep и MinorStep double maxValue = Axis.getMaximum() double minValue = Axis.getMinimum() double stepValue = Axis.getMajorStep() double stepValue = Axis.getMinorStep() Свойства getMaximum() и getMinimum() возвращают максимальное и минимальное значение данных «по оси». Это значение зависит от данных диаграммы и вычисляется автоматически. Для того, чтобы задать апплету «собственные» значения максимума или минимума вместо вычисляемых автоматически, следует воспользоваться свойствами UserMaximum и UserMinimum. Свойства getMajorStep() и getMinorStep() возвращают шаг основных или вспомогательных линий сетки (и, соответственно, основных или вспомогательных делений) по оси. Значение зависит от данных, отображаемых на диаграмме. Например, если минимальное значение данных по оси составляет 0, максимальное - 10, а количество отсчетов равно 20, шаг составит (10-0)/20 = 0.5. Для того, чтобы задать апплету «собственные» значения шагов основных или вспомогательных линий сетки вместо вычисляемых автоматически, следует воспользоваться свойствами UserMajorStep и UserMinorStep.
Параметры yAxisScaleMaximum, yAxisScaleMinimum, yAxisScaleMajor, yAxisScaleMinor и свойства UserMaximum, UserMinimum, UserMajorStep и UserMinorStep Axis.setUserMaximum(double maxValue) double maxValue = Axis.getUserMaximum() Axis.setUserMinimum(double minValue) double minValue = Axis.getUserMinimum() Axis.setUserMajorStep(double stepValue) double stepValue = Axis.getUserMajorStep() Axis.setUserMinorStep(double stepValue) double stepValue = Axis.getUserMinorStep Параметры yAxisScaleMaximum и yAxisScaleMinimum устанавливают, а свойства UserMaximum() и UserMinimum() возвращают или устанавливают «собственные, т.е. определенные пользователем» максимальное и минимальное значение данных «по оси» Y. Значения по умолчанию 0. Эти значения «перекрывают» соответствующие значения, вычисляемые автоматически.
© InterTrust Co. Тел. 956-7928, 956-7929
216
Применение eSuite DevPack 1.0
Параметры yAxisScaleMajor и yAxisScaleMinor устанавливают, а свойства UserMajorStep() и UserMinorStep() возвращают или устанавливают «собственные, т.е. определенные пользователем» шаг основных или вспомогательных линий сетки (и, соответственно, основных или вспомогательных делений) по оси Y. Эти значения «перекрывают» соответствующие значения, вычисляемые автоматически. После изменения значения свойства необходимо вызвать метод refresh().
Параметр yAxisScaleType и свойство ScaleType Axis.setScaleType(String sType) String sType = Axis.getScaleType() Тип шкалы для оси Y. Может быть или "linear" (по умолчанию) - «обычная линейная» шкала, или "percent" - шкала в процентах.
Параметры xAxisLabelsVisible, yAxisLabelsVisible и свойство TickLabelsVisible Axis.setTickLabelsVisible(boolean isVisible) boolean isVisible = Axis.getTickLabelsVisible() True (по умолчанию) означает, что числовые значения, соответствующие делениям на осях X или Y, отображаются, false - не отображаются.
Параметры xAxisLabelsTextColor и yAxisLabelsTextColor Цвет, которым отображаются числовые значения делений на осях X или Y.
Параметры xAxisLabelsFont и yAxisLabelsFont Название, размер и стиль шрифта, которым отображаются числовые значения, соответствующие делениям на осях X или Y.
Параметр yAxisNumberFormat и свойства NumberFormat и NumberFormatDecimals myObject.setNumberFormat(String format, decimals ) String format = myObject.getNumberFormat() int decimals = myObject.getNumberFormatDecimals() Значение параметра и аргумент или возвращаемое значение свойства format определяет название формата, в соответствии с которым представляются числа, дающие значения делений на оси Y и значений серии (series labels). Основные форматы: "General" (общий, по © InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 217
умолчанию), "Fixed" (фиксированный), "Comma" (с разделителем групп разрядов), "Percent" (процентный). Кроме того, могут использоваться многочисленные "денежные" форматы, например, "US Dollar","ISO US Dollar", "Russian Ruble", "ISO Russian Ruble", "Ukrainian Hryvnia", "Belarusian Ruble", а так же форматы для представления «дата-временных» значений. Полный список приведен в документации по eSuite DevPack. Для некоторых форматов представления чисел в значении параметра format через разделитель «точка с запятой» может задаваться количество знаков после десятичной точки, например, "comma; 2". Аргумент или возвращаемое значение decimals определяет количество десятичных знаков в представлении чисел, дающих значения делений на оси Y и значений серии (series labels). Свойство применимо к объектам Axis (только ось Y) и Series. Кроме того, NumberFormatDecimals не имеет смысла, если NumberFormat равно "general".
11.8.6. Методы, свойства и соответствующие им параметры объекта Series Диаграмма обычно содержит несколько серий данных. Количество серий можно определить свойством SeriesCount() объекта Chart. Каждая серия идентифицируется своим номером, нумерация начинается с 0. Объект Series представляет одну из серий диаграммы.
Метод getIndex int seriesId = Series.getIndex() Возвращает индекс серии.
Метод hasData boolean hasValues = Series.hasData() Возвращает true, если данные серии определены, или false, если нет («пустая» серия).
Параметр seriesN и свойство Data Series.setData(double dataArray) Параметр задает данные для серии с номером N. Номер серии изменяется от 1 до количества серий. Возможны два варианта значения sValue. Если sValue начинается не с символа «%», то оно должно содержать непосредственно значение или список разделенных запятыми значений данных для серии. Если же sValue начинается с символа «%», например, %string, то string интерпретируется как имя одномерного элемента данных с интерфейсом ArrayAccess, содержащего данные для серии. Свойство задает значения данных серии как массив с элементами типа double.
Параметр seriesMixedType и свойство SeriesType Series.setSeriesType(String sType) String sType = Series.getSeriesType() Определяет способ изображения данных серий. Значение sType может быть одним из следующих: bar (по умолчанию) - прямоугольниками, line - «линейчатая» - отрезками линий, area - с заливкой области под «кривой».
© InterTrust Co. Тел. 956-7928, 956-7929
218
Применение eSuite DevPack 1.0
Рис. 11.16 SeriesType = “bar” «с накоплением»
Рис. 11.17 SeriesType = “line” с видимыми маркерами
Рис. 11.18 SeriesType = “area” с видимыми метками данных Свойство применяется к конкретной серии. Для параметра в списке значений, например, "area, line, area", первое значение относится к первой серии, второе значение ко второй серии, и т.д.
Параметр seriesConnectPoints и свойство ConnectPoints Series.setConnectPoints(boolean doConnect) boolean doConnect = Series.getConnectPoints() Для двухмерной линейчатой диаграммы при значении true (по умолчанию) отсчеты данных серии должны «соединяться» линиями, при значении false - не должны. Сами же отсчеты данных изображаются маркерами, если свойство MarkerVisible равно true. Если оба свойства ConnectPoints и MarkerVisible равны false, данные серии вообще не отображаются на диаграмме.
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 219
Параметр должен содержать список из значений true или false для всех серий диаграммы, свойство применяется к конкретной серии.
Параметр seriesLineWidths Толщина линий, соединяющих отсчеты данных серии на двумерной линейчатой диаграмме. Если задано одно значение, оно используется для всех серий диаграммы. Может задаваться список значений, первое значение применяется для первой серии, второе значение для второй серии, и т.д. Каждое значение lWidth может быть одним из следующих: onepixel - толщиной в один пиксель (по умолчанию), verythin - «очень тонкая», thin - тонкая, moderatelythin - «умеренно тонкая, толще тонкой», medium - средней толщины, moderatelythick - «умеренно толстая, толще средней толщины», thick - «толстая», verythick - «более толстая», extremelythick - «очень толстая».
Параметр seriesMarkersVisible и свойство MarkerVisible series.setMarkerVisible(boolean isVisible) boolean isVisible = series.getMarkerVisible() Если значение равно true, то каждый отсчет серии данных «отмечается» маркером, если false (по умолчанию) - маркеры этой серии не видимы. Используется только для плоской линейчатой диаграммы. Свойство применяется к конкретной серии, параметр же имеет отношение к нескольким сериям. Когда для параметра задан список значений, например, "true, false, true", то первое значение используется для первой серии, второе значение - для второй серии, и т.д.
Параметр seriesMarkerTypes и свойство MarkerType series.setMarkerType(String mType) String mType = series.getMarkerType() Тип маркера, которым отображаются отсчеты данных серии на двухмерной линейчатой диаграмме. Может быть одним из следующих: "FilledSquare" - «квадрат с заливкой», "FilledCircle" - «круг с заливкой», "FilledUpTriangle" - «треугольник вершиной вверх с заливкой», "FilledDownTriangle" - «треугольник вершиной вниз с заливкой», "FilledDiamond" «ромб с заливкой», "FilledStar" - «звезда с заливкой», "Square" - «квадрат без заливки», "Circle" - «круг без заливки», "UpTriangle" - «треугольник вершиной вверх без заливки», "DownTriangle" - «треугольник вершиной вниз без заливки», "Diamond" - «ромб без заливки», "Star" - «звезда без заливки». По умолчанию для серий плоской линейчатой диаграммы маркеры назначаются в приведенной последовательности: "FilledSquare" для серии 1, "FilledCircle" для серии 2, "FilledUpTriangle" для серии 3 и т.д. Свойство применяется к конкретной серии, параметр же имеет отношение к нескольким сериям. Когда для параметра задан список значений, например, "filledsquare, filledcircle, filledstar", то первое значение используется для первой серии, второе значение - для второй серии, и т.д.
© InterTrust Co. Тел. 956-7928, 956-7929
220
Применение eSuite DevPack 1.0
Параметр seriesMarkerColors и свойство MarkerColor Series.setMarkerColor(java.awt.Color mColor) java.awt.Color mColor = Series.getMarkerColor() Цвет маркера, которым отображаются отсчеты данных серии на двухмерной линейчатой диаграмме. Для свойства цвет задается объектом класса java.awt.Color (по умолчанию Color.lightGray), а для получения этого объекта в JavaScript используется метод createColor() апплета ScriptHelper. Для параметра цвет задается названием цвета или «шестнадцатеричным» RGB-значением наподобие "FF00FF". Свойство применяется к конкретной серии, параметр же имеет отношение к нескольким сериям. Если задано одно значение параметра, оно используется для всех серий диаграммы. Если для параметра задан список значений, первое значение используется для первой серии, второе значение - для второй серии, и т.д.
Параметр seriesMarkerSizes и свойство MarkerSize series.setMarkerSize(integer mSize) integer mSize = series.getMarkerSize() Размер маркера, которым отображаются отсчеты данных серии на двухмерной линейчатой диаграмме. Допустимые значения от 1 до 100, по умолчанию 12. Свойство применяется к конкретной серии, параметр же имеет отношение к нескольким сериям. Если задано одно значение параметра, оно используется для всех серий диаграммы. Если для параметра задан список значений, например, "25, 25, 25", то первое значение используется для первой серии, второе значение - для второй серии, и т.д.
Параметр и свойство PieSliceExplodePercent Series.setPieSliceExplodePercent(int percent) int percent = Series.getPieSliceExplodePercent() Определяет «расстояние» от центра круговой диаграммы до вершины сегмента. Это «расстояние» указывается в процентах от радиуса диаграммы. Значение по умолчанию 0. Параметр задает набор этих значений для всех серий на диаграмме, свойство же применяется к конкретной серии.
Параметр seriesValuesVisible и свойство ValueLabelsVisible Series.setValueLabelsVisible(boolean isVisible) boolean isVisible = Series.getValueLabelsVisible() Метки значений данных серии отображаются, если значение равно true, и не отображаются, если значение равно false (по умолчанию). Свойство касается конкретной серии. Если для параметра указано одно значение, оно используется для всех серий диаграммы. Для параметра может задаваться список значений, например, "false, true, false", первое значение из которого относится к первой серии, второе - ко второй второй серии, и т.д. © InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 221
Параметр seriesLabelsPosition и свойство LabelsPosition Series.setLabelsPosition(String position) String position = Series.getLabelsPosition() Местоположение меток данных для серии. При значении "above" (по умолчанию) метки располагаются над отсчетами данных, а для круговой диаграммы - вне секторов. При значении "below" метки данных располагаются под отсчетами данных, а для круговой диаграммы - «на секторах». Свойство применяется к конкретной серии, параметр же обычно имеет отношение к нескольким сериям. Если задано одно значение параметра, оно используется для всех серий диаграммы. Если для параметра задан список значений, первое значение определяет местоположение меток первой серии, второе значение - второй серии, и т.д.
Параметр seriesLabelsTextColors Цвет текста отметок данных для серий диаграммы. Задается названием цвета или «шестнадцатеричным» RGB-значением наподобие "FF00FF". Если задано одно значение, оно используется для всех серий диаграммы. Может задаваться список значений, разделенных запятыми, например "yellow, red, blue". В таком случае первая серия будет иметь желтый цвет текста, вторая - красный, а третья - голубой.
Параметр seriesLabelsFont Задает название, размер и стиль шрифта, которым выводятся метки данных для серий диаграммы. Значение fName может быть helvetica, timesroman (по умолчанию), courier, dialog, zapfdingbats. Целое число fSize определяет размер шрифта в пунктах. Стиль fStyle может быть одним из следующих: PLAIN (по умолчанию), BOLD, ITALIC, BOLD | ITALIC. Если задано одно значение, оно используется для всех серий диаграммы. Может задаваться список из «троек» значений, первая «тройка» определяет шрифт первой серии, вторая «тройка» - шрифт второй серии, и т.д.
Параметр seriesPercentsVisible и свойство PercentLabelsVisible Series.setPercentLabelsVisible(boolean isVisible) boolean isVisible = Series.getPercentLabelsVisible() При значении true метки всех значений серии отображаются на диаграмме в процентах от суммы всех значений этой серии. Если же свойство равно true для всех серий диаграммы, то метки значений данных отображаются на диаграмме в процентах от суммы всех значений во всех сериях. При значении false (по умолчанию) метки представляют значения данных. Свойство применяется к конкретной серии, параметр же имеет отношение к нескольким сериям. Если задано одно значение параметра, оно используется для всех серий диаграммы. Если для параметра задан список значений, например, "false, true, false", то первое значение используется для первой серии, второе значение - для второй серии, и т.д.
© InterTrust Co. Тел. 956-7928, 956-7929
222
Применение eSuite DevPack 1.0
Параметр seriesNumberFormat Определяет название числового формата, в соответствии с которым представляются метки данных серий. Основные форматы: "General" (общий, по умолчанию), "Fixed" (фиксированный), "Comma" (с разделителем групп разрядов), "Percent" (процентный). Кроме того, могут использоваться многочисленные «денежные» форматы, например, "US Dollar","ISO US Dollar", "Russian Ruble", "ISO Russian Ruble", "Ukrainian Hryvnia", "Belarusian Ruble", а так же форматы для представления «дата-временных» значений. Полный список приведен в документации по eSuite DevPack. В списке значений, например, "US Dollar, US Dollar, US Dollar", первое значение применяется для первой серии, второе значение для второй серии, и т.д. Для некоторых числовых форматов через разделитель «точка с запятой» может задаваться количество знаков после десятичной точки, например, "comma; 2, US Dollar; 3"
Параметр seriesLeaderLinesVisible и свойство LeaderLineVisible Series.setLeaderLineVisible(boolean isVisible) boolean isVisible = Series.getLeaderLineVisible() Для серии в круговой диаграмме при значении true между метками данных и соответствующими им секторами «проводятся» соединительные линии, при значении false (по умолчанию) - не проводятся. Свойство применяется к конкретной серии, параметр же имеет отношение к нескольким сериям. Если задано одно значение параметра, оно используется для всех серий диаграммы. Если для параметра задан список значений, первое значение используется для первой серии, второе значение - для второй серии, и т.д.
Параметр seriesBackgroundColors Фоновый цвет серий диаграммы. Задается названием цвета или «шестнадцатеричным» RGB-значением наподобие "FF00FF". Если указано одно значение, оно используется для всех серий диаграммы. Может задаваться список значений, разделенных запятыми, например "yellow, red, blue". В таком случае первая серия будет иметь желтый фон, вторая - красный, а третья - голубой.
Параметр seriesBorderLineColors Цвет линий, образующих бордюр серий диаграммы. Задается названием цвета или «шестнадцатеричным» RGB-значением наподобие "FF00FF". Если задано одно значение, оно используется для всех серий диаграммы. Может задаваться список значений, разделенных запятыми, например "yellow, red, blue". В таком случае первая серия будет иметь желтый цвет бордюра, вторая - красный, а третья - голубой.
Параметр seriesBackgroundTransparent
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 223
VALUE = "isTransparent1, isTransparent2,..., isTransparentN"> Если задано true (по умолчанию), стиль «закраски» соответствующей серии «прозрачный», если false - «сплошной».
Параметр seriesVisible и свойство Visible myObject.setVisible(boolean isVisible) boolean isVisible = myObject.getVisible() Серия отображается при значении true (по умолчанию), и не отображается при значении false. Свойство применяется к конкретной серии. Кроме того, свойство применимо к объекту Plot. Если для параметра задано одно значение, оно используется для всех серий диаграммы. Для параметра может задаваться список значений, например, "false, true, false", первое значение из которого относится к первой серии, второе - ко второй второй серии, и т.д. Пример 1. В приведенном фрагменте HTML-кода апплет Filereader загружает из файла в InfoBus элемент данных dinFileOut, а апплет Chart, находящийся во фрейме апплета AppletContainer, отображает этот элемент данных. Апплет AppletContainer использован исключительно для того, чтобы для апплета Chart отображался InfoCenter. InfoCenter позволяет «визуально» изменять характеристики отображения диаграммы. В частности, выбрав в InfoCenter «Диаграмма/Сохранить как…», можно сохранить все текущие свойства диаграммы в файле-шаблоне (обычно тип такого файла ECHART), а впоследствии, выбрав в InfoCenter «Диаграмма/Открыть…», загрузить файл-шаблон, восстановив тем самым свойства диаграммы.
Рис. 11.19 Апплет Chart с видимым InfoCenter и открытой панелью свойств диаграммы Апплет Chart c InfoCenter в AppletContainer
<APPLET
CODEBASE="/eSuiteDP" CODE="lotus.filereader.FileReader" ARCHIVE="/eSuiteDP/jars/devpack_filereader_app.jar" WIDTH=0 HEIGHT=0> <APPLET CODEBASE="/eSuiteDP" CODE="lotus.fc.AppletContainer" ARCHIVE="jars/devpack_chart_sheet_jdbc_app.jar" WIDTH=400 HEIGHT=300>
Пример 2. В приведенном фрагменте HTML-кода, подобно примеру 1, апплет Filereader загружает из файла в InfoBus элемент данных dinFileOut, а апплет Chart отображает этот элемент данных. Однако здесь управление апплетом Chart осуществляется не из InfoCenter, а «непосредственно из JavaScript». Кнопки, вызывающие функцию f(n, a1) на JavaScript, позволяют изменять наиболее интересные характеристики отображения диаграммы. <APPLET CODEBASE="/eSuiteDP" CODE="lotus.filereader.FileReader" NAME="myFileReader" ARCHIVE="/eSuiteDP/jars/devpack_filereader_app.jar" WIDTH=0 HEIGHT=0> <APPLET CODEBASE="/eSuiteDP" CODE="lotus.chart.Chart" NAME="myChart" WIDTH=500 HEIGHT=320 ARCHIVE="/eSuiteDP/jars/devpack_chart_app.jar">
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 225 <SCRIPT LANGUAGE="JavaScript"> function f(n,a1) { chart = document.myChart; switch(n) { case 1: dims = chart.getPerspective(); if(dims == "2D") chart.setPerspective("3D"); else chart.setPerspective("2D"); break; case 2: chart.setElevation(parseInt(a1)); break; case 3: chart.setRotation(parseInt(a1)); break; case 4: chart.setBackgroundTransparent(!chart.getBackgroundTransparent()); alert("BackgroundTransparent = " + chart.getBackgroundTransparent()); break; case 5: pl = chart.getPlotLayout(); if (pl=="VERTICAL") chart.setPlotLayout("HORIZONTAL"); if (pl=="HORIZONTAL") chart.setPlotLayout("PIE"); if (pl=="PIE") chart.setPlotLayout("VERTICAL"); alert("PlotLayout = " + chart.getPlotLayout()); break; case 6: dir = chart.getParseDirection(); if(dir == "COLUMN") chart.setParseDirection("ROW"); else chart.setParseDirection("COLUMN"); break; case 7: axis = chart.findXAxis(); axis.setMajorGridVisible(!axis.getMajorGridVisible()); break; case 8: axis = chart.findYAxis(); axis.setMajorGridVisible(!axis.getMajorGridVisible()); break; case 9: axis = chart.findXAxis(); axis.setMinorGridVisible(!axis.getMinorGridVisible()); break; case 10: axis = chart.findYAxis();
© InterTrust Co. Тел. 956-7928, 956-7929
226
Применение eSuite DevPack 1.0 axis.setMinorGridVisible(!axis.getMinorGridVisible()); break; case 11: // alert("SeriesCount = " + chart.getSeriesCount()); for (i=0; i < chart.getSeriesCount(); i++) { series = chart.findSeries(i); switch(a1) { case 1: series.setSeriesType("bar"); break; case 2: series.setSeriesType("line"); break; case 3: series.setSeriesType("area"); break; case 4: series.setMarkerVisible(!series.getMarkerVisible()); break; case 5: series.setValueLabelsVisible(!series.getValueLabelsVisible()); break; } } break; case 12: for (i=0; i < chart.getSeriesCount(); i++) { series = chart.findSeries(i); series.setPieSliceExplodePercent(parseInt(a1)); } break; } chart.refresh();
}
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 227
11.9. Апплет Sheet - электронная таблица Апплет Sheet - достаточно мощная электронная таблица, дающая возможность пользователям анализировать числовые данные и создавать полезные финансовые приложения. Базисные функциональные возможности апплета включают:
• • • • • • •
более двадцати из наиболее часто используемых в электронных таблицах функций, включая SUM, AVG, PMT и NPV; сортировка данных по возрастанию или убыванию; импорт и экспорт файлов в нескольких формах; форматирование в ячейках - шрифт, текстовые атрибуты, фоновый цвет, рамки, высота и ширина столбца и строки, выравнивание, различные числовые форматы; применение фоновых изображений - импорт графических файлов GIF и JPEG; общие функциональные возможности электронной таблицы - ориентация, разбиение на страницы; специфические особенности - защищенные и скрытые ячейки, поименованные диапазоны, отображение и скрытие рабочих элементов таблицы. Разработчикам более интересны такие возможности апплета, как:
• • • • • •
защита рабочего пространства от модификации и просмотра любых формул, содержащихся в ячейках; поименованные диапазоны; использование InfoBus для обмена данными с другими апплетами; общее API для формирования специализированных интерфейсов; управление видимостью полос прокрутки, линий сетки и рабочего пространства; использование eSuite Template Builder для создания шаблонов.
Байт-код апплета - Sheet.class. Для работы апплета в броузер должен быть загружен один из JAR-архивов devpack_sheet_app.jar, devpack_chart_sheet_jdbc_app.jar, devpack_sheet_lite.jar или три CAB-архива devpack_infobus.cab, devpack_shared.cab и devpack_sheet.cab. Пример 1. Фрагмент HTML-кода, который «минимально-необходим» для запуска апплета Sheet. При своей инициализации апплет загружает файл D:/MyHTML/eSuiteDocs/Ex1.html-wk, расположенный на локальном диске. <APPLET CODEBASE="/eSuiteDP" CODE="lotus.sheet.Sheet" ARCHIVE="/eSuiteDP/jars/devpack_sheet_app.jar" WIDTH=500 HEIGHT=200 NAME=sheet>
© InterTrust Co. Тел. 956-7928, 956-7929
228
Применение eSuite DevPack 1.0 Cтрока редактирования (EditLine)
Заголовки столбцов (ColumnHeadings)
Рамка таблицы (Frame)
Заголовки строк (RowHeadings)
Сетка (Grid) Текущая ячейка
Cтрока состояния (StatusLine)
Горизонтальная полоса прокрутки (HorizontalScrollBar)
Вертикальная полоса прокрутки (VerticalScrollBar)
Рис. 11.20 Апплет Sheet и его элементы
Параметр documentName Сообщает URL документа, который должен быть загружен в апплет при инициализации. Допустимые типы документов должны иметь расширения .html (документ HTML), .html-wk (электронная таблица eSuite), .html-wkt (шаблон электронной таблицы eSuite), .htm (документ HTM) и .wk1 (электронная таблица wk1 Lotus). Если апплет не сможет по расширению файла определить тип документа, то документ загружается в апплет в формате по умолчанию. Следует задавать или абсолютный URL (начинается с названия протокола) или относительный - относительно URL HTML-документа, содержащего апплет. Для загрузки файлов, расположенных на локальном диске, применяется URL формата "file:///c:\/filename.extension".
Метод openDocument boolean success = Sheet.openDocument(String URL, boolean promptToSave) Открывает в апплете документ, URL которого задан в строке URL. Если аргумент promptToSave равен true, а пользователь выполнил изменения в документе, то при попытке закрыть документ появится диалоговое окно с запросом о сохранении документа или отказе от изменений. Если promptToSave равен false, такое диалоговое окно не появляется и документ не сохраняется. Возвращается true, если документ был успешно открыт, или false, если документ не удалось загрузить или пользователь выбрал Cancel в окне запроса.
Метод openDocumentFromStream boolean success = Sheet.openDocumentFromStream(java.io.DataInput inputStream, boolean promptToSave) Аналогичен методу openDocument, но документ загружается из потока ввода данных (объекта класса java.io.DataInput) и применяется формат по умолчанию. Подробности в описании апплета ScriptHelper.
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 229
Метод newDocument sheet.newDocument() Замещает текущий документ апплета «пустым» новым. Если текущий документ необходимо сохранить, следует вызвать метод saveDocument() перед вызовом newDocument().
Метод isChanged boolean changed = Sheet.isChanged() Возвращает true, если в документ были внесены изменения, и они могут быть потеряны, если документ не будет сохранен, или false, если никаких изменений не было. Метод saveDocument boolean success = Sheet.saveDocument(String URL) Сохраняет документ по текущему (если URL == null) или по указанному URL. Если расширение файла, заданное в строке URL, не распознается апплетом, документ сохраняется в формате по умолчанию. Возвращает true, если документ был успешно сохранен, или false, если нет.
Метод saveDocumentToStream boolean success = Sheet.saveDocumentToStream(java.io.DataOutput outputStream) Аналогично предыдущему, но документ сохраняется в потоке ввода данных (объекте класса java.io.DataOutput). Используется формат по умолчанию. Подробности в описании апплета ScriptHelper. Пример 2. Цель этого примера - продемонстрировать рассмотренные выше методы и упомянутый в описании апплета ScriptHelper подход для передачи документа из апплета на Web-сервер и, наоборот, загрузки документа с Web-сервера в апплет. Рассмотрим простое Web-приложение Domino, в котором хранятся документы-таблицы, создаваемые или редактируемые Web-клиентами «с применением» апплета Sheet. Документ апплета Sheet - таблица в стандартном формате HTML-WK - сохраняется в базе Notes в текстовом поле с именем HTML документа по форме AppletDoc. Эта форма в режиме редактирования дизайна выглядит, как показано на Рис. 11.21. Поле Type содержит «тип документа» - «Sheet». Поля REMOTE_USER, REMOTE_HOST и REQUEST_CONTENT получают значения из соответствующих CGI-переменных (хотя наличие этих полей не принципиально). Формула поля $$Return "<script>history.go(-1);" - «заставляет» броузер после сохранения документа «вернуться в его истории на одну страницу назад».
© InterTrust Co. Тел. 956-7928, 956-7929
230
Применение eSuite DevPack 1.0
Рис. 11.21 Форма AppletDoc Документы Notes, созданные по форме AppletDoc и имеющие в поле Type значение «Sheet», отображаются в виде с именем Sheets. Этот вид доступен только из броузера и имеет лишь одну колонку, формула которой такова: URL:="http://main.inttrust.ru/eSuite.nsf/Sheets/"+@Text(@DocumentUniqueID)+ "?OpenDocument"; Name:=@If(Subject="";"Unknown";Subject); "[" +Name+" ]" Таким образом, «кликание мышью» по строке этого вида в броузере влечет вызов JavaScriptфункции doLoad() с передачей ей в качестве первого аргумента URL документа Notes, содержащего в поле с именем HTML документ-таблицу для апплета Sheet, а в качестве второго - название этого документа из поля Subject. Однако этот вид открывается из броузера «не как он есть», а по специальной форме $$ViewTemplate for Sheets. Эта форма содержит, во-первых, таблицу из двух столбцов, как это показано на Рис. 11.22. В левом столбце таблицы находится элемент Embedded View, содержащий информацию из вида Sheets, а так же кнопки для навигации по этому виду. В правом столбце таблицы содержится «HTML-вставка», включающая видимое поле Subject, кнопку Save document, вызывающую JavaScript-функцию doSave(), скрытые поля с именами HTML и Type, и, наконец, апплеты Sheet и ScriptHelper. Но для того, чтобы клиенту был доступен InfoCenter, апплет Sheet находится во фрейме апплета AppletContainer.
Рис. 11.22 Таблица из формы $$ViewTemplate for Sheets
TYPE=TEXT NAME="Subject" VALUE="Docname"> TYPE=button VALUE="Save document" onClick="doSave( );"> TYPE=hidden NAME="HTML"> TYPE=hidden NAME="Type" VALUE="Sheet">
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 231
<APPLET CODEBASE="/eSuiteDP" CODE="lotus.fc.AppletContainer" ARCHIVE="/eSuiteDP/jars/devpack_chart_sheet_jdbc_app.jar" WIDTH=600 HEIGHT=300 NAME="myContainer"> <APPLET CODEBASE="/eSuiteDP" CODE="lotus.scripthelper.ScriptHelper" NAME="scrHelper" ARCHIVE="/eSuite/jars/devpack_scripthelper_app.jar" WIDTH=1 HEIGHT=1> Во-вторых, форма $$ViewTemplate for Sheets содержит еще одну «HTML-вставку» - текст JavaScriptфункций doLoad() и doSave(). Первая функция выполняет загрузку документа-таблицы в апплет Sheet, а вторая - сохранение документа-таблицы из апплета Sheet в базе Notes. <SCRIPT LANGUAGE="JavaScript">
© InterTrust Co. Тел. 956-7928, 956-7929
232
Применение eSuite DevPack 1.0
function doLoad(URL,Name) { document.forms[0].Subject.value = Name; // Получаем объект апплета Sheet (он содержится в AppletContainer) sheet = myContainer.findContainedAppletByIndex(0); sheet.setCharacterEncoding("" /*"KOI8_R"*/ ); // Загружаем документ в апплет. flag = sheet.openDocument(URL, true); if ( flag == true) alert("Документ загружен\n"+Name+"\n"+URL); else alert("Документ не загружен\n"+Name+"\n"+URL); } //--> Выглядит форма $$ViewTemplate for Sheets в броузере приблизительно следующим образом.
Рис. 11.23 Фрагмент формы $$ViewTemplate for Sheets в броузере На первый взгляд, наша цель легко достигнута. Выбор мышью названия документа в левой части таблицы влечет загрузку соответствующего документа-таблицы в апплет Sheet. Нажатие мышью кнопки Save document влечет сохранение документа-таблицы из апплета в базе Notes. Но учтите, что это всего лишь учебный пример, а не «готовый к использованию рабочий прием». Проблем здесь имеется достаточно много: автоматическое обновление вида со списком документов; создание всякий раз нового документа, а не модификация существующего; вместо HTML-таблицы изящнее использовать фреймы; ограничения на размер текстового поля в Notes влекут соответствующее ограничение на размер сохраняемого документа-таблицы…
Параметр и свойство appletLocale Sheet.setAppletLocale(String locale) String locale = Sheet.getAppletLocale() Код языка и страны. Например, "ru_RU" (русский язык/Россия) или "en_GB" (английский язык/Великобритания).
Параметр и свойство userInterfaceLanguage © InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 233
Sheet.setUserInterfaceLanguage(String languageCode) String languageCode = Sheet.getUserInterfaceLanguage() Язык, применяемый в пользовательском интерфейсе апплета. Например, "ru" или "en".
Параметр и свойство userTimeZone Sheet.setUserTimeZone(String timeZone) String timeZone = Sheet.getUserTimeZone() Временная зона, в которой работает пользователь. Может задаваться одним из следующих обозначений JDK 1.1.x: "GMT", "ECT", "EET", "ART", "EAT", "MET", "NET", "PLT", "IST", "BST", "VST", "CCT", "JST", "ACT", "AET", "SST", "NST", "MIT", "HST", "AST", "PST", "PNT", "MST", "CST", "EST", "IET", "PRT", "CNT", "AGT", "BET".
Параметр и свойство characterEncoding Sheet.setCharacterEncoding(String module) String module = Sheet.getCharacterEncoding() Модуль из JDK 1.1.x, используемый апплетом при перекодировании символов. Например, "Cp1251", "KOI8_R" или "MacCyrillic".
Параметр height Задает в пикселях высоту области, которую апплет занимает во время выполнения. Когда апплет AppletContainer обслуживает более чем один апплет, то значения высот для обслуживаемых им апплетов, расположенных один над другим, в сумме не должны превышать значения параметра height апплета AppletContainer.
Параметр width Задает в пикселях ширину области, которую апплет занимает во время выполнения. Когда апплет AppletContainer обслуживает более чем один апплет, то значения «ширин» для обслуживаемых им апплетов, расположенных слева направо один за другим, в сумме не должны превышать значения параметра width апплета AppletContainer.
Параметр и свойство InfoCenterProfileName Sheet.setInfoCenterProfileName(String fileName) String fileName = Sheet.getInfoCenterProfileName() Определяет файл, созданный в eSuite Template Builder и содержащий настройки для InfoCenter. Файл должен соответствовать апплету (обычно его тип ICC-WK) и должен располагаться или в каталоге, из которого запускается приложение, или задаваться URL относительно документа, содержащего апплет.
© InterTrust Co. Тел. 956-7928, 956-7929
234
Применение eSuite DevPack 1.0
Метод findEntireSheetRange Range Range = Sheet.findEntireSheetRange() Возвращает диапазон (объект класса Range), представляющий всю таблицу.
Метод findRangeByCoordinates Range Range = Sheet.findRangeByCoordinates( int startCol, int startRow, int endCol, int endRow) Возвращает диапазон (объект Range), представляющий часть таблицы, расположенную от ячейки с координатами (startCol, startRow) до ячейки с координатами (endCol, endRow). Нумерация начинается с нуля. Строка 1 имеет индекс 0, строка 2 - индекс 1 и т.д. Столбец A имеет индекс 0, B - индекс 1 и т.д.
Метод findRangeByString Range Range = Sheet.findRangeByString(String rangeString) Возвращает объект Range, представляющий часть таблицы, определенную в строке rangeString. Эта строка может содержать или координаты «диагональных ячеек», например, "A1..D10", или имя, ассоциированное с ранее определенным диапазоном, например, "Budget97".
Метод createRangeName Sheet.createRangeName(Range theRange, String rangeName) Ассоциирует имя rangeName с диапазоном theRange в таблице Sheet.
Метод deleteRangeName Range.deleteRangeName(String rangeName) Отменяет имя rangeName, ассоциированное с диапазоном Range. Сам диапазон и другие имена, ассоциированные с ним, при этом никак не меняются.
Свойство Selection Sheet.setSelection(Range selRange) Range selRange = Sheet.getSelection() Текущий выделенный диапазон в таблице. Свойство get возвращает диапазон, выделенный в таблице, а свойство set указывает диапазон для выделения.
Методы getStartRow, getStartColumn, getEndRow, getEndColumn и toString int rowInt = Range.getStartRow() int columnInt = Range.getStartColumn() int rowInt = Range.getEndRow() int columnInt = Range.getEndColumn() String rangeStr = Range.toString() Позволяют получить границы диапазона «как целые» или, методом toString(), как строку наподобие "A1..D12". © InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 235
Параметр и свойство alignment Sheet.setAlignment(String alignType) String alignType = Sheet.getAlignment() Выравнивание для данных в таблице. Возможные значения: "default" - числовые данные выравниваются вправо, строковые - влево; "left" - влево, "center" - по центру, "right" - вправо. По умолчанию применяется выравнивание "default".
Параметр Font и свойствa Font, FontName, FontSize, Bold, Italic myObject.setFont(java.awt.Font theFont) java.awt.Font theFont = myObject.getFont() myObject.setFontName(String fName) String fName = myObject.getFontName() myObject.setFontSize(int tSize) int tSize = myObject.getFontSize() myObject.setBold(boolean isBold) boolean isBold = myObject.getBold() myObject.setItalic(boolean isItalic) boolean isItalic = myObject.getItalic() Шрифт, используемый при выводе текста в ячейках: имя шрифта (FontName), размер (FontSize) и стиль шрифта (обычный, полужирный (Bold), курсив (Italic)…). В качестве значения параметра font применяется "строка из трех элементов", например, "Helvetica, 10, BOLD". В качестве значения свойства Font используется объект класса java.awt.Font. Параметр распространяет свое действие на всю таблицу, свойство же может применяться как к таблице, так и к ее диапазону.
Параметр и свойство numberFormat Sheet.setNumberFormat(String formatName) Range.setNumberFormat(String formatName, int decimals) String formatName = Sheet.getNumberFormat() String formatName = Range.getNumberFormat() Название формата, в соответствии с которым в ячейках таблицы отображаются числовые значения. Основные форматы: "General" (общий, по умолчанию), "Fixed" (фиксированный), "Comma" (с разделителем групп разрядов), "Scientific" (экспоненциальный), "Percent" (процентный). Кроме того, могут использоваться многочисленные «денежные» форматы, например, "US Dollar","ISO US Dollar", "Russian Ruble", "ISO Russian Ruble", "Ukrainian Hryvnia", "Belarusian Ruble", а так же форматы для представления «дата-временных» значений. Полный список приведен в документации по eSuite DevPack. Параметр распространяет свое действие на всю таблицу, свойство же может применяться как к таблице, так и к ее диапазону.
© InterTrust Co. Тел. 956-7928, 956-7929
236
Применение eSuite DevPack 1.0
Параметр и свойство NumberFormatDecimals Sheet.setNumberFormatDecimals(int numDecimals) int numDecimals = Sheet.getNumberFormatDecimals() int numDecimals = Range.getNumberFormatDecimals() Для ряда числовых форматов задает количество знаков в представлении чисел. Допустимые значения от 0 до 15. По умолчанию 0. Параметр и установка свойства распространяют свое действие на всю таблицу, чтение же свойства может применяться как для таблицы, так и для ее диапазона.
Параметр и свойство TextColor myObject.setTextColor(java.awt.Color tColor) java.awt.Color tColor = myObject.getTextColor() Цвет текста в ячейках таблицы. В качестве значения параметра могут задаваться названия цветов: "aqua", "black" (значение по умолчанию), "blue", "cyan", "darkGray", "fuchsia", "gray", "green", "grey", "lightGray", "lime", "magenta", "maroon", "navy", "olive", "orange", "pink", "purple", "red", "silver", "teal", "white", "yellow", или «строковые шестнадцатеричные RGBзначения» цветов, например "FF00FF". В качестве значения свойства используется объект класса java.awt.Color, а для его создания в JavaScript может применяться метод createColor() апплета ScriptHelper. Параметр распространяет свое действие на всю таблицу, свойство же может применяться как к таблице, так и к ее диапазону.
Параметр и свойство BackgroundColor myObject.setBackgroundColor(java.awt.Color backgroundColor) java.awt.Color backgroundColor = myObject.getBackgroundColor() Фоновый цвет для ячеек таблицы. В качестве значения параметра могут задаваться названия цветов (см. параметр и свойство TextColor, значение по умолчанию - "white") или «строковые шестнадцатеричные RGB-значения» цветов, например "FF00FF". В качестве значения свойство используется объект класса java.awt.Color, а для его создания в JavaScript может применяться метод createColor() апплета ScriptHelper. Параметр распространяет свое действие на всю таблицу, свойство же может применяться как к таблице, так и к ее диапазону.
Параметр и свойство BackgroundImageName Sheet.setBackgroundImageName(String fileName) String fileName = Sheet.getBackgroundImageName() URL для файла, содержащего изображение, применяемое в качестве фонового для таблицы. Должен задаваться или абсолютный URL или URL относительно документа, содержащего апплет. Поддерживаются форматы .jpg и .gif.
Параметр и свойство FrameColor
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 237
Sheet.setFrameColor(java.awt.Color theColor) java.awt.Color theColor = Sheet.getFrameColor() Цвет рамки таблицы. В качестве значения параметра могут задаваться названия цветов (см. параметр и свойство TextColor, значение по умолчанию - "green") или "строковые шестнадцатеричные RGB-значения" цветов, например "FF00FF". В качестве значения свойство используется объект класса java.awt.Color, а для его создания в JavaScript может применяться метод createColor() апплета ScriptHelper.
Параметр и свойство Protection myObject.setProtection(boolean isProtected) boolean isProtected = myObject.getProtection() Если значение параметра равно true, все ячейки таблицы будут «защищены» от редактирования пользователем. По умолчанию значение параметра false (информацию в ячейках можно редактировать). Свойство же может применяться как к объекту Sheet (вся таблица), так и к объекту Range (диапазон таблицы). Для таблицы свойство возвращает true, если «защищены» все ячейки таблицы, кроме тех, которые явно входят в «незащищенные» диапазоны. Соответственно, установка свойства для таблицы затрагивает все ячейки таблицы, но кроме тех, которые уже явно входят в диапазоны с иным значением свойства. Для диапазона свойство возвращает true, если все ячейки в этом диапазоне «защищены», иначе (если имеются «незащищенные») - false. Установка свойства для диапазона затрагивает только ячейки в этом диапазоне. По умолчанию в качестве значения свойства для таблицы выбирается false, а для диапазона - true. В связи с таким определением свойства в случае, когда требуется «защитить» все ячейки таблицы, за исключением только некоторых из них, вначале рационально определить диапазоны для этих «некоторых» ячеек и «снять защиту» для этих диапазонов, после чего «установить защиту» для всей таблицы.
Параметры и свойства ColumnHeadingsVisible и RowHeadingsVisible Sheet.setColumnHeadingsVisible(boolean isVisible) boolean isVisible = Sheet.getColumnHeadingsVisible() Sheet.setRowHeadingsVisible(boolean isVisible) boolean isVisible = Sheet.getRowHeadingsVisible() Если значение равно true, заголовки столбцов и строк «видимы» (отображаются апплетом), если false - «не видимы». Значение по умолчанию true.
Параметры и свойства ColumnWidth и RowHeight myObject.setColumnWidth(int width) int width = myObject.getColumnWidth() myObject.setRowHeight(int height)
© InterTrust Co. Тел. 956-7928, 956-7929
238
Применение eSuite DevPack 1.0
int height = myObject.getRowHeight() ColumnWidth определяет ширину столбцов; начальное значение - 10 символов, допустимый диапазон значений - от 1 до 240 символов. RowHeight определяет высоту строк таблицы; начальное значение - 16 пунктов (point's), допустимый диапазон значений - от 1 до 255 пунктов. Установка значения параметра распространяется на всю таблицу, свойство же может применяться как к таблице, так и к ее диапазону.
Параметры и свойства AdornmentsVisible, EditLineVisible, StatusLineVisible, HorizontalScrollBarVisible, VerticalScrollBarVisible Sheet.setAdornmentsVisible(boolean isVisible) boolean isVisible = Sheet.getAdornmentsVisible() Sheet.setEditLineVisible(boolean isVisible) boolean isVisible = Sheet.getEditLineVisible() Sheet.setStatusLineVisible(boolean isVisible) boolean isVisible = Sheet.getStatusLineVisible() Sheet.setHorizontalScrollBarVisible(boolean isVisible) boolean isVisible = Sheet.getHorizontalScrollBarVisible() Sheet.setVerticalScrollBarVisible(boolean isVisible) boolean isVisible = Sheet.getVerticalScrollBarVisible() Если параметр или свойство AdornmentsVisible имеют значение true, все элементы управления таблицей - строка редактирования, строка состояния и обе полосы прокрутки отбражаются апплетом («видимы»), если false - не отображаются. Параметры и свойства EditLineVisible (строка редактирования), StatusLineVisible (строка состояния), HorizontalScrollBarVisible (горизонтальная полоса прокрутки), VerticalScrollBarVisible (горизонтальная полоса прокрутки) определяют «видимость» каждого из этих элементов. По умолчанию все элементы управления «видимы» (значение true).
Параметр и свойство GridLinesVisible Sheet.setGridLinesVisible(boolean isVisible) boolean isVisible = Sheet.getGridLinesVisible() Если параметр или свойство имеют значение true, сетка (линии, разделяющие ячейки) отображается апплетом («видима»), если false - не отображается. По умолчанию сетка отображается (значение true).
Свойство Border и метод clearBorder Range.setBorder(String borderType, java.awt.Color borderColor)
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 239
String borderType = Range.getBorderType() java.awt.Color borderColor = Range.getBorderColor() Range.clearBorder() Тип и цвет бордюра, «обрамляющего» диапазон. Тип может быть одним из следующих: "all", "outer", "inner", "horizontal", "vertical", "left", "right", "top", "bottom". Цвет задается объектом класса java.awt.Color, значение по умолчанию Color.black. В JavaScript объект java.awt.Color обычно создают методом createColor() апплета ScriptHelper. Для «очистки» бордюра, ранее установленного свойством setBorder, используется метод clearBorder().
Свойства ColumnHidden и RowHidden Range.setColumnHidden(boolean isHidden) boolean isHidden = Range.getColumnHidden() Range.setRowHidden(boolean isHidden) boolean isHidden = Range.getRowHidden() Установка свойства в значение true «скрывает» все столбцы (ColumnHidden) или строки (RowHidden) диапазона, а в значение false - «превращает скрытые» столбцы или строки в «видимые». Свойство возвращает true, если все столбцы или строки в диапазоне «скрыты», иначе false.
Свойства HorizontalPageBreak и VerticalPageBreak Range.setHorizontalPageBreak(boolean isInserted) boolean isInserted = Range.getHorizontalPageBreak() Range.setVerticalPageBreak(boolean isInserted) boolean isInserted = Range.getVerticalPageBreak() Установка свойства в значение true вставляет признак перехода на новую страницу непосредственно перед верхней (HorizontalPageBreak) или перед левой (VerticalPageBreak) границей диапазона, а в значение false - убирает ранее установленный признак перехода на новую страницу.
Свойство RecalcManual и метод recalc Sheet.setRecalcManual(boolean isManual) boolean isManual = Sheet.getRecalcManual() Sheet.recalc() Значение true включает для таблицы режим «ручного» пересчета вычисляемых ячеек, значение false - режим автоматического пересчета. Пересчет вычисляемых ячеек таблицы инициируется методом recalc().
Методы deleteColumns и deleteRows Range.deleteColumns() Range.deleteRows() Удаляют столбцы (deleteColumns) или строки (deleteRows), входящие в диапазон.
© InterTrust Co. Тел. 956-7928, 956-7929
240
Применение eSuite DevPack 1.0
Методы insertColumns и insertRows Range.insertColumns(int numCols) Range.insertRows(int numRows) Добавляют в таблицу непосредственно перед левой (insertColumns) или верхней (insertRows) границей диапазона заданное количество пустых строк или столбцов.
Методы getCellContents, getCellValueAsString, getCellValueAsNumber String theContents = Range.getCellContents() String theValue = Range.getCellValueAsString() double theNumber = Range.getCellValueAsNumber() Метод getCellContents() возвращает содержимое левой верхней ячейки диапазона в форме строки. Для ячейки, содержащей формулу, возвращает строковое представление самой формулы, а не ее значения. Метод getCellValueAsString() возвращает в форме строки значение из левой верхней ячейки диапазона. Для ячейки, содержащей формулу, возвращает строковое представление значения этой формулы. Метод getCellValueAsNumber() возвращает вещественное число, содержащееся в левой верхней ячейки диапазона. Если значение ячейки не может быть преобразовано в число, возвращается 0.
Методы setCellContentsFromString и setCellContentsFromNumber Range.setCellContentsFromString(String contents) Range.setCellContentsFromNumber(double contents) Методы заносят в левую верхнюю ячейку диапазона указанное строковое или числовое значение. Если значение метода setCellContentsFromString содержит формулу, то в ячейку заносится формула.
Методы isEmptyCell, isNumberCell, isStringCell, isFormulaCell, isNACell, isERRCell boolean isEmpty = Range.isEmptyCell() boolean isNumber = Range.isNumberCell() boolean isString = Range.isStringCell() boolean isFormula = Range.isFormulaCell() boolean isNA = Range.isNACell() boolean isERR = Range.isERRCell() Возвращают true, если в левой верхней ячейке диапазона содержится "пустое" значение (isEmptyCell), числовое значение (isNumberCell), строковое значение (isStringCell), формула (isFormulaCell), значение неопределенного типа (isNACell), или в формуле имеется ошибка (isERRCell). В противном случае возвращается false.
Методы clear, cut, copy, paste Range.clear()
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 241
Range.cut() Range.copy() Range.paste() Методы реализуют основные операции с буфером обмена на уровне диапазонов таблицы. Метод clear() удаляет диапазон из таблицы без помещения его копии в буфер обмена, а cut() - с помещением его копии в буфер обмена. Метод copy() помещает копию диапазона в буфер обмена, не удаляя при этом сам диапазон в таблице. Метод paste() помещает информацию из буфера обмена в диапазон, к которому применяется метод.
Метод scrollTo Sheet.scrollTo(Range scrollRange) «Прокручивает» таблицу в окне апплета так, чтобы «стал виден» верхний левый угол диапазона.
Метод sort Sheet.sort(Range primaryKey, boolean primaryAscending, Range secondaryKey, boolean secondaryAscending) Выполняет сортировку строк всей таблицы по значениям в одном или в двух ее столбцах. Диапазон primaryKey должен определять столбец, значения из которого используются при сортировке в качестве первичного ключа. Если флаг primaryAscending равен true, сортировка выполняется по возрастанию значения первичного ключа, если false - по убыванию первичного ключа. Диапазон secondaryKey должен определять столбец, значения из которого используются в качестве вторичного ключа. Если флаг secondaryAscending равен true, сортировка выполняется по возрастанию вторичного ключа, если false - по убыванию вторичного ключа. Чтобы сортировка выполнялась только по одному столбцу (столбцу первичного ключа), необходимо в качестве значения аргумента secondaryKey передать null, а в качестве secondaryAscending - false.
Методы printDocument и printRange Sheet.printDocument() Sheet.printRange(Range theRange) Выполняют печать содержимого всей таблицы или ее диапазона.
11.10. Апплет WordProcessor – текстовый процессор Апплет WordProcessor реализует достаточно мощный тестовый редактор, поддерживающий форматирование, вставку в документ полей, таблиц, изображений, гипертекстовых ссылок и т.п. Он поддерживает работу с документами форматов HTML 3.2 и ASCII и импорт документов формата RTF. Байт-код апплета - WordProcessor.class. Для работы апплета в броузер должен быть загружен один из JAR-архивов devpack_wp_app.jar, devpack_wp_app_unsigned.jar, devpack_wp_lite.jar или три CAB-архива devpack_infobus.cab, devpack_shared.cab и devpack_wp.cab. Пример 1. Фрагмент HTML-кода, который «минимально-необходим» для запуска апплета WordProcessor с «видимым» InfoCenter. При своей инициализации апплет загружает файл 1.html-wp, расположенный на Web-сервере.
© InterTrust Co. Тел. 956-7928, 956-7929
242
Применение eSuite DevPack 1.0
<APPLET CODEBASE="/eSuiteDP" CODE="lotus.fc.AppletContainer" ARCHIVE="/eSuiteDP/jars/devpack_wp_app.jar" WIDTH=640 HEIGHT=250>
Рис. 11.24 Апплет WordProcessor с видимым InfoCenter Все основные параметры, свойства и методы апплета WordProcessor во многом аналогичны параметрам, свойствам и методам апплета Sheet. Рассмотрим свойства и методы, которые применяются для создания, редактирования и печати документа в апплете WordProcessor. Эти свойства и методы можно разделить на следующие группы:
• • • • •
изменение внешнего вида текстового редактора; перемещение по редактируемому тексту; редактирование текста, вставка и получение фрагментов текста; форматирование текста; печать документа.
11.10.1.
Изменение внешнего вида текстового редактора
Фоновое изображение WordProcessor.setBackgroundImageName(String bgImageName) String bgImageName = WordProcessor.getBackgroundImageName() Установка и получение имя файла с изображением, которое будет использоваться в качестве фона. Изображение должно быть в формате JPEG или GIF.
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 243
Параметры фонового изображения WordProcessor.setBackgroundImageOptions(String bgimageOptions) String bgimageOptions = WordProcessor.getBackgroundImageOptions() Установка и получение параметров фонового изображения. Параметром является строка с одним из двух значений: “titled” или “nottitle”. Если значение равно “titled”, то фоновое изображение будет повторяться столько раз, сколько будет необходимо, чтобы заполнить все поле редактирования, в противном случае, фоновое изображение будет отображаться в центре поля редактирования.
Цвет текста WordProcessor.setTextColor(java.awt.Color color) java.awt.Color color = WordProcessor.getTextColor() Установка и получение цвета текста.
Цвет фона WordProcessor.setBackgroundColor(java.awt.Color color) java.awt.Color color = WordProcessor.getBackgroundColor() Установка и получение цвета фона.
Цвет гипертекстовых ссылок WordProcessor.setLinkColor(java.awt.Color color) java.awt.Color color = WordProcessor.getLinkColor() Установка и получение цвета гипертекстовых ссылок.
Цвет границы вокруг объектов WordProcessor.setBorderColor(java.awt.Color color) java.awt.Color color = WordProcessor.getBorderColor() Установка и получение цвета границы, вокруг объектов (например, вокруг вставленного в документ изображения).
Цвет зачеркивающей линии WordProcessor.setStrikethroughColor(java.awt.Color color) java.awt.Color color = WordProcessor.getStrikethroughColor() Установка и получение цвета линии, которая будет перечеркивать текст, обозначенный как «зачеркнутый».
Цвет полосы смещения WordProcessor.setMarginColor(java.awt.Color color) java.awt.Color color = WordProcessor.getMarginColor() Установка и получение цвета полосы смещения, находящуюся слева от редактируемого текста.
© InterTrust Co. Тел. 956-7928, 956-7929
244
Применение eSuite DevPack 1.0
Цвет поля ввода и подсказки WordProcessor.setClickHereColor(java.awt.Color color) java.awt.Color color = WordProcessor.getClickHereColor() Установка и получение цвета поля ввода типа ClickHere и подсказки к нему.
Режим масштабирования шрифтов WordProcessor.setScaleFonts(boolean flag) boolean flag = WordProcessor.getScaleFonts() Установка и получение режима масштабирования шрифтов. Если значение true, то тестовый процессор принудительно масштабирует шрифты в соответствии с установленными для масштабирования значениями.
Коэффициенты деления и умножения при масштабировании шрифтов WordProcessor.setFontScaleDivisor(int denominator) int denominator = WordProcessor.getFontScaleDivisor() Установка и получение делителя масштабирования шрифтов. Размер шрифта будет уменьшен в заданное количество раз.
Коэффициент умножения при масштабировании шрифтов WordProcessor.setFontScaleMultiplier(int multi) int multi = WordProcessor.getFontScaleMultiplier() Установка и получение множителя масштабирования шрифтов. Размер шрифта будет увеличен в заданное количество раз.
Режим предварительного просмотра WordProcessor.setPrintPreview(boolean flag) boolean flag = WordProcessor.getPrintPreview() Установка и получение режима предварительно просмотра. Если значение true, то в документе отображаются разрывы страниц, номера страниц, нижние и верхние колонтитулы.
11.10.2.
Перемещение по редактируемому тексту
Большинство функций для перемещения по тексту имеет единственный параметр select типа boolean. Если этот параметр равен true, то текст, по которому будет происходить перемещение, будет выделяться, так, как если бы вы при перемещении по тексту с помощью клавиатуры держали бы нажатой клавишу SHIFT. Возвращаемое значение имеет тип boolean, и если оно равно true, то операция перемещения прошла успешно. status = WordProcessor.left(select) Перемещение на один символ влево. status = WordProcessor.right(select) Перемещение на один символ вправо. status = WordProcessor. gotoPreviousCharacter(select)
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 245
Перемещение на один символ влево. status = WordProcessor. gotoNextCharacter(select) Перемещение на один символ вправо. status = WordProcessor. gotoPreviousWord(select) Перемещение на начало предыдущего слова. status = WordProcessor. gotoNextWord(select) Перемещение на начало следующего слова. status = WordProcessor.gotoPreviousLine(select) Перемещение на одну строку вверх. status = WordProcessor.gotoNextLine(select) Перемещение на одну строку вниз. status = WordProcessor.gotoBeginningOfLine(select) Перемещение в начало строки. status = WordProcessor.gotoEndOfLine(select) Перемещение в конец строки. status = WordProcessor.gotoBeginningOfWord(select) Перемещение в начало слова. status = WordProcessor.gotoEndOfWord(select) Перемещение в конец слова. status = WordProcessor.gotoBeginningOfParagraph(select) Перемещение в начало текущего параграфа. status = WordProcessor.gotoEndOfParagraph(select) Перемещение в конец текущего параграфа. status = WordProcessor.gotoBeginningOfDocument(select) Перемещение в начало документа. status = WordProcessor.gotoEndOfDocument(select) Перемещение в конец документа. status = WordProcessor. backspace() Удаление предыдущего символа Эквивалентно нажатию на клавишу Backspace. status = WordProcessor.gotoPage(page, select) Перемещение на страницу, номер которой задан параметром page типа int. status = WordProcessor.gotoText(text, select) Перемещение к местонахождению текста, заданного параметром text класса String.
© InterTrust Co. Тел. 956-7928, 956-7929
246
Применение eSuite DevPack 1.0
status = WordProcessor.gotoHeader() Перемещение в начало верхнего колонтитула. status = WordProcessor.gotoFooter() Перемещение в начало нижнего колонтитула. int page = WordProcessor.getCurrentPageNumber() Получить номер текущей страницы.
11.10.3.
Редактирование текста, вставка и получение фрагментов текста
Получить символ String character = WordProcessor.getCharacter() Получить символ, расположенный в местонахождении курсора.
Получить слово String word = WordProcessor.getWord() Получить слово, расположенное в местонахождении курсора.
Получить параграф String paragraph = WordProcessor.getParagraph() Получить параграф, расположенный в местонахождении курсора.
Получить выделенный текст String text = WordProcessor.getSelectedText() Получить выделенный (подсвеченный) фрагмент документа.
Стандартные операции текстового процессора boolean status = WordProcessor.undo() Отменяет предыдущее действие с документом. boolean status = WordProcessor.copy() Копирует выделенный фрагмент документа в буфер обмена. boolean status = WordProcessor.cut() Копирует выделенный фрагмент документа в буфер обмена и удаляет выделенный фрагмент. boolean status = WordProcessor.paste() Вставляет в документ текст, находящийся в буфере обмена.
Получить количество страниц в документе int count = WordProcessor.getPageCount() © InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 247
Получить количество слов в документе int count = WordProcessor.getWordCount()
Содержимое документа в виде текста WordProcessor.setDocumentContents(String contents) String contents = WordProcessor.getDocumentContents() Получить и установить содержимое документа без команд форматирования (команд HTML). Абзацы отделяются друг от друга ASCII символами «новая строка».
Содержимое документа в виде текста WordProcessor.setDocumentContentsAsHTML(String contents) String contents = WordProcessor.getDocumentContentsAsHTML() Получить и установить содержимое документа, включая команды форматирования (команды HTML).
Номер первой страницы WordProcessor.setStartingPageNumber(int pageNum) int pageNum = WordProcessor.getStartingPageNumber() Получить и установить номер первой страницы документа.
Вставка текста в документ boolean status = WordProcessor.insertText(String text) Вставка текста в документ в местонахождение курсора.
Вставка конца строки boolean status = WordProcessor.insertLineBreak() Вставка конца строки перед курсором. Новый абзац не создается.
Вставка конца страницы boolean status = WordProcessor.insertPageBreak() Вставка конца страницы в местонахождение курсора.
Вставка конца абзаца boolean status = WordProcessor.splitParagraph() Вставка конца абзаца в местонахождение курсора.
11.10.4.
Печать документа
Печать всего документа boolean status = WordProcessor.printDocument()
© InterTrust Co. Тел. 956-7928, 956-7929
248
Применение eSuite DevPack 1.0
Документ печатается на выбранном в данный момент принтере. Если результат выполнения данного метода равен true, то печать завершилась успешно. В случае ошибки, значение равно false.
Печать части страниц документа документа boolean status = WordProcessor.printRange(int start, int end) Печать документа, начиная со страницы start и заканчивая страницей end.
Горизонтальный отступ для печати WordProcessor.setPrintOffsetLeft(int offset) int offset = WordProcessor.getPrintOffsetLeft() Установка и получение отсупов между документом и краем печатного листа по горизонтали.
Вертикальный отступ для печати WordProcessor.setPrintOffsetTop(int offset) int offset = WordProcessor.getPrintOffsetTop() Установка и получение отсупов между документом и краем печатного листа по вертикали.
11.11. Завершая рассмотрение eSuite DevPack Из числа входящих в состав eSuite DevPack 1.0 нами не были рассмотрены апплеты Scheduler (планировщик проектов) и Presentation (редактор-демонстратор презентационной графики). Это относительно сложные, с большим количеством параметров, свойств и методов, апплеты. Однако авторы выражают сомнение, что эти апплеты станут столь же широко применяться на практике, как, например, WordProcessor, Sheet или Chart. Поэтому ограничим их рассмотрение единственным примером. Пример 1. Хотя это и не логично, поместим в апплет AppletContainer сразу два «никак не связанных друг с другом» апплета - Scheduler и Presentation. <APPLET CODEBASE="/eSuiteDP" CODE="lotus.fc.AppletContainer" WIDTH=640 HEIGHT=400>
NAME="applet0" VALUE="lotus.graphics.Presentation"> NAME="name0" VALUE="pre"> NAME = "pre.backgroundColor" VALUE = "white"> NAME="pre.height" VALUE="200">
© InterTrust Co. Тел. 956-7928, 956-7929
Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 249
Рис. 11.25 Апплеты Scheduler и Presentation в AppletContainer.Поскольку «текущим» выбран апплет Presentation, отображается его InfoCenter Ожидается, что в состав eSuite DevPack 1.5 будут добавлены еще два апплета: Calendar (работа с календарем) и Address Book (книга адресов). Много других достаточно интересных примеров применения апплетов eSuite DevPack 1.0 можно найти в базе данных eSuite DevPack 1.0 Leaning Center, которая в настоящее время доступна по ссылке http://www.lotus.com/learningcenters/esuitelc.nsf. В целом eSuite DevPack 1.0 воспринимается авторами как теоретически правильный, несомненно перспективный, уже вполне работоспособный, но все еще «немного сырой» продукт, особенно в части поставляемой с ним документации. Поэтому авторы призывают читателей не судить их строго, если обнаружатся отдельные неточности в материале данной главы.
© InterTrust Co. Тел. 956-7928, 956-7929
250 Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0
ЛИТЕРАТУРА 1. К. Джамса, С. Лалани, С. Уикли. Программирование в Web для профессионалов. Пер. с англ. - Мн.: ООО "Попурри", 1997. -632 с. 2. С. Спейнаур, В. Куэрсиа. Справочник Web-мастера. Пер. с англ. - К.: Издательская группа BHV, 1997. -368 c. 3. Н.Н. Ионцев. Администрирование Lotus Notes версий 4.1.x и Lotus Domino версий 4.5.x. Новые возможности сервера Lotus Domino 4.6. - М., Изд. фирма «Светотон», 1998. - 405 с. 4. Н.Н. Ионцев, В.К. Кулаков, В.А. Панов. Lotus Notes R. 4: разработка приложений, язык LotusScript, встроенные классы. - М., Изд. компания «Научная книга», 1996. - 574 с. 5. http://www.machaon.ru/digest/rusinter.HTML.html. Введение в HTML на WWW-сервере Махаон. Ссылки на различные руководства, справочники и прочие пособия по WWW и HTML.
© InterTrust Co. Тел. 956-7928, 956-7929
251 Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0
ПРЕДМЕТНЫЙ УКАЗАТЕЛЬ $$HTMLHead, 56, 58 для фреймов, 73
&OldSearchQuery, 41 &ParentUNID, 39
$$NavigatorBody, 56, 58
&Query, 41
$$NavigatorTemplate, 59
&SearchMax, 41
$$NavigatorTemplateDefault, 59
&SearchOrder, 41
$$QueryOpenAgent, 57, 69
&SearchThesaurus, 41
$$QuerySaveAgent, 70
&SearchWordVariants, 41
$$Return, 56
&Start, 40
$$ReturnAuthenticationFailure, 60
?CreateDocument, 37
$$ReturnAuthorizationFailure, 60
?DeleteDocument, 37
$$ReturnDocumentDeleted, 60
?EditDocument, 37
$$ReturnGeneralError, 60
?Open, 35
$$Search, 59
?OpenAbout, 36
$$SearchSiteTemplate, 60
?OpenAgent, 42
$$SearchTemplate, 60
?OpenDatabase, 36
$$SearchTemplateDefault, 60
?OpenDocument, 37
$$ViewBody, 56, 58
?OpenElement, 38
$$ViewList, 56, 59
?OpenForm, 39
$$ViewTemplate, 59
?OpenHelp, 36
$$ViewTemplateDefault, 59
?OpenIcon, 36
$Body, 47
?OpenNavigator, 41
$defaultform, 39
?OpenServer, 35
$defaultNav, 42
?OpenView, 40
$defaultView, 40
?ReadForm, 39
$File, 38, 47
?SaveDocument, 38
$icon, 36
?SearchSite, 41
$OLEOBJINFO, 38
?SearchView, 41
$SearchForm, 41
Active Server Pages, 30
&Collapse, 40
AppAssembler, 74
&CollapsView, 40
Certificate Authority (CA), 123
&Count, 40, 61
CGI, 29, 53
&Expand, 40
AUTH_TYPE, 30
&ExpandSection, 39
CONTENT_LENGTH, 31, 32
&ExpandView, 40
CONTENT_TYPE, 31, 32
&FieldElemFormat, 38
Content-type, 32
&Login, 36
GATEWAY_INTERFACE, 31 © InterTrust Co. Тел. 956-7928, 956-7929
252 Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0
Location, 32
… , 24
QUERY_STRING, 30, 31
... , 8
REMOTE_ADDR, 31
, 11
REMOTE_ADDR, пример, 66
, 18
REMOTE_HOST, 31
<MAP>…, 22
REMOTE_IDENT, 31
<META>, 13
REMOTE_USER, 31, 53
<META>, пример, 77
REQUEST_METHOD, 32, 67
… , 24
SERVER_NAME, 32
… , 10
SERVER_PORT, 32
, 18
SERVER_PROTOCOL, 32
...
, 8
Status, 32
… , 9
DocumentContext, 66
<SCRIPT>…, 27
Domino, 30
<SELECT>…, 18
Domino.Action, 74
, 14
Domino.Merchant, 74, 84
… ., 15
FAQ, 71
… , 18
Folders, 42
… ., 15
FRAMESET
, 10
база, 72
ACTION, 16
пример, 82
ARCHIVE, 26
GET, 5, 32, 66
Author, 14
getenv(), 30, 32
CODE, 26
GIF89a, 46
CODEBASE, 26
Go WebServer, 30
Content-language, 14
GWAPI, 29
Content-type, 14
HEAD, 6, 32
COORDS, 22
HTML
Copyright, 14
&-последовательности, 7
Description, 14
, 8
ENCTYPE, 16
, 12
FACE, 80
, 13
Generator, 14
… , 12
HREF, 22
<APPLET>…, 26
HTTP-EQUIV, 14
, 22
LANGUAGE, 27
, 9
METHOD, 16
… , 16
NOHREF, 22
, 24
Refresh, 14
© InterTrust Co. Тел. 956-7928, 956-7929
253 Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0
SHAPE, 22
TCP/IP, 5
изображения, 11
Treat document contents as HTML, 44, 58
карты-изображения, 22, 61
Trusted Roots, 124
комментарии, 8
Upload, 59
ненумерованный список, 10
URL, 3, 29
нумерованный список, 10
абсолютные, 3
представление абзацев в виде списков, 10
относительные, 4
служебная информация, 13
VBScript, 27, 29
таблицы, 14
Versoning, 43
теги, 7
ViewNextPage, 61
форматирование текста в документе, 8
ViewPreviousPage, 61
формы, 16
Web Pages
фреймы, 23
базы, 73
HTML Attributes, 58
WebQueryOpen, 53, 69
HTML-поле, 58
WebQuerySave, 70
IP-адрес, 3
WebSphere Application Server, 30
ISAPI, 29
World Wide Web, 29
Java Servlet Development Kit, 30
Активный броузер, 29
Java WebServer, 30
Активный сервер, 29
JavaScript, 27, 29
Алгоритм хеширования MD5, 118
Java-апплеты, 26
Алгоритм шифрования RSA, 117
JPEG, 46
Алгоритмы шифрования DES, RC4, IDEA, 120
KeyRing-файл (Key Ring File), 126 Lines per view page, 61 MIME, 5, 31 NSAPI, 29 Pass-Thru HTML, 58
Апплет AppletContainer AppletIndex, 192 appletn, 192 appletName.PARAM, 192 compactInfoCenter, 193
PKCS (Public Key Cryptography Standards), 136
findContainedApplet, 193
POST, 6, 31, 32, 66
findContainedAppletByIndex, 193
printf(), 32
getContainedAppletCount, 192
Rollover, 50
height, 193
Run agent as Web User, 65
infoCenterVisible, 193
scanf(), 32
layoutStyle, 194
Secure Sockets Layer (SSL), 117
namen, 192
SSL Handshake, 122
propertyBagn, 194
stdin, 30
width, 193
stdout, 30 Submit, 48
Апплет Chart AppletLocale, 197 © InterTrust Co. Тел. 956-7928, 956-7929
254 Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0
backgroundColor, 201
LeaderLineVisible, 221
BackgroundImage, 202
legendBackgroundColor, 202
BackgroundImageName, 202
legendBackgroundTransparent, 202
backgroundImageOptions, 202
legendBorderLineColor, 204
BackgroundTransparent, 202
legendBorderLineWidth, 205
Bold, 206
legendBorderVisible, 204
BorderColor, 204
LegendFont, 206
BorderLineWidth, 204
LegendItemName, 198
BorderVisible, 210
legendPosition, 203
CharacterEncoding, 197
legends, 198
ConnectPoints, 218
legendTextColor, 205
createSeries, 197
LegendVisible, 203
Data, 217
LineColor, 212
DataInputIndirectItemName, 198
LineWidth, 205, 211
dataInputItemName, 198
MajorGridColor, 212
DataInputItemName, 198
MajorGridVisible, 212
Elevation, 200
MajorGridWidth, 213
findLegend, 196
MajorStep, 214
findNote, 196
MajorTickColor, 214
findPlot, 196
MajorTicksVisible, 213
findSeries, 196
MajorTickWidth, 214
findTitle, 196
MarkerColor, 219
findXAxis, 196
MarkerSize, 219
findXAxisTitle, 196
MarkerType, 219
findYAxis, 196
MarkerVisible, 218
findYAxisTitle, 196
Maximum, 214
Font, 206
Minimum, 214
FontName, 206
MinorGridColor, 212
FontSize, 206
MinorGridVisible, 212
getDocumentName, 207
MinorGridWidth, 213, 214
getIndex, 216
MinorStep, 214
hasData, 217
MinorTickColor, 214
height, 198
MinorTicksVisible, 213
InfoCenterProfileName, 208
newDocument, 207
isChanged, 208
note, 199
isRefreshEnabled, 207
noteAlignment, 204
Italic, 206
noteBackgroundColor, 202
LabelsPosition, 220
noteBackgroundTransparent, 202
© InterTrust Co. Тел. 956-7928, 956-7929
255 Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0
noteBorderLineColor, 204
seriesLeaderLinesVisible, 221
noteBorderLineWidth, 205
seriesLineWidths, 218
noteBorderVisible, 204
seriesMarkerColors, 219
NoteFont, 206
seriesMarkerSizes, 219
noteTextColor, 205
seriesMarkersVisible, 218
NoteVisible, 203
seriesMarkerTypes, 219
NumberFormat, 216
seriesMixedType, 217
NumberFormatDecimals, 216
seriesN, 217
openDocument, 208
seriesNumberFormat, 221
openDocumentFromStream, 208
seriesPercentsVisible, 221
ParseDirection, 200
SeriesType, 217
PercentLabelsVisible, 221
seriesValuesVisible, 220
Perspective, 199
seriesVisible, 222
PieLabelsVisible, 203
setRefreshEnabled, 207
PieMultiple, 201
Text, 210
PieSliceDirection, 201
TextColor, 205
PieSliceExplodePercent, 220
TextItemName, 210
plotBackgroundColor, 209
TickLabelsVisible, 215
plotBackgroundTransparent, 209
title, 199
plotBorderLineColor, 209
titleAlignment, 204
plotBorderLineWidth, 209
titleBackgroundColor, 202
plotBorderVisible, 209
titleBackgroundTransparent, 202
PlotLayout, 200
titleBorderLineColor, 204
Position, 203
titleBorderLineWidth, 205
refresh, 207
titleBorderVisible, 204
Rotation, 200
TitleFont, 206
saveDocument, 208
TitleTextColor, 205
saveDocumentToStream, 208
TitleVisible, 203
ScaleType, 215
UserInterfaceLanguage, 197
seriesBackgroundColors, 222
UserMajorStep, 215
seriesBackgroundTransparent, 222
UserMaximum, 215
seriesBorderLineColors, 222
UserMinimum, 215
seriesConnectPoints, 218
UserMinorStep, 215
SeriesCount, 196
UserTimeZone, 197
seriesLabelsFont, 221
ValueLabelsVisible, 220
seriesLabelsPosition, 220
Visible, 209, 222
seriesLabelsTextColors, 220
width, 198
SeriesLayout, 201
xAxisLabels, 199
© InterTrust Co. Тел. 956-7928, 956-7929
256 Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0
xAxisLabelsFont, 216
yAxisScaleMaximum, 215
XAxisLabelsItemName, 199
yAxisScaleMinimum, 215
XAxisLabelsPosition, 204
yAxisScaleMinor, 215
xAxisLabelsTextColor, 216
yAxisScaleType, 215
xAxisLabelsVisible, 215
yAxisTitle, 211
xAxisLineColor, 212
yAxisTitleFont, 211
xAxisLineVisible, 211
yAxisTitleTextColor, 211
xAxisLineWidth, 211
yAxisTitleVisible, 211
xAxisMajorGridColor, 212
Апплет FileReader
xAxisMajorGridsVisible, 212
debug, 169
xAxisMajorGridWidth, 213
DocumentName, 168
xAxisMajorTickColor, 214
DocumentNameItemName, 169
xAxisMajorTicksVisible, 213
OutputItemName, 168
xAxisMajorTickWidth, 214
verbose, 169
xAxisTitle, 211
Апплет FormReader
xAxisTitleFont, 211
abort, 180
xAxisTitleTextColor, 211
AllowUI, 179
xAxisTitleVisible, 211
CharacterEncoding, 178
yAxisLabelsFont, 216
Debug, 180
yAxisLabelsTextColor, 216
HTMLInputName, 179
yAxisLabelsVisible, 215
OutputItemName, 177
yAxisLineColor, 212
paramInputItemName, 178
yAxisLineVisible, 211
parse, 180
yAxisLineWidth, 211
SearchIndex, 178
yAxisMajorGridColor, 212
SearchString, 178
yAxisMajorGridsVisible, 212
URL, 178
yAxisMajorGridWidth, 213
Апплет Gateway
yAxisMajorTickColor, 214
ButtonLabel, 185
yAxisMajorTicksVisible, 213
cancelPost, 184
yAxisMajorTickWidth, 214
Debug, 185
yAxisMinorGridColor, 212
inputCharacterEncoding, 186
yAxisMinorGridsVisible, 212
inputName, 183
yAxisMinorGridWidth, 213
InputParameterString, 183
yAxisMinorTickColor, 214
inputType, 182
yAxisMinorTicksVisible, 213
inputValue, 183
yAxisMinorTickWidth, 214
outputCharacterEncoding, 186
yAxisNumberFormat, 216
outputFormat, 185
yAxisScaleMajor, 215
outputItemName, 186
© InterTrust Co. Тел. 956-7928, 956-7929
257 Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0
submit, 184
BackgroundImageName, 236
Trigger, 185
Bold, 234
UILevel, 184
Border, 238
URL, 183
characterEncoding, 232
URLEncode, 184
clear, 240
Апплет ScriptHelper
clearBorder, 238
Applet.openDocumentFromStream, 167
ColumnHeadingsVisible, 236
Applet.saveDocumentToStream, 166
ColumnHidden, 238
createColor, 166
ColumnWidth, 237
createDate, 166
copy, 240
createInfoBusVector, 160
createRangeName, 233
createInputStream, 167
cut, 240
createOutputBuffer, 166
deleteColumns, 239
createTimeZone, 166
deleteRangeName, 233
DataItemReader.dispose, 163
deleteRows, 239
DataItemReader.getDimensionCount, 162
documentName, 227
DataItemReader.getDimensionSize, 162
EditLineVisible, 237
DataItemReader.isArrayAccess, 162
findEntireSheetRange, 233
DataItemReader.isImmediateAccess, 162
findRangeByCoordinates, 233
DataItemReader.readArrayValueAsString, 162
findRangeByString, 233
DataItemReader.readImmediateValueAsObj ect, 162 DataItemReader.readImmediateValueAsStri ng, 162
Font, 234 FontName, 234 FontSize, 234 FrameColor, 236
findInfoBusItem, 161
getCellContents, 239
InfoBusVector.addValue, 160
getCellValueAsNumber, 239
InfoBusVector.appendColumnValue, 161
getCellValueAsString, 239
InfoBusVector.appendRow, 161
getEndColumn, 234
OutputBuffer.getOutputStream, 166
getEndRow, 234
OutputBuffer.getString, 167
getStartColumn, 234
publishStringToInfoBus, 161
getStartRow, 234
publishVectorToInfoBus, 161
GridLinesVisible, 238
readStringFromInfoBus, 161
height, 232
Апплет Sheet
HorizontalPageBreak, 238
AdornmentsVisible, 237
HorizontalScrollBarVisible, 237
alignment, 234
InfoCenterProfileName, 233
appletLocale, 232
insertColumns, 239
BackgroundColor, 235
insertRows, 239
© InterTrust Co. Тел. 956-7928, 956-7929
258 Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0
isChanged, 228
AllowUI, 189
isEmptyCell, 240
AutoConnect, 189
isERRCell, 240
Autoload, 189
isFormulaCell, 240
CharacterEncoding, 189
isNACell, 240
Command, 190
isNumberCell, 240
Database, 190
isStringCell, 240
Debug, 190
Italic, 234
Driver, 190
newDocument, 228
Host, 190
numberFormat, 235
Password, 190
NumberFormatDecimals, 235
Proxy, 191
openDocument, 228
Retrievals, 191
openDocumentFromStream, 228
User, 191
paste, 240
Апплет TableReader
printDocument, 241
abort, 174
printRange, 241
AllowUI, 173
Protection, 236
CharacterEncoding, 172
recalc, 239
Debug, 174
RecalcManual, 239
HTMLInputItemName, 173
RowHeadingsVisible, 236
OutputItemName, 172
RowHeight, 237
paramInputItemName, 173
RowHidden, 238
parse, 174
saveDocument, 228
SearchIndex, 172
saveDocumentToStream, 228
SearchString, 172
scrollTo, 240
URL, 172
Selection, 234
Апплет WordProcessor
setCellContentsFromNumber, 239
BackgroundColor, 242
setCellContentsFromString, 239
BackgroundImageName, 242
sort, 240
BackgroundImageOptions, 242
StatusLineVisible, 237
backspace, 245
TextColor, 235
BorderColor, 243
toString, 234
ClickHereColor, 243
userInterfaceLanguage, 232
copy, 246
userTimeZone, 232
cut, 246
VerticalPageBreak, 238
DocumentContents, 246
VerticalScrollBarVisible, 237
DocumentContentsAsHTML, 246
width, 233
FontScaleDivisor, 243
Апплет SQL/JDBC
© InterTrust Co. Тел. 956-7928, 956-7929
FontScaleMultiplier, 243
259 Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0
getCharacter, 245
ScaleFonts, 243
getCurrentPageNumber, 245
splitParagraph, 247
getPageCount, 246
StartingPageNumber, 246
getParagraph, 245
StrikethroughColor, 243
getSelectedText, 246
TextColor, 242
getWord, 245
undo, 246
getWordCount, 246
Базы данных
gotoBeginningOfDocument, 245
CERTCA.NSF, 127
gotoBeginningOfLine, 244
CERTSRV.NSF, 131, 132
gotoBeginningOfParagraph, 245
DOMCFG.NSF, 104
gotoBeginningOfWord, 244
DOMLOG.NSF, 101
gotoEndOfDocument, 245
Гипертекстовые ссылки, 12
gotoEndOfLine, 244
Документы
gotoEndOfParagraph, 245
Certificate Authority Profile, 129
gotoEndOfWord, 244
Certificate Request Approval, 140
gotoFooter, 245
Create Certificate Authority Key Ring, 128
gotoHeader, 245
Create Key Ring, 130, 133
gotoNextCharacter, 244
Create Server Certificate Request, 135
gotoNextLine, 244
Install Certificate into Key Ring, 141
gotoNextWord, 244
Install Trusted Root Certificate, 139
gotoPage, 245
Mapping Error Messages, 105
gotoPreviousCharacter, 244
Person, 144
gotoPreviousLine, 244
Server, Секция HTTP Server, 95
gotoPreviousWord, 244
Server, секция Internet Port and Security Configuration, 143, 146
gotoText, 245 insertLineBreak, 247 insertPageBreak, 247 insertText, 247 left, 244 LinkColor, 242 MarginColor, 243 paste, 246 printDocument, 247 PrintOffsetLeft, 247 PrintOffsetTop, 247 PrintPreview, 244 printRange, 247 right, 244
Server, Секция Internet Port and Security Configuration, 93 Submit a Server Certificate Request, 136 Virtual Server, 104 Ключ открытый (public), 117 секретный (private), 117 Ключ шифрования, 120 Переменные NOTES.INI BillingClass, 101 DominoAnalyzeFormulas, 99 DominoDefaultCacheValid, 100 DominoEnableJavaServlets, 111 DominoNoFace, 80
© InterTrust Co. Тел. 956-7928, 956-7929
260 Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0
DominoTraceCmdCache, 100
класс javax.servlet.GenericServlet, 106
JavaUserClasses, 111
класс javax.servlet.HttpServlet, 106
ServerTasks, 93
класс ServletManager, 111
Протоколы прикладного уровня
метод destroy, 107
FTP, 4
метод doGet, 107
HTTP, 4, 93
метод doPost, 107
mailto, 4, 5
метод getLastModified, 107
Сервлеты
метод getServletInfo, 107
интерфейс javax.servlet.http.HttpServletRequest, 107 интерфейс javax.servlet.http.HttpServletResponse, 107 интерфейс 107
javax.servlet.ServletRequest,
интерфейс 107
javax.servlet.ServletResponse,
метод init, 106 метод service, 106 файл SERVLET.CNF, 112 Сертификат X.509, 119, 123, 145 Сертификат, самоподписанный, 120 Скрипт, 27
© InterTrust Co. Тел. 956-7928, 956-7929
Файл *.KYR, 128, 131, 133
261 Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0
ОГЛАВЛЕНИЕ 1.
Введение в протокол HTTP........................................................................................ 3 1.1.
Гипертекстовые ссылки и URL .................................................................................... 3
1.1.1.
URL для протокола HTTP ..................................................................................................3
1.1.2.
Абсолютные URL................................................................................................................3
1.1.3.
Относительные URL ...........................................................................................................4
1.2.
Протокол HTTP.............................................................................................................. 4
1.2.1.
Обзор протокола HTTP.......................................................................................................4
1.2.2.
Основные методы запроса для протокола HTTP..............................................................5
2.
Введение в HTML ........................................................................................................ 7 2.1.
Создание документов HTML ........................................................................................ 7
2.1.1.
&-последовательности ........................................................................................................7
2.1.2.
Теги.......................................................................................................................................7
2.1.3.
Структура документа HTML..............................................................................................8
2.1.4.
Комментарии .......................................................................................................................8
2.1.5.
Форматирование текста в документе ................................................................................8
2.1.6.
Представление абзацев в виде списков ...........................................................................10
2.1.7.
Изображения в документе HTML....................................................................................11
2.1.8.
Гипертекстовые ссылки в документе HTML ..................................................................12
2.1.9.
Тег <META> - служебная информация в заголовке документа....................................13
2.2.
Таблицы в документах HTML .................................................................................... 14
2.3.
Формы в документах HTML ....................................................................................... 16
2.3.1.
Использование форм.........................................................................................................16
2.3.2.
Создание форм...................................................................................................................16
2.3.3.
Элементы форм .................................................................................................................17
2.4.
Карты-изображения ..................................................................................................... 22
2.5.
Фреймы ......................................................................................................................... 23
2.5.1.
Устройство фреймов .........................................................................................................23
2.5.2.
Создание фреймов.............................................................................................................24
2.5.3.
Описание фреймов ............................................................................................................24
2.6.
Java-апплеты................................................................................................................. 26
2.7.
JavaScript и VBScript.................................................................................................... 27
3.
Введение в серверные объекты ............................................................................... 29 3.1.
Что такое активный WWW-сервер............................................................................. 29
3.2.
Виды серверных объектов .......................................................................................... 29
3.3.
Программирование CGI-скриптов.............................................................................. 30
3.3.1.
Жизненный цикл CGI-скриптов.......................................................................................30
© InterTrust Co. Тел. 956-7928, 956-7929
262 Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0 3.3.2.
Переменные среды CGI.................................................................................................... 30
3.3.3.
Потоки ввода вывода stdin и stdout ................................................................................. 32
3.3.4.
Пример CGI-скрипта ........................................................................................................ 33
4.
Web-сервер Domino и интерпретация им URL .................................................... 35 4.1.
Общий вид URL Domino............................................................................................. 35
4.2.
URL для обращения к базам....................................................................................... 36
4.3.
URL для работы с документами................................................................................. 37
4.4.
URL для работы с видами и папками ........................................................................ 40
4.5.
Поисковые URL........................................................................................................... 41
4.6.
URL для открытия навигаторов ................................................................................. 41
4.7.
URL для запуска агентов ............................................................................................ 42
5.
Разработка форм для Web-приложений Domino................................................. 43 5.1.
Введение....................................................................................................................... 43
5.1.1.
Обзор свойств формы применительно к Web-приложениям........................................ 43
5.1.2.
Разные формы для пользователей Notes и Web ............................................................. 45
5.2.
Простые формы ........................................................................................................... 45
5.2.1.
Использование таблиц...................................................................................................... 45
5.2.2.
Растровые изображения в Notes ...................................................................................... 46
5.2.3.
Horisontal Rules ................................................................................................................. 47
5.2.4.
Кнопки в форме, кнопки в Action Bar и Hotspot-ы. Применение JavaScript................ 48
5.2.5.
Псевдособытия HTML Attributes..................................................................................... 51
5.2.6.
Поля и их HTML-аттрибуты. Обеспечение функционирования полей ключевых слов52
5.2.7.
Поле $$Return.................................................................................................................... 52
5.2.8.
Доступ к переменным CGI............................................................................................... 53
5.2.9.
События WebQueryOpen и WebQuerySave..................................................................... 54
5.2.10. Computed Text ................................................................................................................... 55 5.2.11. $$-поля............................................................................................................................... 56 5.2.12. Способы внедрения HTML в конструкции Notes .......................................................... 57
5.3.
Web-элементы для форм............................................................................................. 58
5.3.1.
Embedded Navigator .......................................................................................................... 58
5.3.2.
Embedded View.................................................................................................................. 58
5.3.3.
Embedded Folder Pane ....................................................................................................... 59
5.3.4.
File Upload Control ............................................................................................................ 59
5.4.
Формы-шаблоны.......................................................................................................... 59
5.4.1.
Формы-шаблоны для видов ............................................................................................. 59
5.4.2.
Формы-шаблоны для навигаторов .................................................................................. 59
5.4.3.
Формы-шаблоны для поиска ........................................................................................... 59
5.4.4.
Формы-шаблоны обработки ошибок в Domino ............................................................. 60
© InterTrust Co. Тел. 956-7928, 956-7929
263 Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0
6. Domino
Разработка видов, навигаторов и карт-изображений для Web-приложений 61
6.1.
Виды.............................................................................................................................. 61
6.2.
Навигаторы и карты-изображения ............................................................................. 61
7.
Разработка агентов для Web-приложений Domino ............................................. 65 7.1.
Агенты с опцией Run agent as Web User.................................................................... 65
7.2.
Агенты - аналоги программ CGI ................................................................................ 66
7.3.
Агент на событие WebQueryOpen .............................................................................. 69
7.4.
Агент на событие WebQuerySave ............................................................................... 70
8.
Создание сайта на основе Lotus Domino ................................................................ 71 8.1.
Обзор примеров из каталога Sample (R4.6) ............................................................... 71
8.1.1.
Domino 4.6 Samples: FAQ .................................................................................................71
8.1.2.
Domino 4.6 Samples: Registration......................................................................................71
8.1.3.
Domino 4.6 Samples: Frameset...........................................................................................72
8.1.4.
Domino 4.6 Samples: Web Pages, Site1, Site 2, Site 3 .......................................................73
8.2.
Планирование сайта..................................................................................................... 74
8.3.
Разработка сайта .......................................................................................................... 75
8.3.1.
Общие рекомендации........................................................................................................75
8.3.2.
Home Page ..........................................................................................................................75
8.3.3.
Информация о компании ..................................................................................................78
8.3.4.
«Новости/Свежие новости»..............................................................................................79
8.3.5.
«Продукция/услуги» .........................................................................................................83
8.3.6.
«Дискуссии» ......................................................................................................................86
8.3.7.
Прайс-листы.......................................................................................................................89
8.3.8.
«Работа» .............................................................................................................................89
8.3.9.
Регистрация........................................................................................................................89
8.3.10. Полнотекстовый поиск .....................................................................................................90
8.4. 9.
Развитие и обслуживание сайта ................................................................................. 92 Конфигурирование Web-сервера Domino версий 4.6.x....................................... 93
9.1.
Настройки в документе Server.................................................................................... 93
9.1.1.
Секция Internet Port and Security Configuration документа Server .................................93
9.1.2.
Секция HTTP Server документа Server............................................................................95
9.2.
База данных Domino Web Server Configuration....................................................... 104
9.2.1.
Виртуальные серверы Domino (hosting multiple sites on one server) ...........................104
9.2.2.
Собственные страницы «в ответ» на ошибочные ситуации........................................105
9.3.
Поддержка сервлетов на Web-сервере Domino....................................................... 106
9.3.1.
Что такое «сервлет» ........................................................................................................106
9.3.2.
Конфигурирование поддержки сервлетов сервером Domino......................................111
9.4.
Кластеры из Web-серверов Domino: реалии и перспектива .................................. 113
© InterTrust Co. Тел. 956-7928, 956-7929
264 Разработка Web-приложений на основе Lotus Domino 4.6.x и Lotus eSuite DevPack 1.0
10.
Secure Sockets Layer в Lotus Domino 4.6.1 ........................................................... 117
10.1. Основы SSL................................................................................................................ 117 10.2. Обзор реализации SSL в Domino ............................................................................. 121 10.3. Сертификаты X.509, Certificate Authority, Trusted Roots и KeyRing-файлы ........ 123 10.4. Обеспечение поддержки SSL серверами Domino .................................................. 126 10.4.1. База Certificate Authority................................................................................................. 127 10.4.2. База Server Certificate Administration............................................................................. 132 10.4.3. Настройка SSL на сервере Domino................................................................................ 142
10.5. Настройка клиентского броузера............................................................................. 147 10.6. SSL, Domino и Notes.................................................................................................. 155 11.
Применение eSuite DevPack 1.0............................................................................. 157
11.1. Апплет ScriptHelper................................................................................................... 160 11.2. Апплет FileReader...................................................................................................... 168 11.3. Апплет TableReader................................................................................................... 171 11.4. Апплет FormReader ................................................................................................... 176 11.5. Апплет CGI Gateway ................................................................................................. 182 11.6. Апплет SQL/JDBC..................................................................................................... 189 11.7. Апплеты InfoCenter и AppletContainer..................................................................... 191 11.8. Апплет Chart - построитель графиков и диаграмм................................................. 195 11.8.1. Методы для получения ссылок на «вложенные» объекты.......................................... 195 11.8.2. Параметры, методы и свойства объекта Chart ............................................................. 197 11.8.3. Свойства объекта Plot и соответствующие им параметры.......................................... 209 11.8.4. Свойства объекта TextElement....................................................................................... 210 11.8.5. Свойства объекта Axis и соответствующие им параметры ........................................ 210 11.8.6. Методы, свойства и соответствующие им параметры объекта Series........................ 217
11.9. Апплет Sheet - электронная таблица ....................................................................... 227 11.10.Апплет WordProcessor – текстовый процессор ...................................................... 241 11.10.1. Изменение внешнего вида текстового редактора ........................................................ 242 11.10.2. Перемещение по редактируемому тексту..................................................................... 244 11.10.3. Редактирование текста, вставка и получение фрагментов текста .............................. 246 11.10.4. Печать документа ........................................................................................................... 247
11.11.Завершая рассмотрение eSuite DevPack .................................................................. 248
© InterTrust Co. Тел. 956-7928, 956-7929
Конфигурирование Web-сервера Domino версий 4.6.x
265
© InterTrust Co. Тел. 956-7928, 956-7929