Показаны сообщения с ярлыком Программирование. Показать все сообщения
Показаны сообщения с ярлыком Программирование. Показать все сообщения

28 июня 2016 г.

Как отсыпать совсем немножечко рута для Java и разрешить захватывать сетевые пакеты

В различных дистрибутивах Linux такие программы, как tcpdump и wireshark, использующиеся для анализа сетевого трафика, обычно требуют прав суперпользователя для получения доступа к возможностям захвата пакетов. Точно также дело обстоит и с Java-программами, которые используют системную библиотеку libpcap. Причем в этом случае вам придется запустить с неограниченными правами саму виртуальную машину Java, которая уже в свою очередь будет исполнять ваш код. Я думаю, мало кто любит лишний раз сорить суперправами направо и налево, поэтому в Linux, начиная с ядра 2.2 появилась такая штука, как Linux Capabilites, которая позволяет наделить непривилегированные процессы только необходимыми возможностями суперпользователя. В данном случае, например, нас интересует только возможность перехвата и отправки сетевых пакетов. Для установки и просмотра Linux Capabilites необходимы программы setcap и getcap, соответственно. У меня в openSUSE эти утилиты находятся в пакете libcap-progs, а в Ubuntu в пакете libcap2-bin.

Установка возможности захвата и отправки сетевых пакетов и возможности изменения конфигурации интерфейсов выглядит так:
setcap cap_net_raw,cap_net_admin=eip /usr/local/lib64/jdk1.8.0_77/bin/java
Просмотр установленных возможностей:
getcap /usr/local/lib64/jdk1.8.0_77/bin/java
/usr/local/lib64/jdk1.8.0_77/bin/java = cap_net_admin,cap_net_raw+eip
Всё просто, но если после установки этих возможностей попробовать запустить программу java из под обычного пользователя, то это не очень получится:
java -version
java: error while loading shared libraries: libjli.so: cannot open shared object file: No such file or directory
Это происходит из-за того, что при наличии у непривилегированного процесса возможностей, которыми он вроде как обладать не должен, загрузчик динамических библиотек запрещает загрузку библиотек из недоверенных каталогов. Доверенными каталогами по умолчанию являются /lib и /usr/lib (а также /lib64 и /usr/lib64).

С помощью утилиты ldd посмотрим, какие динамические библиотеки использует java: 
ldd /usr/local/lib64/jdk1.8.0_77/bin/java
        linux-vdso.so.1 (0x00007ffc91ffd000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fc3dc124000)
        libjli.so => /usr/local/lib64/jdk1.8.0_77/bin/../lib/amd64/jli/libjli.so (0x00007fc3dbf0d000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007fc3dbd09000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fc3db961000)
        /lib64/ld-linux-x86-64.so.2 (0x00005584e041d000)
Как видно из вывода команды ldd, при запуске java не удалось загрузить как раз ту самую библиотеку, которая находится в недоверенном каталоге ../lib/amd64/jli/.

Это можно легко пофиксить, добавив файл с расширением .conf  в каталог /etc/ld.so.conf.d, в котором перечислить все необходимые пути. В случае с java это всего лишь один каталог:
echo /usr/local/lib64/jdk1.8.0_77/lib/amd64/jli > /etc/ld.so.conf.d/java.conf
После изменения файлов в /etc/ld.so.conf.d может потребоваться перестроить кэш библиотек, для этого нужно выполнить:
ldconfig
Проверяем, что загрузчик видит нашу библиотеку:
ldconfig -v |grep jli
/usr/local/lib64/jdk1.8.0_77/lib/amd64/jli:
     libjli.so -> libjli.so
Ну и на всякий случай, команда для удаления всех дополнительных возможностей у программы:
setcap -r /usr/local/lib64/jdk1.8.0_77/bin/java
Ещё хотелось бы отметить, что не стоит без лишней необходимости добавлять нестандартные возможности вашей глобальной системной Java-машине, потому что в этом случае любая запущенная Java-программа сможет ими воспользоваться. Для разработки и запуска программ с завышенными потребностями лучше завести отдельный экземпляр Java-машины.

Где отрыто

Как приструнить Wireshark
Небаг в багтрекере Java
Куришка: man capabilities


29 июня 2015 г.

Eclipse Mars, GTK+ 3, Adwaita и маленький CSS-напильник

