You are on page 1of 12

1 мая 2011 г. hello-kitty.

nw 1

Введение. В этом документе описана программа «Hello Kitty1 » — мобильный клиент для во-
дителей такси ООО «Удача». Для работы программы необходим телефон, поддерживающий запуск
Java ME-приложений.
Организация, заказавшая этот мобильный клиент — довольно большая для такого маленько-
го города, как Уссурийск, таксистская фирма; она насчитывает в своем составе несколько сотен
таксистов, и в среднем, около 150 таксистов находятся в движении по городу. В до-мобильные вре-
мена все аспекты управления этими таксистами целиком и полностью возлагались на диспетчеров,
работающих по широковещательной радиосвязи. Такой подход к работе была плох, неудобен и неэф-
фективен, и когда в миру появились новые технологии — мобильный GPRS-интернет и телефоны
с Java-приложениями, уклад работы диспетчеров и таксистов существенно упростился. Теперь дис-
петчеры сидят за терминалами, принимают заказы клиентов, вносят их в компьютерную систему
и следят за выполнением, а координацией работы таксистов: раздачей им заказов, и соблюдением
очередности занимается компьютерная система.
Функциональность Какую функциональность продукт предложит своим пользователям? Способ-
ность к изменениям Какие изменения могут потребоваться в программном продукте в бу- дущем?
Какие изменения маловероятны (а, следовательно, вам не нужно обеспечивать их простое внесе-
ние в будущем)? Производительность Какую производительность должен обеспечивать продукт?
Емкость Сколько пользователей будет одновременно работать с системой? Какой объем данных си-
стема должна хранить для своих пользова- телей? Экосистема Как система будет взаимодействовать
с другими системами в экоси- стеме, в которой она будет развернута? Модульность Как задача напи-
сания программного продукта делится на рабочие задания (модули) – и особенно модули, которые
могут разрабаты- ваться независимо друг от друга, при этом легко и точно дополняя потребно-
сти друг друга? Удобство построения Может ли программный продукт строиться в виде набора
компо- нентов, реализуемых и тестируемых независимо друг от друга? Ка- кие компоненты можно
позаимствовать из других продуктов, а ка- кие придется приобретать у внешних поставщиков? 40
Глава 1. Что такое архитектура? Технологичность Если продукт существует в нескольких верси-
ях, то как он может разрабатываться в контексте линейки продуктов, с использованием общности
версий? По какой стратегии должны разрабатываться продукты, входящие в линейку (Weiss and
Lai 1999)? Какие капита- ловложения потребуются на создание линейки программных про- дуктов?
Какую предполагаемую прибыль принесет разработка раз- ных продуктов, входящих в линейку? В
частности, возможно ли начать с разработки минимально полез- ного продукта, а затем разрабаты-
вать дополнительные продукты линейки посредством добавления (и удаления) компонентов без из-
менения ранее написанного кода? Безопасность Требует ли использование продукта авторизации,
должен ли про- дукт ограничивать доступ к своим данным, как обеспечить безопас- ность данных?
Как защититься от атак «отказа в обслуживании» (DoS, Denial of Service) и других видов атак?

1 Копирайт ○
c 2011 ООО «Телеавтоматика», Уссурийск.
1 мая 2011 г. hello-kitty-build.nw 2

Сборка и запуск проекта. Для сборки и запуска проекта используется фреймворк Apache Maven.
Его выбор обусловлен следующими преимуществами:

∙ стандартизированная схема проекта и генератор структуры проекта;


∙ стандартизированный механизм управлением зависимостями в проекте — поддержка большого
количества репозиториев с пакетами Java-библиотек;

∙ поддержка нескольких проектов;


∙ автоматическая загрузка плагинов при необходимости, особенно — наличие качественных плу-
гинов для разработки приложений для платформы Java ME;
∙ автоматическая генерация веб–сайта и документации проекта;

∙ интеграция с самыми популярными инструментами управления исходным кодом (например,


Subversion).

Сборка и запуск проекта в эмуляторе осуществляется с помощью консольной программы mvn


фреймворка Maven в терминале Windows Power Shell или любом из терминалов Linux и Mac OS X.

mvn clean очищает целевую директорию от созданных в процессе сборки файлов;


mvn compile только компилирует проект;
mvn package собирает проект в JAD–архив, готовый к установке на телефон или к запуску в эму-
ляторе;

