Библиотека сайта rus-linux.net
Фреймворк Jitsi
Глава 10 из книги "Архитектура приложений с открытым исходным кодом", том 1.
Оригинал: "Jitsi", глава 10 из 1 тома книги "The Architecture of Open Source Applications"
Автор: Emil Ivov
Перевод: Н.Ромоданов
10.4. Сервис провайдера протоколов
ProtocolProviderService
в Jitsi определяет то, как будут себя вести все реализации протоколов. Это интерфейс, который в других сборках (например, в пользовательском интерфейсе) будет использоваться в случаях, когда нужно отправлять и получать сообщения, совершать звонки и обмениваться файлами через сети, к которым Jitsi подключен.
Все интерфейсы сервисов протоколов можно найти в пакете net.java.sip.communicator.service.protocol
. Есть много реализаций сервиса, по одной для каждого поддерживаемого протокола, и все они хранятся в net.java.sip.communicator.impl.protocol.protocol_name
.
Давайте начнем с каталогом service.protocol
. Наиболее интересным фрагментом является интерфейс ProtocolProviderService. Всякий раз, когда нужно выполнить задачу, связанную с использованием протоколов, нужно искать реализацию этого сервиса в BundleContext
. Сервис и его реализации позволяют Jitsi подключаться к любой из поддерживаемых сетей, получать статус и подробности соединения, а главное — получать ссылки на классы, в которых реализованы конкретные коммуникационные задачи, например, чат и осуществление звонков.
10.4.1. Наборы операций
Как мы уже упоминали ранее, ProtocolProviderService
необходим для единообразного использования различных коммуникационных протоколов и сведения их различий к минимуму. Хотя это, в частности, исключительно просто для тех функций, которые используются во всех протоколах, например, функция отправки сообщений, все становится гораздо сложнее для тех задач, которые поддерживаются только в некоторых протоколах. Иногда эти различия связаны с самим сервисом: например, большинство сервисов SIP не поддерживают списки контактов, хранящихся на сервере, хотя это относительно хорошо поддерживаемая функция во всех других протоколах. Другим хорошим примером являются сервисы MSN и AIM: в свое время ни в одном из них не было возможности оставлять сообщения абонентам, не находящимся в сети, хотя в остальных сервисах эта возможность была (с тех пор все изменилось).
Суть заключается в том, что в нашем ProtocolProviderService
должен быть способ обработки этих различий с тем, чтобы другие сборки, например, графический интерфейс, действовали согласовано; нет смысла добавлять в AIM contact кнопку вызова, если, в действительности, нет возможности делать вызов.
В качестве спасательного средства используется OperationSets (рис. 10.3). Неудивительно, что есть набор операций и предлагается интерфейс, который сборки Jitsi используют для управления реализациями протоколов. Методы, которые вы можете найти в интерфейсе набора операций, является тем, что касается конкретных возможностей.
В OperationSetBasicInstantMessaging, например, содержатся методы для создания и отправки мгновенных сообщений и регистрации слушателей (listeners), которые позволяют Jitsi находить сообщения, которые он получает. В другом примере, OperationSetPresence, есть методы запроса статуса контактов в вашем списке и установки собственного статуса. Поэтому, когда графический интерфейс обновляет статус отображаемого контакта или отправляет сообщение для конкретного контакта, он сначала может запросить у соответствующего провайдера, поддерживаются ли контакты и передача сообщений. К методам, которые в ProtocolProviderService
определены для этой цели, относятся следующие:
public Map<String, OperationSet> getSupportedOperationSets(); public <T extends OperationSet> T getOperationSet(Class<T> opsetClass);
Наборы OperationSets должны быть сконструированы таким образом, чтобы была маловероятной такая ситуация, когда новый протокол, который мы добавим, имеет поддержку только некоторых из операций, которые определены в OperationSet. Например, в некоторых протоколах не поддерживается хранение списков контактов на сервере даже в случае, если в них пользователям разрешается запрашивать статус друг друга. Поэтому вместо того, чтобы в OperationSetPresence
объединять управление хранением данных и использование списка друзей, мы также определили набор OperationSetPersistentPresence
, который используется только с протоколами, в которых контакты можно хранить в Интернете. С другой стороны, мы еще не сталкивались с протоколом, в котором можно только посылать сообщения и нельзя их получать, поэтому такие операции, как отправка и получение сообщений, можно смело объединять.
Рис.10.3: Наборы операций
10.4.2. Аккаунты, фабрики и экземпляры провайдеров
Важной характеристикой сервиса ProtocolProviderService
является то, что один экземпляр соответствует ровно одному аккаунту протокола. Поэтому в любой заданный момент времени у вас в BundleContext
есть столько возможных реализаций сервисов, сколько у вас есть аккаунтов, зарегистрированных пользователем.
В этот момент вам может стать интересно, кто создает и регистрирует провайдеров протоколов. В этом участвуют две сущности. Во-первых, имеется фабрика ProtocolProviderFactory
. Это сервис, который позволяет другим сборкам получать отдельные экземпляры провайдеров, а затем регистрировать их в качестве сервисов. Для каждого протокола есть одна фабрика и каждая фабрика отвечает за создание провайдеров для конкретного протокола. Реализации фабрики хранятся вместе с остальными внутренними частями протокола. Например, для SIP у нас есть net.java.sip.communicator.impl.protocol.sip.ProtocolProviderFactorySipImpl
.
Второй сущностью, участвующей в создании аккаунта, является визард протокола (protocol wizard). В отличие от фабрик, визарды отделены от остальной части реализации протокола, поскольку они связаны с графическим пользовательским интерфейсом. Визард, который позволяет пользователям создавать аккаунты для SIP, можно, например, найти в net.java.sip.communicator.plugin.sipaccregwizz
.
Продолжение статьи: 10.5. Медиасервис.