С переходом на новый Eclipse Mars, я решил кое-что ещё поменять в своей жизни. Хотя правильнее сказать, что сам Eclipse предложил мне эти изменения, а я не стал сопротивляться. Как известно, Eclipse Mars теперь по умолчанию использует GTK+ версии 3. Для второй версии GTK+ у меня уже много лет стоит тема oxygen-gtk. Страшненькая, да... но уже привычная. Поэтому как-то даже мысли не возникало попробовать поменять её. А тут оказалось, что для GTK+ 3 у меня вообще эта тема не стоит, и используется тема по умолчанию, которая называется Adwaita. И что-то я так поглядел на неё, и в принципе мой глаз посчитал её чуть менее страшной и чуть более секси, чем oxygen-gtk. Осталось только решить несколько бросившихся сразу в глаза проблем.

Проблемы

Проблема 1. Какое-то неадекватно большое значение padding у большинства GUI-элементов.


Проблема 2. Странный tooltip для javadoc с белым шрифтом на чёрном фоне.

 
Проблема 3. Смазанные шрифты после скролинга некоторых окон (Project Explorer, Package Explorer, Outline). Особенно ярко проблема проявляется, если скролить колесом мыши.


Решение

В GTK+ 3 для описания тем больше не используются rc-файлы собственного формата. Теперь для стилизации применяются более понятные CSS-подобные файлы.

Проблемы 1 и 2 решаются созданием файла ~/.config/gtk-3.0/gtk.css со следующим содержанием:
* {
    padding: 1px;
}

GtkToolbar {
    padding: 2px;
}

GtkMenuBar {
    padding: 2px;
}

GtkMenuItem {
    padding: 2px 6px;
}

.tooltip {
    background-color: #CAE1FF;
    color: #333;
    text-shadow: none;
}

Кратко поясню. Сначала устанавливаем padding абсолютно для всех элементов равным 1px. Затем для элементов GtkToolbar, GtkMenuBar и GtkMenuItem делаем отступы чуть более разумными. CSS-класс tooltip вероятно прописан где-то в коде и назначен, как для всплывающего окна javadoc, так и для хинтов различных графических элементов. Свойство text-shadow необходимо, чтобы ликвидировать тень текста хинта, которая становится заметной и неуместной после изменения его фона и цвета текста:


Обратите внимание, что файл ~/.config/gtk-3.0/gtk.css будет действовать и переопределять стили для любой темы GTK+ 3, выбранной пользователем, у которого в домашнем каталоге есть этот файл, а не только для темы Adwaita.

Проблему 3 я решил довольно тупо, сняв флажок с Use mixed fonts and colors for labels в настройках внешнего вида (Window / Preferences / General / Appearance). Мне легче смириться с одноцветным черным лейблом, чем с таким поломанным шрифтом.

Тут я вынужден обновить сообщение и добавить, что после решения проблемы 3 появилась проблема 4 :) которая выглядет, как практически нечитаемый выбранный пункт во всплывающем окне автодополнения.


Эта неприятность также фиксится добавлением некоторых строчек в gtk.css:
GtkTreeView:selected {
    color: #FFF;
    background-color: #4A90D9;
}

Результаты






Ссылки

Тем, кто захочет ещё что-нибудь подкрутить или сделать более тонкую настройку, а не такую кувалдообразную, как у меня, рекомендую сначала заглянуть сюда, и конкретно вот сюда. А ещё здесь интересно.

Когда терпение кончилось

Спустя некоторое время, должен признать, что это далеко не все глюки с UI, которые мне повстречались при использовании GTK+ 3 в Eclipse. И у меня больше нет сил подкручивать эти гайки. Я устал, я ухожу. Теперь перед запуском Eclipse у меня выполняется export SWT_GTK3=0, что заставляет Eclipse использовать GTK+ 2 по старинке.

29 октября 2013 г.

Выбор года и месяца в GWT DatePicker с помощью ListBox

Стандартный DatePicker в GWT очень неудобный. Для выбора нужного года и месяца пользователь вынужден кликать по соответствующим стрелочкам и перемещаться на один месяц вперед или на зад. Например, если пользователю необходимо выбрать свою дату рождения, скажем, 29 февраля 1980 года, а в календаре по умолчанию установлена текущая дата 25 октября 2013 года, то представьте сколько раз нужно будет кликнуть бедняге по стрелочке, чтобы добраться до дня своего рождения!
Стандартный DatePicker в GWT
Конечно, в качестве простого решения, можно просто дать пользователю возможность ввести дату самому в текстовое поле. И в общем-то нет, наверное, ничего плохого в таком решении. Но иногда просто хочется сделать немного более красиво. В этом смысле Datepicker из jQuery UI вполне себе красив и позволяет выбирать год и месяц с помощью выпадающих списков, что очень сокращает путь до необходимой даты.