mvn j2me:run запускает проект в эмуляторе;


mvn install добавляет JAR–архив с вашим проектом в репозиторий для использования в качестве
библиотеки, но в этом нет необходимости;
mvn site создает веб–сайт проекта;

mvn javadoc:javadoc создает HTML-документацию в из комментариев Javadoc.

Объектная модель проекта. Объектная модель проекта (англ. Project Object Model ) это XML-
файл ⟨./pom.xml⟩ в котором содержится информация о проекте и его конфигурация, которая ис-
пользуется Maven’ом для сборки проекта. Большая часть конфигурации проекта остается дефолтной,
например, расположение директорий:

target директория сборки проекта;


src/main/java директория с исходниками;

src/main/resources директория с ресурсами, которые будут включены в собраный JAR.

Некоторые параметры конфигурации проекта указаны особо, как то: зависимости от сторонних
внешних и локальных библиотек и плугинов, настройки плугинов, цели сборки, версия и название
проекта, его описание, имена разработчиков и тому подобное.
⟨./pom.xml⟩≡
<?xml version="1.0" encoding="ISO-8859-1"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0">
<!– @version $Revision: 2870 $ ($Author: vlads $) $Date: 2008-12-26 19:20:33 -0500 (Fri, 26 Dec 2008) $ –>
<modelVersion>4.0.0</modelVersion>

<groupId>teleautomatics</groupId>
1 мая 2011 г. hello-kitty-build.nw 3

<artifactId>hello-kitty</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Hello Kitty J2ME Application</name>

<organization>
⟨Сведения о организации⟩
</organization>

<licenses>
⟨Сведения о лицензии⟩
</licenses>

<developers>
⟨Сведения о разработчиках⟩
</developers>

<properties>
⟨Сведения о платформе⟩
</properties>

<repositories>
⟨Сведения о репозиториях⟩
</repositories>

<pluginRepositories>
⟨Сведения о репозиториях плугинов⟩
</pluginRepositories>

<dependencies>
⟨Сведения о зависимостях от внешних библиотек⟩
</dependencies>

<build>
<defaultGoal>install</defaultGoal>

<plugins>
⟨Сведения о плугинах⟩
</plugins>
</build>
</project>
Проект разработан в компании «Телеавтоматика».
⟨Сведения о организации⟩≡
<name>Teleautomatics</name>
<url>http://xn–80aaagnayqdnv6bfd.xn–p1ai</url>
Сведения о лицензии указаны чисто на всякий случай.
⟨Сведения о лицензии⟩≡
<license>
<name>Proprietary</name>
<distribution>binary</distribution>
<comments>A closed-source license</comments>
</license>
1 мая 2011 г. hello-kitty-build.nw 4

Информация для связи с разработчиками программы.


