Adiciona catálogo de plugins e script único de build/run.
plugins.registry.json e scripts/pitiupi.sh substituem lista fixa de módulos; screen cast em MenuCategory.Streaming; README e docs atualizados. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
f02acaf131
commit
b10c196fc9
9 files changed
+496
-47
No files matched your search
@@ -1,50 +1,114 @@
|
|||||||
# pitiupi
|
# pitiupi
|
||||||
|
|
||||||
Ferramenta **P2P** para práticas de Redes de Computadores: núcleo em Java com arquitetura de **plugins** (chat, compartilhamento de tela, exemplos multi-protocolo).
|
Ferramenta **P2P** para práticas de Redes de Computadores: núcleo em Java com arquitetura de **plugins** (chat, compartilhamento de tela, chat multi-protocolo).
|
||||||
|
|
||||||
**Documentação completa:** [docs/README.md](docs/README.md)
|
**Documentação completa:** [docs/README.md](docs/README.md) · **Quickstart:** [docs/documentation/00_quickstart.md](docs/documentation/00_quickstart.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Início rápido (um comando)
|
||||||
|
|
||||||
|
Na **raiz do repositório**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x scripts/pitiupi.sh # só na primeira vez
|
||||||
|
./scripts/pitiupi.sh run --all
|
||||||
|
```
|
||||||
|
|
||||||
|
Compila o núcleo, os plugins do [catálogo](plugins.registry.json), instala JARs em `pitiupi/plugins/` e abre a aplicação.
|
||||||
|
|
||||||
|
1. Login: **nome** e **porta** (ex.: `5000`).
|
||||||
|
2. Menus dos plugins: barra **Plugin → Social | Jogos | Streaming** (cada plugin registra a categoria no código).
|
||||||
|
3. P2P no mesmo PC: segunda instância com **porta diferente** (ex.: `5001`).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/pitiupi.sh list # ids, categorias, JAR buildado?
|
||||||
|
./scripts/pitiupi.sh check # ferramentas + catálogo
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Catálogo de plugins (`plugins.registry.json`)
|
||||||
|
|
||||||
|
Novos módulos entram no repositório adicionando uma entrada no JSON (não é preciso editar o script):
|
||||||
|
|
||||||
|
| Campo | Significado |
|
||||||
|
| --- | --- |
|
||||||
|
| `id` | Usado em `--plugins chat,meuJogo` |
|
||||||
|
| `dir` | Pasta do módulo (ex.: `pitiupi.xadrez`) |
|
||||||
|
| `build` | `ant` ou `make` |
|
||||||
|
| `jar` | Caminho do JAR relativo a `dir` |
|
||||||
|
| `menuCategory` | `Social`, `Jogos` ou `Streaming` — filtro CLI e documentação |
|
||||||
|
|
||||||
|
Plugins de referência hoje:
|
||||||
|
|
||||||
|
| id | Categoria (menu) | Pasta |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `chat` | Social | `pitiupi.chat` |
|
||||||
|
| `mpchat` | Social | `pitiupi.mpChat` |
|
||||||
|
| `screencast` | Streaming | `pitiupi.screenCast` |
|
||||||
|
|
||||||
|
A **categoria na interface** vem do `MenuCategory` no Java (`guiManager.createMenu(...)`), não do nome do JAR. O campo `menuCategory` no JSON alinha build/link com a doc.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/pitiupi.sh run --all
|
||||||
|
./scripts/pitiupi.sh run --category Social
|
||||||
|
./scripts/pitiupi.sh run --plugins chat,screencast
|
||||||
|
./scripts/pitiupi.sh discover # pastas pitiupi.* com SPI ainda não no catálogo
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Novo plugin (resumo)
|
||||||
|
|
||||||
|
1. Copiar estrutura de `pitiupi.chat` → `pitiupi.meuPlugin` ([tutorial](docs/documentation/10_tutorial_plugin.md)).
|
||||||
|
2. Em `createPlugin`, registrar menu: `guiManager.createMenu(MenuCategory.Jogos, ...)` (ou Social / Streaming).
|
||||||
|
3. Adicionar entrada em [`plugins.registry.json`](plugins.registry.json).
|
||||||
|
4. `./scripts/pitiupi.sh run --plugins meuId`.
|
||||||
|
|
||||||
|
O núcleo carrega **todos os `*.jar`** em `pitiupi/plugins/` (pasta única). Detalhes: [pitiupi/plugins/README.md](pitiupi/plugins/README.md).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Pré-requisitos
|
## Pré-requisitos
|
||||||
|
|
||||||
| Ferramenta | Uso |
|
| Ferramenta | Uso |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| **JDK** com `javac` | Compilação (OpenJDK **25** recomendado; núcleo compila com target **17**) |
|
| **JDK** com `javac` | Compilação (OpenJDK **25** recomendado) |
|
||||||
| **Apache Ant** 1.10+ | `pitiupi/`, `pitiupi.chat/`, `pitiupi.screenCast/` |
|
| **Apache Ant** | Módulos NetBeans |
|
||||||
| **GNU Make** | `pitiupi.mpChat/` |
|
| **GNU Make** | `pitiupi.mpChat` |
|
||||||
|
| **python3** | Script `scripts/pitiupi.sh` (ler o catálogo) |
|
||||||
Exemplo Ubuntu / WSL:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt install openjdk-25-jdk ant make
|
sudo apt install openjdk-25-jdk ant make
|
||||||
javac -version # deve existir — JRE sozinho não basta
|
./scripts/pitiupi.sh check
|
||||||
```
|
```
|
||||||
|
|
||||||
## Módulos
|
**GUI:** Swing — WSLg / `DISPLAY=:0`.
|
||||||
|
|
||||||
| Pasta | Descrição | Build |
|
---
|
||||||
| --- | --- | --- |
|
|
||||||
| `pitiupi/` | Núcleo (GUI, UDP multicast, TCP, heartbeat) | `ant jar` |
|
|
||||||
| `pitiupi.chat/` | Plugin referência — chat | `ant jar` |
|
|
||||||
| `pitiupi.screenCast/` | Plugin referência — screen cast | `ant jar` |
|
|
||||||
| `pitiupi.mpChat/` | Plugin referência — chat multicast + TCP | `make` |
|
|
||||||
|
|
||||||
Compile cada módulo no seu diretório (núcleo primeiro). Instale os JARs dos plugins em `pitiupi/plugins/` — ver [pitiupi/plugins/README.md](pitiupi/plugins/README.md).
|
## Comandos do script
|
||||||
|
|
||||||
Exemplo de symlinks (Linux):
|
| Comando | Ação |
|
||||||
|
| --- | --- |
|
||||||
|
| `run` | Build + `plugins/` + app |
|
||||||
|
| `build` | Build + `plugins/` |
|
||||||
|
| `link` | Só symlinks (JARs já existem) |
|
||||||
|
| `list` | Catálogo e status do JAR |
|
||||||
|
| `discover` | Sugestão de módulos `pitiupi.*` |
|
||||||
|
| `check` | PATH + JSON válido |
|
||||||
|
|
||||||
```bash
|
Opções: `--all` (padrão), `--plugins ids`, `--category Social|Jogos|Streaming`.
|
||||||
cd pitiupi/plugins
|
|
||||||
ln -sf ../../pitiupi.chat/dist/pitiupi.chat.jar pitiupi.chat.jar
|
|
||||||
ln -sf ../../pitiupi.screenCast/dist/pitiupi.screenCast.jar pitiupi.screenCast.jar
|
|
||||||
ln -sf ../../pitiupi.mpChat/dist/mpChat.jar mpChat.jar
|
|
||||||
```
|
|
||||||
|
|
||||||
Execute o núcleo (a partir de `pitiupi/`):
|
---
|
||||||
|
|
||||||
```bash
|
## Teste em rede
|
||||||
cd pitiupi
|
|
||||||
java -jar dist/pitiupi.jar
|
|
||||||
```
|
|
||||||
|
|
||||||
Quickstart: [docs/documentation/00_quickstart.md](docs/documentation/00_quickstart.md).
|
Duas instâncias, portas distintas, mesma LAN. Ver [docs/documentation/15_testes_e_gate.md](docs/documentation/15_testes_e_gate.md) e [appendix_portas_e_multicast.md](docs/documentation/appendix_portas_e_multicast.md).
|
||||||
Trabalho prático (plugin próprio): [docs/documentation/10_tutorial_plugin.md](docs/documentation/10_tutorial_plugin.md).
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Origem
|
||||||
|
|
||||||
|
Projeto base UFSJ (Redes). GitHub: [GabrielFSSantos/pitiupi](https://github.com/GabrielFSSantos/pitiupi).
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
```
|
```
|
||||||
pitiupi/ # clone (este repositório)
|
pitiupi/ # clone (este repositório)
|
||||||
|
├── plugins.registry.json # catálogo de módulos (build/link via scripts/pitiupi.sh)
|
||||||
|
├── scripts/pitiupi.sh
|
||||||
├── pitiupi/ # núcleo P2P (executável)
|
├── pitiupi/ # núcleo P2P (executável)
|
||||||
├── pitiupi.chat/ # plugin referência — chat
|
├── pitiupi.chat/ # plugin referência — chat
|
||||||
├── pitiupi.screenCast/ # plugin referência — captura de tela
|
├── pitiupi.screenCast/ # plugin referência — captura de tela
|
||||||
@@ -27,7 +29,7 @@ Todos dependem do JAR do núcleo no classpath de compilação.
|
|||||||
|
|
||||||
## O que o aluno cria
|
## O que o aluno cria
|
||||||
|
|
||||||
Novo diretório irmão, por exemplo `pitiupi.xadrez/`, copiando a estrutura de `pitiupi.chat` (Ant + `META-INF/services`).
|
Novo diretório irmão, por exemplo `pitiupi.xadrez/`, copiando a estrutura de `pitiupi.chat` (Ant + `META-INF/services`). Registre o módulo em `plugins.registry.json` e use `MenuCategory` adequado no código.
|
||||||
|
|
||||||
Não é obrigatório commitar o plugin do aluno neste repositório base; o professor pode definir fork ou entrega em zip.
|
Não é obrigatório commitar o plugin do aluno neste repositório base; o professor pode definir fork ou entrega em zip.
|
||||||
|
|
||||||
|
|||||||
@@ -49,16 +49,50 @@ Arquivo `src/META-INF/services/pitiupi.models.Plugin`:
|
|||||||
pacote.MeuPlugin
|
pacote.MeuPlugin
|
||||||
```
|
```
|
||||||
|
|
||||||
## 5. Build e instalação
|
## 5. Categoria no menu
|
||||||
|
|
||||||
|
Escolha onde o plugin aparece na barra **Plugin**:
|
||||||
|
|
||||||
|
| `MenuCategory` | Uso |
|
||||||
|
| --- | --- |
|
||||||
|
| `Social` | Chat, presença |
|
||||||
|
| `Jogos` | Jogos entre peers |
|
||||||
|
| `Streaming` | Screen cast, mídia |
|
||||||
|
|
||||||
|
Exemplo:
|
||||||
|
|
||||||
|
```java
|
||||||
|
guiManager.createMenu(MenuCategory.Jogos, new MeuMenu(...));
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. Registrar no catálogo
|
||||||
|
|
||||||
|
Adicione uma entrada em [`plugins.registry.json`](../../plugins.registry.json) na raiz do repo:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "xadrez",
|
||||||
|
"dir": "pitiupi.xadrez",
|
||||||
|
"build": "ant",
|
||||||
|
"jar": "dist/pitiupi.xadrez.jar",
|
||||||
|
"menuCategory": "Jogos"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
O `id` é o que você passa para `./scripts/pitiupi.sh run --plugins xadrez`.
|
||||||
|
|
||||||
|
## 7. Build e instalação
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd pitiupi.meuPlugin && ant jar
|
./scripts/pitiupi.sh build --plugins xadrez
|
||||||
ln -sf ../../pitiupi.meuPlugin/dist/*.jar ../pitiupi/plugins/
|
# ou, manualmente:
|
||||||
|
cd pitiupi.xadrez && ant jar
|
||||||
|
ln -sf ../../pitiupi.xadrez/dist/pitiupi.xadrez.jar ../pitiupi/plugins/xadrez.jar
|
||||||
```
|
```
|
||||||
|
|
||||||
Reinicie o Pitiupi após trocar JARs.
|
Reinicie o Pitiupi após trocar JARs.
|
||||||
|
|
||||||
## 6. Teste
|
## 8. Teste
|
||||||
|
|
||||||
Duas instâncias, mesma rede, portas distintas se no mesmo host. Ver [00_quickstart.md](00_quickstart.md).
|
Duas instâncias, mesma rede, portas distintas se no mesmo host. Ver [00_quickstart.md](00_quickstart.md).
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ Três exemplos no repositório para comparar estilos de integração. Todos deve
|
|||||||
| | pitiupi.chat | pitiupi.screenCast | pitiupi.mpChat |
|
| | pitiupi.chat | pitiupi.screenCast | pitiupi.mpChat |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| Build | Ant | Ant | Make |
|
| Build | Ant | Ant | Make |
|
||||||
|
| id (`plugins.registry.json`) | `chat` | `screencast` | `mpchat` |
|
||||||
| Classe | `ChatPlugin` | `ScreenCastPlugin` | `MultiProtocolChat` |
|
| Classe | `ChatPlugin` | `ScreenCastPlugin` | `MultiProtocolChat` |
|
||||||
| Categoria menu | `Social` | (menu custom via `GuiManager`) | `Social` (multicast + unicast) |
|
| Categoria menu | `Social` | `Streaming` | `Social` (multicast + unicast) |
|
||||||
| Mensagem | `ChatMessage` | `ScreenCastMessage` | `MpChatMessage` |
|
| Mensagem | `ChatMessage` | `ScreenCastMessage` | `MpChatMessage` |
|
||||||
| Transporte principal | UDP (via `ConnectionManager`) | UDP / payloads maiores | UDP público + **TCP privado** |
|
| Transporte principal | UDP (via `ConnectionManager`) | UDP / payloads maiores | UDP público + **TCP privado** |
|
||||||
| TCP avançado | Não | Depende da versão do módulo | `receivePrivateConnection`, `receiveBytes` |
|
| TCP avançado | Não | Depende da versão do módulo | `receivePrivateConnection`, `receiveBytes` |
|
||||||
|
|||||||
@@ -9,7 +9,13 @@ Não há suíte JUnit integrada ao repositório. A validação principal é:
|
|||||||
|
|
||||||
## Gate de build (recomendado)
|
## Gate de build (recomendado)
|
||||||
|
|
||||||
Sequência:
|
Na raiz do clone (todos os módulos do catálogo):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/pitiupi.sh build --all
|
||||||
|
```
|
||||||
|
|
||||||
|
Equivalente manual:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd pitiupi && ant jar
|
cd pitiupi && ant jar
|
||||||
@@ -18,7 +24,7 @@ cd ../pitiupi.screenCast && ant jar
|
|||||||
cd ../pitiupi.mpChat && make
|
cd ../pitiupi.mpChat && make
|
||||||
```
|
```
|
||||||
|
|
||||||
Falha se `java`, **`javac`**, Ant ou Make estiverem ausentes (instale `openjdk-*-jdk`, não só JRE).
|
Falha se `java`, **`javac`**, Ant, Make ou `python3` estiverem ausentes (instale `openjdk-*-jdk`, não só JRE).
|
||||||
|
|
||||||
## Checklist manual (rede)
|
## Checklist manual (rede)
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public class ScreenCastPlugin extends Plugin {
|
|||||||
@Override
|
@Override
|
||||||
public void createPlugin(ConnectionManager connectionManager, GuiManager guiManager) {
|
public void createPlugin(ConnectionManager connectionManager, GuiManager guiManager) {
|
||||||
this.screenCastWindow = new ScreenCastWindow(connectionManager, guiManager);
|
this.screenCastWindow = new ScreenCastWindow(connectionManager, guiManager);
|
||||||
guiManager.createMenu(MenuCategory.Social, new ScreenCastMenu(screenCastWindow));
|
guiManager.createMenu(MenuCategory.Streaming, new ScreenCastMenu(screenCastWindow));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,18 +1,33 @@
|
|||||||
# Plugins instalados
|
# Plugins instalados
|
||||||
|
|
||||||
O núcleo carrega arquivos `.jar` desta pasta ao iniciar (relativo ao diretório de trabalho — execute `java -jar dist/pitiupi.jar` a partir de `pitiupi/`).
|
O núcleo carrega **todos os arquivos `.jar`** desta pasta ao iniciar. Execute sempre a partir de `pitiupi/`:
|
||||||
|
|
||||||
## Desenvolvimento
|
```bash
|
||||||
|
java -jar dist/pitiupi.jar
|
||||||
|
```
|
||||||
|
|
||||||
Após compilar os módulos de referência, use symlinks (Linux):
|
## Pasta única (sem subpastas por categoria)
|
||||||
|
|
||||||
|
Os JARs ficam lado a lado em `plugins/`. A divisão **chat / jogo / streaming** aparece no menu **Plugin → Social | Jogos | Streaming**, definida por cada plugin com `MenuCategory` no código.
|
||||||
|
|
||||||
|
## Instalação automática (recomendado)
|
||||||
|
|
||||||
|
Na raiz do repositório, o catálogo [`plugins.registry.json`](../../plugins.registry.json) lista módulos buildáveis:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/pitiupi.sh link --all
|
||||||
|
./scripts/pitiupi.sh build --plugins chat
|
||||||
|
```
|
||||||
|
|
||||||
|
Symlinks gerados: `plugins/{id}.jar` → `../../{módulo}/{jar}`.
|
||||||
|
|
||||||
|
## Manual
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd pitiupi/plugins
|
cd pitiupi/plugins
|
||||||
ln -sf ../../pitiupi.chat/dist/pitiupi.chat.jar pitiupi.chat.jar
|
ln -sf ../../pitiupi.chat/dist/pitiupi.chat.jar chat.jar
|
||||||
ln -sf ../../pitiupi.screenCast/dist/pitiupi.screenCast.jar pitiupi.screenCast.jar
|
|
||||||
ln -sf ../../pitiupi.mpChat/dist/mpChat.jar mpChat.jar
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Ordem de build: núcleo (`pitiupi`) primeiro, depois cada plugin. Ver [docs/documentation/00_quickstart.md](../../docs/documentation/00_quickstart.md).
|
Não commite `.jar` — apenas este README e symlinks locais.
|
||||||
|
|
||||||
Os JARs gerados não devem ser commitados — apenas este README e symlinks locais.
|
Novo módulo: registrar no catálogo e ver [docs/documentation/10_tutorial_plugin.md](../../docs/documentation/10_tutorial_plugin.md).
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"id": "chat",
|
||||||
|
"dir": "pitiupi.chat",
|
||||||
|
"build": "ant",
|
||||||
|
"jar": "dist/pitiupi.chat.jar",
|
||||||
|
"menuCategory": "Social"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "screencast",
|
||||||
|
"dir": "pitiupi.screenCast",
|
||||||
|
"build": "ant",
|
||||||
|
"jar": "dist/pitiupi.screenCast.jar",
|
||||||
|
"menuCategory": "Streaming"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mpchat",
|
||||||
|
"dir": "pitiupi.mpChat",
|
||||||
|
"build": "make",
|
||||||
|
"jar": "dist/mpChat.jar",
|
||||||
|
"menuCategory": "Social"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Executable
+302
@@ -0,0 +1,302 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Build, instala plugins em pitiupi/plugins/ e executa o núcleo (catálogo: plugins.registry.json).
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
CORE="${REPO_ROOT}/pitiupi"
|
||||||
|
PLUGINS_DIR="${CORE}/plugins"
|
||||||
|
REGISTRY="${REPO_ROOT}/plugins.registry.json"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Uso: scripts/pitiupi.sh <comando> [opções]
|
||||||
|
|
||||||
|
Comandos:
|
||||||
|
run Compila, atualiza plugins/ e abre a aplicação (padrão: --all)
|
||||||
|
build Compila e atualiza plugins/
|
||||||
|
link Só symlinks em pitiupi/plugins/ (JARs já buildados)
|
||||||
|
list Lista plugins do catálogo (id, categoria, JAR presente)
|
||||||
|
discover Sugere entradas para o catálogo (pastas pitiupi.* com SPI)
|
||||||
|
check Ferramentas no PATH + valida plugins.registry.json
|
||||||
|
|
||||||
|
Opções (exclusivas; padrão em run/build/link: --all):
|
||||||
|
--all Todos os plugins do catálogo
|
||||||
|
--plugins ids IDs separados por vírgula (ex.: chat,screencast)
|
||||||
|
--category Nome Social | Jogos | Streaming
|
||||||
|
|
||||||
|
Exemplos:
|
||||||
|
./scripts/pitiupi.sh list
|
||||||
|
./scripts/pitiupi.sh run --all
|
||||||
|
./scripts/pitiupi.sh run --category Social
|
||||||
|
./scripts/pitiupi.sh run --plugins chat
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
registry_python() {
|
||||||
|
python3 - "$REGISTRY" "$REPO_ROOT" "$@" <<'PY'
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
registry_path = Path(sys.argv[1])
|
||||||
|
repo = Path(sys.argv[2])
|
||||||
|
mode = sys.argv[3]
|
||||||
|
|
||||||
|
data = json.loads(registry_path.read_text(encoding="utf-8"))
|
||||||
|
plugins = data.get("plugins", [])
|
||||||
|
|
||||||
|
def by_id(pid):
|
||||||
|
for p in plugins:
|
||||||
|
if p["id"] == pid:
|
||||||
|
return p
|
||||||
|
return None
|
||||||
|
|
||||||
|
def jar_path(entry):
|
||||||
|
return repo / entry["dir"] / entry["jar"]
|
||||||
|
|
||||||
|
if mode == "validate":
|
||||||
|
if not plugins:
|
||||||
|
print("ERRO: nenhum plugin no catálogo", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
for p in plugins:
|
||||||
|
for key in ("id", "dir", "build", "jar", "menuCategory"):
|
||||||
|
if key not in p:
|
||||||
|
print(f"ERRO: campo ausente {key} em {p}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
if mode == "list":
|
||||||
|
for p in plugins:
|
||||||
|
jp = jar_path(p)
|
||||||
|
built = "sim" if jp.is_file() else "não"
|
||||||
|
print(f"{p['id']}\t{p['menuCategory']}\t{p['dir']}\tjar:{built}")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
if mode == "discover":
|
||||||
|
known_dirs = {p["dir"] for p in plugins}
|
||||||
|
for child in sorted(repo.glob("pitiupi.*")):
|
||||||
|
if not child.is_dir():
|
||||||
|
continue
|
||||||
|
spi = list(child.rglob("META-INF/services/pitiupi.models.Plugin"))
|
||||||
|
if not spi:
|
||||||
|
continue
|
||||||
|
status = "registrado" if child.name in known_dirs else "sugerido"
|
||||||
|
build = "make" if (child / "Makefile").is_file() else "ant"
|
||||||
|
print(f"{status}\t{child.name}\tbuild:{build}")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
if mode == "resolve":
|
||||||
|
filter_mode = sys.argv[4]
|
||||||
|
arg = sys.argv[5] if len(sys.argv) > 5 else ""
|
||||||
|
|
||||||
|
selected = []
|
||||||
|
if filter_mode == "all":
|
||||||
|
selected = plugins
|
||||||
|
elif filter_mode == "category":
|
||||||
|
cat = arg.strip()
|
||||||
|
selected = [p for p in plugins if p["menuCategory"] == cat]
|
||||||
|
if not selected:
|
||||||
|
print(f"ERRO: categoria vazia ou inválida: {cat}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
elif filter_mode == "plugins":
|
||||||
|
ids = [x.strip() for x in arg.lower().split(",") if x.strip()]
|
||||||
|
for i in ids:
|
||||||
|
p = by_id(i)
|
||||||
|
if not p:
|
||||||
|
print(f"ERRO: id desconhecido no catálogo: {i}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
selected.append(p)
|
||||||
|
else:
|
||||||
|
print(f"ERRO: modo resolve {filter_mode}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
for p in selected:
|
||||||
|
print(p["id"])
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
if mode == "field":
|
||||||
|
pid = sys.argv[4]
|
||||||
|
field = sys.argv[5]
|
||||||
|
p = by_id(pid)
|
||||||
|
if not p:
|
||||||
|
sys.exit(1)
|
||||||
|
print(p[field])
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
print(f"ERRO: modo desconhecido {mode}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
PY
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve_filter_mode() {
|
||||||
|
if [[ -n "${FILTER_PLUGINS:-}" ]]; then
|
||||||
|
echo "plugins"
|
||||||
|
elif [[ -n "${FILTER_CATEGORY:-}" ]]; then
|
||||||
|
echo "category"
|
||||||
|
else
|
||||||
|
echo "all"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve_filter_arg() {
|
||||||
|
local mode="$1"
|
||||||
|
case "$mode" in
|
||||||
|
plugins) echo "${FILTER_PLUGINS}" ;;
|
||||||
|
category) echo "${FILTER_CATEGORY}" ;;
|
||||||
|
all) echo "" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
selected_ids() {
|
||||||
|
local mode arg
|
||||||
|
mode="$(resolve_filter_mode)"
|
||||||
|
arg="$(resolve_filter_arg "$mode")"
|
||||||
|
registry_python resolve "$mode" "$arg"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_core() {
|
||||||
|
(cd "${REPO_ROOT}/pitiupi" && ant jar)
|
||||||
|
}
|
||||||
|
|
||||||
|
build_one_plugin() {
|
||||||
|
local id="$1"
|
||||||
|
local dir build_cmd
|
||||||
|
dir="$(registry_python field "$id" dir)"
|
||||||
|
build_cmd="$(registry_python field "$id" build)"
|
||||||
|
case "$build_cmd" in
|
||||||
|
ant) (cd "${REPO_ROOT}/${dir}" && ant jar) ;;
|
||||||
|
make) (cd "${REPO_ROOT}/${dir}" && make) ;;
|
||||||
|
*)
|
||||||
|
printf 'ERRO: build desconhecido para %s: %s\n' "$id" "$build_cmd" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
build_plugins_from_selection() {
|
||||||
|
local id
|
||||||
|
while IFS= read -r id; do
|
||||||
|
[[ -z "$id" ]] && continue
|
||||||
|
build_one_plugin "$id"
|
||||||
|
done < <(selected_ids)
|
||||||
|
}
|
||||||
|
|
||||||
|
link_plugins_from_selection() {
|
||||||
|
local id dir jar_rel link_name
|
||||||
|
mkdir -p "${PLUGINS_DIR}"
|
||||||
|
rm -f "${PLUGINS_DIR}/"*.jar
|
||||||
|
|
||||||
|
while IFS= read -r id; do
|
||||||
|
[[ -z "$id" ]] && continue
|
||||||
|
dir="$(registry_python field "$id" dir)"
|
||||||
|
jar_rel="$(registry_python field "$id" jar)"
|
||||||
|
link_name="${id}.jar"
|
||||||
|
ln -sf "../../${dir}/${jar_rel}" "${PLUGINS_DIR}/${link_name}"
|
||||||
|
done < <(selected_ids)
|
||||||
|
|
||||||
|
local count
|
||||||
|
count="$(find "${PLUGINS_DIR}" -maxdepth 1 -name '*.jar' 2>/dev/null | wc -l)"
|
||||||
|
if [[ "$count" -eq 0 ]]; then
|
||||||
|
printf 'AVISO: nenhum plugin em %s.\n' "${PLUGINS_DIR}" >&2
|
||||||
|
else
|
||||||
|
printf 'Plugins ativos em %s:\n' "${PLUGINS_DIR}"
|
||||||
|
ls -1 "${PLUGINS_DIR}"/*.jar
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_tools() {
|
||||||
|
local ok=0
|
||||||
|
for cmd in java javac ant make python3; do
|
||||||
|
if command -v "${cmd}" >/dev/null 2>&1; then
|
||||||
|
printf 'OK %s\n' "${cmd}"
|
||||||
|
else
|
||||||
|
printf 'ERRO: %s não está no PATH\n' "${cmd}" >&2
|
||||||
|
ok=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [[ ! -f "${REGISTRY}" ]]; then
|
||||||
|
printf 'ERRO: catálogo ausente: %s\n' "${REGISTRY}" >&2
|
||||||
|
ok=1
|
||||||
|
else
|
||||||
|
registry_python validate
|
||||||
|
printf 'OK plugins.registry.json\n'
|
||||||
|
fi
|
||||||
|
return "${ok}"
|
||||||
|
}
|
||||||
|
|
||||||
|
CMD="run"
|
||||||
|
FILTER_PLUGINS=""
|
||||||
|
FILTER_CATEGORY=""
|
||||||
|
USE_ALL=1
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
run | build | link | check | list | discover)
|
||||||
|
CMD="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--all)
|
||||||
|
USE_ALL=1
|
||||||
|
FILTER_PLUGINS=""
|
||||||
|
FILTER_CATEGORY=""
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--plugins)
|
||||||
|
USE_ALL=0
|
||||||
|
FILTER_PLUGINS="${2:-}"
|
||||||
|
FILTER_CATEGORY=""
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--category)
|
||||||
|
USE_ALL=0
|
||||||
|
FILTER_CATEGORY="${2:-}"
|
||||||
|
FILTER_PLUGINS=""
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h | --help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
printf 'Argumento desconhecido: %s\n' "$1" >&2
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "$USE_ALL" -eq 1 && -z "$FILTER_PLUGINS" && -z "$FILTER_CATEGORY" ]]; then
|
||||||
|
: # default --all
|
||||||
|
elif [[ -n "$FILTER_PLUGINS" && -n "$FILTER_CATEGORY" ]]; then
|
||||||
|
printf 'ERRO: use apenas um de --plugins, --category ou --all\n' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${CMD}" in
|
||||||
|
check)
|
||||||
|
check_tools
|
||||||
|
;;
|
||||||
|
list)
|
||||||
|
registry_python list
|
||||||
|
;;
|
||||||
|
discover)
|
||||||
|
registry_python discover
|
||||||
|
;;
|
||||||
|
link)
|
||||||
|
link_plugins_from_selection
|
||||||
|
;;
|
||||||
|
build)
|
||||||
|
check_tools || exit 1
|
||||||
|
build_core
|
||||||
|
build_plugins_from_selection
|
||||||
|
link_plugins_from_selection
|
||||||
|
;;
|
||||||
|
run)
|
||||||
|
check_tools || exit 1
|
||||||
|
build_core
|
||||||
|
build_plugins_from_selection
|
||||||
|
link_plugins_from_selection
|
||||||
|
cd "${CORE}"
|
||||||
|
exec java -jar dist/pitiupi.jar
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Reference in new issue
Block a user