jQuery Datepicker
На самом деле, такую же возможность очень несложно реализовать и в GWT DatePicker. Для этого нужно просто написать свою собственную реализацию абстрактного класса MonthSelector, который представляет из себя визуальный компонент, отвечающий за установку текущего года и месяца в DatePicker. 

15 ноября 2012 г.

Сборка jNetPcap из исходников в openSUSE 12.1

Набрел тут на интересную java-обёртку для libpcap. Называется она jNetPcap. По описаниям и примерам выглядит достойно. Но главное, что в отличие от Jpcap, с которой я как-то давненько имел интимные отношения, jNetPcap продолжает развиваться.

Если кто не в курсе, кратко поясню, что libpcap это библиотека для захвата и анализа пакетов, проходящих через сетевые интерфейсы. Её, например, используют такие программы, как wireshark, tcpdump, nmap, ipcad и многие другие.

На сайте разработчиков, есть готовые сборки для Ubuntu, RedHat Enterprise, Fedora и Windows. Архив сборки содержит два интересующих меня файла jnetpcap.jar и libjnetpcap.so. Сборка для Fedora сомнительно, но гордо называется Linux (Generic). Сначала я попробовал именно её. При запуске примера она искала libpcap.so.0.9, но ничего не нашла, т.к. у меня стоит версия 1.3.0. В принципе, простой симлинк в /usr/lib libpcap.so.0.9 -> libpcap.so.1.3.0 решает проблему, и пример начинает работать, но что-то меня смущает такая большая разница в версиях libpcap. Поэтому пришлось собирать jNetPcap из исходников.

Сборка прошла не совсем гладко, поэтому оставлю тут для себя, а может и ещё для кого, заметку поэтому поводу.

Теперь кратко о проблемах:
  1. При попытке собрать jnetpcap.jar (команда ant build-jar):
    [taskdef] Could not load definitions from resource cpptasks.tasks. 
    It could not be found.
    
    [typedef] Could not load definitions from resource cpptasks.types.
    It could not be found.
    
    build.xml:119: taskdef class org.vafer.jdeb.ant.DebAntTask cannot be found 
    using the classloader AntClassLoader[]
    
  2. При попытке собрать libjnetpcap.so (команда ant comp-jni-linux):
    [cc] /home/eqlbin/SRC/jnetpcap-src-1.3.0-1/src/c/jnetpcap.cpp:996:6: 
    error: invalid suffix "xpackage" on integer constant
    
    [cc] :0:1: error: "not" cannot be used as a macro name as it is an
    operator in C++
    
Я, честно говоря, не совсем понял, как надо правильно настраивать сборку по мнению самих разработчиков, и в документации ничего путного не нашлось, а долго ковырять чужой билд-скрипт и проперти-файлы желания большого не было, поэтому проблемы решил так как получилось :)

Для сборки, помимо JDK, понадобятся такие естественные штуки, как gcc, gcc-c++, libpcap-devel, ant, ant-junit, ant-contrib. Возможно я что-то упустил, но это основное.

Поехали:
  1. Качаем и распаковываем исходники jNetPcap в гипотетический каталог ~/jnetpcap-src
  2. Качаем cpptasks для ant и кладём файл cpptasks.jar например в ~/jnetpcap-src/lib
  3. Дальше, если у вас есть желание создать из всего хозяйства файл deb, то понадобится найти библиотеку jdeb.jar с соответствующими тасками для ant. Её можно найти уже собранную или же собрать самому. У меня такого желания не образовалось, поэтому я просто  закомментировал строку в файле build.xml:
  4. Теперь необходимо подправить build.xml, чтобы ant смог найти cpptasks.jar и jdeb.jar (если вы, используете jdeb и не закомментировали строку, как в п.3): Вот это: Надо привести к виду, вроде этого: Всё, конечно, зависит от того, как называются ваши jar-файлы и где они лежат... Короче, думаю, что и так тут всё ясно.
  5. Добавить в файл Linux.properties строку compiler.LIBPCAP_VERSION = 100
  6. Запустить ant clean comp-jni-linux build-jar
  7. Забрать из ~/jnetpcap-src/build/lib вожделенные jnetpcap.jar и libjnetpcap.so (там еще у меня появился файл libjnetpcap.so.1.3.0, но судя по его размеру, это тот же libjnetpcap.so)

P.S. - Если build.xml кажется вам страшным и непонятным, почитайте это.

28 апреля 2012 г.

