Hungry Mind , Blog about everything in IT - C#, Java, C++, .NET, Windows, WinAPI, ...

Hacking WL-500gP Part 2

Продолжаю мучить WL-500gP. В предыдущей части были разобраны такие пункты:

  1. SSH
  2. 4 Gb Flash
  3. Установка пакетов
  4. syslog-ng
  5. Создание пользователей

Эта часть коснется установки и настройки VSFTPD и Samba 3.

Поставить FTP сервер и Samba по отдельности - не проблема. Проблема в том, чтобы везде использовалась одинаковая кодировка и корректно отображалась кириллица. Единственное рабочее решение, которое было найдено - использовать UTF8 на файловой системе и FTP сервер, который позволяет выполнять перекодировку UTF8<->Windows-1251.

Установка и настройка Samba 3

Ставим:

ipkg install samba

Файл конфигурации по-умолчанию отсутствует, создаем:

vim /opt/etc/samba/smb.conf
[global]
workgroup = MYWORKGROUP
guest account = nobody

security = share

browseable = yes
guest ok = yes
guest only = no
log level = 0
log file = /opt/var/log/smbd.log
max log size = 100
encrypt passwords = yes
dns proxy = no
load printers = no
invalid users = root
netbios name = WL500gP
interfaces = br0
bind interfaces only = yes
server string = ASUS WL500g Premium
socket options = TCP_NODELAY IPTOS_LOWDELAY SO_KEEPALIVE SO_SNDBUF=8192
preserve case = yes
short preserve case = yes

dos charset = CP866
unix charset = UTF-8
display charset = UTF-8

wins support = no
#wins server = 192.168.1.1
time server = yes
os level = 255
local master = no

[PersonalShare]
path = /opt/home/SomeUser
writeable = yes
force user = SomeUser
force group = someuser
browseable = yes

[GroupShare]
path = /opt/home/GroupShare
writeable = yes
force user = SomeGroup
force group = somegroup
browseable = yes
create mode = 0664
directory mode = 0775

[FTP]
path = /opt/home/ftp
writeable = yes
force user = ftp
force group = ftp
browseable = yes
create mode = 0664
directory mode = 0775

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

Скрипт запуска - /opt/etc/init.d/S08samba. Его нужно отредактировать и, желательно, переименовать, чтобы Samba запускалась в самом конце:

sed 's/samba_active=0/samba_active=1/' /opt/etc/init.d/S08samba > /opt/etc/init.d/S95samba
rm -f /opt/etc/init.d/S08samba

Не забываем также про остановку системы, файл /usr/local/sbin/pre-shutdown:

if [ `pidof smbd` -ne "" ]; then
        $log 'Terminating smbd'
        /bin/kill `pidof smbd`
fi
if [ `pidof nmbd` -ne "" ]; then
        $log 'Terminating nmbd'
        /bin/kill `pidof nmbd`
fi

Установка и настройка VSFTPD

VSFTPD - единственный сервер, который удовлетворяет требованиям по кодировке. И то, прийдется поднатужиться для его сборки...

Сборка VSFTPD

С сайта http://vsftpd.devnet.ru/rus/ нужно скачать последний архив в исходниками и скомпилировать его.

Для этого нам понадобятся следующие "маленькие" пакеты:

ipkg install optware-devel
ipkg install buildroot
ipkg install openssl-dev

Можно смело пойти погулять полчасика.

Компилируем:

mkdir -p /opt/usr/src
cd /opt/usr/src
wget http://vsftpd.devnet.ru/files/2.0.5/ext.4/vsftpd-2.0.5.ext4.tar.gz
tar zxvf vsftpd-2.0.5.ext4.tar.gz vsftpd-2.0.5.ext4
cd vsftpd-2.0.5.ext4
cp defs.h defs.h.orig
sed 's/\/etc\/vsftpd\/vsftpd.conf/\/opt\/etc\/vsftpd.conf/' defs.h.orig > defs.h
mv builddefs.h builddefs.h.orig
echo "#ifndef VSF_BUILDDEFS_H"      >> builddefs.h
echo "#define VSF_BUILDDEFS_H"      >> builddefs.h
echo ""                             >> builddefs.h
echo "#undef VSF_BUILD_TCPWRAPPERS" >> builddefs.h
echo "#define VSF_BUILD_PAM"        >> builddefs.h
echo "#define VSF_BUILD_SSL"        >> builddefs.h
echo ""                             >> builddefs.h
echo "#endif /* VSF_BUILDDEFS_H */" >> builddefs.h