⟨Сведения о разработчиках⟩≡
<developer>
<id>zahardzhan</id>
<name>Roman Zaharov</name>
<email>zahardzhan@gmail.com</email>
<url>http://zahardzhan.github.com</url>
<organization>Teleautomatics</organization>
<organizationUrl>http://xn–80aaagnayqdnv6bfd.xn–p1ai</organizationUrl>
<roles>
<role>developer</role>
</roles>
<timezone>-10</timezone>
</developer>
Программа рассчитана на работу на телефонах, поддерживающих конфигурацию Connected Limited
Device Configuration API версии 1.1 и профиль Mobile Information Device Profile API версии 2.0; а
также Bluetooth API и GPS API (на будущее).
⟨Сведения о платформе⟩≡
<me2Version>2.0.3</me2Version>
<wtk.home>${env.WTK_HOME}</wtk.home>
<j2me.midlet.vendor>${project.organization.name}</j2me.midlet.vendor>
<j2me.midlet.name>${project.name}</j2me.midlet.name>
<j2me.midlet.version>1.0-SNAPSHOT</j2me.midlet.version>
<j2me.midlet.configuration>CLDC-1.1</j2me.midlet.configuration>
<j2me.midlet.profile>MIDP-2.0</j2me.midlet.profile>
<wtk.bluetooth.enabled>true</wtk.bluetooth.enabled>
<wtk.locationservices.enabled>true</wtk.locationservices.enabled>
<!– See other properties http://antenna.sourceforge.net/index.php#setup
<wtk.wma.enabled>true</wtk.wma.enabled>
<wtk.wma.version>2.0</wtk.wma.version>
<wtk.optionalpda.enabled>true</wtk.optionalpda.enabled>
–>
Проект Pyx4J (http://pyx4j.com) предоставляет эмулятор телефона MicroEmulator, качественный плу-
гин для разработки Java ME-приложений pyx4me и множество полезных библиотек.
⟨Сведения о репозиториях плугинов⟩≡
<pluginRepository>
<id>pyx4j-web-snapshot</id>
<url>http://repository.pyx4j.com/maven2-snapshot</url>
</pluginRepository>

⟨Сведения о репозиториях⟩≡
<repository>
<id>pyx4j-web-snapshot</id>
<url>http://repository.pyx4j.com/maven2-snapshot</url>
</repository>

⟨Сведения о зависимостях от внешних библиотек⟩≡


<dependency>
<groupId>org.microemu</groupId>
<artifactId>microemulator</artifactId>
<version>${me2Version}</version>
<scope>provided</scope>
</dependency>
1 мая 2011 г. hello-kitty-build.nw 5

В программе используется библиотека для логирования Microlog — неплохой маленький (но с широ-
кими возможностями) аналог большой библиотеки Log4J. Подробные сведения о её использовании
можно узнать:
∙ в блоге автора библиотеки http://mvnrepository.com/artifact/net.sf.microlog;
∙ в статье на сайте корпорации Sun http://java.sun.com/developer/technicalArticles/javame/javame-logging;
∙ в руководстве на форуме Nokia http://wiki.forum.nokia.com/index.php/Microlog:_A_Log4j-based_
tool_for_the_JavaME_platform.
⟨Сведения о репозиториях⟩+≡
<repository>
<id>microlog.sourceforge.repo</id>
<url>http://microlog.sourceforge.net/repo/m2-repository</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
⟨Сведения о зависимостях от внешних библиотек⟩+≡
<dependency>
<groupId>net.sf.microlog</groupId>
<artifactId>microlog-logger-core</artifactId>
<version>2.3.2</version>
</dependency>
Библиотека JSOM ME используется для работы с JSON. Руководство по работе с библиотекой на
сайте Sun http://java.sun.com/developer/technicalArticles/javame/json-me.
⟨Сведения о зависимостях от внешних библиотек⟩+≡
<dependency>
<groupId>org.json.me</groupId>
<artifactId>json</artifactId>
<version>1.0</version>
</dependency>
Для юнит-тестирования используется фреймворк JMUnit. Javadoc API находится на сайте http://
hammingweight.com/modules/jmunit/api/index.html.
⟨Сведения о зависимостях от внешних библиотек⟩+≡
<dependency>
<groupId>jmunit</groupId>
<artifactId>jmunit</artifactId>
<version>1.2.1</version>
<classifier>cldc1.1</classifier>
</dependency>
Помимо библиотек из репозиториев, программа зависит от множества библиотек с телефонными
API, идущих в составе фирменного комплекта средств разработки Sun Wireless Toolkit. Эти библио-
теки устанавливаются на локальную машину, поэтому зависимости прописываются как «системные»
(system) и для их удовлетворения требуется определить в операционной системе переменную пути
WTK_HOME со значением, к примеру /opt/wtk под линуксом или C:\java\wtk под виндой.
∙ Bluetooth API:
⟨Сведения о зависимостях от внешних библиотек⟩+≡
<dependency>
<groupId>come.sun.wtk</groupId>
<artifactId>jsr082</artifactId>
<version>2.2</version>
<scope>system</scope>
<systemPath>${env.WTK_HOME}/lib/jsr082.jar</systemPath>
</dependency>
1 мая 2011 г. hello-kitty-build.nw 6

∙ Location API — поддержка GPS:


⟨Сведения о зависимостях от внешних библиотек⟩+≡
<dependency>
<groupId>come.sun.wtk</groupId>
<artifactId>jsr179</artifactId>
<version>2.2</version>
<scope>system</scope>
<systemPath>${env.WTK_HOME}/lib/jsr179.jar</systemPath>
</dependency>

∙ Неиспользуемые сейчас зависимости, возможно когда-нибудь пригодятся:

<!-- WMA
<dependency>
<groupId>org.microemu</groupId>
<artifactId>microemu-jsr-120</artifactId>
<version>${me2Version}</version>
<scope>provided</scope>
</dependency> -->

<!-- JSR-82
<dependency>
<groupId>net.sf.bluecove</groupId>
<artifactId>bluecove</artifactId>
<version>2.1.0</version>
<scope>provided</scope>
</dependency> -->

<!-- WTK
<dependency>
<groupId>come.sun.wtk</groupId>
<artifactId>jsr082</artifactId>
<version>2.2</version>
<scope>system</scope>
<systemPath>${WTK_HOME}/lib/jsr082.jar</systemPath>
</dependency> -->

Компиляция производится для JVM версии 1.4.


⟨Сведения о плугинах⟩≡
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.4</source>
<target>1.4</target>
<compilerArguments>
<bootclasspath>${settings.localRepository}/org/microemu/cldcapi11/${me2Version}/cldcapi11-${me2Versio
</compilerArguments>
</configuration>
<dependencies>
<dependency>
<groupId>org.microemu</groupId>
<artifactId>midpapi20</artifactId>
<version>${me2Version}</version>
</dependency>
</dependencies>
</plugin>
1 мая 2011 г. hello-kitty-build.nw 7

Настройки плугина pyx4me. Подробнее на офсайте http://pyx4me.com/pyx4me-maven-plugins/j2me-maven-plugin.


⟨Сведения о плугинах⟩+≡
<plugin>
<groupId>com.pyx4me</groupId>
<artifactId>j2me-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
<configuration>
<wtkHome>${env.WTK_HOME}</wtkHome>
<proguardInclude>proguard.conf</proguardInclude>
<proguard>true</proguard>
<obfuscate>true</obfuscate>
<jadAttributes>
<MIDlet-Vendor>${project.organization.name}</MIDlet-Vendor>
<Created-By>Zahardzhan</Created-By>
<MIDlet-Permissions>javax.microedition.io.Connector.http</MIDlet-Permissions>
<!– To ask the platform to optionally grant permissions provided certain API-subsets are available, u
<MIDlet-Permissions-Opt>javax.wireless.messaging.sms.receive,javax.wireless.messaging.sms.send</MIDle
</jadAttributes>
<midlets>
<!– for each MIDlet entry-point, simply reiterate this section –>
<MIDlet>
<name>Hello Kitty App</name>
<icon>/pyx.png</icon>
<class>teleautomatics.HelloKitty</class>
</MIDlet>
<!– midlet for running tests –>
<MIDlet>
<name>Hello Kitty Test App</name>
<class>teleautomatics.test.MessageTest</class>
</MIDlet>
</midlets>
<!– If you are going to use ProGuard instead of WTK
<useWtkLibs>false</useWtkLibs>
<libs>
<lib>${settings.localRepository}/org/microemu/cldcapi11/${me2Version}/cldcapi11-${me2Version}.jar</lib>
<lib>${settings.localRepository}/org/microemu/midpapi20/${me2Version}/midpapi20-${me2Version}.jar</lib>
</libs>
<dependencies>
<dependency>
<groupId>org.microemu</groupId>
<artifactId>microemulator</artifactId>
<exclude>true</exclude>
</dependency>
</dependencies>
–>
</configuration>
</plugin>

<plugin>
<groupId>com.pyx4me</groupId>
<artifactId>obex-maven-plugin</artifactId>
<configuration>
<jarfile>hello-kitty-1.0-SNAPSHOT-me.jar</jarfile>
</configuration>
</plugin>
1 мая 2011 г. hello-kitty-build.nw 8

Установка JAR-файла в директорию site.


⟨Сведения о плугинах⟩+≡
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>site</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<copy overwrite="true"
file="${project.build.directory}/${project.build.finalName}-me.jar"
tofile="${project.build.directory}/site/hello-kitty.jar"/>
<copy overwrite="true"
file="${project.build.directory}/${project.build.finalName}-me.jad"
tofile="${project.build.directory}/site/hello-kitty.jad"/>
<replace value="hello-kitty.jar" token="${project.build.finalName}-me.jar"
dir="${project.build.directory}/site">
<include name="hello-kitty.jad"></include>
</replace>
</tasks>
</configuration>
</execution>
</executions>
</plugin>

Обфускация JAR-файла. Во время сборки JAR-файла плугином pyx4me производится обфус-


кация программой Proguard. Настройки обфускатора хранятся в файле ⟨./proguard.conf⟩. Подробнее
о настройках, и выдаваемых обфускатором замечаниях, предупреждениях и ошибках можно узнать
на офсайте http://proguard.sourceforge.net/index.html#/manual/troubleshooting.html.
⟨./proguard.conf⟩≡
-overloadaggressively
-defaultpackage ”
-allowaccessmodification
-dontusemixedcaseclassnames
Чтобы обфускатор не выдавал замечания о динамическом создании классов в фреймворке для
тестирования я добавил строчку настроек.
⟨./proguard.conf⟩+≡
-keep class jmunit.framework.cldc11.TestCase
1 мая 2011 г. hello-kitty.nw 9

Исходники.
⟨./src/main/java/teleautomatics/Agent.java⟩≡
package teleautomatics;

import teleautomatics.message.Message;

public interface Agent {


void sendMessage(final Message message);
void startup();
void shutdown();
}
1 мая 2011 г. hello-kitty.nw 10

⟨./src/main/java/teleautomatics/Reactor.java⟩≡
package teleautomatics;

import java.util.Hashtable;
import net.sf.microlog.core.Logger;
import teleautomatics.message.Message;
import teleautomatics.message.Message.MalformedException;

/**
*
* @author haru
*/
public class Reactor implements Agent {

final Logger log ← LoggerMaker.makeLogger("Reactor");

final Queue inbox ← new Queue();

public synchronized void sendMessage(final Message message) {


inbox.add(message);
reactorController.awake();
}

public synchronized void startup() {


reactorController.restart();
}

public synchronized void shutdown() {


reactorController.stop();
}

final Hashtable reactions ← new Hashtable();

public synchronized void setReaction(final String messageType, final Reaction reaction) {


if (messageType ̸≡ null ∧ reaction ̸≡ null) reactions.put(messageType, reaction);
}

final ReactorController reactorController ← new ReactorController();

final class ReactorController implements ThreadController {

public void start() {


log.trace("Starting reactor thread.");
synchronized (Reactor.this) {
reactorThread ← new ReactorThread();
reactorThread.start();
}
}

public void stop() {


log.trace("Stopping reactor thread.");
synchronized (Reactor.this) {
if (isAlive()) {
reactorThread.interrupted ← true;
reactorThread.interrupt();
}
reactorThread ← null;
}
}

public void restart() {


1 мая 2011 г. hello-kitty.nw 11

synchronized (Reactor.this) {
stop();
start();
}
}

public void awake() {


log.trace("Awaking reactor thread.");
synchronized (Reactor.this) {
if (isAlive())
synchronized (reactorThread) {
reactorThread.notify();
}
}
}

public boolean isAlive() {


synchronized (Reactor.this) {
return reactorThread ̸≡ null ∧ reactorThread.isAlive();
}
}

volatile ReactorThread reactorThread;

final class ReactorThread extends Thread {

public boolean interrupted ← false;

public void run() {


reactOnMessageLoop:
for (Message message;;)
try {
if (interrupted) throw new InterruptedException();

awaitForIncomingMessage:
for (;;) {
synchronized (Reactor.this) {
if (¬inbox.isEmpty()) break awaitForIncomingMessage;
}
synchronized (this) { wait(); }
}

synchronized (Reactor.this) {
message ← (Message) inbox.remove();
}

if (message ̸≡ null) {
String type ← message.getTypeField().value();
if (type ≡ null ∨ type.equals("")) {
log.error("Cannot react on message with undefined type.");
continue reactOnMessageLoop;
}
if (¬reactions.containsKey(type)) {
log.error("Reaction on message of type " + type + " undefined.");
continue reactOnMessageLoop;
}
log.debug("Reacting on " + type + " message.");
Reaction reaction ← (Reaction) reactions.get(type);
try {
reaction.react(message);
} catch (Exception e) {
1 мая 2011 г. hello-kitty.nw 12

try {
log.error("Reaction on message "
+ message.toJSON().toString() + " failed: " + e.toString());
} catch (MalformedException ex) {
log.error("Reaction on message " + type + " failed: " + e.toString());
}
}
}
} catch (InterruptedException e) {
return;
}
}
};
}
}

Кусочки кода.

Индекс.

You might also like