Автоматическое создание Runnable JAR в Eclipse и ресурсы

Когда разрабатывается относительно небольшое десктопное приложение на Java, частенько возникает вполне, на мой взгляд, естественное желание запихать все классы, библиотеки и ресурсы в один исполняемый JAR-файл. В некоторых случаях именно такое решение является предпочтительным.

В Eclipse IDE это можно сделать очень легко и, кроме того, автоматизировать это действие, чтобы в дальнейшем делать сборку JAR одной кнопкой.

Сборка 

Кликаем правой кнопкой по проекту, который надо упаковать в исполняемый JAR и нажимаем Export.

В окне выбираем Java -> Runnable JAR и жмём Next

5 апреля 2012 г.

Список CMS на Java

Давно хотел найти для себя какую-нибудь удобную CMS, а точнее WCMS, которая:
  1. Создана на стеке Java-технологий
  2. Open Source
  3. Легко разворачивается
  4. Имеет развитую и относительно простую систему шаблонов
  5. Более или менее легко интегрируется с другими веб-приложениями
  6. Проста в освоении для "нетехнических" людей, которые будут наполнять контент 
Понятное дело, что ничего идеального не бывает, поэтому просто хочется найти компромиссное решение. Это будет непросто, т.к. я никогда ни с какими CMS не общался достаточно тесно и знаю о них не особо много.

В качестве первого шага на пути к поиску наиболее подходящего кандидата, я поспрашивал у могучего Интернета, какие вообще есть открытые CMS, на Джаве писанные. Оказалось, что как и любых других CMS, решений на базе Java уже вагон и маленькая тележка, причем открытых. Этот список найденных CMS я тут и оставлю. В первую очередь это, конечно, для себя любимого, но может он будет полезен и ещё кому-нибудь.

Список я разделил на две части. В первом списке главные кандидаты. Это те CMS, с которыми я уже успел немного познакомиться: какие-то разворачивал и тыкал ранее, а какие-то просто внимательно изучал на официальных сайтах и они мне на первый взгляд понравились. Во втором списке системы, в которых я не особо уверен, потому что пока не уделил им достаточно внимания. Возможно, с течением времени эти списки будут пополняться или между ними будут происходить перестановки.

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

Итак, списки.

Главные претенденты:

Запасной состав:

Многие CMS из этих списков имеют версии Enterprise и Community, которые, соответственно, распространяются под разными лицензиями: закрытой и открытой. Также, некоторые кандидаты являются не только WCMS, а большими разухабистыми ECMS (как, например, Alfresco) с возможностями WCMS. А вот в запасной список наоборот могли закрасться те, которые вообще не умеют WCMS, а являются к примеру только DMS.



11 октября 2011 г.

Плагин Google для Eclipse: обновления о которых не просят

Обнаружил интересную особенность у плагина Google для Eclipse, позволяющего разрабатывать приложения с использованием GWT и App Engine.

После очередного перезапуска контейнера сервлетов Jetty, который используется плагином для запуска GWT приложений на локальном хосте, он как-то необычно призадумался на старте. Вывел мне на консоль "Initializing App Engine server" и замолчал. Понимаю, что тужится, но не понимаю с чего это вдруг. Подождал я его несколько минут и он выдавил на консоль что-то вроде этого:
INFO: Unable to access http://appengine.google.com/api/updatecheck?runtime=java&release=1.5.4×tamp=1315604504&api_versions=['1.0']
Оказалось, что этот негодяй при каждом старте проверяет наличие обновлений, а у меня тут как раз отвалился интернет. Мне в принципе не жалко, пусть проверяет, но ждать его по несколько минут при каждом перезапуске когда нет сети как-то не особо хочется.

Первым делом я, конечно, полез в настройки Eclipse (Window -> Preferences -> Google) и убрал галку с пункта "Notify me about updates", но ничего не изменилось. Немного пошарив по интернету, я наткнулся на забавное описание метода allowedToCheckForUpdates() класса UpdateCheck в пакете com.google.appengine.tools.info. По названию пакета можно сделать некоторые выводы о том, для чего он нужен. Вот описание этого метода:
Returns true if the user wants to check for updates even when we don't need to. We assume that users will want this functionality, but they can opt out by creating an .appcfg_no_nag file in their home directory.
В общем, надо или не надо, этот метод все равно возвращает true, т.к. разработчики уверены что, если пользователь даже отключил проверку обновлений, то он всё равно хочет обновлений. Как-то так получается :) Однако, всё-таки можно эту проверку отключить, создав в домашнем каталоге пользователя, под которым запускается контейнер, файл .appcfg_no_nag. После того, как я это сделал, "задумчивость" контейнера на старте прошла, но tcpdump показывает, что он всё равно продолжает стучаться на appengine.google.com.