make

ipkg install vsftpd

cp vsftpd /opt/sbin/
cp vsftpd.8 /opt/share/man/man8/
cp vsftpd.conf.5  /opt/share/man/man5/

UPD: 05/04/2009

Последняя сборка 2.1.0 (ext.1). Чтобы ее собрать необходимо скачать и поставить свежую версию openssl.

cd /opt/usr/src/
wget http://www.openssl.org/source/openssl-0.9.8k.tar.gz
tar zxvf openssl-0.9.8k.tar.gz
cd openssl-0.9.8k
./config --prefix=/opt --openssldir=/opt shared
make install

Перед выполнением этой команды нужно убить все несистемные процессы - для сборки просто не хватает памяти. Также неплохо, чтобы образовалась следующая картинка:

[root@WL500gP lib]$ ls /opt/lib/*libssl* -al
-rw-r--r-- 1 root root 480756 Apr  5 17:52 /opt/lib/libssl.a
lrwxrwxrwx 1 root root     15 Apr  5 17:52 /opt/lib/libssl.so -> libssl.so.0.9.8
lrwxrwxrwx 1 root root     15 Apr  5 18:13 /opt/lib/libssl.so.0 -> libssl.so.0.9.8
-r-xr-xr-x 1 root root 351912 Apr  5 17:52 /opt/lib/libssl.so.0.9.8

Также нужно поправить файл vsf_findlibs.sh (-lcrypt вместо -lcrypto):

if find_func SSL_library_init ssl.o; then
  echo "-lssl -lcrypto";
fi

Настройка VSFTPD

Создаем пользователей и правильно выставляем права (важно):

echo "ftp:x:2:ftp" >> /etc/group
echo "ftp:x:1000:2:Anonymous FTP user:/opt/home/ftp:/sbin/nologin" >> /etc/passwd

mkdir -p /opt/home/nobody
mkdir -p /opt/home/ftp
mkdir -p /opt/home/ftp/incoming

chown nobody:nobody /opt/home/nobody
chown -R ftp:ftp /opt/home/ftp

chmod 555 /opt/home/nobody
chmod 555 /opt/home/ftp
chmod 775 /opt/home/ftp/incoming

Конфигурация /opt/etc/vsftpd.conf:

# Example config file /opt/etc/vsftpd.conf
#
# The default compiled in settings are fairly paranoid. This sample file
# loosens things up a bit, to make the ftp daemon more usable.
# Please see vsftpd.conf.5 for all compiled in defaults.
#
# READ THIS: This example file is NOT an exhaustive list of vsftpd options.
# Please read the vsftpd.conf.5 manual page to get a full idea of vsftpd's
# capabilities.
listen=YES
check_shell=NO
chroot_local_user=YES
secure_chroot_dir=/opt/home/nobody
anon_root=/opt/home/ftp
convert_charset_enable=1
local_charset=UTF-8
remote_charset=WIN1251
syslog_enable=YES
#
# Allow anonymous FTP? (Beware - allowed by default if you comment this out).
anonymous_enable=YES
#
# Uncomment this to allow local users to log in.
local_enable=YES
#
# Uncomment this to enable any form of FTP write command.
write_enable=YES
#
# Default umask for local users is 077. You may wish to change this to 022,
# if your users expect that (022 is used by most other ftpd's)
local_umask=022
#
# Uncomment this to allow the anonymous FTP user to upload files. This only
# has an effect if the above global write enable is activated. Also, you will
# obviously need to create a directory writable by the FTP user.
anon_upload_enable=YES
#
# Uncomment this if you want the anonymous FTP user to be able to create
# new directories.
anon_mkdir_write_enable=YES
#
# Activate directory messages - messages given to remote users when they
# go into a certain directory.
dirmessage_enable=YES
#
# Activate logging of uploads/downloads.
xferlog_enable=YES
#
# Make sure PORT transfer connections originate from port 20 (ftp-data).
connect_from_port_20=YES
#
# If you want, you can arrange for uploaded anonymous files to be owned by
# a different user. Note! Using "root" for uploaded files is not
# recommended!
#chown_uploads=YES
#chown_username=whoever
#
# You may override where the log file goes if you like. The default is shown
# below.
vsftpd_log_file=/opt/var/log/vsftpd.log
#
# If you want, you can have your log file in standard ftpd xferlog format
#xferlog_std_format=YES
#
# You may change the default value for timing out an idle session.
#idle_session_timeout=600
#
# You may change the default value for timing out a data connection.
#data_connection_timeout=120
#
# It is recommended that you define on your system a unique user which the
# ftp server can use as a totally isolated and unprivileged user.
nopriv_user=nobody
#
# Enable this and the server will recognise asynchronous ABOR requests. Not
# recommended for security (the code is non-trivial). Not enabling it,
# however, may confuse older FTP clients.
#async_abor_enable=YES
#
# By default the server will pretend to allow ASCII mode but in fact ignore
# the request. Turn on the below options to have the server actually do ASCII
# mangling on files when in ASCII mode.
# Beware that turning on ascii_download_enable enables malicious remote parties
# to consume your I/O resources, by issuing the command "SIZE /big/file" in
# ASCII mode.
# These ASCII options are split into upload and download because you may wish
# to enable ASCII uploads (to prevent uploaded scripts etc. from breaking),
# without the DoS risk of SIZE and ASCII downloads. ASCII mangling should be
# on the client anyway..
#ascii_upload_enable=YES
#ascii_download_enable=YES
#
# You may fully customise the login banner string:
ftpd_banner=Welcome.
#
# You may specify a file of disallowed anonymous e-mail addresses. Apparently
# useful for combatting certain DoS attacks.
#deny_email_enable=YES
# (default follows)
#banned_email_file=/opt/etc/vsftpd.banned_emails
#
# You may specify an explicit list of local users to chroot() to their home
# directory. If chroot_local_user is YES, then this list becomes a list of
# users to NOT chroot().
#chroot_list_enable=YES
# (default follows)
#chroot_list_file=/opt/etc/vsftpd.chroot_list
#
# You may activate the "-R" option to the builtin ls. This is disabled by
# default to avoid remote users being able to cause excessive I/O on large
# sites. However, some broken FTP clients such as "ncftp" and "mirror" assume
# the presence of the "-R" option, so there is a strong case for enabling it.
ls_recurse_enable=YES

Запускаем:

/opt/sbin/vsftpd >/dev/null 2>&1 &

Пробуем логинится как anonymous. Если сервер отвечает 500 OOPS: child died, то, вероятно, что-то неправильно с правами доступа или путями.

Добавляем в автозапуск:

echo "/opt/sbin/vsftpd /opt/etc/vsftpd.conf >/dev/null 2>&1 &" > /opt/etc/init.d/S60vsftpd
chmod +x /opt/etc/init.d/S60vsftpd

Последний штрих - остановка системы, файл /usr/local/sbin/pre-shutdown:

if [ `pidof vsftpd` -ne "" ]; then
        $log 'Terminating vsftpd'
        /bin/kill `pidof vsftpd`
fi

Не забываю сделать

flashfs save && flashfs commit && flashfs enable

Added smiles to my blog

Всегда хотел добавить поддержку смайлов в блог! :-) 8-)

Vista filesystem wierdness

Что за ерунда?!

Vista filesystem wierdness

Java SE Development Kit 6 Update 4

Вышла Java SE Development Kit 6 Update 4. Download link.


ЗЫ: Поздравляю себя с сотенкой постов. 100 posts

Easy reporting to Word, PDF, HTML

Тяжело работать с людьми, которые сами не знают, чего хотят. Еще хуже, если эти люди являются заказчиками программного обеспечения. Они требуют за копейки кнопку "Сделать все". А потом еще чуть-чуть. И я уже не первый раз наблюдаю эту ситуацию. А самое веселое, когда дело доходит до отчетов. Мы хотим, чтобы был дизайнер. А еще мы хотим, чтобы все было попроще. А еще мы не знаем, что это будут за отчеты, так что сделайте универсальное решение. И ломай потом голову.

Я считаю, что дизайнер стоит кучу денег, для его написания нужен не один человеко-год. И пока что не видел ни одного универсального решения, с которым пользователь ощущал бы себя не обезьяной. Наиболее приемлемый вариант - вбивать логику построения отчета в программу. Дешево и сердито! Ну, дальше изложу один из вариантов такого решения.

Для получения отчета нужно:

  1. Данные

    Строки, числа, даты необходимые для построения отчета.

  2. Шаблон

    Набор правил построения отчета.

  3. Процессор

    Механизм, преобразующий данные по правилам.

В самом сложном варианте эти компоненты создаются индивидуально для каждого отчета. Но, лучше, конечно, по-максимуму автоматизировать каждую часть и их взаимодействие. В идеале, шаблон редактируется с помощью developer-friendly designer, процессор является универсальным готовым решением, а данные представляют собой расширяемый формат, в который можно положить любые данные.

XML, XSLT 2.0 и Altova StyleVision

Итак, данные в формате XML преобразуются XSLT процессором в выходной файл.

Altova StyleVision является нашим самым главным фигурантом и помощником, он же developer-friendly designer. Это визуальный редактор, который позволяет получить на выходе XSLT 2.0 файл, преобразующий XML в HTML, RTF или PDF!

Я уже точно не помню, зачем понадобился именно XSLT 2.0, вероятно из-за каких-то фич дизайнера, но вот найти бесплатный процессор для Java было напряжно. Из коммерческих есть Oracle XML Developer's Kit, из некоммерческих - Saxon. Других не нашел! С .NET ситуация хуже, под него только Saxon. Ну, Saxon так Saxon!

Исходные данные

Исходные данные получаем из источника данных (БД, например) и формируем XML файл с определенной схемой, которая описывается в XSD. Механизм формирования не имеет значения, но, если данные качаются из БД, я бы предпочел возложить этот процесс на сервер (далее в примере я буду получать от любимой СУБД Oracle сразу XML, а если поднатужиться, то и файл с отчетом можно получить!).

Я буду использовать существующую схему SH (Sales History). Как ее установить написано здесь.

Итак, наш отчет будет выдавать некую информацию о клиенте - имя, фамилия, пол, дата рождения и т.д. StyleVision хочет видеть XSD схему документов, которые прийдется использовать в качестве данных. Схему можно создавать либо вручную, подгоняя потом под нее XML, либо построить по существующему XML. Все это, кстати умеет делать Altova XMLSpy. Вот моя схема (Customer.xsd):

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <xs:simpleType name="T_Valid">
      <xs:restriction base="xs:string">
         <xs:enumeration value="I"/>
         <xs:enumeration value="A"/>
      </xs:restriction>
   </xs:simpleType>
   <xs:simpleType name="T_Gender">
      <xs:restriction base="xs:string">
         <xs:enumeration value="M"/>
         <xs:enumeration value="F"/>
      </xs:restriction>
   </xs:simpleType>
   <xs:complexType name="T_Customer">
      <xs:sequence>
         <xs:element ref="FirstName"/>
         <xs:element ref="LastName"/>
         <xs:element ref="Gender"/>
         <xs:element ref="YearOfBirth"/>
         <xs:element ref="Address"/>
         <xs:element ref="Valid"/>
      </xs:sequence>
   </xs:complexType>
   <xs:complexType name="T_Address">
      <xs:sequence>
         <xs:element ref="Street"/>
         <xs:element ref="PostalCode"/>
         <xs:element ref="City"/>
         <xs:element ref="StateProvince"/>
         <xs:element ref="Country"/>
      </xs:sequence>
   </xs:complexType>
   <xs:element name="YearOfBirth" type="xs:short"/>
   <xs:element name="Valid" type="T_Valid"/>
   <xs:element name="Street" type="xs:string"/>
   <xs:element name="StateProvince" type="xs:string"/>
   <xs:element name="PostalCode" type="xs:int"/>
   <xs:element name="LastName" type="xs:string"/>
   <xs:element name="Gender" type="T_Gender"/>
   <xs:element name="FirstName" type="xs:string"/>
   <xs:element name="Customer" type="T_Customer"/>
   <xs:element name="Country" type="xs:string"/>
   <xs:element name="City" type="xs:string"/>
   <xs:element name="Address" type="T_Address"/>
</xs:schema>

Соответственно, Oracle SQL запрос (в SQL Server этот запрос был бы на пару страниц неразбираемого текста):

SELECT XMLElement("Customer",
                  XMLElement("FirstName", c.cust_first_name),
                  XMLElement("LastName", c.cust_last_name),
                  XMLElement("Gender", c.cust_gender),
                  XMLElement("YearOfBirth", c.cust_year_of_birth),
                  XMLElement("Address",
                             XMLElement("Street", c.cust_street_address),
                             XMLElement("PostalCode", c.cust_postal_code),
                             XMLElement("City", c.cust_city),
                             XMLElement("StateProvince", c.cust_state_province),
                             XMLElement("Country",
                                        (SELECT country_name FROM sh.countries WHERE country_id = c.country_id)
                             )
                  ),
                  XMLElement("Valid", c.cust_valid)) AS DATA
  FROM sh.customers c
 WHERE c.cust_id = 43228

Вместо 43228, конечно, нужно сделать bindable переменную, но мне лень.

И его результат (Customer.xml):

<Customer>
   <FirstName>Abner</FirstName>
   <LastName>Everett</LastName>
   <Gender>M</Gender>
   <YearOfBirth>1957</YearOfBirth>
   <Address>
      <Street>117 West Gloucester Avenue</Street>
      <PostalCode>72059</PostalCode>
      <City>Los Angeles</City>
      <StateProvince>CA</StateProvince>
      <Country>United States of America</Country>
   </Address>
   <Valid>I</Valid>
</Customer>

Altova StyleVision

File -> New -> New from XML Schema / DTD..., указать путь к XSD файлу и желательно предоставить ему сразу файл-пример с данными, соответствующий этой схеме, конечно же.

После окончания создания шаблона (template.sps) нужно его сохранить в XSLT (transform-rtf.xslt): File -> Save Generated Files -> Save Generated XSLT-RTF File....

Saxon

What is Saxon?

The Saxon package is a collection of tools for processing XML documents. The main components are:

  • An XSLT 2.0 processor, which can be used from the command line, or invoked from an application, using a supplied API. This can also be used to run XSLT 1.0 stylesheets.
  • An XPath 2.0 processor accessible to applications via a supplied API.
  • An XQuery 1.0 processor that can be used from the command line, or invoked from an application by use of a supplied API.
  • An XML Schema 1.0 processor. This can be used on its own to validate a schema for correctness, or to validate a source document against the definitions in a schema. It is also used to support the schema-aware functionality of the XSLT and XQuery processors. Like the other tools, it can be run from the command line, or invoked from an application.
  • On the Java platform, when using XSLT, XPath, or XML schema validation, the API supported by Saxon is the JAXP API, which means it is possible for a Java application to switch between different XSLT, XPath, and XML Schema processors without changing the application code. At the time of writing, however, Saxon is still the only JAXP implementation that offers support for XSLT 2.0. Saxon offers two APIs for XQuery processing: its own native API, which has been present in the product for some time, and an early implementation of the XQJ specification which is under development as part of the Java Community Process.
  • On the .NET platform, Saxon offers an API that enables close integration with other services available from .NET, notably the XML-related classes in the System.Xml namespace. It isn't possible to use Saxon as a transparent plug-in replacement for the System.Xml.Xsl processor, because the API for the Microsoft engine using concrete classes rather than abstract interfaces. However, it is possible to use it as a functional replacement with minor changes to your application code.

Saxon implements XSLT 2.0, XPath 2.0, and XQuery 1.0 as defined in the final Recommendations of 23 January 2007. It also includes an implementation of the XML Schema 1.0 Recommendation.

Full details of Saxon's conformance to the specifications are provided in the Conformance section.

In addition, Saxon provides an extensive library of extensions, all implemented in conformance with the XSLT and XQuery Recommendations to ensure that portable stylesheets and queries can be written. These include the EXSLT extension libraries common, sets, math, and dates-and-times. Many of these extensions were pioneered in Saxon and have since become available in other products.

These extension functions are in general accessible from XQuery and XPath as well as XSLT, except where they depend on stylesheet information. Some extensions are available in Saxon-SA only.

Компиляция XSLT файла

Библиотека Saxon позволяет компилировать XSLT файл:

The term compile is stretching a point. The executable that is produced does not contain machine instructions, or even interpreted Java bytecode. It contains instructions in the form of a data structure that Saxon itself can interpret. Note that the format of compiled stylesheets is unlikely to be stable from one Saxon release to the next.

Можно, конечно, не компилировать, но я предпочитаю прятать исходники шаблона (в т.ч. из лицензионных соображений). Кстати, из-за этого на моей прошлой работе разработчику прийдется все переделывать с нуля - файлы шаблона и схемы безвозвратно утеряны с моим уходом (злобный смешок). Команда компиляции выглядит так:

java -cp d:\Development\Libs\Java\Saxon.v9\saxon9.jar net.sf.saxon.Compile transform-rtf.xslt transform-rtf.saxon

transform-rtf.xslt - входной файл, transform-rtf.saxon - выходной.

Java код

Все просто - подключение к БД, выполнение запроса, получение потока XML, загрузка скомпилированного шаблона, создание трансформера и преобразование XML в RTF.

 0: /**
 1:  *
 2:  */
 3: package com.chabster.reporting.app;
 4:
 5: import java.io.File;
 6: import java.io.InputStream;
 7: import java.sql.Connection;
 8: import java.sql.DriverManager;
 9:
