Files
pitiupi/docs/documentation/09_sistema_de_plugins.md
T
Gabriel Felipe Souza SantosandCursor eeb1936f6d Entrega v1 aula: shell com abas, PITIUPI_HOME e plugins de referência.
Consolida núcleo (presença, peer actions, MessageDispatcher), chat e screencast na galeria, documentação PT-BR e testes JUnit; remove mpChat do catálogo em favor do chat unificado.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-27 11:08:21 -03:00

3.9 KiB

Sistema de plugins

O sistema de plugins permite extensão modular sem alterar o núcleo. O contrato está em pitiupi.models.Plugin (classe abstrata).

Interface Plugin

Métodos obrigatórios:

Método Função
getName(), getAuthor(), getVersion(), getIdentifier() Identificação (o identifier distingue plugins em conexões TCP dedicadas)
getDisplayName() Texto na galeria e título de aba (padrão: getName())
createPlugin(ConnectionManager, PluginWorkspace) Inicialização na shell: painel na aba, peer actions, rede
createPlugin(ConnectionManager, GuiManager) Legado — adapter na carga; não usar em plugins novos
getMessages() Lista de classes Message que o plugin desserializa
receiveMessage(Message) Processamento após o PluginManager identificar o tipo

Métodos opcionais (ciclo de vida e TCP avançado):

Método Função
onShellTabClosed() Usuário fechou a aba do plugin no topo; liberar timers, captura, envio contínuo
receiveAllTypes() Receber todas as mensagens públicas
receivePrivateConnection(TcpConnection) Aceitar conexão TCP direcionada ao plugin
receiveBytes(TcpConnection, byte[]) Ler payload bruto na conexão privada
onSocketClosed(TcpConnection) Limpar estado ao fechar socket

Descoberta de plugins

Para serem reconhecidos, os plugins devem possuir os arquivos de configuração do Java Service Provider Interface (SPI):

MeusPlugins
|
+---META-INF
    |
    +---services
        |
        +---pitiupi.models.Plugin

O arquivo pitiupi.models.Plugin deve conter o nome completo das classes que implementam a interface Plugin:

MeusPlugins.plugins.NomeDaClasse

Para serem carregados, os plugins devem estar empacotados como arquivos JAR e colocados no diretório plugins da aplicação.

Carregamento de plugins

O PluginManager.loadPlugins() (chamado pela MainShellFrame):

  1. Lista arquivos .jar em PITIUPI_HOME/plugins (ver 00_quickstart.md; symlinks de dev via ./scripts/pitiupi.sh link).
  2. Para cada JAR, cria um URLClassLoader e usa ServiceLoader.load(Plugin.class, classLoader).
  3. Chama createPlugin(connectionManager, pluginWorkspace) em cada instância (ShellPluginWorkspace).
  4. Na recepção UDP/TCP, tenta desserializar com PluginObjectInputStream e despacha para plugins que declararam o tipo em getMessages().

Ao fechar uma aba dinâmica de plugin, TabWorkspacePanel notifica PluginManager.notifyShellTabClosed(pluginId) antes de remover o conteúdo, para o plugin encerrar trabalho em segundo plano.

Implementação: pitiupi/src/pitiupi/control/plugins/PluginManager.java.

Shell e abas (PluginWorkspace)

Na MainShellFrame, createPlugin(ConnectionManager, PluginWorkspace) registra o painel com bindShellWorkspaceContent(JPanel) sem abrir aba no boot. A galeria Plugins e as peer actions abrem a aba sob demanda.

Peer actions na lista lateral

PeerActionBroker.getAllActionsFor(target) agrupa ações de todos os plugins (submenu por getDisplayName()). Destinos: SINGLE_PEER (um usuário) ou ALL_PEERS (linha Todos).

Envio didático (núcleo)

PluginRoutingPanel (núcleo) padroniza destino, forma de envio e dica embaixo para chat, screencast e futuros plugins.

MessageDispatcher envia com TransportMode e SendTarget. PluginTransportCatalog define quais transportes cada plugin mostra na UI (sala geral vs um IP). Os combos usam textos didáticos (describeForUi) com o termo técnico entre parênteses (multicast UDP, UDP unicast, TCP). Na sala geral o campo IP fica desativado; um resumo “Como esta mensagem vai” (chat) deixa explícito o transporte escolhido — na sala pode ser multicast ou cópias unicast/TCP para cada pessoa, conforme o plugin. Para um peer use o IP manualmente ou a peer action na lista lateral.