29 сентября 2011 г.

Основы использования системы сборки Apache Ant

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

А теперь представьте, что из всего этого безобразия необходимо собрать всего один файл сжатого архива, который пользователь мог бы скачать с вашего сайта, распакавать и сразу же запустить ваш продукт. Вам нужно будет собрать вместе все файлы с исходным кодом Java и скомпилировать их, прогнать тесты, чтобы убедиться что проект никто не поломал, полученные class-файлы упаковать в JAR (или несколько JAR'ов), для которого ещё необходимо сгенерировать правильный манифест, содержащий CLASSPATH, имя главного класса, номер версии и т.п., затем собрать вместе все остальные файлы вроде библиотек, картинок и конфигов, распихать это все в правильные каталоги, сгенерировать документацию, создать из всего этого архив и залить его на ваш вэб-сервер, а всё произошедшее записать в лог и сохранить его в базе данных, которая хранит информацию о различных сборках. Делать всё это руками довольно уныло, да и не должен психически здоровый человек этим заниматься.

Системы сборки, такие как Apache Ant, были созданы для того, чтобы автоматизировать весь этот порой достаточно сложный и рутиный процесс по сборке проекта. Причем, в случае с Apache Ant проект не обязательно должен быть на Java, и не обязательно должен быть вообще программным обеспечением. Это может быть что угодно, хотя ориентирован он, конечно же, в первую очередь на Java. В данной статье я хочу на очень простом примере показать, как можно облегчить себе жизнь с помощью Apache Ant.

14 августа 2011 г.

Вычисление БПФ на GPU с использованием Java и CUDA

В последнее время у меня на работе встала задача создания спектрограмм для довольно большого объема данных. Главным инструментом для этого является алгоритм Быстрого Преобразования Фурье. На сегодняшний день для Java написано уже множество библиотек, реализующих вычисление БПФ и другие математические инструменты, например, мне нравится Commons Math от Apache project. Но для того, чтобы обрабатывать большие объемы данных с помощью этой библиотеки за более или менее разумное время, нужна довольно мощная и недешевая машина, которой у меня нет. Поэтому я и обратил свой взор на технологию NVIDIA CUDA, которая позволяет очень шустро производить расчеты с плавающей точкой на чипе видеокарты. А, как известно, БПФ это очень даже плавающая точка :) Вдвойне приятно то, что хорошие люди уже давно написали Java-интерфейс JCuda для нативной библиотеки CUDA. И ещё больше я обрадовался, когда обнаружил, что библиотека CUDA имеет в своем составе модуль CUFFT, который предоставляет средства для расчета БПФ, использующие по полной программе возможности видеокарты для выполнения параллельных вычислений с плавающей точкой.

CUDA поддерживается видеокартами NVIDIA GeForce начиная с чипа G80, т.е. с восьмой серии. Машина, на которой я тестирую в данный момент связку Java + CUDA довольно старенькая и имеет на борту процессор AMD Athlon X2 4200+, видеокарту NVIDIA GeForce 8800 GTS 640 Mb, всего 2 Gb оперативной памяти и управляется операционной системой openSUSE 11.4.

25 марта 2011 г.

Красивое использование косвенной адресации в bash-скриптах

Косвенная адресация это когда, грубо говоря, одна переменная ссылается на какое-либо значение через другую переменную. Если говорить точнее и применительно к bash'у, то это когда одна переменная хранит имя другой переменной, которая в свою очередь содержит, например, какое-либо значение. С помощью косвенной адресации можно, используя первую переменную, сразу получить доступ к значению, которое содержит вторая переменная. Как это работает вроде бы ясно, но, возможно, не сразу понятна нужность всего этого.

Итак, допустим у нас есть переменная X, которая содержит строку "значение". Так же есть переменная Y, которая в качестве значения содержит имя переменной X. Красивость заключается в том, что с помощью прямой и косвенной адресации, используя переменную Y, можно получить соответственно имя и значение переменной X.

Простой пример:
X="значение"
Y=X
echo "$Y: ${!Y}"
В этом примере с помощью прямой адресации $Y мы получаем доступ к имени переменной X, а с помощью косвенной ${!Y} - к её значению. В старых версиях bash косвенная адресация могла использоваться только так eval Z=\$$Y, а начиная со 2 версии она стала выглядеть проще, хотя старый вариант так же может использоваться.