10: import javax.xml.transform.*;
11: import javax.xml.transform.stream.StreamResult;
12: import javax.xml.transform.stream.StreamSource;
13:
14: import net.sf.saxon.Configuration;
15: import net.sf.saxon.PreparedStylesheet;
16: import oracle.jdbc.OraclePreparedStatement;
17: import oracle.jdbc.OracleResultSet;
18: import oracle.jdbc.driver.OracleDriver;
19: import oracle.sql.OPAQUE;
20:
21: /**
22:  * @author Chabster
23:  */
24: public class Startup
25: {
26:
27:   static String query = "SELECT XMLElement(\"Customer\",\r\n" +
28:         "                 XMLElement(\"FirstName\", c.cust_first_name),\r\n" +
29:         "                 XMLElement(\"LastName\", c.cust_last_name),\r\n" +
30:         "                 XMLElement(\"Gender\", c.cust_gender),\r\n" +
31:         "                 XMLElement(\"YearOfBirth\", c.cust_year_of_birth),\r\n" +
32:         "                 XMLElement(\"Address\",\r\n" +
33:         "                            XMLElement(\"Street\", c.cust_street_address),\r\n" +
34:         "                            XMLElement(\"PostalCode\", c.cust_postal_code),\r\n" +
35:         "                            XMLElement(\"City\", c.cust_city),\r\n" +
36:         "                            XMLElement(\"StateProvince\", c.cust_state_province),\r\n" +
37:         "                            XMLElement(\"Country\",\r\n" +
38:         "                                       (SELECT country_name FROM sh.countries WHERE country_id = c.country_id)\r\n" +
39:         "                            )\r\n" +
40:         "                 ),\r\n" +
41:         "                 XMLElement(\"Valid\", c.cust_valid)) AS DATA\r\n" +
42:         "  FROM sh.customers c\r\n" +
43:         " WHERE c.cust_id = 43228";
44:
45:   public static void main(String[] args) {
46:      try {
47:         DriverManager.registerDriver(new OracleDriver());
48:
49:         Connection conn = DriverManager.getConnection("jdbc:oracle:thin:chabster/***@localhost:1521/MAIN");
50:         OraclePreparedStatement preparedStmt = (OraclePreparedStatement) conn.prepareStatement(query);
51:
52:         OracleResultSet oraRS = (OracleResultSet) preparedStmt.executeQuery();
53:         oraRS.next();
54:         OPAQUE xmlObj = oraRS.getOPAQUE(1);
55:         Configuration configuration = new Configuration();
56:         InputStream xmlStream = xmlObj.getStream();
57:
58:         PreparedStylesheet preparedStylesheet = PreparedStylesheet.loadCompiledStylesheet(configuration, "transform-rtf.saxon");
59:
60:         Transformer transformer = preparedStylesheet.newTransformer();
61:         File outputFile = new File("out.rtf");
62:         Source xmlSource = new StreamSource(xmlStream);
63:         Result output = new StreamResult(outputFile);
64:
65:         transformer.transform(xmlSource, output);
66:
67:         xmlStream.close();
68:         oraRS.close();
69:         preparedStmt.close();
70:         conn.close();
71:      }
72:      catch (Exception ex) {
73:         ex.printStackTrace();
74:      }
75:   }
76: }

Выводы

Механизм прост и удобен для разработчика. Генерация файлов происходит быстро, поддерживаются основные форматы документов - HTML, RTF и PDF. Правда, есть и свои нюансы, связанные с ограниченными возможностями дизайнера Altova StyleVision. Например, если в отчет нужно вставить картинку из БД, то прийдется это писать частично вручную. Также минимальный размер генерируемого файла - 46 Kb! Плюс вечно плавающие стандарты W3C и отсутствие библиотек, которые их поддерживают.

Copyright 2007-2011 Chabster