Теперь приведу более жизненный пример. У меня есть скрипт, который настраивает iptables. Косвенная адресация в нем используется для того, чтобы сделать проще изменение настроек скрипта и создать красивый вывод. Приведу пример поясняющий основную суть.
#!/bin/bash

# список сервисов и их портов
SSH=22
HTTP=80
HTTPS=443
SAMBA="137 138 139 445"

# локальные сервисы на которые разрешен доступ снаружи
INPUT_PORTS_ACCEPT="SSH SAMBA HTTP HTTPS"

echo "Удаленный доступ к сервисам хоста:"
# открываем доступ на разрешенные сервисы
for SERVICE_NAME in $INPUT_PORTS_ACCEPT
do
    # для каждого порта сервиса добавляем разрешающие правила в iptables
    PORTS=${!SERVICE_NAME} # устаревший вариант: eval PORTS=\$$SERVICE_NAME
    for PORT in $PORTS
    do
        iptables -t filter -A INPUT -i eth0 -p tcp --dport $PORT -j ACCEPT
        iptables -t filter -A INPUT -i eth0 -p udp --dport $PORT -j ACCEPT
    done

    # выводим имя и порты сервиса
    echo "$SERVICE_NAME: $PORTS --accept"
done
Вывод скрипта:

Удаленный доступ к сервисам хоста:
SSH: 22 --accept
SAMBA: 137 138 139 445 --accept
HTTP: 80 --accept
HTTPS: 443 --accept

Таким образом, для настройки скрипта в переменной INPUT_PORTS_ACCEPT нужно указывать не номера портов, а просто имена сервисов, и в выводе наглядно показано на какие локальные сервисы открыт доступ и какие порты им соответствуют. Красиво :)

11 марта 2011 г.

JDOM: работа с XML на Java - проще простого

JDOM – это максимально упрощенная open source Java-библиотека для создания, парсинга, изменения и сериализации XML-документов. В отличие от других подобных DOM APIs, JDOM ориентированна на язык Java, а не на спецификации XML, что очень упрощает код и облегчает его интуитивное понимание. При этом JDOM не является "велосипедом" и не содержит в себе свой собственный парсер, а использует уже существующие наработки – стандартные пакеты javax.xml и org.xml.sax. Если вам понадобилось работать с XML, то обратите сначала внимание именно на эту библиотеку, скорее всего вам она понравится.

Краткое описание модели библиотеки JDOM

Так же, как и сам XML, JDOM APIs являются древовидными. Для представления XML в библиотеке, главным образом, используются классы Document, Element и Attribute.

Документ XML в JDOM представляет из себя дерево, корнем которого является объект класса Document. Экземпляр Document является контейнером для всех остальных элементов и обязательно содержит один корневой элемент (экземпляр Element). Главной характеристикой объекта Element является его содержание (Content) и список атрибутов (Attribute). Класс Content является родительским для классов Element, Comment и Text (а так же для некоторых других), поэтому экземпляры перечисленных классов могут быть содержимым объекта Element. Объект Element есть ничто иное как XML-тег, у которого обязательно должно быть имя и могут быть атрибуты. Классы Comment и Text соответственно представляют комментарий и текст внутри тега. Экземпляры Attribute, Comment и Text не могут содержать внутри себя никаких элементов и по сути являются объектами, которые содержат только текстовые значения. Значение экземпляра Attribute может быть получено по имени в отличие от Comment и Text, у которых имени нет.

1 февраля 2011 г.

Работа со звуковыми WAVE-файлами на Java

Мне на работе иногда приходится иметь дело с WAVE-файлами (или WAV по расширению) по той причине, что в них довольно удобно хранить научные данные и не надо выдумывать формат. Решил написать маленькую заметку о работе с этим форматом на Java. Сразу оговорюсь, что речь тут пойдет не о воспроизведении звуковых файлов с помощью Java, а о том как можно их создавать, изменять, и читать из них данные.

7 декабря 2010 г.

Файлы внутри скриптов или deploy на bash'е

Одним из интересных свойств bash-скриптов является то, что в них можно запихивать файлы, которые затем сам скрипт будет из себя извлекать при запуске. Таким образом, например, устроены скрипты установки JRE и JDK для Linux. Используя это свойство, можно довольно легко создавать скрипты для автоматизированного развертывания каких-либо систем, библиотек и т.п.. Приведу примеры извлечения текстовых и бинарных данных из bash-скриптов.

26 ноября 2010 г.

Создание документа ODF с помощью ODFDOM Simple Java API

Документ ODF, как известно, представляет из себя ZIP-архив, который содержит xml-файлы и различные ресурсы документа, например картинки. Наиболее значимые xml-файлы это content.xml, который содержит по сути весь текст документа и его структуру, и styles.xml, который хранит стили документа.

Элементы файла content.xml, содержащие текст, могут использовать стили, описанные в файле styles.xml, обращаясь к ним по имени. Проще говоря, в элементе файла content.xml указывается имя стиля из styles.xml, которое должно применяться для текста, параграфа и т.п. Стили так же представляют из себя набор XML-элементов.

Изучать стрктуру и все элементы ODF дело скучное да и мало кому, я думаю, нужное. Для того, чтобы работать с форматом ODF на высоком уровне существует библиотека ODFDOM. На самом деле эта библиотека не такая уж и простая, и чтобы ею пользоваться нужно все же понимать устройство ODF и уметь работать с XML при помощи Apache Xerces-J. Но для действительно простой работы с ODF теперь есть надстройка над ODFDOM, которая называется Simple Java API for ODF. Раньше я писал о том, как можно работать с документами ODF из Java-программы используя OpenOffice. Использование библиотеки ODFDOM Simple Java API намного удобнее как с точки зрения написания кода, так и тем, что вам теперь не нужен установленный OpenOffice. Благодаря этой библиотеке вы сами легко можете создавать программы работающие с ODF.

22 сентября 2010 г.

Запуск внешней программы на Java

Удобным средством для запуска внешних программ из java-кода является класс ProcessBuilder. С помощью экземпляра этого класса можно указать программу для запуска, параметры её запуска, переменные окружения, рабочий каталог и включить перенаправление потока вывода ошибок на стандартный вывод.

Ниже приведу простой пример использования ProcessBuilder с комментариями.

7 мая 2010 г.

Java и MongoDB вместе

Сегодня стало очень модным использование нереляционных баз данных. Вот и мне захотелось такое подергать. Мой выбор пал на MongoDB просто потому что слышал о этой штуке много положительных отзывов. Для себя сделал эту заметку, что бы потом не пришлось все изучать по второму разу, если ещё кому-нибудь пригодится, то и замечательно.
Всё, что здесь написано, основывается на документации с официального сайта MongoDB и конкретно на разделе посвященному Java, а кое-что и вовсе является просто переводом. Некоторые примеры из документации я немного переделал для более ясной, на мой субъективный взгляд, демонстрации возможностей.

4 мая 2010 г.

Хитрости Apache Tomcat: Кодировка

При разработке сервлетов, которые на основе запроса от HTML или JSP-страницы генерируют другую страницу, можно натолкнуться на некоторые трудности с кодировкой данных, отправляемых на сервер (request) и получаемых от него (response).

Для определения кодировки данных ответа необходимо использовать метод setCharacterEncoding объекта класса HttpServletResponse. Например, для установки UTF-8:
public class FooServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
        
        response.setCharacterEncoding("UTF-8");
        
        // далее остальной код...
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
        doPost (request, response);
    }
}
А вот с кодировкой данных, которые будут отправлены в запросе на сервер есть небольшая хитрость. Казалось бы, если страница сформирована, допустим, в кодировке UTF-8, то и данные запроса должны обрабатываться сервером, как UTF-8. Однако, этого не происходит, потому что в запросе браузер не передает информацию о кодировке данных. Если для отправки данных формы используется метод POST, то все просто - можно точно так же вызвать метод setCharacterEncoding, только для объекта класса HttpServletRequest:
request.setCharacterEncoding("UTF-8");
Проблема возникнет, если для отправки данных формы будет использоваться метод GET. В таком случае request.setCharacterEncoding("UTF-8") уже не сработает и Tomcat будет обрабатывать строку запроса так, как-будто она в кодировке ISO8859-1.

Для решения этой проблемы необходимо подправить конфигурационный файл Apache Tomcat server.xml и в тег Connector добавить параметр useBodyEncodingForURI="true":
<Connector connectionTimeout="20000" 
      port="8081" protocol="HTTP/1.1" 
      redirectPort="8443" useBodyEncodingForURI="true"/>
После этого перезагружаем Tomcat и для метода GET можно будет также использовать request.setCharacterEncoding("UTF-8") для указания кодировки запроса:
public class FooServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
        
        response.setCharacterEncoding("UTF-8"); // кодировка ответа
        request.setCharacterEncoding("UTF-8");  // кодировка запроса; необходимо указать до
                                                // вызова request.getParameter()
        
        // далее остальной код...
        String param1=request.getParameter("param1");  
        String param2=request.getParameter("param2");
      
        // ...
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
        doPost (request, response);
    }
}
В том же теге Connector, используя параметр URIEncoding вместо useBodyEncodingForURI, можно явно установить нужную для вас кодировку, например URIEncoding="UTF-8", решайте сами, что для вас удобнее.

23 апреля 2010 г.

Добавление контейнера сервлетов Apache Tomcat в Eclipse

При разработке сервлетов и JSP в Eclipse можно настроить использование контейнера сервлетов Apache Tomcat. Это очень удобно, т.к. после этого Eclipse сам будет деплоить проекты на Tomcat, а так же запускать и перезапускать Tomcat, когда это необходимо, вдобавок к этому появляется удобная возможность управления настройками Tomcat.

Добавление Apache Tomcat

1. Качаем Apache Tomcat и распаковываем его например в каталог ~/Programs/apache-tomcat-v6

2. В Eclipse выбираем пункт меню Window -> Preferences -> Server -> Runtime Environments и нажимаем кнопку Add

3. Выбираем версию устанавливаемого контейнера сервлетов (в моем случае это Apache Tomcat v6.0) и нажимаем Next

4. Указываем имя сервера, которое удобно для нас, затем путь к каталогу с Tomcat (~/Programs/apache-tomcat-v6) и выбираем среду выполнения Java, в которой должен выполняться Tomcat (можно выбрать default JRE, т.е. ту в которой выполняется сам Eclipse, либо одну из ранее добавленных в Eclipse). После этого нажимаем Finish.


22 апреля 2010 г.

Формирование отчетов в OpenOffice.org Calc и Writer из Java-программы

При создании прикладных программ, работающих с базой данных, довольно часто возникает необходимость выгрузки данных в какой-нибудь текстовый редактор, который может быть использован для корректировки информации и печати получившегося документа. В этой статье я расскажу, как решил эту задачу для себя, используя язык программирования Java и офисный пакет OpenOffice.org, что позволило обеспечить кроссплатформенность этого решения.
Для начала необходимо, что бы был установлен OpenOffice.org 3 версии, ну и разумеется JDK со средой разработки, или кому как нравится.
Для разработки понадобятся следующие библиотеки OpenOffice.org:
  • juh.jar, jurt.jar, ridl.jar, unoloader.jar из каталога /opt/openoffice.org3/basis-link/ure-link/share/java (если OpenOffice.org установлен не из официальных репозиториев) 
  • unoil.jar из каталога /opt/openoffice.org3/basis-link/program/classes
  • bootstrapconnector.jar, который можно скачать здесь
Можно скопировать данные библиотеки в директорию jre/lib/ext, но лучше подключить их в своей среде разработки, как User Libraries.
Библиотеки juh.jar, jurt.jar, ridl.jar, unoil.jar и unoloader.jar представляют собой необходимый набор классов API OpenOffice.org.
Библиотека bootstrapconnector.jar необходима для решения некоторых проблем, которые могут возникнуть во время подключения приложения к работающему экземпляру OpenOffice.org при определенных условиях. Подробнее об этих проблемах можно почитать здесь (на англ. яз), там же есть ссылка на саму библиотеку.
Когда всё установлено и все библиотеки подключены можно приступать к разработке. Приведу пример рабочих классов и методов для работы с OpenOffice.org Calc и OpenOffice.org Writer.

Интеграция Apache Derby в Java-приложение

При создании небольших прикладных программ, решающих относительно простые задачи, очень часто приходится использовать базы данных для хранения информации, потому что это очень удобно. Так же, обычно, у таких программ не предполагается обработка и хранение больших объемов информации, работа в сети и многопользовательский доступ к базе данных. В таком случае зачастую очень не хочется заморачиваться с использованием таких СУБД, как PostgreSQL или MySQL, т.к. при установки такой программы необходимо, что бы либо пользователь обладал определенными знаниями в этой области и смог настроить СУБД для работы с созданной нами программой, либо для программы придется писать дополнительную программу-установщик, что бы избавить конечного пользователя от совершенно ненужных ему плясок вокруг установки и настройки сервера базы данных.
Но есть более простой выход - использование СУБД Apache Derby, которая может быть интегрированна в Java-приложение. В этой статье я кратко расскажу как можно реализовать такой подход.
При разработке я использовал ОС Linux и среду разработки Eclipse, поэтому статья ориентированна на эти системы, но точно так же всё написанное можно переоформить для MS Windows и любой другой среды разработки.