UNIVERSIDADE FEDERAL DE SANTA CATARINA … · FIGURA 24 – CONFIGURAÇÃO DE AUTENTICAÇÃO ......
Transcript of UNIVERSIDADE FEDERAL DE SANTA CATARINA … · FIGURA 24 – CONFIGURAÇÃO DE AUTENTICAÇÃO ......
1
UNIVERSIDADE FEDERAL DE SANTA CATARINA DEPARTAMENTO DE INFORMÁTICA E ESTATÍSTICA
CURSO DE CIÊNCIAS DA COMPUTAÇÃO
ROQUE OLIVEIRA BEZERRA
SISTEMA DE LISTA DE DISCUSSÃO (FÓRUM) PARA OS CURSOS DE GRADUAÇÃO DA UFSC
FLORIANÓPOLIS, 2007
2
UNIVERSIDADE FEDERAL DE SANTA CATARINA DEPARTAMENTO DE INFORMÁTICA E ESTATÍSTICA
CURSO DE CIÊNCIAS DA COMPUTAÇÃO
ROQUE OLIVEIRA BEZERRA
SISTEMA DE LISTA DE DISCUSSÃO (FÓRUM) PARA OS CURSOS DE GRADUAÇÃO DA UFSC
Trabalho de conclusão de curso apresentado como parte dos requisitos para obtenção do
grau de Bacharel em Ciências da Computação.
Orientador: Prof. Renato Cislaghi
Membros da Banca: José Marcos da Silva
Alexandre Gava Menezes
FLORIANÓPOLIS, 2007
3
Roque Oliveira Bezerra
SISTEMA DE LISTA DE DISCUSSÃO (FÓRUM) PARA OS CURSOS DE GRADUAÇÃO DA UFSC
Trabalho de conclusão de curso apresentado como parte dos requisitos para obtenção do grau de Bacharel em Ciências da Computação.
Orientador: _______________________________________ Prof. Renato Cislaghi
Banca examinadora
_______________________________________ José Marcos da Silva
_______________________________________ Alexandre Gava Menezes
4
"Mais vale lançar-se à luta, alcançar triunfo e glória, mesmo expondo-
se ao insucesso, do que formar fila com pobres de espírito, que não
amam muito nem sofrem muito, mas vivem nessa penumbra cinzenta
sem conhecer vitória nem derrota".
(Franklin D. Roosevelt)
5
À minha família
6
Agradecimentos
Agradeço a minha família por ter me dado todo o apoio e as condições
necessárias ao meu crescimento pessoal e profissional.
A minha mãe Dilma por ter desde pequeno me tratado com muito amor e
carinho e me dado uma boa educação, com valores indispensáveis como o caráter
e os ensinamentos de vida.
Aos meus verdadeiros amigos, que torcem pelo meu sucesso e me dão a
energia necessária para alcançá-lo.
Aos meus membros de banca e envolvidos no trabalho, em especial ao José
Marcos da Silva, meu supervisor de estágio. Agradeço também ao professor
Renato Cislaghi, Alexandre Gava Menezes e ao Núcleo de Processamento de
Dados, que me deu todas as condições necessárias para a concepção desse
trabalho.
7
Resumo
Nesse trabalho propôs-se a implementação de um sistema de fórum para ser
usado pela Graduação da Universidade Federal de Santa Catarina. Para tanto,
procurou-se entender como funciona um sistema de fórum, fazendo uma pesquisa
sobre suas principais características e funcionalidades. Logo em seguida, foi
analisada a estrutura acadêmica da Universidade, bem como o estudo das
soluções de comunicação já utilizadas por ela. Após isso, foi feita a análise dos
requisitos necessários a elaboração de um protótipo, levando-se em conta as
necessidades dos seus usuários e das características técnicas disponíveis. Por
fim, começou-se a implementação do protótipo do sistema, que foi sendo
incrementalmente modificado com base nos testes de aceitação do mesmo e das
funcionalidades sugeridas.
Palavras-Chave: Fórum, Listas de Discussão, Graduação, Universidade, JaveEE,
JBoss, Java Server Faces.
8
Abstract
In this project, it was suggested a forum system implementation, which will be
used in the graduation of Universidade Federal de Santa Catarina. For this, it was
tried to understand how a forum system works, doing a research about its main
features and functionalities. Then, the academic structure of the graduation was
analyzed, in addition to the current communication solutions used by it. After that, it
has been made a requisite analysis, thinking about the user necessities and the
necessary technical characteristics. Finally, a system prototype was implemented,
which was gradually modified based on acceptation tests and the suggested
functionalities.
Keywords: Forum, Discussion Lists, Graduation, University, JaveEE, JBoss, Java
Server Faces.
!
9
Sumário
1 INTRODUÇÃO ......................................................................................................................... 13
2 OBJETIVOS ............................................................................................................................. 14 2.1 OBJETIVO GERAL ............................................................................................................................... 14 2.2 OBJETIVOS ESPECÍFICOS .................................................................................................................. 14 2.3 METODOLOGIA ................................................................................................................................... 15
O SISTEMA DE FÓRUM .................................................................................................................. 16
2.4 O SOFTWARE ..................................................................................................................................... 16 2.5 ADMINISTRAÇÃO E MODERAÇÃO ....................................................................................................... 17 2.6 MEMBROS E USUÁRIOS ..................................................................................................................... 18 2.7 ORGANIZAÇÃO DO FÓRUM ................................................................................................................. 18 2.8 COMPARAÇÃO COM OUTRAS APLICAÇÕES WEB ................................................................................ 18
3 ESTRUTURA ACADÊMICA DA GRADUAÇÃO ..................................................................... 20
3.1 ÓRGÃOS ............................................................................................................................................. 20 3.1.1 Órgãos Deliberativos Centrais ............................................................................................. 20 3.1.2 Órgãos Executivos Centrais ................................................................................................. 21 3.1.3 Órgãos Deliberativos Setoriais ............................................................................................ 23 3.1.4 Órgãos Executivos Setoriais ................................................................................................ 24
3.2 SISTEMA DE INFORMAÇÃO ................................................................................................................. 25 3.2.1 Sistema de Controle Acadêmico da Graduação ............................................................... 25 3.2.2 Modelagem do Banco de Dados ......................................................................................... 26
4 SOLUÇÕES APLICADAS NA UFSC ATUALMENTE ............................................................ 27 4.1 LISTAS DE DISCUSSÃO POR EMAIL DA UNIVERSIDADE ..................................................................... 27 4.2 LISTAS DE DISCUSSÃO POR EMAIL TERCEIRIZADAS ......................................................................... 28 4.3 SISTEMA DE FÓRUM ........................................................................................................................... 28
5 ANÁLISE DOS REQUISITOS DO SISTEMA .......................................................................... 30
6 ANÁLISE DAS SOLUÇÕES EXISTENTES ............................................................................. 31
6.1 SOFTWARE - PHPBB .......................................................................................................................... 31 6.2 SOFTWARE - JFORUM ........................................................................................................................ 33 6.3 ANÁLISE DE VIABILIDADE ................................................................................................................... 34
7 DESENVOLVIMENTO .............................................................................................................. 35
7.1 PRIMEIRO PROTÓTIPO ....................................................................................................................... 35 7.1.1 Definição dos Atores e Casos de Uso ................................................................................ 36 7.1.2 Banco de Dados ..................................................................................................................... 45 7.1.3 Tecnologias e Ferramentas Usadas ................................................................................... 48 7.1.4 Modelagem da Estrutura do Software ................................................................................ 56 7.1.5 Avaliação do Protótipo .......................................................................................................... 59
7.2 CORREÇÃO DE PROBLEMAS E INCLUSÃO DE FUNCIONALIDADES ..................................................... 60 7.2.1 Funcionalidade – Listagem dos Membros ......................................................................... 61 7.2.2 Funcionalidade – Envio de Mensagens .............................................................................. 62 7.2.3 Funcionalidade – Sistema de Busca ................................................................................... 65 7.2.4 Funcionalidade – Perfil do Usuário ..................................................................................... 68 7.2.5 Funcionalidade – Monitoramento de Tópicos e Notificação de Postagens .................. 71 7.2.6 Sistema de Autenticação ...................................................................................................... 74 7.2.7 Otimização de Tempo de Resposta .................................................................................... 78
10
7.3 DEFINIÇÃO DA VERSÃO FINAL E INCLUSÃO DE FUNCIONALIDADES .................................................. 80 7.3.1 Repositório Individual de Arquivos ...................................................................................... 80 7.3.2 Exibição de Fotos dos Usuários .......................................................................................... 82 7.3.3 Inclusão de Arquivos Anexos nos Tópicos e Mensagens ............................................... 87 7.3.4 Alunos Especiais e Monitores .............................................................................................. 90 7.3.5 Busca por Usuários ............................................................................................................... 91
8 CONSIDERAÇÕES FINAIS ..................................................................................................... 94
9 REFERÊNCIAS BIBLIOGRÁFICAS ........................................................................................ 96
10 ANEXOS ................................................................................................................................... 98
10.1 MANUAL DE UTILIZAÇÃO ............................................................................................................... 98 10.2 GUIA DE INSTALAÇÃO .................................................................................................................. 109
INSTALANDO O SISTEMA DE FÓRUM EM UMA MÁQUINA COM O JBOSS 4.0.X .................. 109 10.3 CÓDIGO FONTE ........................................................................................................................... 112 10.4 ARTIGO ........................................................................................................................................ 174 RESUMO .................................................................................................................................................... 174 ABSTRACT .................................................................................................................................................. 174 INTRODUÇÃO ............................................................................................................................................. 175 O SISTEMA DE FÓRUM .............................................................................................................................. 175 SOLUÇÕES APLICADAS NA UFSC ATUALMENTE ....................................................................................... 175 SOLUÇÕES APLICADAS NA UFSC ATUALMENTE ....................................................................................... 176 ANÁLISE DE SOLUÇÕES EXISTENTES ........................................................................................................ 176 DESENVOLVIMENTO ................................................................................................................................... 176
Figuras FIGURA 1 – MODELAGEM CONCEITUAL DO BANCO DE DADOS DO CAGR ..................................................... 26 FIGURA 2 – FÓRUM DA REDE INF .................................................................................................................... 29 FIGURA 3 – LISTAGEM DE SALAS NO PHPBB .................................................................................................. 33 FIGURA 4 – LISTAGEM DE TÓPICOS NO JFORUM ............................................................................................ 34 FIGURA 5 – ESTRUTURA DO BANCO DE DADOS .............................................................................................. 46 FIGURA 6 – ARQUITETURA JSF BASEADA NO MODELO MVC ......................................................................... 54 FIGURA 7 – SUB-SISTEMAS DO PRIMEIRO PROTÓTIPO ................................................................................... 57 FIGURA 8 – SUB-SISTEMA DE PERSISTÊNCIA .................................................................................................. 58 FIGURA 9 – ÍNDICE DO FÓRUM – LISTAGEM DE SALAS .................................................................................... 59 FIGURA 10 – TABELA PARAMETROFORUM_PAF DO BANCO DE DADOS ........................................................... 63 FIGURA 11 – CONFIGURAÇÕES DO RECEBIMENTO DE EMAIL .......................................................................... 64 FIGURA 12 – FORMULÁRIO DE ENVIO DE MENSAGEM A UM MEMBRO DO FÓRUM ........................................... 64 FIGURA 13 – FORMULÁRIO DE ENVIO DE MENSAGEM AOS MEMBROS DE UMA SALA ....................................... 65 FIGURA 14 – FORMULÁRIO DE BUSCA DE TÓPICOS ......................................................................................... 66 FIGURA 15 – RESULTADO DA BUSCA POR TÓPICOS ........................................................................................ 66 FIGURA 16 – FORMULÁRIO DE BUSCA POR SALAS DE DISCUSSÃO ................................................................. 67 FIGURA 17 – RESULTADO DA BUSCA POR SALAS DE DISCUSSÃO ................................................................... 68 FIGURA 18 – PERFIL DO ALUNO ...................................................................................................................... 70 FIGURA 19 – PERFIL DO PROFESSOR ............................................................................................................. 71 FIGURA 20 – LINK “MONITORAR ESSE TÓPICO” .............................................................................................. 72 FIGURA 21 – LISTA DE TÓPICOS MONITORADOS ............................................................................................ 72 FIGURA 22 – OPÇÃO DE NOTIFICAÇÃO DE POSTAGEM ................................................................................... 73 FIGURA 23 – EMAIL DE NOTIFICAÇÃO DE POSTAGEM ..................................................................................... 73 FIGURA 24 – CONFIGURAÇÃO DE AUTENTICAÇÃO – WEB.XML ........................................................................ 76 FIGURA 25 – TELA DE LOGIN ........................................................................................................................... 77 FIGURA 26 – DIAGRAMA DO PROCESSO DE LOGIN ......................................................................................... 78 FIGURA 27 – SISTEMA DE ARQUIVOS NO FÓRUM ........................................................................................... 82
11
FIGURA 28 – CARTEIRA DE IDENTIFICAÇÃO ESTUDANTIL ............................................................................... 83 FIGURA 29 – CÓDIGO PARA INSERÇÃO DE IMAGEM NO BANCO DE DADOS ..................................................... 83 FIGURA 30 – CADASTRO DE FOTOS – MUDANDO UMA FOTO .......................................................................... 84 FIGURA 31 – CADASTRO DE FOTOS – MUDANDO VÁRIAS FOTOS ................................................................... 84 FIGURA 32 – EXIBIÇÃO DE FOTOS NA LISTAGEM DE MEMBROS ..................................................................... 85 FIGURA 33 – EXIBIÇÃO DE FOTO NO PERFIL ................................................................................................... 86 FIGURA 34 – EXIBIÇÃO DE FOTO NO PERFIL ................................................................................................... 86 FIGURA 35 – INCLUSÃO DE ANEXOS NO FORMULÁRIO DE TÓPICO ................................................................. 88 FIGURA 36 – INCLUSÃO DE ANEXOS NO FORMULÁRIO DE TÓPICO ................................................................. 89 FIGURA 37 – LISTAGEM DE MEMBROS INCLUINDO MONITORES E ALUNOS ESPECIAIS ................................... 91 FIGURA 38 – RESULTADO DE BUSCA POR ALUNOS ........................................................................................ 92 FIGURA 39 – RESULTADO DE BUSCA POR PROFESSORES ............................................................................. 92 FIGURA 40 – RESULTADO DE BUSCA POR MONITORES .................................................................................. 93 FIGURA 41 – FORMULÁRIO DE BUSCA POR USUÁRIOS ................................................................................... 93 Tabelas TABELA 1 – CASO DE USO – AUTENTICAR-SE NO SISTEMA ........................................................................... 37 TABELA 2 – CASO DE USO – LISTAR AS SALAS DE DISCUSSÃO (ALUNO) ...................................................... 37 TABELA 3 – CASO DE USO – LISTAR AS SALAS DE DISCUSSÃO (PROFESSOR) ............................................. 38 TABELA 4 – CASO DE USO – LISTAR AS SALAS DE DISCUSSÃO (DEPARTAMENTO)....................................... 39 TABELA 5 – CASO DE USO – LISTAR AS SALAS DE DISCUSSÃO (CURSO)...................................................... 40 TABELA 6 – CASO DE USO – LISTAR AS SALAS DE DISCUSSÃO (ADMINISTRAÇÃO) ....................................... 41 TABELA 7 – CASO DE USO – LISTAR OS TÓPICOS DA SALA DE DISCUSSÃO .................................................. 42 TABELA 8 – CASO DE USO – LISTAR AS MENSAGENS DE UM TÓPICO ............................................................ 42 TABELA 9 – CASO DE USO – POSTAR UM NOVO TÓPICO ............................................................................... 43 TABELA 10 – CASO DE USO – POSTAR UMA NOVA MENSAGEM EM UM TÓPICO ............................................ 44
12
Lista de Abreviações AOP Aspect Oriented Programming
API Application Programming Interface
ASP Active Server Pages
BBS Bulletin Board System
BSD Berkeley Software Distribution
CAGR Controle Acadêmico da Graduação
CPF Cadastro de Pessoa Física
CVS Control Version System
EJB Enterprise Java Bean
GNU GNU Not Unix
IDE Integrated Development Enviromment
INE Departamento de Informática e Estatística
JAAS Java Authentication and Authorization Services
JavaEE Java Enterprise Edition
JMX Java Management Extensions
JSP Java Server Page
MVC Model View Controller
NPD Núcleo de Processamento de Dados
PHP Hipertext Preprocessor
PREG Pró Reitoria de Ensino de Graduação
RG Registro Geral
RSS Really Simple Syndication
UFSC Universidade Federal de Santa Catarina
WYSIWYG What You See Is What You Get
13
1 Introdução
A Universidade Federal de Santa Catarina, atualmente com mais de
quarenta cursos de Graduação e vinte e seis mil alunos, não possui um sistema
completo que torne possível a integração da informação entre seus alunos,
professores e coordenadorias. Ocorre uma grande disparidade entre os diversos
Cursos, Departamentos e Centros. Enquanto alguns deles possuem sistemas de
discussão e listas de email, outros não os possuem, dificultando a comunicação e
o controle.
A difusão da informação não encontra um meio fácil para se propagar, pois
não existe uma ferramenta que centralize o universo dos alunos e professores do
meio acadêmico. Os Centros de Ensino encontram-se geralmente isolados, isto é,
questões que muitas vezes são relevantes a todos acabam não sendo discutidas
plenamente ou não atingem o alcance desejado entre o público universitário.
A principal maneira, até então, de se atingir o grande público, é através das
listas de discussão por email, que apesar de cumprirem em parte o seu papel de
propagar a informação, são de uso restrito e reguladas por moderadores.
A Universidade, através de seu Sistema de Controle Acadêmico (CAGR),
possui uma base de dados extremamente rica, contendo todos os dados
referentes à Graduação. Por que não aproveitá-la na concepção de uma
ferramenta que ajude a integrar as pessoas na Universidade?
A idéia será criar um sistema de Listas de Discussão, que seja integrado ao
CAGR e contemple todos os cursos de graduação da UFSC. Através dele o
usuário pode interagir com os seus colegas de curso ou mesmo de outros cursos.
Neste projeto, conta-se com o apoio do Núcleo de Processamento de Dados
(NPD), órgão responsável pela implementação de soluções de informática na
UFSC e interessado nessa iniciativa.
14
2 Objetivos
2.1 Objetivo Geral
Desenvolver uma aplicação WEB que facilite a integração dos participantes
da Graduação da UFSC e a difusão das informações referentes a esse universo.
2.2 Objetivos Específicos
• Verificar as soluções já existentes no mercado, e analisar a sua
viabilidade de aplicação;
• Compreender como é organizada a Graduação na Universidade, tanto
em termos conceituais como em aspectos referentes à sua gestão em
sistemas de informação;
• Verificar as possíveis soluções individuais usadas na Graduação;
• Estudo de soluções tecnológicas viáveis para a concepção e
elaboração do sistema;
• Estudo de aspectos referentes à usabilidade do sistema e a análise e
projeto do mesmo;
• Verificar a aceitação dos protótipos desenvolvidos e melhorá-los a
medida do necessário.
15
2.3 Metodologia
Pretende-se primeiramente efetuar uma grande pesquisa dentro do universo
de soluções já existentes no mercado. Logo em seguida, analisar a viabilidade dos
seus usos e, caso não possam ser aproveitadas, verificar em que elas teriam a
contribuir no desenvolvimento de um sistema original e específico.
O passo seguinte é avaliar as informações colhidas na pesquisa e decidir se
são suficientes para se preparar um primeiro protótipo do projeto. Caso sejam
suficientes, o mesmo será feito e apresentado aos interessados no projeto. Estes
podem opinar e sugerir melhorias e correções. A idéia é trabalhar num modelo
incremental, onde o software vá se moldando as necessidades dos interessados.
A última etapa é desenvolver a parte escrita do trabalho, isto é, o TCC.
16
O Sistema de Fórum
Um fórum é um recurso oferecido na Internet para lidar com discussão e
conteúdo postado pelos usuários. Os primeiros fóruns datam de 1995, oferecendo
funções similares aos BBS (bulletins boards1) e aos newsgroups2, que eram
numerosos entre 1980 e 1990.
Geralmente se desenvolve uma consciência de comunidade virtual nesses
fóruns, onde alguns assuntos discutidos são tecnologia, política e esportes.
Existem, porém, fóruns dos mais variados assuntos. Também são conhecidos
como listas de discussão.
2.4 O Software
Um fórum é basicamente um site composto por um número de tópicos
escritos por seus usuários. Em cada tópico, existe uma discussão que é composta
por uma série de mensagens. Os tópicos permanecem gravados no site para
leitura futura indefinidamente, ou até que sejam excluídos por um moderador. Os
usuários podem, portanto, consultar e responder os tópicos. A função básica de
um sistema de fórum é essa. Porém, um software de fórum é bem mais complexo.
A maioria desses sistemas permite que mais de um fórum seja criado. Eles,
por sua vez, encapsulam os tópicos criados pela comunidade. Dependendo das
permissões atribuídas pela administração do fórum, os usuários podem criar
novos tópicos ou responder os já existentes.
Os fóruns podem ser divididos basicamente entre aqueles que permitem que
os usuários postem anonimamente e aqueles que exigem que o usuário seja
registrado.
Na primeira opção, o usuário, toda vez que vai postar, coloca um pseudo-
nome, pelo qual é identificado. A desvantagem desse sistema é que não é
1 Bulletins boards – http://en.wikipedia.org/wiki/Bulletin_Boards 2 Newsgroups – http://en.wikipedia.org/wiki/Newsgroups
17
possível moderar adequadamente, pois não se sabe quem é a pessoa, assim não
tendo como bloquear sua participação.
Na segunda opção, o usuário deve fazer um registro no sistema antes de
poder participar das discussões. Nesse caso, os dados ao qual o usuário deverá
preencher podem ser simplesmente um login e senha ou outros dados, como o
email (utilizado para validação) ou mesmo identificações pessoais como CPF, RG,
etc.
Existem diversas soluções de fórum disponíveis na Internet, sendo
desenvolvidas nas mais variadas linguagens de programação, como PHP, ASP,
Java, etc. As configurações do fórum e as mensagens podem ser gravadas tanto
em arquivos de textos como em banco de dados.
Dependendo do software utilizado, vários recursos estão disponíveis. Nos
mais simples, as mensagens são compostas por texto puro. Nos mais complexos,
existem elementos de multimídia e formatação de texto.
2.5 Administração e Moderação
O Administrador do fórum tipicamente tem o poder de editar, mover, excluir
e modificar todos os tópicos do fórum. Possui também o poder de punir os
membros que não estejam tendo um comportamento adequado. Parte do poder do
Administrador pode ser delegada a outros membros do fórum, que são
responsáveis por salas específicas (sub-fóruns) do mesmo. Essa moderação é
necessária para impedir que as regras do fórum sejam desrespeitas. Geralmente o
fórum possui um estatuto, que deve ser lido antes de o usuário começar a utilizá-
lo.
Outro método de moderação é feito através de scripts automatizados, que
automaticamente cortam palavras de baixo calão e textos que não dizem respeito
aos assuntos discutidos. Essa moderação, porém, é bem menos eficiente do que
a feita pelos moderadores.
18
2.6 Membros e Usuários
Os membros de um fórum possuem geralmente certos direitos. Eles podem
criar tópicos, responder, excluir suas mensagens e alterar suas configurações. Na
maioria dos sistemas, eles também podem colocar uma pequena figura que os
identifiquem, também chamada de avatar. Também têm a opção de contatar
individualmente outros membros do fórum, através de mensagens privadas.
2.7 Organização do Fórum
Os fóruns podem variar em complexidade e em organização visual. O mais
comum é composto por diferentes “salas”, que na verdade são sub-fóruns sobre
um determinado assunto. Em cada sub-fórum, pode ocorrer a postagem, onde os
tópicos mais novos ficam na parte de cima da tela, caso esses mesmos tenham
postagens recentes. Geralmente os tópicos que possuem novas mensagens vão
sendo movidos para o topo da lista, do mesmo modo que os tópicos com poucas
mensagens vão sendo movidos para baixo.
2.8 Comparação com outras aplicações web
Uma diferença significante entre os fóruns e listas de discussão por email é
que essas listas automaticamente enviam as novas mensagens para o usuário,
enquanto que os fóruns requerem ao usuário a visita constante ao site para checar
novas mensagens. Devido ao fato de os membros perderem respostas dos tópicos
que estão interessados, vários sistemas modernos de fórum possibilitam que os
membros sejam notificados por email, caso o tópico seja respondido. Outro
recurso interessante é o RSS, que permite aos visitantes terem um sumário das
novas postagens usando um software agregador de RSS.
19
Em comparação com os grupos de discussão (newsgroups), os fóruns não
necessitam de softwares adicionais para serem utilizados. Geralmente, somente
um navegador web é necessário. Os newsgroups, ao contrário, necessitam que o
usuário tenha um programa cliente, para fazer a leitura das notícias.
Fóruns, ao contrário dos wikis, não permitem que o usuário edite outras
mensagens. Alguns membros, porém, possuem o poder de moderar o conteúdo
das mesmas (como por exemplo, se mensagens de spam forem postadas).
Diferentemente dos blogs, os fóruns tipicamente permitem que qualquer um
inicie uma nova discussão (tópico) ou responda a uma já existente. A diversidade
de assuntos discutidos nos fóruns é tipicamente superior, já que eles geralmente
possuem várias salas, sobre assuntos diferentes. Enquanto isso, o blog somente
permite que o usuário responda, sendo que apenas poucas pessoas podem criar
novos tópicos.
Os fóruns também diferem de salas de bate papo e de serviços de
mensagens instantâneas, pois os participantes não precisam estar conectados ao
mesmo tempo. Fóruns lidam com tópicos, isto é, um assunto em comum, portanto
conversas individuais são desencorajadas, isto é, não fazem parte de sua filosofia.
Os usuários de fóruns têm a mentalidade de que tudo o que eles dizem é de
conhecimento público, e ficará armazenado por tempo indefinido. Devido a esse
fato, os fóruns tornam-se os melhores locais para encontrar respostas a perguntas
pouco comuns, por exemplo, como arrumar um determinado problema de
computador.
20
3 Estrutura Acadêmica da Graduação
A estrutura organizacional da UFSC é organizada de forma hierárquica e
composta por órgãos, que podem ser deliberativos ou executivos, centrais ou
setoriais. Segundo o Guia Acadêmico da Graduação3:
3.1 Órgãos
3.1.1 Órgãos Deliberativos Centrais
Conselho Universitário – Cun
O Conselho Universitário é o órgão máximo deliberativo e normativo,
competindo-lhe definir as diretrizes da política universitária, acompanhar
sua execução e avaliar os seus resultados, em conformidade com as finalidades
e os princípios da Instituição.
Câmaras
• Ensino de Graduação - Órgão deliberativo e consultivo em matéria de
Ensino de Graduação;
• Pós-Graduação - Órgão deliberativo e consultivo em matéria de Pós-
Graduação;
• Extensão - Órgão deliberativo e consultivo em matéria de Extensão;
• Pesquisa - Órgão deliberativo e consultivo em matéria de pesquisa.
Conselho de Curadores – CC
O Conselho de Curadores é o órgão deliberativo e consultivo em matéria de
fiscalização econômica e financeira da Universidade.
3 http://notes.ufsc.br/aplic/guiaAcad.nsf
21
3.1.2 Órgãos Executivos Centrais
Reitoria
Órgão executivo e coordenador da administração superior da
Universidade, exercida pelo Reitor. O mandato é de quatro anos, permite uma
recondução. Ela é composta por:
• Gabinete do Reitor – GR;
• Procuradoria Geral – PG;
• Escritório de Assuntos Internacionais – ESAI;
• Agência de Comunicação – AGECON;
• Coordenadoria de Controle Interno – CCI;
• Assessorias Especiais.
Vice-Reitoria
É exercida pelo Vice-Reitor, eleito nos termos da legislação vigente,
tendo atribuições permanentes, previstas no Estatuto e Regimento da
Universidade, além de ser o substituto do Reitor nas suas faltas e impedimentos.
Os órgãos vinculados a ela são:
• Biblioteca Universitária – BU;
• Hospital Universitário – HU.
Pró-Reitorias
São órgãos que auxiliam ao Reitor no exercício de suas tarefas
executivas, sendo-lhes delegadas atribuições concernentes às respectivas
áreas de atuação. A atual estrutura prevê cinco Pró-Reitorias:
22
Pró-Reitoria de Ensino de Graduação
• Coordenadoria de Ensino Básica – CEB;
• Coordenadoria Técnica de Ensino – CTE;
• Departamento de Administração Escolar – DAE;
• Departamento de Ensino de Graduação – DEG;
• Comissão Permanente do Vestibular – COPERVE.
Pró-Reitoria de Pesquisa e Pós-Graduação
• Departamento de Apoio à Pesquisa – DAP;
• Departamento de Apoio à Pós-Graduação – DPG;
• Biotério Central.
Pró-Reitoria de Assuntos da Comunidade Universitária
• Departamento de Assuntos Estudantis – DEAE;
• Departamento de Recursos Humanos – DRH;
• Restaurante Universitário – RU.
Pró-Reitoria de Administração
• Central de Segurança Física e Patrimonial;
• Coordenadoria de Programação e Acompanhamento;
• Prefeitura Universitária – PU;
• Departamento de Administração Geral – DAG;
• Imprensa Universitária – IU;
23
• Escritório Técnico da UFSC – ETUFSC;
• Núcleo de Manutenção.
Pró-Reitoria de Cultura e Extensão
• Departamento de Apoio à Extensão – DAEx;
• Editora Universitária – EU;
• Museu Universitário – UM;
• Departamento Artístico Cultural – DAC.
Secretaria Especial de Planejamento – SEPLAN
• Coordenadoria de Planejamento, Projetos e Acompanhamento –
COPLAN;
• Departamento de Contabilidade e Finanças – DCF.
Unidades de Educação Básica
• Colégio de Aplicação;
• Colégio Agrícola de Camboriú.
3.1.3 Órgãos Deliberativos Setoriais
Conselho Departamental
É o órgão máximo deliberativo e consultivo da administração dos
Centros, composto por representantes do corpo docente, discente e dos
servidores técnicos e administrativos.
24
Departamento
É a menor fração dos Centros. Compete ao Departamento elaborar
planos de trabalho, atribuir encargos de ensino, pesquisa e extensão aos
docentes nele lotados e praticar todos os atos que lhe são inerentes.
3.1.4 Órgãos Executivos Setoriais
Diretoria de Centro
A Diretoria de Centro, órgão executivo, é exercida por um Diretor,
que como órgão executivo, dirige, coordena, fiscaliza e superintende as
atividades da unidade. Cada Centro tem um Vice-Diretor que substitui o
Diretor nas suas faltas e impedimentos e ao qual são delegadas atribuições
administrativas de caráter permanente.
Chefia de Departamento
Cada Departamento tem um chefe e um sub-chefe eleitos pelo
Departamento através do voto direto e secreto, dentre os Professores
integrantes da carreira do magistério e designados pelo Reitor, para um
mandato de 2 (dois) anos, podendo ser reconduzido por mais 1 (um) período.
A UFSC possui, ainda, um Núcleo de Desenvolvimento Infantil
(Educação Infantil de 3 meses a 6 anos), o Colégio de Aplicação (ensino de
1o e 2o Graus) ligado ao Centro de Ciências da Educação, e 2 (dois) Colégios
Agrícolas (ensino de 2o Grau) - Colégio Agrícola de Camboriú e Colégio
Agrícola Senador Gomes de Oliveira em Araquari, atualmente vinculados
à PREG.
25
3.2 Sistema de Informação
3.2.1 Sistema de Controle Acadêmico da Graduação
O Controle Acadêmico do ensino da Graduação é uma tarefa auferida ao
Departamento de Administração Escolar – DAE. Trata-se de uma das tarefas mais
importantes da Universidade, e também uma das mais onerosas, já que cerca de
80% da população estudantil da Instituição é formado por alunos graduandos.
Soma-se a isso, a grande dimensão e a complexidade de uma universidade do
porte da UFSC.
Dentro desse contexto, o Núcleo de Processamento de Dados (NPD),
dedica-se a informatizar as atividades acadêmicas exercidas pelo DAE,
adequando as normas vigentes e concentrado esforços na modernização do
sistema, com o intuito de:
• Agilizar e otimizar as atividades de controle acadêmico;
• Disponibilizar as bases de dados por tempo integral;
• Diminuir os custos envolvidos;
• Fornecer informações para a tomada de decisão a nível gerencial;
• Melhorar a eficiência.
Para se atender esses objetivos, os seguintes níveis de acesso foram
criados:
• Gerência Administrativa;
• Gerência Acadêmica;
• Colegiado do Curso;
• Departamento de Ensino.
A tarefa de manutenção do Controle Acadêmico é uma tarefa árdua e
continua, que se baseia nas constantes transformações que incluem mudanças de
tecnologias, legislações e políticas administrativas.
26
3.2.2 Modelagem do Banco de Dados
A atual modelagem do banco de dados do CAGR começou a ser
desenvolvida em 1998. O servidor de banco de dados escolhido foi o Sybase
Adaptive Server4. A modelagem conceitual do sistema é mostrada na figura
abaixo:
AlunosGraduacaomatriculaAluno
nomeAlunocodigoCurso (FK)numeroCanditado (FK)
CadastroPessoalUFSCmatriculaProfessor
nomeProfessorsiglaDepartamento (FK)
TurmaGraduaçãocodigoDisciplina (FK)codigoTurma
matriculaProfessor (FK)siglaCentro (FK)codigoEspaçoFisico (FK)codigoCurso (FK)
CursoGraduaçãocodigoCurso
nomeCursosiglaCentro (FK)
CentroAcadêmicosiglaCentro
nomeCentro
DepartamentoEnsinosiglaDepartamento
nomeDepartamentosiglaCentro (FK)
DisciplinaGraduaçãocodigoDisciplina
nomeDisciplinasiglaDepartamento (FK)
EspaçoFísicosiglaCentro (FK)codigoEspaçoFisico
descriçãoEspaçoFísico
SistemaVestibularnumeroCanditado
nomeCandidatoopçãoCurso
MatriculasGraduaçãomatriculaAluno (FK)codigoDisciplina (FK)codigoTurma (FK)
CurrículoCursocodigoCurso (FK)codigoDisciplina (FK)
HistóricoEscolarcodigoTurma (FK)matriculaAluno (FK)codigoDisciplina (FK)
notaAluno
Figura 1 – Modelagem Conceitual do Banco de Dados do CAGR
Notemos que as principais entidades estão representadas através das
tabelas e dos seus relacionamentos. As tabelas geralmente são identificadas
através de chaves compostas, isto é, é necessário fornecer dois ou mais valores
de dados para se identificar univocamente um elemento delas.
4 http://www.sybase.com/products/databasemanagement/adaptiveserverenterprise
27
Essa modelagem de dados, apesar de se mostrar bastante satisfatória nesse
ambiente acadêmico, não segue a maneira convencional de se modelar um fórum.
Neste, utiliza-se geralmente chaves primárias simples, do tipo auto-
incrementáveis. Discuti-se nos próximos capítulos as soluções encontradas para
se lidar com esses problemas.
4 Soluções Aplicadas na UFSC atualmente
Alguns cursos da UFSC, ou mesmo seus alunos e professores, possuem
soluções individuais para a comunicação entre si. Esse capítulo dedica-se a
estudar quais são elas e o que elas têm a contribuir na concepção do Sistema de
Fórum. Abaixo, algumas delas são apresentadas:
4.1 Listas de Discussão por Email da Universidade
Listas de Discussão por Email é um sistema automatizado que envia aos
membros da lista a mensagem de email escrita por um dos seus usuários. O
gerenciamento dessas listas é feito geralmente pelo software Mailman, que é o
mais popular desse segmento. Comumente essas listas possuem moderadores,
que podem filtrar o conteúdo das mensagens. Outra característica desse sistema
é que somente os usuários cadastrados na lista podem participar e ler as
discussões, isto é, o acesso ao resto do público é vetada. Esse tipo de lista de
discussão tem o aspecto de ser isolacionista, isto é, fechada aos seus membros.
O exemplo maior de aplicação dessas listas da Universidade é a Lista de
Discussão do Departamento de Informática e Estatística (INE). Este possui um
sistema que cria automaticamente, a cada semestre, listas de discussão para
cada disciplina cursada pelos seus alunos (Ciências da Computação e Sistemas
da Informação).
Os dados dessa lista são extraídos do CAGR através de um script
automatizado, que replica as informações do banco de dados da Graduação para
o banco localizado em sua rede interna. Possui, portanto, a desvantagem de não
28
estar em sincronismo com o Sistema Acadêmico. Isto é, se por ventura ocorrer
ajustes de matrícula, o script tem que ser novamente executado e o banco de
dados inteiramente realimentado.
Se por um lado temos a vantagem de receber por email as mensagens, por
outro não se tem a idéia de um repositório como há em um fórum. Não é possível
pesquisar em mensagens passadas, a não ser que o usuário receptor das
mensagens faça um arquivo em sua máquina por conta própria.
Apesar de possuírem essas desvantagens, esse tipo de lista funciona de
maneira satisfatória nos cursos oferecidos pelo INE, sendo que essas listas já são
usadas há vários anos.
4.2 Listas de Discussão por Email Terceirizadas
Esse tipo de lista é, provavelmente, a mais utilizada na universidade. Trata-
se de um método informal de reunir os emails das pessoas envolvidas.
Geralmente uma pessoa é encarregada de coletar os emails e cadastrá-los num
serviço de listas de discussão. Muitas vezes o próprio professor da disciplina toma
a iniciativa de reunir os emails. O serviço mais famoso provavelmente é o
Grupos5, que oferece, além de lista de discussão, serviços como fórum, blogs,
disco virtual, etc.
O uso dessas listas é a principal alternativa aos cursos que não dispõem de
suporte oficial dado pela Universidade. Sofrem dos mesmos méritos e defeitos das
listas citadas no tópico anterior. Seu caráter informal faz com que sejam
desconhecidas do restante do universo universitário, sendo somente acessíveis
aos seus membros cadastrados.
4.3 Sistema de Fórum
O sistema de fórum também já está sendo utilizado pela Universidade. O
Departamento de Informática de Estatística, que já possuía o sistema de listas, 5 http://www.grupos.com.br
29
inaugurou um dezembro de 2006, um fórum dedicado aos envolvidos nos seus
cursos. Tanto alunos, professores e técnicos administrativos podem ter acesso ao
conteúdo do fórum. A estruturação das salas de discussão, porém, não leva em
consideração as disciplinas que o aluno está cursando. As salas são referentes
aos assuntos do Curso de modo geral.
Não é possível visualizar as discussões sem estar autenticado, isto é, ter
permissão de acesso ao sistema. Somente alunos do INE podem utilizar o fórum,
pois só eles podem se autenticar. O fórum possui um caráter isolacionista, pois
não compartilha seu conteúdo com o restante do público universitário.
O sistema é baseado numa solução feita em PHP, sendo que a base de
dados dos usuários é proveniente da rede INF, que fornece serviços de
hospedagem e email aos seus integrantes.
Figura 2 – Fórum da rede INF
30
5 Análise dos Requisitos do Sistema
Logo após se ter estudado a estrutura acadêmica da Graduação da UFSC e
as soluções já existentes na Universidade, buscou-se orientação com o analista
de sistemas do NPD, José Marcos da Silva.
Discutiu-se aspectos referentes às funcionalidades do fórum, e quais as
classes de usuários que participariam do mesmo. Nessa conversa, chegou-se as
seguintes conclusões:
1. O fórum deveria estar disponível a alunos, professores, responsáveis
pelos Cursos, responsáveis pelos Departamentos e responsáveis pela
Administração da Graduação;
2. A autenticação desses usuários deve ser a mesma usada por eles no
Sistema de Controle Acadêmico da Graduação;
3. Deveriam existir salas destinadas a todos os graduandos, salas
destinadas aos cursos e salas destinadas a seus formandos;
4. As salas dos alunos e professores deveriam ser equivalentes às
disciplinas que eles estão cursando e ministrando respectivamente;
5. Deve existir uma hierarquia de autoridade. Os professores podem
moderar as salas de disciplinas que ministram, os responsáveis pelos
cursos moderam as disciplinas do curso, os responsáveis pelo
departamento moderam as disciplinas que eles oferecem e os
responsáveis pela administração da graduação moderam todas as
salas;
6. Utilizar o banco de dados da graduação e ser integrado com o novo
Sistema de Controle Acadêmico da Graduação;
7. Ter as funcionalidades básicas de um fórum, isto é, poder ler, postar e
responder tópicos;
31
8. Ser desenvolvido na linguagem de programação JAVA e ser acessível
por uma interface WEB.
Após ter-se avaliado os requisitos mínimos, procurou-se pesquisar algumas
soluções existentes, com o intuito de checar se alguma delas poderia ser usada.
Fala-se sobre isso no próximo capítulo.
6 Análise das Soluções Existentes
Nesse capítulo procura-se analisar as principais soluções existentes no
mercado. Como são muitas as disponíveis, tenta-se classificá-las por linguagem
de programação, e escolher o representante mais popular de cada uma delas.
O próximo passo, após analisar essas soluções, é decidir se as mesmas são
viáveis na concepção do projeto.
6.1 Software - phpBB
O phpBB é provavelmente o software mais popular e tradicional de
gerenciamento de fóruns. Ele é um software escrito na linguagem PHP, e
disponibilizado gratuitamente sobre a licença GNU.
O desenvolvimento do phpBB começou com James Atkinson como um
simples sistema de fórum para seu site, em 17 de junho de 2000. Nathan Codding
e John Abela (agora membros do time de desenvolvimento) juntaram-se ao
desenvolvimento logo que o repositório CVS do sistema foi movido para a
SourceForge6. A primeira versão estável do phpBB foi lançada em 9 de dezembro
de 2000. Atualmente encontra-se na versão 2.0.22, lançada em 23 de dezembro
de 2006.
Algumas das funcionalidades do phpBB são:
• Um sistema de estilos baseado em templates, que torna fácil a sua
customização;
6 http://www.sourceforge.net
32
• Suporte a internacionalização, até 2006 eram 64 traduções
disponíveis;
• Compatibilidade com múltiplos sistemas de banco de dados;
• Uma grande comunidade que provê suporte gratuito e customizações;
• Possibilidade de ser escalonizado em diversos servidores – aumento
de redundância e confiabilidade;
Várias soluções de banco de dados são suportadas através de uma camada
de abstração, incluindo MySQL, PostgreSQL, Microsoft SQL Server, Microsoft
Access e Oracle. A camada de abstração lida com as diferenças de sintaxe entre
os bancos.
A camada de abstração também está presente no modo como o phpBB
apresenta os dados ao usuário. O layout é separado do código da aplicação e
definido através de templates. Esses geralmente não possuem textos em
linguagem especifica. Essa tarefa cabe aos pacotes de linguagem, que são
responsáveis pela internacionalização do programa.
33
Figura 3 – Listagem de Salas no phpBB
6.2 Software - JForum
O JForum é uma solução de sistema de fórum muito semelhante ao phpBB,
porém é construído sobre a plataforma JAVA. O sistema possui uma interface
amigável, um sistema eficiente e interface administrativa fácil de usar. Está
disponível gratuitamente sobre a licença BSD Open Source.
34
Ele foi construído sobre o framework MVC, podendo ser instalado em
diversos containers de Aplicação, como o Tomcat e o Resin. A sua implementação
o tornaria fácil para ser expandido e customizado.
As suas funcionalidades são muito semelhantes ao phpBB, podemos dizer, a
grosso modo, que são equivalentes.
Figura 4 – Listagem de Tópicos no JForum
6.3 Análise de Viabilidade
Tanto o phpBB quanto o JForum são soluções populares e confiáveis para o
propósito a que se propõe. Em condições normais, satisfariam tranquilamente as
necessidades do sistema.
No caso da UFSC, porém, tais soluções não poderiam ser facilmente
aplicadas. Tomando em primeiro lugar o phpBB, tal solução foi escrita em PHP.
Há, atualmente, uma tendência por parte dos analistas de sistema da
Universidade em utilizar a linguagem de programação JAVA, principalmente pelo
35
seu poder, escalabilidade e flexibilidade. Não seria interessante, portanto ter uma
aplicação dessa magnitude escrita em PHP. O segundo fator relevante, é que até
o momento o phpBB não suporta o banco de dados Sybase, que é utilizado no
sistema CAGR. Mesmo que fosse possível escrever uma camada de abstração
para esse banco de dados, o esforço necessário não compensaria.
Sobre o JForum, a vantagem primordial dele é ser escrito em Java.
Acontece, porém, o mesmo problema do phpBB, que é a falta de suporte ao banco
de dados Sybase. Como uma das propostas do sistema é ter uma alta integração
com o Sistema Acadêmico da Graduação (CAGR), que roda sobre o Sybase, usar
essa solução demandaria inúmeras adaptações.
Além das duas soluções citadas, utilizar qualquer solução pronta demandaria
um esforço considerável. Como já mostrado nos capítulos “Estrutura Acadêmica
da Graduação” e “Análise dos Requisitos do Sistema”, o banco de dados que
mantém os dados da Graduação não segue um formato que seja compatível ou
facilmente adaptável aos esquemas de banco utilizados nesses sistemas. A
integração com o CAGR ficaria prejudicada, já que possivelmente seria necessário
replicar em um novo banco tanto os dados referentes a salas de discussão como
os referentes aos usuários do sistema. Seria muito difícil definir as regras de
autenticação, postagem e exibição de salas que estavam previstas. Não haveria a
transparência e a consolidação entre o CAGR e o Fórum, que são requisitos do
sistema.
Devido a todos esses fatores, optou-se por desenvolver uma solução
original, que não fosse baseada em nenhuma solução já existente. Aspectos como
usabilidade e interface visual, porém, são inspirados em soluções já existentes.
7 Desenvolvimento
7.1 Primeiro Protótipo
36
Após ter-se efetuado as etapas acima, procurou-se desenvolver um primeiro
protótipo, que englobasse os requisitos mínimos especificados.
Para desenvolvê-lo, buscou-se fazer uma pequena análise do projeto,
especificando quais os atores participariam do sistema, os casos de uso e a
modelagem do banco de dados. Mais detalhes abaixo:
7.1.1 Definição dos Atores e Casos de Uso
Como já definido na análise de requisitos, o sistema deve ser usado por
alunos, professores, responsáveis pelos cursos, departamento e pela
administração da graduação. Esses são os atores do sistema, que serão
chamados de Aluno, Professor, Departamento, Curso e Administração
respectivamente. Os casos de uso especificados nesse primeiro protótipo são:
1. Autenticar-se no sistema;
2. Listar as Salas de Discussão (Aluno);
3. Listar as Salas de Discussão (Professor);
4. Listar as Salas de Discussão (Departamento);
5. Listar as Salas de Discussão (Curso);
6. Listar as Salas de Discussão (Administração);
7. Listar os Tópicos da Sala de Discussão;
8. Listar as Mensagens de um Tópico;
9. Postar um novo tópico;
10. Postar uma nova mensagem em um tópico.
Caso de Uso: Autenticar-se no Sistema
Atores: Aluno, Professor, Departamento, Curso, Administração
Finalidade: Autenticar o usuário para utilização do fórum
37
Visão Geral: O usuário digita sua identificação, sua senha e sua classe de usuário e
pressiona o botão de autenticação
Tabela 1 – Caso de Uso – Autenticar-se no Sistema
Seqüência Típica de Eventos:
1. O usuário ao entrar no fórum é requisitado a digitar sua
identificação, sua senha e classe de usuário;
2. Após preencher essas informações, o usuário pressiona um botão
para autenticar-se;
3. O sistema, com base na classe do usuário, consulta o banco de
dados para conferir se os dados são válidos;
4. Se positivo, as informações sobre esse usuário são consultadas no
banco de dados e armazenadas na sessão da aplicação;
5. O usuário é redirecionado a tela de Listagem de Salas de
Discussão.
Seqüência Alternativa de Eventos:
1. Se a checagem no banco de dados não for positiva, o sistema irá
informar que os dados não são validos, encaminhando o usuário
novamente a tela de autenticação.
Caso de Uso: Listar as Salas de Discussão (Aluno)
Atores: Aluno
Finalidade: Apresentar ao aluno as salas de discussão em que ele pode participar
Visão Geral: O aluno solicita a listagem de suas salas de discussão
Tabela 2 – Caso de Uso – Listar as Salas de Discussão (Aluno)
38
Seqüência Típica de Eventos:
1. O sistema obtém da sessão atual a identificação do aluno (sua
matrícula);
2. O subsistema de banco de dados, sabendo que se trata de um aluno,
executa o comando adequado no banco de dados;
3. O sistema recebe do banco as salas das disciplinas em que o aluno
está matriculado, juntamente com a sala dos Graduandos da UFSC,
Graduandos do seu Curso e dos Formandos (caso o aluno esteja
nessa condição);
4. Os dados são apresentados na tela.
Seqüência Alternativa de Eventos:
1. Se o usuário não estiver autenticado no sistema, ele será
redirecionado a tela de autenticação;
Caso de Uso: Listar as Salas de Discussão (Professor)
Atores: Professor
Finalidade: Apresentar ao professor as salas de discussão em que ele pode
participar
Visão Geral: O professor solicita a listagem de suas salas de discussão
Tabela 3 – Caso de Uso – Listar as Salas de Discussão (Professor)
Seqüência Típica de Eventos:
1. O sistema obtém da sessão atual a identificação do professor (sua
matrícula na instituição);
2. O subsistema de banco de dados, sabendo que se trata de um
professor, executa o comando adequado no banco de dados;
39
3. O sistema recebe do banco as salas das disciplinas em que o
professor leciona, juntamente com a sala dos Graduandos da
UFSC e Graduandos dos cursos em que o professor ministra
aulas;
4. Os dados são apresentados na tela.
Seqüência Alternativa de Eventos:
1. Se o usuário não estiver autenticado no sistema, ele será
redirecionado a tela de autenticação;
Caso de Uso: Listar as Salas de Discussão (Departamento)
Atores: Departamento
Finalidade: Apresentar ao departamento as salas de discussão em que ele pode
participar
Visão Geral: O departamento solicita a listagem de suas salas de discussão
Tabela 4 – Caso de Uso – Listar as Salas de Discussão (Departamento)
Seqüência Típica de Eventos:
1. O sistema obtém da sessão atual a identificação do departamento
(login do CAGR);
2. O subsistema de banco de dados, sabendo que se trata de um
departamento, executa o comando adequado no banco de dados;
3. O sistema recebe do banco as salas das disciplinas que o
departamento oferece e a sala da Graduação;
4. Os dados são apresentados na tela.
40
Seqüência Alternativa de Eventos:
1. Se o usuário não estiver autenticado no sistema, ele será
redirecionado à tela de autenticação;
Caso de Uso: Listar as Salas de Discussão (Curso)
Atores: Curso
Finalidade: Apresentar ao Curso as salas de discussão em que ele pode participar
Visão Geral: O Curso solicita a listagem de suas salas de discussão
Tabela 5 – Caso de Uso – Listar as Salas de Discussão (Curso)
Seqüência Típica de Eventos:
1. O sistema obtém da sessão atual a identificação do curso (login da
coordenação do curso);
2. O subsistema de banco de dados, sabendo que se trata de um
curso, executa o comando adequado no banco de dados;
3. O sistema recebe do banco as salas das disciplinas que o curso
possui, compostas por:
a. Salas dos Graduandos da UFSC;
b. Salas dos cursos sobre responsabilidade da coordenação
do curso;
c. Sala dos formandos dos cursos da coordenação.
4. Os dados são apresentados na tela.
Seqüência Alternativa de Eventos:
1. Se o usuário não estiver autenticado no sistema, ele será
redirecionado a tela de autenticação;
41
Caso de Uso: Listar as Salas de Discussão (Administração)
Atores: Administração
Finalidade: Apresentar à Administração as salas de discussão em que ela pode
participar
Visão Geral: A Administração solicita a listagem de suas salas de discussão
Tabela 6 – Caso de Uso – Listar as Salas de Discussão (Administração)
Seqüência Típica de Eventos:
1. O sistema obtém da sessão atual a identificação da Administração
(sua identificação);
2. O subsistema de banco de dados, sabendo que se trata da
Administração, executa o comando adequado no banco de dados;
3. O sistema recebe do banco todas as salas de discussão
cadastradas no sistema;
4. Os dados são apresentados na tela.
Seqüência Alternativa de Eventos:
1. Se o usuário não estiver autenticado no sistema, ele será
redirecionado a tela de autenticação;
Caso de Uso: Listar os Tópicos da Sala de Discussão
Atores: Aluno, Professor, Departamento, Curso, Administração
Finalidade: Listagem dos tópicos que uma determinada sala possui
Visão Geral: O usuário é encaminhando para uma tela que lista os tópicos de uma
42
sala de discussão
Tabela 7 – Caso de Uso – Listar os Tópicos da Sala de Discussão
Seqüência Típica de Eventos:
1. O usuário, já autenticado no sistema, pode pressionar um link que
o encaminha para listagem de tópicos da sala, ou digitar
diretamente o endereço dela no seu navegador;
2. O sistema vai obter o identificador da sala, que faz parte do link ou
do endereço que foi digitado no navegador;
3. O sistema vai consultar o banco de dados e obter a listagem dos
tópicos;
4. A listagem dos tópicos será apresentada na tela;
Seqüência Alternativa de Eventos:
1. Se o usuário não estiver autenticado no sistema, ele será
redirecionado a tela de autenticação;
2. Se o identificador da sala não existir, ele será notificado de que a
sala não existe.
Caso de Uso: Listar as Mensagens de um Tópico
Atores: Aluno, Professor, Departamento, Curso, Administração
Finalidade: Listagem das mensagens que um determinado tópico possui
Visão Geral: O usuário é encaminhando para uma tela que lista as mensagens de
um tópico
Tabela 8 – Caso de Uso – Listar as Mensagens de um Tópico
43
Seqüência Típica de Eventos:
1. O usuário, já autenticado no sistema, pode pressionar um link que
o encaminha para listagem de mensagens de um tópico, ou digitar
diretamente o endereço dela no seu navegador;
2. O sistema vai obter o identificador do tópico, que faz parte do link
ou do endereço que foi digitado no navegador;
3. O sistema vai consultar o banco de dados e obter a listagem das
mensagens;
4. A listagem das mensagens será apresentada na tela;
Seqüência Alternativa de Eventos:
1. Se o usuário não estiver autenticado no sistema, ele será
redirecionado a tela de autenticação;
2. Se o identificador do tópico não existir, ele será notificado de que o
tópico não existe.
Caso de Uso: Postar um Novo Tópico
Atores: Aluno, Professor, Departamento, Curso, Administração
Finalidade: Adicionar um novo tópico a uma determinada sala de discussão
Visão Geral: O usuário solicita que seja criado um novo tópico, preenchendo um
formulário
Tabela 9 – Caso de Uso – Postar um Novo Tópico
Seqüência Típica de Eventos:
1. O usuário, já autenticado no sistema, pode pressionar um link que
o redireciona a tela de postagem de um novo tópico;
44
2. O usuário preenche o título do novo tópico e o texto da primeira
mensagem dele, em seguida pressiona um botão para submeter a
postagem;
3. O sistema cria o novo tópico, adiciona a primeira mensagem a ele
e redireciona o usuário a tela de listagem de mensagens do tópico;
Seqüência Alternativa de Eventos:
1. Se o usuário não estiver autenticado no sistema, ele será
redirecionado a tela de autenticação;
2. O usuário pode não ter permissão para postar na sala, sendo o
mesmo, portanto, avisado;
3. Pode ser necessário solicitar permissão ao moderador da sala para
que um novo tópico seja criado, nesse caso um formulário de
requisição de criação de tópico será apresentado;
4. Se o usuário não preencher os campos do formulário
corretamente, o mesmo será notificado a preencher os dados
novamente;
Caso de Uso: Postar uma Nova Mensagem em um Tópico
Atores: Aluno, Professor, Departamento, Curso, Administração
Finalidade: Adicionar uma nova mensagem a um determinado tópico
Visão Geral: O usuário solicita que seja criada uma novo mensagem, preenchendo
um formulário
Tabela 10 – Caso de Uso – Postar uma Nova Mensagem em um Tópico
Seqüência Típica de Eventos:
45
1. O usuário, já autenticado no sistema, pode pressionar um link que
o redireciona a tela de postagem de uma nova mensagem;
2. O usuário preenche o título da nova mensagem (opcional) e o seu
texto, em seguida pressiona um botão para submeter a postagem;
3. O sistema cria a nova mensagem e redireciona o usuário para a
tela de listagem de mensagens do tópico;
Seqüência Alternativa de Eventos:
1. Se o usuário não estiver autenticado no sistema, ele será
redirecionado a tela de autenticação;
2. O usuário pode não ter permissão para postar na sala em que o
tópico se encontra, sendo o mesmo, portanto, avisado;
3. Se o usuário não preencher os campos do formulário
corretamente, o mesmo será notificado a preencher os dados
novamente;
7.1.2 Banco de Dados
A etapa de modelagem do banco de dados é de extrema importância na
concepção do primeiro protótipo. Um dos requisitos fundamentais é ter uma
integração concisa com o banco de dados do CAGR. Desse banco deve ser
extraídos os dados referentes às salas de discussão e aos usuários dos fóruns.
O problema maior nesse caso é que não existem tabelas prontas para esses
elementos. Na modelagem do banco, procurou-se abstrair esses dados, criando
tabelas conceituais que representariam tais recursos. A modelagem do banco do
protótipo foi feita usando o software DBDesigner7, e se encontra abaixo:
7 http://fabforce.net
46
Figura 5 – Estrutura do Banco de Dados
Nota-se que a modelagem proposta é bastante simples. De modo geral, a
modelagem de dados de um fórum não é complexa. Com um mínimo de quatro
tabelas, podemos armazenar praticamente todas as informações necessárias.
Nessa etapa do projeto, porém, é necessário definir de que modo os
usuários e as salas seriam representadas no sistema. Efetuou-se uma pequena
pesquisa na base de dados do CAGR, para identificar de onde viriam os dados
que seriam representados. Analisando primeiramente os usuários:
• Alunos – a base de alunos está disponível no CAGR através da tabela
alunosGraduacao_aln;
• Professores – os professores estão cadastrados no banco ADRH
(administração de recursos humanos) na tabela cadastroPessoal_pss.
Existe um identificador nessa tabela que identifica qual é a função da
pessoa envolvida, que nesse caso são professores;
• Curso, Departamento e Administração – Estão cadastrados na tabela
coordenaCurso_coc do CAGR. Existe um identificador que atribuiu à
47
função da pessoa, como coordenadores de curso, secretários de
Departamento ou administradores da Graduação.
Verificando agora como que funciona a dinâmica das salas do usuário:
• Salas de Discussão dos Alunos – são obtidas através do espelho de
matrícula do aluno no semestre atual. Esse espelho se encontra
disponível na tabela espelhoMatricula_esp do CAGR. O aluno pode
também ser um formando, nesse caso o sistema checará na tabela
alunosGraduacao_aln se o semestre provável de formatura é o
mesmo que o semestre atual (obtido na tabela
parametroGraduacao_prm). Nesse caso a sala “Formandos do Curso
X” será adicionada, onde X é o curso em que o aluno está;
• Salas de Discussão dos Professores – as informações de quais
disciplinas, turmas e cursos onde o professor ministra são obtidas
através da tabela alocaçãoProfessor_alp do CAGR. Através dela,
portanto, podemos montar as salas do professor. As salas
“Graduandos do Curso X” também são adicionadas, onde X
representa os cursos em que o professor leciona;
• Salas do Curso, Departamento e Administração – todas as disciplinas
da Graduação, organizadas em turmas, estão disponíveis na tabela
turmaGraduacao_trm. A diferença na apresentação dos resultados
para cada usuário é feita através de diferentes filtros de seleção
desses dados. Podemos filtrar por curso, por departamento ou
simplesmente listar tudo (no caso da Administração).
Após ter-se identificado as origens dos dados no banco de dados, tornou-se
necessário escolher a melhor forma de utilizá-los no sistema. Optou-se,
primeiramente, pelo uso do framework de persistência Hibernate, que permite que
se trate um banco de dados relacional como um sub-sistema orientado a objetos.
Tal solução permitiria organizar melhor o código fonte do projeto, tornando-o mais
claro e intuitivo.
48
Viu-se, porém, que não seria tão fácil. A estrutura do banco de dados do
CAGR é muito complexa, com diversos elementos como chaves compostas que
tornam muito difícil o mapeamento para o Hibernate. Tentou-se, a princípio, utilizar
essa solução, porém a dificuldade em implementá-la seria tão grande que não
valeria a pena. Essa solução somente seria interessante caso fosse possível
construir um banco de dados inteiramente novo, justamente para que se
adaptasse aos requisitos desejáveis ao uso do Hibernate.
Chegou-se a conclusão de que a melhor forma de gerenciar o banco de
dados seria através de stored procedures. Stored procedures são basicamente
comandos que ficam armazenados no banco de dados e que são executados
quando requisitados. A principal vantagem que trazem é que o Administrador de
Banco de Dados tem total autonomia para alterá-las, sem que seja necessário
modificar o código fonte da aplicação. Como o banco de dados do CAGR está
constantemente em mudança, achou-se mais adequado utilizar essa solução.
O subsistema de banco de dados fica, portanto isolado da aplicação. O
sistema não conhece quais são as tabelas que ele possui, apenas conhece os
comandos das stored procedures e quais resultados elas trazem.
7.1.3 Tecnologias e Ferramentas Usadas
Na definição do primeiro protótipo, era necessário definir de antemão quais
tecnologias e ferramentas seriam utilizadas.
Ter o sistema desenvolvido em Java já um requisito definido anteriormente,
portanto não poderia ser alterado. Dentro do universo Java, porém, pode-se
escolher qual ambiente de desenvolvimento e framework de interface gráfica usar.
No ambiente de desenvolvimento, a opção que se tem a princípio era o
Eclipse8 com o plug-in de desenvolvimento Jboss IDE9. Essa solução, porém,
8 http://www.eclipse.org 9 http://www.jboss.org
49
possuía a desvantagem de não contar com um mecanismo WYSIWYG10 para a
exibição das páginas JSP que devem ser construídas, isto é, a confecção das
mesmas deveria ser feita diretamente pelo código fonte. Isso iria diminuir o ritmo
do projeto, já que muito tempo seria perdido nessa etapa. Felizmente, nesse
mesmo período a ferramenta JDeveloper11 da Oracle foi lançada. Começou-se a
fazer testes com ela, e a mesma foi escolhida, com base nas seguintes
características:
• interface agradável e muito semelhante com o Eclipse;
• ênfase no desenvolvimento WEB. Destaque as diversas tecnologias
suportadas nativamente, onde no Eclipse deveriam ser instaladas
manualmente através de plug-ins;
• diversos frameworks de interface gráfica suportados, como o Java
Server Faces12, Struts 13e o JSP puro;
• editor visual WYSIWYG para o HTML e demais tecnologias visuais;
• altíssimo grau de produtividade (enfoque principal da ferramenta)
Analisando essas características, portanto, optou-se pelo JDeveloper. O
único ponto negativo, porém, é o fato de ferramenta utilizar grandes recursos de
máquina, sendo algumas vezes lenta. O aumento de produtividade, porém,
compensa essa deficiência.
Dentro dos frameworks de interface gráfica, existiam basicamente três
opções: o Struts, JSP e Java Server Faces.
O Struts é um framework de desenvolvimento cujo principal enfoque é a
organização lógica e estrutural do sistema. Seu atrativo é que ele claramente
separa as camadas de modelo, controle e visualização. Sua estrutura permite a
construção de templates, que tornam possíveis vários níveis de visualização. Uma
10 WYSIWYG – What You See Is What You Get – O que você vê é o que você tem 11 http://www.oracle.com/technology/software/products/jdev/index.html 12 http://java.sun.com/javaee/javaserverfaces 13 http://struts.apache.org
50
desvantagem, porém, é que sua burocracia não permite construir aplicações de
uma maneira rápida e produtiva.
O JSP (Java Server Pages) é a implementação básica para construção de
páginas WEB. Ela carece de recursos que facilitam o desenvolvimento, sendo
pouco recomendada para aplicações de maior porte. Ela seria, portanto,
recomendada a pequenas aplicações, que não possuem grande complexidade.
O Java Server Faces é um framework que possibilita um desenvolvimento
rápido de interfaces gráficas com um bom nível de organização de código. Sua
utilização se assemelha muito aos ambientes de desenvolvimento de aplicações
desktop, como o Delphi ou Visual Basic, o que faz com que seja a melhor opção
pra quem busca produtividade e facilidade de uso.
Analisando os três frameworks, optou-se pelo uso do Java Server Faces. Os
principais fatores que influenciaram nessa escolha foram a produtividade e a
facilidade de uso. O suporte nativo que o JDeveloper possui a essa tecnologia
também foi considerado.
O sistema foi desenvolvido em cima da plataforma JavaEE, que é uma
especificação para o desenvolvimento de aplicações empresariais de alta
complexidade, que atualmente está se tornando cada vez mais um padrão no
mercado.
Abaixo, faz-se uma pequena abordagem sobre as principais tecnologias
empregadas nesse trabalho.
JavaEE
O JavaEE (Java Enterprise Edition) é uma plataforma de programação para o
desenvolvimento de aplicações em arquitetura multicamadas, baseado em
componentes de software modulares rodando num servidor de aplicação. A
plataforma Java EE é definida por uma especificação. Informalmente pode-se
considerá-la como um padrão, já que os fornecedores de tecnologia devem aceitar
51
certas regras e convenções para poderem declarar seus produtos como sendo
compatíveis com JavaEE.
O JavaEE inclui diversas especificações de API, como o JDBC, RMI, e-mail,
JMS, web services, XML, etc. e define como coordená-las. O JavaEE também
fornece especificações para componentes, entre eles os Enterprise Java Beans
(EJB), servlets, portlets, Java Server Pages (JSP) e várias tecnologias para web
services. Isso permite que sejam criadas aplicações de grande porte que podem
ser portadas entre diferentes plataformas com escalabilidade, permitindo a
integração com tecnologias de legado já existentes. Outro ponto muito positivo é
que o servidor de aplicação pode lidar com aspectos referentes às transações,
segurança, escalabilidade, concorrência e gerenciamento de componentes. Isso
permite que o desenvolvedor se preocupe muito mais com a lógica de negócio do
que com os aspectos de infra-estrutura e integração.
Outro ponto muito positivo do JavaEE, é a possibilidade de podermos
começar a desenvolver tendo um baixo custo. A implementação JavaEE da Sun
Microsystems14 pode ser obtida gratuitamente. Existem excelentes ferramentas de
desenvolvimento gratuitas, que estendem a funcionalidade da plataforma e/ou
agilizam em muito o desenvolvimento.
JBoss
O JBoss é um servidor de aplicações que segue a implementação das
especificações JavaEE da Sun.
Servidores de aplicação Java se tornaram um grande “agregado”. Para
justificar os altos preços cobrados, os vendedores destes sistemas procuram se
diferenciar entregando junto com o servidor de aplicação, um conjunto de
ferramentas e outros softwares tais como: ambientes de desenvolvimento de
aplicações, gerenciadores de conteúdo e portais, etc.
14 http://www.sun.com
52
Por ser gratuito, o caminho seguido pelo JBoss para a diferenciação é bem
diferente: ele se integra muito bem com uma série de ferramentas para a criação
de ambientes de desenvolvimento de software bastante completo e robusto. Por
exemplo: o IDE Eclipse, o gerenciador de versão de software CVS, o construtor de
aplicações Ant, o framework Java Server Faces, etc.
A diferenciação também se dá do ponto de vista de sua arquitetura interna: o
JBoss é baseado em uma arquitetura de microkernel JMX, onde todos os módulos
que compõem o servidor, além das próprias aplicações, são componentes
(MBeans), plugados ou substituídos dinamicamente, em tempo de execução, sem
a necessidade de paradas no servidor. Esta funcionalidade, que é chamada de
“hot deploy”, dá uma grande flexibilidade e robustez ao servidor. Por se modular,
dificilmente o servidor irá ficar indisponível por completo, já que somente os
módulos com problemas serão afetados.
O JBoss 4.0 inclui um framework para AOP (Programação Orientada à
Aspectos) que permite que os desenvolvedores possam facilmente acrescentar
serviços como transações, persistência e replicação de cache à partir de objetos
Java comuns, sem a necessidade de criar EJBs. O framework AOP cuida de todo
o trabalho de transformar o objeto Java em um EJB, e libera o desenvolvedor para
se concentrar na lógica de negócio das aplicações.
Java Server Faces
Java Server Faces (JSF) é uma tecnologia que incorpora características de
um framework MVC para WEB e de um modelo de interfaces gráficas baseado em
eventos. Por basear-se no padrão de projeto MVC, uma de suas melhores
vantagens é a clara separação entre a visualização e regras de negócio (modelo).
A idéia do padrão MVC é dividir uma aplicação em três camadas: modelo,
visualização e controle. O modelo é responsável por representar os objetos de
negócio, manter o estado da aplicação e fornecer ao controlador o acesso aos
dados. A visualização representa a interface com o usuário, sendo responsável
53
por definir a forma como os dados serão apresentados e encaminhar as ações dos
usuários para o controlador. Já a camada de controle é responsável por fazer a
ligação entre o modelo e a visualização, além de interpretar as ações do usuário e
as traduzir para uma operação sobre o modelo, onde são realizadas mudanças e,
então, gerar uma visualização apropriada.
No JSF, o controle é composto por um servlet denominado FacesServlet, por
arquivos de configuração e por um conjunto de manipuladores de ações e
observadores de eventos. O FacesServlet é responsável por receber requisições
da WEB, redirecioná-las para o modelo e então remeter uma resposta. Os
arquivos de configuração são responsáveis por realizar associações e
mapeamentos de ações e pela definição de regras de navegação. Os
manipuladores de eventos são responsáveis por receber os dados vindos da
camada de visualização, acessar o modelo, e então devolver o resultado para o
FacesServlet.
O modelo representa os objetos de negócio e executa uma lógica de negócio
ao receber os dados vindos da camada de visualização. Finalmente, a
visualização é composta por component trees (hierarquia de componentes UI),
tornando possível unir um componente ao outro para formar interfaces mais
complexas. A figura abaixo mostra a arquitetura do Java Server Faces baseada no
modelo MVC.
54
Figura 6 – Arquitetura JSF baseada no modelo MVC
Java Server Faces oferece ganhos no desenvolvimento de aplicações WEB
por diversos motivos:
• Permite que o desenvolvedor crie componentes de interface através de um
conjunto de componentes já existentes;
• Fornece um conjunto de tags JSP para acessar os componentes;
• Reusa componentes da página;
• Associa os eventos do lado cliente com os manipuladores dos eventos do
lado servidor (os componentes de entrada possuem um valor local
representando o estado no lado servidor);
• Fornece separação de funções que envolvem a construção de aplicações
WEB.
55
Stored Procedures
Uma stored procedure é uma subrotina disponível para aplicações
acessarem um banco de dados relacional. Elas são armazenadas no próprio
banco, sendo muitas vezes chamadas de sproc ou SP.
O uso típico de stored procedures inclui a validação de dados (integrada ao
banco de dados) e mecanismos de controle de acesso. Outro uso delas é o de
centralizar e consolidar a lógica que originalmente foi implementada na aplicação.
Processamentos longos e complexos, que podem requerer a execução de vários
comandos SQL são encapsulados em stored procedures. Os aplicativos as
utilizam, portanto, para o acesso aos dados.
Os principais benefícios de se utilizar stored procedures são:
• Pré-compilação de consultas SQL – consultas SQL implementadas
como stored procedures rodam muitas mais rapidamente, por serem
pré-compiladas. O plano de execução da stored procedure é
armazenado juntamente com ela no banco de dados. Isso faz com
que não seja necessária a compilação do código SQL, o que
representa um gargalo muito grande algumas vezes;
• Execução no Servidor de Banco de Dados – stored procedures rodam
diretamente dentro do sistema de banco de dados. Isso significa que
ela tem acesso direto aos dados a serem acessados, não havendo,
portanto o gargalo de acesso a rede, que é particularmente sensível
quando se está lidando com uma série de comandos complexos;
• Simplificação do Gerenciamento de Dados – as stored procedures
permitem que a camada lógica seja anexada ao servidor de banco de
dados, o que simplifica o gerenciamento de dados a reduz a
necessidade de se ficar alterando os programas cliente. Além disso, é
menos provável que haja corrupção de dados, já que as stored
procedures dispõem de mecanismos que ajudam a verificar a
consistência e a integridade dos dados. Alguns críticos afirmam que
56
os banco de dados só devem ser utilizados para armazenamento, e
que a lógica de negócio deve ser implementada através de uma
camada de negócios, por onde o usuário acessará os dados.
Entretanto, o uso de stored procedures não invalida a função da
camada de negócios;
• Segurança – Stored procedures bem escritas permitem especificar
boas diretrizes de segurança ao banco de dados. Por exemplo, os
programas clientes podem ficar restritos ao acesso do banco, a não
ser pelas stored procedures que estarão disponíveis.
7.1.4 Modelagem da Estrutura do Software
Optou-se por seguir o modelo de programação MVC (Model, View, Control),
onde separa-se explicitamente as camadas de modelo, visualização e controle. A
utilização do MVC é um padrão hoje em dia, e torna-se necessária à medida que
os projetos vão ficando mais complexos, demandando a participação de equipes
cada vez maiores trabalhando em partes do sistema.
O sub-sistema de modelo é responsável pela definição dos objetos que
compõem a lógica da aplicação. No caso do fórum, têm-se os objetos que
representam o usuário, a sala de discussão, o tópico e a mensagem.
A visualização representa a interface do usuário com o sistema. Ela
engloba todos os mecanismos necessários para isso. No caso de uma aplicação
WEB, as páginas que o usuário acessa em seu navegador são sua maior
representação.
O controle, por sua vez, é responsável por processar as informações
recebidas para que haja uma resposta ao usuário. Ele manipula as informações do
modelo para que isso possa ocorrer. O sub-sistema de persistência geralmente
faz parte do controle, mas pode ser isolado, caso sua complexidade seja
considerável.
57
Seguindo o padrão MVC, procura-se dividir o fórum em quatro sub-sistemas,
que são os três descritos acima e o de persistência, que foi isolado do controle por
ser demasiadamente complexo.
class Diagrama Classes - Prototipo 1
controle
+ LogicaFacade+ faces
visual
+ HtmlGeneratorUtils+ Páginas JSP
persistencia
+ DatabaseFactory+ DBUtils+ IDatabaseFacade+ sybase
modelo
+ Mensagem+ SalaDiscussao+ Topico+ Usuario
Figura 7 – Sub-sistemas do Primeiro Protótipo
Analisando cada sub-sistema:
• Controle - Esse subsistema controla a lógica da aplicação. Foi
escolhido criar uma classe de fachada, a LogicaFacade, que fica
responsável por administrar toda a lógica da aplicação. O pacote faces
possui as classes responsáveis pelo controle das páginas JSP. Toda
página JSP que utiliza Java Server Faces possui uma classe de
controle, chamada de back bean. Essas classes por sua vez, utilizam
a fachada lógica para efetuarem suas operações;
• Modelo – como já explicado anteriormente, possui as classes
conceituais do domínio de aplicação do sistema;
58
• Persistência – esse talvez seja o sub-sistema mais importante num
sistema de Fórum. Ele é responsável por todas as operações que
ocorrem no banco de dados, sendo, portanto, de crucial importância
para o desempenho e integridade da aplicação. Foi utilizado uma
interface chamada IDatabaseFacade, que possui a assinatura de
todos os métodos utilizados na persistência. Essa interface permite
que a solução de banco de dados (no caso o Sybase) seja isolada do
restante do sistema. A classe DatabaseFactory é a responsável por
delegar as funções as classe do Sybase. Se, por ventura, no futuro
fosse necessário utilizar outro banco de dados, isso poderia ser
facilmente feito implementado a interface IDatabaseFacade e
alterando a classe DatabaseFactory;
class Persistencia 1
persistencia::DatabaseFactory
+ getDatabaseFactory() : IDatabaseFacade
«interface»persistencia::IDatabaseFacade
DatabaseFacadeSybase
Figura 8 – Sub-sistema de Persistência
• Visual – a classe HtmlGeneratorUtils possui alguns códigos html pré-
definidos (links, botões), que são utilizados na construção das
páginas, servindo como suporte. Nota-se que as páginas JSP foram
colocadas dentro desse pacote. Trata-se de um artifício teórico, já que
um pacote em Java não pode conter páginas JSP. Optou-se por essa
apresentação para enfatizar a clara divisão dos subsistemas com suas
atividades específicas.
59
Analisando o conjunto de sub-sistemas expresso no diagrama, nota-se que o
Controle é a única forma do sub-sistema visual se comunicar. Isso é bastante
desejável, já que possibilita um baixo acoplamento e faz com que seja possível
alterar a interface gráfica facilmente, sem grandes traumas.
O controle também interage com a persistência e o modelo. Esse é
justamente o seu papel, coordenar as atividades entre os dois para que o
resultado seja entregue de forma satisfatória ao subsistema visual.
7.1.5 Avaliação do Protótipo
Após a especificação do primeiro protótipo, o mesmo foi implementado. Essa
etapa demandou uma quantia considerada de tempo, já que não se conhecia, a
priori, as tecnologias e ferramentas empregadas. Passado esse tempo, porém, o
primeiro protótipo foi finalizado. Usou-se uma máquina multiprocessada, utilizando
o sistema operacional Linux e o servidor de aplicações JBoss 3.2. O fórum ficou
disponível, portanto, aos alunos, professores, e coordenadores.
Figura 9 – Índice do Fórum – listagem de salas
Com as funcionalidades básicas, descritas na especificação inicial, o fórum
começou a ser testado pelos usuários. Algumas conclusões adquiridas foram:
• O formato de exibição de salas, organizado primordialmente pelas
disciplinas, foi ao encontro da maioria dos usuários. Essa organização
permitiu que as pessoas já familiarizadas com fóruns, e mesmo as que
60
não eram, pudessem desfrutar de uma experiência agradável
navegando no site;
• Somente as funcionalidades básicas foram implantadas, faltaram
outras que são típicas de fóruns, como listagem dos membros das
salas, o envio de mensagens individuais e em grupo e um sistema de
busca;
• Era desejável ter uma funcionalidade de perfil do usuário, para que se
pudessem obter maiores informações sobre eles, como por exemplo,
no caso de alunos, o curso que estão cursando e no de professores, a
qual departamento pertencem. Informações como as salas em que
fazem parte e o endereço da página pessoal também são desejáveis;
• O sistema de autenticação não era integrado com o do CAGR, isso
fazia com que o usuário tivesse que digitar novamente seus dados de
autenticação, mesmo depois de autenticado no CAGR;
• O sistema não era muito rápido. Isso se devia basicamente ao gargalo
que o banco de dados oferecia. Seria necessário encontrar alguma
forma de aumentar a velocidade de navegação, pois a mesma é
crucial para o sucesso do fórum.
Após ter-se chegado a essas conclusões, passou-se para próxima etapa de
desenvolvimento. Nela, procurou-se corrigir os problemas do protótipo e
acrescentar as novas funcionalidades.
7.2 Correção de Problemas e Inclusão de Funcionalidades
Nessa etapa do projeto, procurou-se solucionar os problemas e incluir as
funcionalidades que foram apontadas na análise feita acima. Para isso, cada uma
delas foi analisada individualmente, buscando-se encontrar a melhor solução
possível.
61
7.2.1 Funcionalidade – Listagem dos Membros
Essa funcionalidade visa uma maior interação entre os membros da sala. Era
de interesse dos usuários saber quais membros fazem parte da sala e poder
enviar mensagens a eles.
A funcionalidade de listagem de membros consiste em:
1. Obter o identificador da sala de discussão que o usuário requisita
listagem de membros;
2. Através desse identificador, consultar o banco de dados e descobrir
de qual tipo de sala se trata. Dependendo desse tipo:
a. Sala de Graduandos da UFSC – a listagem dos membros
dessa sala não está disponível, mas trataria-se de uma
consulta a tabela alunosGraduacao_aln, selecionando os
alunos ativos;
b. Sala dos Graduandos do Curso ‘X’ – a listagem nessas salas é
feita através de uma consulta a tabela alunosGraduacao_aln,
selecionando os alunos ativo do determinado curso;
c. Sala de Formandos do Curso ‘X’ – os membros dessa sala são
os alunos que possuem o provável semestre de formatura igual
ao semestre letivo atual. Essas informações são obtidas nas
tabelas alunosGraduacao_aln e parametroGraduacao_prm
respectivamente;
d. Sala de Disciplinas – os membros dessas salas são compostos
pelos professores que lecionam a disciplina numa determinada
turma e pelos alunos que a cursam. Essas informações podem
ser obtidas nas tabelas alocaçãoProfessor_alp e
espelhoMatricula_esp respectivamente;
3. Apresentar na tela, em forma de tabela, os membros da sala, junto
com seu tipo (aluno, professor), matrícula, e links para o envio de
mensagem e visualização de perfil.
62
O acesso ao banco de dados foi feito utilizando uma stored procedure, que
automatiza o processo descrito acima e exime o sistema lógico do fórum de se
preocupar com a montagem desses dados. As demais funcionalidades também
foram implementadas dessa forma.
7.2.2 Funcionalidade – Envio de Mensagens
A funcionalidade de Envio de Mensagens tem o objetivo de prover
comunicação entre os membros do fórum. Basicamente, tem-se a opção de enviar
mensagens a um determinado usuário ou aos usuários de uma determinada sala.
O processo consiste basicamente em:
1. O usuário escolhe se deseja enviar uma mensagem a um determinado
membro ou a uma sala;
2. Dependendo do usuário:
a. Membro de Fórum
i. O sistema obtém o identificador do usuário, bem como o
seu tipo;
ii. O sistema acessa o banco de dados e verifica se o
usuário permite que sejam enviadas mensagens a ele;
b. Sala de Discussão
i. O sistema checa se a sala possui listagem de membros
e se o usuário remetente faz parte da mesma, caso
contrário uma mensagem de erro será apresentada;
3. O sistema apresenta um formulário onde é possível escrever a
mensagem, bem como anexar arquivos a ela;
4. Após o formulário ter sido submetido, o sistema acessará o banco de
dados e obterá o(s) email(s), que dependendo do usuário:
a. Usuários individuais:
i. Aluno – obtido da tabela alunosGraduacao_aln;
63
ii. Professor – obtido da tabela cadastroPessoal_pss
(banco ADRH);
iii. Departamentos, Cursos, Administradores – obtido da
tabela coordenaCurso_coc;
b. Sala de Discussão
i. A lista de emails será obtida utilizando a lógica da
funcionalidade de listagem de membros da sala;
ii. O sistema checará se algum membro da sala não
permite o recebimento de emails, caso exista algum, ele
será excluído da lista de destinatários;
5. O email será enviado ao destinatário, tendo como remetente o usuário
que está autenticado no fórum e que escreveu o email. O mesmo não
tem acesso ao(s) endereço(s) de email(s) do destinatário, para evitar
questões de privacidade.
Como podemos ver nos itens 2.a.ii e 4.b.ii, o sistema deve checar se o
usuário destinatário permite que lhe sejam enviados emails. Para isso, torna-se
necessário criar uma nova tabela no banco de dados, onde seriam armazenados
os parâmetros de preferência dos usuários do fórum.
Figura 10 – Tabela parametroForum_paf do banco de dados
O campo cd_bloquearEmail_paf é referente a escolha que o usuário tem de
receber emails de outros membros ou não. O campo cd_emailAutomatico_paf é
referente aos emails que são mandados aos membros de uma sala de discussão,
onde o usuário que faz parte da mesma pode escolher se deseja ou não receber
emails enviados coletivamente para a sala.
64
Criou-se uma tela com opções de configuração, onde o usuário pode alterar
essas opções.
Figura 11 – Configurações do recebimento de email
Abaixo se encontram, respectivamente, os formulários de envio de
mensagens a usuários e a salas de discussão.
Figura 12 – Formulário de envio de mensagem a um membro do fórum
65
Figura 13 – Formulário de envio de mensagem aos membros de uma sala
7.2.3 Funcionalidade – Sistema de Busca
Com a utilização do fórum, um grande número de tópicos e mensagens
começou a ser armazenado. Isso acabou por criar uma demanda por um sistema
de busca. A idéia básica é que o usuário possa vasculhar em todo o arquivo do
fórum, tanto em salas referentes ao curso do usuário, quanto nas salas dos outros
cursos. Inicialmente, disponibilizou-se a busca por tópicos e por salas de
discussão. A dinâmica de funcionamento é a seguinte:
Busca por Tópicos
1. O usuário entra no formulário de busca, podendo utilizar os seguintes
critérios de busca: título do tópico, sala em que se encontra, a partir de
qual data foi postado, a partir de qual semestre foi postado e matrícula
do autor. Adicionalmente pode escolher organizar os resultados pelo
66
título do tópico e data de postagem, nas ordens ascendente e
descendente;
2. O sistema acessará o banco de dados e efetuará a busca. A tabela
topicosForum_tof será consultada utilizando os filtros definidos na
busca;
3. Os resultados serão apresentados na tela, utilizando os critérios de
classificação escolhidos;
Figura 14 – Formulário de busca de tópicos
Figura 15 – Resultado da busca por tópicos
Busca por Salas de Discussão
1. O usuário entra no formulário de busca, podendo utilizar os seguintes
critérios de busca: nome da sala, código da disciplina, turma da
disciplina, semestre da turma e se a sala é de uma disciplina, de
graduandos, de formandos ou das disciplinas do curso do usuário;
67
2. O sistema irá acessar o banco de dados e dependendo do tipo de
sala:
a. Disciplina – o sistema procurará nas tabelas
disciplinaGraduacao_dis e cadastroTurma_trm, utilizando os
critérios definidos;
b. Graduandos – o sistema irá procurar na tabela
cursoGraduacao_cur;
c. Formandos: - o sistema irá procurar na tabela
cursoGraduacao_cur, retornando as salas dos formandos de
cada semestre;
d. Disciplinas do Curso – o sistema irá procurar na tabela
turmaGraduacao_trm, filtrando os resultados pelo curso que o
usuário está cursando;
3. As salas de discussão são exibidas na tela. Somente salas que
possuem tópicos serão mostradas. As que não os possuem são
excluídas da busca.
Figura 16 – Formulário de busca por salas de discussão
68
Figura 17 – Resultado da busca por salas de discussão
O sistema de busca funcionou de maneira adequada as expectativas. Uma
deficiência dele é que não é muito rápido, e tende a ficar mais lento com o
aumento da quantidade de informação do fórum. O motivo de isso ocorrer é o fato
de o banco de dados utilizado não ser otimizado para operações de busca, o que
causa essa lentidão. Sistemas de fórum semelhantes utilizam geralmente o banco
de dados MySql15, que possui um desempenho superior em operações de busca.
7.2.4 Funcionalidade – Perfil do Usuário
A funcionalidade de perfil do usuário tem o objetivo de fornecer mais
informações sobre um determinado usuário. Essa função é desejável, já que
aumenta a interação e conseqüentemente a comunicação entre os membros do
fórum.
A dinâmica de funcionamento dessa função é simples, tratando-se de uma
consulta a uma stored procedure pré determinada, que recebe os parâmetros
matrícula e tipo do usuário, e retorna os dados desejados. Esses dados são
escolhidos pela stored procedure, de modo que não seja necessário reprogramar
a aplicação caso seja necessário fazer manutenção.
15 http://www.mysql.com
69
Além dos dados do usuário, as salas em que ele está matriculado também
são mostradas. Essas são obtidas através do mesmo procedimento usado para
listar as salas do usuário autenticado no sistema.
É possível, também, enviar email ao usuário. Um botão com a opção de
mandar email é fornecido, junto com os dados do perfil.
As informações mostradas são as seguintes:
• Aluno
o Curso;
o Matrícula;
o Situação Atual (regular, trancamento, etc);
o Website (pode ser modificado nas configurações do fórum);
o Quantidade de mensagens postadas.
70
Figura 18 – Perfil do Aluno
• Professor
o Departamento de Lotação;
o Link para o Currículo (CNPq/Lattes);
o Website (pode ser modificado nas configurações do fórum);
o Quantidade de mensagens postadas.
71
Figura 19 – Perfil do Professor
7.2.5 Funcionalidade – Monitoramento de Tópicos e Notificação de Postagens
Uma das desvantagens do sistema de fórum em relação às listas de
discussão é a necessidade de visitar o fórum constantemente para ver as novas
postagens. Tentou-se contornar essa dificuldade através da inclusão de duas
funcionalidades, o monitoramento de tópicos e a notificação de postagens.
O monitoramento de tópicos consiste numa opção que o usuário tem de ser
notificado quando algum tópico do fórum receber novas postagens. O usuário não
precisa estar necessariamente cadastrado nas salas que possuem esses tópicos.
Para utilizar essa função, o usuário deve clicar no link “monitorar esse tópico”, que
aparece quando se está visualizando as mensagens do mesmo.
72
Figura 20 – Link “Monitorar esse Tópico”
O usuário automaticamente receberá um email quando novas postagens
ocorrerem. Pode-se, através das configurações do fórum, ver quais tópicos estão
sendo monitorados e excluí-los caso se deseje.
Figura 21 – Lista de Tópicos Monitorados
A notificação de postagens funciona de maneira semelhante. Assim como a
opção acima explicada, ela também notifica o usuário quando ocorrem novas
postagens. A diferença básica é que a notificação de postagens é uma opção
dada ao usuário que está criando o novo tópico ou respondendo mensagens. No
momento em que ele está escrevendo, ele dispõe da opção de notificar todos os
membros da sala sobre a nova postagem. Isso é muito importante, por exemplo,
73
caso um professor queira se comunicar com seus alunos, tendo certeza que todos
receberão o email.
Figura 22 – Opção de Notificação de Postagem
O email recebido pelo usuário, tanto no caso de monitoramento como no de
notificação de postagem, é semelhante a este:
Figura 23 – Email de Notificação de Postagem
74
O mecanismo utilizado por essas duas funcionalidades é herdado do “Envio
de Mensagens”, que já foi explicado no item 7.2.2.
No monitoramento de tópicos, uma tabela adicional chamada
monitoraForum_mfo foi criada no banco de dados. Ela é responsável por
armazenar a identificação dos tópicos que o usuário deseja ser notificado. O
acesso a ela é feito através de uma stored procedure.
Na notificação de postagem, o email dos membros que devem ser notificados
é obtido através da listagem de usuários da sala.
Dentro da classe LogicaFacade, os métodos escreverMensagem e
escreverTopico foram reescritos para suportar essas funcionalidades.
7.2.6 Sistema de Autenticação
O requisito de integração com o sistema CAGR não poderia ser cumprido se
não houvesse um sistema de autenticação integrado a ele. Procurou-se, nessa
etapa, estudar a forma como a autenticação é feita no CAGR, e adaptá-la para ser
usada no fórum.
O mecanismo utilizado na autenticação do CAGR é baseado no JAAS, uma
tecnologia da SUN utilizada para definir regras de autenticação e autorização. O
JAAS é implementado diretamente sobre o servidor de aplicação, que deve seguir
a especificação definida pela SUN para poder ser usado.
A vantagem óbvia de utilizar essa tecnologia é que todo o arcabouço
necessário para se fazer um sistema de autenticação, que não é simples, já se
encontra pronto, poupando o desenvolvedor dessa tarefa. Este somente é
responsável por definir as regras de autenticação.
O pacote br.ufsc.cagr.security possui as classes que implementam as
funcionalidades do JAAS. As principais delas são:
75
• CustomLoginModule – essa classe é a implementação principal do
módulo de login do JAAS. Ela é responsável por processar as
informações de login e delegá-las às classes correspondentes;
• CustomPrincipal – essa classe é responsável por armazenar os dados
da entidade que está se autenticando no sistema. Através dela é
possível saber, por exemplo, quais são o nome, senha e classe do
usuário que está acessando o sistema. Essa classe é utilizada pelo
CustomLoginModule para delegar a autenticação à classe
responsável;
• CustomModuleAluno – responsável por autenticar usuários do tipo
aluno;
• CustomModuleProfessor – responsável por autenticar usuários do tipo
professor;
• CustomModuleAdministrador – responsável por autenticar usuários do
tipo administrador;
• CustomModuleCurso – responsável por autenticar usuários do tipo
curso;
• CustomModuleDepartamento – responsável por autenticar usuários do
tipo departamento.
Tendo o módulo de autenticação pronto, o próximo passo é definir as regras
de autenticação. Isso é feito através do arquivo web.xml, que fica dentro do
diretório WEB-INF da aplicação.
Nesse arquivo são definidos quais são as classes de usuário que podem se
autenticar na aplicação e quais são os diretórios que serão protegidos. Também
define-se o módulo de autenticação que será utilizado e os parâmetros referentes
ao formulário de login.
76
Figura 24 – Configuração de autenticação – web.xml
77
Figura 25 – Tela de Login
Após definir os parâmetros de autenticação, procurou-se encontrar uma
forma de incorporar os dados obtidos do login ao fórum. Logo após o usuário ser
autenticado, o sistema deveria carregar os dados referentes ao mesmo.
Estudou-se o uso de um filtro, isto é, um artifício usado pela API do J2EE em
que uma classe que implementa a interface Filter é invocada sempre que um
determinado mapeamento de contexto é chamado. O filtro age imediatamente
depois do processo de autenticação, o que é ideal para que os dados do usuário
sejam carregados na memória da aplicação. Os dados são constituídos pelas
informações do usuário e as salas de discussão em que está cadastrado.
O processo de autenticação é sintetizado sucintamente pela figura abaixo:
78
Figura 26 – Diagrama do Processo de Login
O sistema de autenticação que foi implantado mostrou-se bastante
satisfatório. O requisito de haver integração com o sistema CAGR foi mantido,
existindo inclusive o compartilhamento de dados entre as aplicações. No momento
em que o usuário faz o login no fórum, automaticamente ele o faz no CAGR, e vice
e versa.
7.2.7 Otimização de Tempo de Resposta
Uma das características principais para o sucesso de um fórum é ter um
tempo de resposta satisfatório. Nenhum usuário gosta de esperar muito tempo
para obter uma resposta.
Nesse momento, o fórum não se encaixava nesse quesito, pois o banco de
dados ao qual estava ligado encontrava-se com desempenho saturado devido ao
grande número de acessos e ao seu hardware defasado.
A solução de maior impacto seria, portanto, trocar o servidor de banco de
dados. Infelizmente, isso não seria possível no momento, o que levou a busca por
alternativas que diminuíssem o gargalo do banco de dados.
Dentre as soluções adotadas:
Usuário acessa o sistema Subsistema JAAS está
autenticado?
Formulário de Autenticação
não
Envia requisição deautenticação
Filtro de Loginsim
Acesso ao Sistema
1 - Obtém as informações de autenticação do JAAS2 - Carrega as informações do usuário na memória
79
• Tentar acessar o menos possível o banco de dados. Salvar todas as
informações estáticas na memória da aplicação, precisando obtê-las
somente uma vez do banco de dados;
• Alterar as stored procedures de modo que retornem somente os dados
que serão utilizados, evitando ao máximo o cruzamento entre tabelas
(joins), que degradam em muito o desempenho;
A primeira solução foi implementada utilizando caches baseado nos beans
de sessão do Java Server Faces. Na primeira vez que o usuário faz o login no
sistema, os beans de cache são nulos, o que força o sistema a obter os dados no
banco de dados. Em seguida, os mesmos são armazenados nos caches, o que
evita que sejam novamente acessados no banco de dados. Os beans de sessão
duram enquanto o usuário estiver autenticado no sistema. Caso ele se
desconecte, a sessão é invalidada, tornando-se necessário fazer todo o processo
novamente.
A segunda solução consiste em alterar as stored procudures de modo que
elas sejam mais eficientes e, portanto processadas mais rapidamente.
Dependendo do modo que são programadas, o tempo de resposta pode mudar
drasticamente. Procurou-se evitar o máximo possível o uso de associações
desnecessárias e de valores que não são usados pelo programa. As tabelas
consultadas possuem índices, o que agiliza bastante a consulta dos dados.
As soluções apresentadas acima contribuíram para aumentar a velocidade
do fórum. Porém, o impacto do gargalo do banco de dados se mostrou bem visível
ainda. Felizmente, houve uma reestruturação no servidor de banco de dados, o
que o tornou muito mais rápido. Isso, aliado as otimizações que foram feitas,
tornou o fórum bastante rápido, aumentando sua usabilidade.
80
7.3 Definição da Versão Final e Inclusão de Funcionalidades
As funcionalidades e aperfeiçoamentos efetuados acima foram suficientes
para definir o fórum como sendo uma versão final. O sistema foi, portanto,
implantado para ser utilizado pelos seus usuários. À medida que eles iam
utilizando o fórum, sugestões de inclusão de funcionalidades foram sendo feitas.
Procurou-se analisar essas propostas de funcionalidades e decidir se seriam
relevantes ao fórum. Optou-se por implementar aquelas que teriam um maior
impacto na usabilidade e que contribuiriam para uma melhor interação entre os
usuários. Abaixo, são explicadas cada uma delas:
7.3.1 Repositório Individual de Arquivos
Os usuários do fórum não possuíam até então uma forma fácil de armazenar
seus arquivos. Era necessário utilizar servidores externos para isso.
Optou-se por criar um repositório individual para cada usuário. O repositório
consiste de um espaço de 50MB, que pode ser utilizado para o armazenamento
de qualquer arquivo. De modo a coibir a pirataria, os arquivos somente podem ser
baixados pelos usuários do fórum, isto é, é necessário se autenticar antes de fazer
essa operação.
Na implementação dessa funcionalidade, pesquisou-se o uso de algum
mecanismo que permitisse o envio de arquivos através de formulários HTML.
Devido ao fato de a implementação padrão da SUN do Java Server Faces não
possuir suporte ao envio de arquivos, utilizou-se o componente UploadBean da
JavaZoom16.
O UploadBean pode ser integrado em qualquer aplicativo que utiliza
JSP/Servlets. Os arquivos podem ser gravados num diretório do servidor, num
arquivo ZIP, num banco de dados ou na memória. Pode-se aplicar restrições como
tamanho de arquivo, banir certas extensões de arquivo e o número máximo de
arquivos a enviar. 16 http://www.javazoom.net
81
Optou-se por gravar os arquivos no servidor que roda a aplicação. Não se
utilizou o banco de dados, pois o mesmo seria sobrecarregado pelos inúmeros
arquivos que seriam armazenados.
O sistema de envio de arquivos é constituído das funcionalidades de envio,
download e exclusão. Explica-se rapidamente abaixo o funcionamento de cada
um delas:
• Envio de Arquivos – o sistema apresenta ao usuário um formulário
onde o mesmo pode enviar arquivos. Se por acaso a soma do
tamanho do arquivo que está sendo enviado junto com os arquivos
que estão armazenados for maior que o limite estabelecido (50MB), o
arquivo é recusado;
• Download – esse trabalho é feito por um servlet que lê o arquivo do
servidor e o envia ao usuário. As regras de autenticação são
aplicadas em cima dele, o que impede que usuários não autorizados
possam fazer o download do arquivo;
• Exclusão – o usuário, depois de autenticado, tem a opção de excluir
os arquivos que armazena. O espaço que é alocado quando ocorre a
exclusão pode ser usado para o envio de outros arquivos.
A funcionalidade de arquivos está disponível no menu principal do fórum, na
opção “Meus Arquivos”.
82
Figura 27 – Sistema de Arquivos no Fórum
7.3.2 Exibição de Fotos dos Usuários
Uma das funcionalidades propostas pelos usuários do fórum é a inclusão de
fotos nos perfis dos usuários. Isso permitiria identificar facilmente cada um deles e
seria um atrativo ao uso do sistema.
Para os alunos, pensou-se inicialmente em permitir-lhes a escolha de sua
foto. Essa escolha, porém, foi vetada, pois se temia que eles não colocassem
fotos verdadeiras, tornando-se uma “bagunça”.
Recorreu-se, portanto, ao cadastro de fotos da carteirinha de Identificação
Universitária, que até então servia para acesso ao Restaurante Universitário.
83
Figura 28 – Carteira de Identificação Estudantil
O banco de fotos do cadastro de carteirinhas, porém, não era integrado ao
CAGR, o que impedia a alimentação automática das fotos no sistema. Tornou-se
necessário desenvolver um programa que pudesse migrar as fotos do cadastro de
carteirinhas para o banco de dados do CAGR.
Não se sabia, a priori, de que forma se poderia armazenar as fotos no banco
de dados Sybase. Pesquisando em sites e conversando com colegas de trabalho
descobriu-se que o banco possui um campo do tipo image, que pode ser usado
para o armazenamento de imagens. Através da programação em Java, pode-se
gravar nesse campo utilizando um stream de dados binários. Um trecho do código
utilizado para isso se encontra abaixo:
Figura 29 – Código para inserção de imagem no banco de dados
84
Após ter-se o conhecimento de como armazenar as imagens no banco de
dados, procurou-se desenvolver o programa. As fotos encontravam-se em uma
pasta, nomeadas pela matrícula do usuário. O programa deveria permitir que
todas essas fotos fossem enviadas ao servidor simultaneamente e também
permitir a mudança da foto de um usuário específico.
O programa foi desenvolvido na linguagem JAVA, utilizando uma interface
simples e funcional, já que seria utilizado somente para essa atividade específica.
Figura 30 – Cadastro de Fotos – Mudando uma foto
Figura 31 – Cadastro de Fotos – Mudando várias fotos
85
Os testes realizados com esse programa mostraram que ele se adéqua muito
bem as suas funções. Inicialmente uma base de 5000 fotos foi enviada ao servidor
sem maiores problemas.
O próximo passo é cuidar da visualização das fotos no ambiente WEB do
fórum. Optou-se por utilizar um servlet para exibir as fotos dos usuários. Os
parâmetros requeridos por ele são a matrícula do usuário e o seu tipo (aluno ou
professor). O servlet utiliza uma estrutura de cache, isto é, ele somente acessa o
banco de dados uma vez para carregar a foto. Na próxima vez que a mesma foto
for acessada, ela já estará na memória.
As fotos foram colocadas na parte de perfil e listagem de membros do fórum.
Existe a opção de bloquear a exibição da foto, caso algum usuário não queira que
ela seja exibida.
Figura 32 – Exibição de fotos na Listagem de Membros
86
Figura 33 – Exibição de foto no Perfil
No caso dos professores, não se dispunha de uma base cadastral de fotos.
Optou-se por dá-los a opção de enviar uma foto para ser usada no perfil. O
sistema automaticamente redimensiona a foto para o tamanho correto.
Figura 34 – Exibição de foto no Perfil
87
7.3.3 Inclusão de Arquivos Anexos nos Tópicos e Mensagens
Apesar de já existir a funcionalidade do repositório “Meus Arquivos”, a
mesma não é muito adequada para se usada junto aos tópicos e mensagens.
Além de ser um repositório de somente 50 MB, o intuito dessa funcionalidade é de
ser um repositório individual, onde os arquivos lá armazenados seriam de uso
somente do seu usuário.
Devido a esse fato e a crescente demanda de professores e alunos,
implementou-se a funcionalidade de anexar arquivos aos tópicos e mensagens. O
seu funcionamento é muito semelhantes ao repositório “Meus Arquivos”. Os
arquivos são armazenados no servidor da aplicação, para evitar gargalos no
banco de dados. Não se estipulou, a princípio, limites para os tamanhos dos
arquivos. Como eles são de uso da comunidade que freqüenta os tópicos e podem
ser grandes, como apresentações, por exemplo, concluiu-se que um limite nos
arquivos seria um empecilho.
A funcionalidade foi implementada nos formulários de criação de tópicos e
mensagens. Além dos campos de assunto e mensagem, existem três campos de
arquivos, que são usados para o envio dos mesmos.
88
Figura 35 – Inclusão de Anexos no Formulário de Tópico
Logo após a submissão do formulário, o tópico ou a mensagem será criado,
tendo os links dos arquivos anexados junto a ela.
89
Figura 36 – Inclusão de Anexos no Formulário de Tópico
A forma de se fazer download é a mesma da funcionalidade dos “Meus
Arquivos”. O mesmo servlet é usado, inclusive utilizando as mesmas regras de
autenticação. Somente usuários cadastrados no fórum podem fazer download dos
arquivos.
Notou-se que essa funcionalidade despertou grande interesse nos usuários
do fórum. Praticamente todos os professores que o utilizam colocam materiais de
aula, desde listas de freqüência, notas e apresentações. Com a inclusão da
funcionalidade de arquivos, a interação entre os usuários ficou muito maior.
90
7.3.4 Alunos Especiais e Monitores
O fórum inicialmente estava previsto para ser usado somente por
graduandos regularmente matriculados nas disciplinas. Isso, de certa forma,
excluía do uso os alunos especiais (isolados/ouvintes) e dos monitores de uma
disciplina. É de interesse, principalmente dos professores, que esses usuários
pudessem fazer parte dos membros da sala, pois assim poderiam receber os
emails e interagir com o restando do pessoal. Procurou-se, portanto, atender a
esse requisito. Dividindo nos dois casos temos:
Alunos Especiais
Os alunos especiais são aqueles que não possuem uma matrícula regular na
graduação. Por causa disso, não possuem acesso ao CAGR e, portanto não
podem se autenticar no fórum. Porém, eles estão vinculados as disciplinas através
de um cadastro especial. Esse cadastro constitui-se pelas tabelas
alunosComunidade_acm e matriculaDisciplina_mtd. A primeira tabela contém o
cadastro dos alunos, e a segunda os relaciona com as disciplinas que estão
cursando. Alterando-se a stored procedured responsável pela listagem de
membros da sala, bem como a que obtém o perfil, podemos incluí-los no sistema
do fórum. É importante salientar que os ouvintes somente são aptos a receber os
emails das salas em que estão matriculados. Não podem, portanto, ter acesso
total ao fórum.
Monitores
Monitores são alunos regularmente matriculados na Universidade que
exercem a função em determinadas disciplinas. O cadastro dos mesmos é
responsabilidade da Pró Reitoria de Ensino e Graduação (PREG). Seus dados
portanto, não fazem parte do CAGR, e não se encontram no mesmo local no
banco de dados. O banco moni é acessado quando se deseja obter informações
sobre eles. A tabela monitor_mon contém o nome do aluno, sua matrícula e as
91
disciplinas em que está monitorando. De maneira semelhante ao que ocorre com
os alunos especiais, as stored procedures são adaptadas para incluí-los também
na listagem de salas.
Como os monitores são alunos e, portanto usuários ativos do fórum, é
necessário também alterar as stored procedures que cuidam de postagens e
controle de exclusão. Os monitores possuem o mesmo poder que professores nas
salas, podendo atuar como moderadores.
Figura 37 – Listagem de Membros incluindo monitores e alunos especiais
Como podemos ver acima, os dois novos tipos de usuário são adicionados a
listagem de membros da sala. Isso faz com que eles sejam automaticamente
notificados por email quando novos tópicos e mensagens forem postados.
7.3.5 Busca por Usuários
O sistema de busca do fórum abrangia até então somente tópicos e salas de
discussão. Não era possível buscar pelos usuários do fórum. Notou-se que havia
uma demanda por essa funcionalidade, pois era de interesse dos participantes
poder procurar por alunos, professores e monitores de disciplinas. Procurou-se
implementar essa funcionalidade de maneira semelhante ao item 7.2.3, levando
em conta a seguinte dinâmica:
92
Busca por Alunos
1. Os critérios usados nessa busca são o nome e o curso do aluno. Se
esse último não for especificado, o sistema irá procurar pelo nome do
aluno em todos os cursos;
2. O sistema retorna a foto, matrícula, nome e qual curso o aluno está
cursando.
Figura 38 – Resultado de Busca por Alunos
Busca por Professores
1. Os critérios usados são o nome do professor e o seu departamento.
Pode-se obter a lista de todos os professores de um departamento ou
ainda procurar pelo nome de um professor em todos os
departamentos da UFSC;
2. O sistema retorna a foto, matrícula, nome e qual alocação (geralmente
departamento) o professor se encontra;
Figura 39 – Resultado de Busca por Professores
93
Busca por Monitores
1. Os critérios usados nessa busca os mesmos da busca por alunos.
Pode-se, porém, omitir o nome do aluno e saber todos os monitores
de um determinado curso;
2. O sistema retorna a foto, matrícula, nome e disciplina que o aluno está
monitorando.
Figura 40 – Resultado de Busca por Monitores
O formulário de busca de usuários segue o mesmo estilo das demais buscas
implementadas. Pode-se escolher qual tipo de usuário, seu nome, curso e
departamento (se aplicáveis).
Figura 41 – Formulário de Busca por Usuários
94
8 Considerações Finais
Na concepção e desenvolvimento desse trabalho, conseguiu-se alcançar os
objetivos propostos inicialmente.
O estudo da estrutura acadêmica, e de que forma ela é organizada em
termos tecnológicos e conceituais, permitiu obter o conhecimento necessário para
a concepção do sistema. Junto a isso, efetuou-se a pesquisa acerca as soluções
atualmente utilizadas na UFSC. Essa pesquisa permitiu que se identificassem
seus pontos fortes e fracos, e de que forma elas poderiam contribuir para o novo
sistema proposto.
O sistema de fórum não é uma idéia original, e como já explicada nesse
trabalho, possui anos de uso na comunidade da Internet. Procurou-se aprender
através do estudo das soluções de fórum já existentes no mercado. Se de um
lado, não se pôde aproveitar integralmente alguma delas, por outro forneceram
uma base de inspiração que foi essencial na elaboração do sistema.
Na etapa em que a análise e o projeto do sistema foram desenvolvidos,
conseguiu-se chegar a um consenso quanto as funcionalidades que o sistema
deveria oferecer e de que forma elas deveriam ser organizadas, em termos de
usabilidade e apresentação do sistema. A participação do público da Graduação,
nas figuras dos alunos, professores e coordenadores de curso, foi fundamental
nesse processo. A medida que o protótipo ia sendo desenvolvido, novas
funcionalidades e correções iam sendo feitas, mesmo quando chegou-se a versão
final do sistema.
Algumas sugestões para trabalhos futuros podem ser feitas. Uma delas é o
fato de o sistema ter sido baseado nas tecnologias vigentes na época do
desenvolvimento do Sistema Acadêmico da Graduação.
Novas tecnologias, porém, foram desenvolvidas em períodos posteriores e
com certeza poderiam ser implementadas em novas versões do sistema.
95
Entre elas destacam-se os Enterprise Java Beans (EJBs), que permitiram
uma separação maior entre a lógica da aplicação e o modelo de visualização.
Poder-se-ia, também, pesquisar soluções alternativas para persistência de
dados, redundância e escalabilidade do fórum. Fala-se isso porque não se pôde
avaliar o desempenho do sistema em condições de tráfego mais intenso e com
uma quantidade maior de dados. Soluções que foquem nesses aspectos são
muito bem vindas como temas de trabalhos futuros.
Os recursos de comunicação do fórum podem ser aprimorados à medida que
seja necessário aumentar a interação entre os usuários e seus conteúdos. Pode-
se buscar inspiração em serviços já existentes, como o Orkut17 e o MySpace18.
A divulgação do fórum à comunidade acadêmica também é muito importante.
No presente momento em que esse trabalho é escrito, grande parte do público do
fórum é composto pelos alunos e professores do curso de Engenharia e
Aqüicultura, os cursos do Centro Tecnológico e alguns cursos do Centro de
Ciências da Educação. Nota-se que uma grande parcela do público potencial
ainda está inerte quanto a utilização do fórum. Um trabalho bem feito de
divulgação, com o intuito de tornar o fórum uma “cultura” universitária com certeza
é muito bem vindo.
17 http://www.orkut.com 18 http://www.myspace.com
96
9 Referências Bibliográficas
SUN MICROSYSTEMS. The Source for Java Developers.
Disponível em: <http://java.sun.com>. Acesso em: 23 de maio de 2007
SUN MICROSYSTEMS. Java Server Faces Technology.
Disponível em: <http://java.sun.com/javaee/javaserverfaces>. Acesso em: 18 de
maio de 2007
JBOSS GROUP. JBoss Application Server.
Disponível em: <http://labs.jboss.com/jbossas >. Acesso em: 20 de abril de 2007
PHPBB GROUP. phpBB.
Disponível em: <http://www.phpbb.com>. Acesso em: 10 de abril de 2007
WIKIPEDIA. Internet Forum.
Disponível em: <http://en.wikipedia.org/wiki/Internet_forum>. Acesso em: 30 de
março de 2007
WIKIPEDIA. Electronic Mailing List.
Disponível em: <http://en.wikipedia.org/wiki/Electronic_mailing_list>. Acesso em:
28 de março de 2007
97
WIKIPEDIA. Apache Struts.
Disponível em: <http://en.wikipedia.org/wiki/Struts>. Acesso em: 25 de abril de
2007
WIKIPEDIA. Stored Procedure.
Disponível em: <http://en.wikipedia.org/wiki/Stored_procedure>. Acesso em: 10 de
maio de 2007
WIKIPEDIA. Java Plataform, Enterprise Edition.
Disponível em: <http://en.wikipedia.org/wiki/Java_ee >. Acesso em: 10 de abril de
2007
UNIVERSIDADE FEDERAL DE SANTA CATARINA. Guia Acadêmico da Graduação. Santa Catarina.
Disponível em: <http://notes.ufsc.br/aplic/guiaAcad.nsf>. Acesso em: 15 de abril
de 2007.
UNIVERSIDADE FEDERAL DE SANTA CATARINA. Sistema Acadêmico da Graduação: Manual do Usuário. Santa Catarina, outubro 2006.
BODOFF, S. The J2EE Tutorial. Boston: Addison-Wesley, 2002.
LEMAY, L.; CADENHEAD, R. Sams teach yourself Java 2 in 21 days.
Indianapolis, IN: Sams Publishing, 1999.
KURNIAWAN, B. Java for the Web with Servlets, JSP, and EJB: a developer’s
guide to J2EE Solutions. 1. ed. Indianapolis: New Riders, 2002.
98
10 Anexos
10.1 Manual de Utilização
Fórum da Graduação
O Fórum dos cursos de graduação da UFSC tem o objetivo de contribuir no intercâmbio de informações e conhecimentos entre professores, graduandos e coordenação do curso, principalmente numa comunidade onde o tempo é escasso e o encontro com os colegas de curso limita-se à aula. O Fórum deve ser usado com critério, onde os participantes prestam sua contribuição.
Neste Fórum a colaboração criará uma verdadeira conexão entre os participantes, dando a cada contribuição a importância da opinião, da troca de experiências, da dúvida, do pensamento e do respeito pelas idéias.
Em um ambiente virtual a monitoração é de fundamental importância, pois amplia e exercita os limites e as capacidades para o desenvolvimento da inteligência coletiva. Esta monitoração deverá ser exercida pelos próprios participantes e pelos cursos (coordenações). As coordenações, avaliando as mensagens inúteis e que não acrescentam nada ao assunto discutido, poderão desativá-las.
Os conteúdos dos Fóruns de discussão são determinados pelos participantes que devem ser co-autores da construção do conhecimento e de seu próprio processo de aprendizagem. É importante que todos tenham um relacionamento cordial, existindo à liberdade e à responsabilidade de cada participante em fazer suas próprias interpretações.
O Fórum contempla as seguintes salas de discussão: 1.Fórum de discussão das disciplinas matriculadas no semestre.
As discussões e reflexões podem ser organizadas em tópicos de interesses e criados pelos participantes da turma (graduandos e professores), com validade durante o semestre letivo.
2.Fórum de discussão dos graduandos do curso;
Discussões de interesse do curso em que o graduando está vinculado. Os tópicos devem ser criados através da coordenação do curso específico, para isso basta argumentar com a coordenação do curso, colocando sua necessidade quanto ao tópico em questão, chegando a um consenso para sua criação.
3.Fórum de discussão dos prováveis formandos do semestre;
Discussões de interesse dos prováveis formandos do curso em que o graduando está vinculado. Os participantes serão incluídos automaticamente pela coordenação do curso, quando da identificação dos prováveis formandos do semestre.
99
4.Fórum de discussão dos graduandos da UFSC. Discussões de interesse global da instituição, pelos
participantes, com temas de interesse da comunidade universitária. Os tópicos devem ser solicitados através da coordenação do curso e criados pelo administrador do Fórum.
Considerações A Universidade Federal de Santa Catarina não têm qualquer
responsabilidade sobre o conteúdo postado pelos participantes do Fórum da Graduação.
Não garantimos a funcionalidade ou responsabilidade pelas conseqüências causadas pelo uso das informações e dicas sugeridas pelos participantes.
Não são permitidos propagandas de produtos, serviços e comércio (marketing, compra e venda) no Fórum.
As regras do Fórum poderão ser alteradas sem prévio aviso. O Fórum, por questões de segurança, registra o IP do autor das mensagens postadas. Regras: Comportamento no Fórum O participante deve ajudar aos demais, respondendo dúvidas e
solucionando problemas. Aqueles que participarem do Fórum apenas postando críticas destrutivas correrão o risco de desativação.
Não são permitidas ofensas ou difamação a qualquer membro do fórum, seja por racismo, diferenças ideológicas, preferência pessoal, etc.
Críticas e reclamações sobre o comportamento de outros participantes devem ser evitadas! Se desejar reclamar sobre o comportamento de um outro participante entre em contato com a coordenação do fórum específico.
O fórum não é lugar para discussões pessoais. As discussões que se tornarem pessoais (com ataques, ofensas ou ameaças) serão desativadas. Pelo mesmo motivo evite entrar em discussões, responder a provocações de outros participantes.
O participante deve evitar se comportar como um moderador do Fórum, devendo limitar suas respostas às dúvidas postadas. Regras: Tópicos e Respostas
Mensagens e tópicos relacionados à pirataria e/ou que ferem as Leis ou com códigos destrutivos e/ou maliciosos, informações sigilosas e/ou pessoais e similares serão desativadas e seu autor responsabilizado. Mensagens que incitem a discriminação racial, religiosa ou partidária são EXPRESSAMENTE PROÍBIDAS.
O título do tópico deve conter obrigatoriamente o assunto da discussão (não utilize títulos, tais como: "Socorro!!!") e não os direcione a uma única pessoa. Não poste em letras maiúsculas, além de ser desagradável de ler, é injusto, pois faz com que sua mensagem tenha mais destaque que as demais.
100
Equipe CAGR email:[email protected]
Procedimentos de Uso
Os Graduandos, Professores e Coordenações de Cursos da Graduação poderão participar do Fórum acessando-o através de suas matrículas e senhas pré-definidas no Sistema de Controle de Acadêmico da Graduação (CAGR). Ver figura 01.
Figura 01 – Tela de acesso ao CAGR e Fórum de Discussão
Após a autenticação, é disponibilizado o acesso ao Fórum de discussão em que o participante é membro.
Alunos: Fórum de discussão dos graduandos da UFSC; Fórum de discussão dos graduandos do curso; Fórum de discussão dos prováveis formandos do semestre; e Fórum de discussão das disciplinas e turmas em que está matriculado no semestre.
Professores: Fórum de discussão dos graduandos da UFSC; e Fórum de discussão das disciplinas e turmas do semestre em que o professor está alocado no CAGR. Os professores devem estar cadastrados no Sistema de Administração de Recursos Humanos (ADRH) que serão identificados pela matrícula da UFSC.
Curso: Fórum de discussão dos graduandos da UFSC; Fórum de discussão dos graduandos do curso; Fórum de discussão dos prováveis formandos do curso no semestre; e Fórum de discussão das disciplinas e turmas oferecidas para o curso, no semestre. A figura 02 mostra fórum de discussão, onde consta a quantidade de
tópicos e o número de visitas em cada fórum.
101
Figura 02 – Fóruns de discussão em que o graduando é participante
Ao Escolher um dos fóruns será mostrada informação dos tópicos existentes, contendo: quantidade respostas postadas, total de consultas efetuadas, identificação do autor do tópico e a última mensagem registrada pelo participante responsável. Ver figura 03. Os membros participantes do fórum poderão ser listados através do
botão ‘ ’ e e-mail poderá ser enviado a todos os membros através
do botão ‘ ’, arquivos poderão ser atachados ao e-mail, o aluno poderá bloquear o envio de e-mail pelos participantes através da opção ‘configurações’
Novo tópico poderá ser criado ou solicitado pelo participante
através do botão ‘ ’, ver figura 05. A última mensagem registrada
no tópico poderá ser vista clicando em: ‘ ’.
102
Figura 03 – Exemplo de tópicos de fórum
Ao Escolher um dos tópicos do fórum serão mostradas todas as respostas registradas pelos participantes, com informações que o
identificam (botão ‘ ’). E-mail poderá ser enviado ao responsável
pela resposta através do botão ‘ ’. Ver figura 04.
O botão ‘ ’ permite que o participante exponha suas idéias e conhecimentos, colaborando com o enriquecimento do fórum, veja figura 06.
A opção ‘Monitorar esse tópico’ habilita o envio de e-mail sempre que houver postagem no tópico assinalado.
A última mensagem poderá ser consultada acessando a página
mostrada, conforme exemplo: ‘ ’
O botão ‘ ’ permitirá que o participante que registrou a mensagem ou coordenador do fórum desative a mensagem. A desativação de quantidade pré-definida de mensagens postada pelo participante inviabilizará nova postagem pelo mesmo.
103
Figura 04 – Exemplo de respostas registradas pelos participantes do
tópico
Quando o participante desejar criar tópicos, através do botão
‘ ’ em fórum de interesse coletivo, deve preencher solicitação com o titulo e texto explicativo do assunto a abordar, que será enviada por e-mail a coordenação para análise e providências. Ver figura 05.
104
Figura 05 – Exemplo de solicitação de criação de tópicos em fórum de uso
geral
Para responder a tópicos de interesse, o participante, através do
botão ‘ ’ deverá formular sua resposta utilizando o editor mostrado na figura 06. A resposta deverá ser concisa, não ultrapassar duas páginas e ser digitada no tempo estipulado para processamento (timeout da sessão), aconselha-se a elaborar a resposta e inclui-la no fórum quando finalizada. Inclua sites de interesse, com dicas para os visitantes, sempre que possível.
Antes de acionar o botão ‘ ’ utilize o botão ‘ ’ para visualizar se sua resposta está dentro de seu padrão exigido.
105
Figura 06 – Editor para registro de respostas no fórum, indicando
ferramentas utilizadas
Pesquisas poderão ser realizadas utilizando a opção ‘busca’, preencha os itens desejados e efetue a pesquisa em tópicos ou nas salas
de discussão através do botão ‘ ’. Ver figura 07.
106
Figura 07 – Exemplo de pesquisa no fórum por tópicos
Configurações poderão ser realizadas utilizando a opção ‘Configurações’. As atualizações do website e e-mail do participante e bloqueios de recebimentos de e-mail podem ser efetuadas através do botão ‘enviar’.
O participante do fórum pode requerer o bloqueio de recebimentos de e-mail por qualquer usuário do fórum, ou bloquear recebimentos de e-mail nas turmas em que está matriculado (exceto quando o e-mail for enviado pelo professor ou coordenação do curso).
Os tópicos selecionados através da opção ‘Monitorar esse tópico’ (como mostrado na figura 04), estarão relacionados em ‘configurações’ e poderão ser excluídos da monitoração, veja figura 08.
107
Figura 08 – Configurações: e-mail e tópicos a monitorar
Em ‘meus arquivos’ será permitido gravar arquivos de interesse do usuário até o limite indicado e disponibilizado ao público através do link relacionado, figura 09.
Figura 09 – Arquivos do usuário
108
Em ‘meu perfil’ estarão disponíveis as informações sobre as disciplinas matriculadas, e-mail, website e a foto da carteira de identificação, figura 10.
Figura 10 – Perfil do usuário
Equipe CAGR email:[email protected]
109
10.2 Guia de Instalação
Instalando o Sistema de Fórum em uma máquina
com o JBoss 4.0.x O sistema de Fórum da Graduação foi projetado para ser integrado e executar junto com o Sistema de Controle Acadêmico da Graduação (CAGR). Para que ele possa ser instalado corretamente, é necessário fazer algumas alterações no servidor de aplicação JBOSS, que serão explicadas abaixo: 1° passo – Instalar as bibliotecas compartilhadas Tanto o CAGR quanto o fórum utilizam algumas bibliotecas que devem ser instaladas no JBOSS. São elas:
• cagr.jar – contém informações sobre o modelo e lógica dessa aplicação, com suas classes e configurações;
• jconn3d.jar – driver de conexão utilizado para conexão com o banco Sybase.
Deve‐se copiar esses dois arquivos para a pasta {JBOSS}\server\default\lib NOTA: Os arquivos cagr.jar e jconn3d.jar estão disponíveis no CVS do laboratório, no repositórios do CAGR ou do fórum. 2° passo – Configurar o módulo de login Um módulo de login foi escrito especialmente para ser usado na autenticação do fórum e do CAGR. Deve‐se configurá‐lo da seguinte forma:
1. Editar o arquivo {JBOSS}\server\default\conf\login‐config.xml; 2. Dentro da tag <policy>, adicionar o seguinte:
<application‐policy name = "cagr">
<authentication>
<login‐module code="br.ufsc.cagr.security.CustomLoginModule" flag = "required">
<module‐option name="DefaultCacheTimeout">60</module‐option>
<module‐option name="principalClass">br.ufsc.cagr.security.CustomPrincipal</module‐option>
</login‐module>
</authentication>
</application‐policy>
3. Salvar o arquivo.
110
3° passo – Configurar o host da aplicação A aplicação CAGR e o fórum são acessíveis através dos endereços www.cagr.ufsc.br e www.cagr.ufsc.br/forum respectivamente. Isso deve ser configurado no servidor JBoss da seguinte forma:
1. editar o arquivo {JBOSS}\ server\default\deploy\jbossweb‐tomcat55.sar \server.xml;
2. Dentro da tag <Engine>, colocar o seguinte código:
<Host name="cagr" autoDeploy="false" deployOnStartup="false" deployXML="false" configClass="org.jboss.web.tomcat.security.config.JBossContextConfig" >
<Alias>cagr.ufsc.br</Alias>
<Alias>www.cagr.ufsc.br</Alias>
<Alias>localhost</Alias>
<Valve className="org.apache.catalina.authenticator.SingleSignOn"/>
<Valve className="org.apache.catalina.valves.FastCommonAccessLogValve"
prefix="localhost_access_log." suffix=".log"
pattern="common" directory="${jboss.server.home.dir}/log"
resolveHosts="false" />
</Host>
3. Salvar o arquivo.
4° passo – Configurar o DataSource para acesso ao banco de dados A aplicação do CAGR e do fórum acessam o banco de dados através de um data source, que é configurado através de um arquivo XML colocado dentro do servidor JBoss. Para isso deve‐se:
1. Copiar o arquivo cagr_prod‐ds.xml para {JBOSS}\server\default\deploy; 2. Editar esse arquivo e prestar atenção nas tags <connection‐url>, <user‐name>,
<password>, que devem ser configuradas com o endereço do servidor de banco de dados, nome do usuário de acesso e sua senha respectivamente;
3. Salvar o arquivo.
NOTA: O arquivo cagr_prod‐ds.xml está disponível no CVS do laboratório, nos repositórios do CAGR ou do fórum. 5° passo – Instalar a aplicação CAGR (recomendado) O sistema de fórum pode rodar sem a aplicação CAGR estar instalada na mesma máquina. Porém, é altamente recomendável instalá‐la, devido a fatores relativos a integração do sistema e autenticação. Para se fazer isso, deve‐se:
1. Obter os códigos fontes da aplicação CAGR dentro do repositório CVS do laboratório; 2. Fazer o empacotamento da aplicação, obtendo o arquivo 3cagr.war;
111
3. Copiar esse arquivo para a pasta {JBOSS}\server\default\deploy; 4. Verificar se a aplicação está funcionando, acessando o endereço www.cagr.ufsc.br;
NOTA: Os passos 1 a 5 devem ser executados antes, pois são necessários tanto para o CAGR, quanto para o fórum funcionar. 6° passo – Instalar a aplicação do Fórum Para se instalar o Sistema de Fórum, deve‐se tomar cuidado com alguns parâmetros que mudam dependendo da versão do JBoss (4.0.4 e 4.0.5). Deve se efetuar o seguinte procedimento:
1. Obter os códigos fontes da aplicação Fórum dentro do repositório CVS do laboratório; 2. Verificar se as bibliotecas de implementação do Java Server Faces estão instaladas no
JBoss, da seguinte forma: a. Acessar a pasta {JBOSS}\server\default\deploy\jbossweb‐tomcat55.sar\jsf‐
libs; b. Verificar se os arquivos myfaces‐api.jar e myfaces‐impl.jar existem;
3. Fazer o empacotamento da aplicação do Fórum. Se os arquivos descritos em 2.b existirem, antes de empacotar a aplicação no arquivo WAR, deve‐se impedir que os arquivos jsf‐api.jar e jsf‐impl.jar sejam anexados a ele. Isso pode ser feito na tela de configuração de deployment da aplicação (JDeveloper ou Eclipse‐JBossIDE). SOLUÇÃO ALTERNATIVA: Pode‐se também apagar os arquivos descritos em 2.b e utilizar as bibliotecas descritas em 3. Essa solução, porém, não é muito recomendada, pois altera a configuração original do JBoss.
4. Após o empacotamento, o arquivo cagrForum.war será criado. Ele deve ser copiado para a pasta {JBOSS}\server\default\deploy.
5. Verificar se o fórum está funcionando, acessando o endereço www.cagr.ufsc.br/forum.
112
10.3 Código Fonte Fachada Lógica package br.ufsc.cagr.listaDiscussao.controle; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import javax.activation.FileDataSource; import javax.mail.Message; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import org.apache.commons.mail.EmailAttachment; import org.apache.commons.mail.HtmlEmail; import br.ufsc.cagr.listaDiscussao.controle.excecoes.ExcecaoNegacaoPostagem; import br.ufsc.cagr.listaDiscussao.controle.excecoes.ExcecaoSalaNaoPermiteCriarTopico; import br.ufsc.cagr.listaDiscussao.controle.excecoes.ExcecaoUsuarioNaoCadastrado; import br.ufsc.cagr.listaDiscussao.controle.excecoes.ExcecaoUsuarioNaoPodeExcluir; import br.ufsc.cagr.listaDiscussao.controle.faces.RedirectFacade; import br.ufsc.cagr.listaDiscussao.controle.faces.SessionContextContainer; import br.ufsc.cagr.listaDiscussao.controle.faces.bean.SalasUsuario; import br.ufsc.cagr.listaDiscussao.controle.faces.util.Paths; import br.ufsc.cagr.listaDiscussao.controle.faces.util.UploadUtils; import br.ufsc.cagr.listaDiscussao.controle.util.EmailValidator; import br.ufsc.cagr.listaDiscussao.controle.util.ImageUtils;
113
import br.ufsc.cagr.listaDiscussao.controle.util.LeitorParametros; import br.ufsc.cagr.listaDiscussao.modelo.Arquivo; import br.ufsc.cagr.listaDiscussao.modelo.CriterioBuscaSala; import br.ufsc.cagr.listaDiscussao.modelo.CriterioBuscaTopico; import br.ufsc.cagr.listaDiscussao.modelo.CriterioBuscaUsuario; import br.ufsc.cagr.listaDiscussao.modelo.DestinatarioEmail; import br.ufsc.cagr.listaDiscussao.modelo.Mensagem; import br.ufsc.cagr.listaDiscussao.modelo.SalaDiscussao; import br.ufsc.cagr.listaDiscussao.modelo.Topico; import br.ufsc.cagr.listaDiscussao.modelo.Usuario; import br.ufsc.cagr.listaDiscussao.modelo.autorizacoes.AutorizacaoContainer; import br.ufsc.cagr.listaDiscussao.modelo.dto.ConfiguracoesDTO; import br.ufsc.cagr.listaDiscussao.modelo.dto.EscreverEmailDTO; import br.ufsc.cagr.listaDiscussao.modelo.dto.EscreverMensagemDTO; import br.ufsc.cagr.listaDiscussao.modelo.dto.EscreverTopicoDTO; import br.ufsc.cagr.listaDiscussao.modelo.dto.RequisicaoCriarTopicoDTO; import br.ufsc.cagr.listaDiscussao.persistencia.DatabaseFactory; import br.ufsc.cagr.listaDiscussao.persistencia.IDatabaseFacade; import br.ufsc.cagr.listaDiscussao.visual.HtmlGeneratorUtils; import br.ufsc.cagr.listaDiscussao.visual.bean.MensagensPaginadas; public class LogicaFacade { private static LogicaFacade instance; private IDatabaseFacade db; private static Map<Integer, byte[]> fotosUsuarios = new HashMap<Integer, byte[]>(); public static LogicaFacade getInstance() { if (instance == null) { instance = new LogicaFacade(); } return instance; } private LogicaFacade() { db = DatabaseFactory.getDatabaseFacade(); } public byte[] getUsuarioImagem(String matricula, String usuarioTipo) { byte[] imagemCache = fotosUsuarios.get(matricula);
114
byte[] imagemDB = null; if (imagemCache == null) { imagemDB = db.getUsuarioImagem(matricula, usuarioTipo); fotosUsuarios.put(new Integer(matricula), imagemDB); return imagemDB; } else { return imagemCache; } } public void logout() { SessionContextContainer.invalidarSessao(); } public void mudarConfiguracoes(ConfiguracoesDTO config) { Usuario usuario = getUsuario(); try { File redimTemp = File.createTempFile("foto", usuario.getLogin()); if (config.getFoto() != null) { InputStream foto = new FileInputStream(config.getFoto()); FileOutputStream out = new FileOutputStream(redimTemp); int h0 = LeitorParametros.getInstance().getInt( "FOTO_NORMAL_HEIGHT"); int w0 = LeitorParametros.getInstance().getInt( "FOTO_NORMAL_WIDTH"); ImageUtils.redimensionarImagem(foto, out, w0, h0); out.flush(); out.close(); config.setFoto(redimTemp); } db.atualizarDadosUsuario(usuario.getLogin(), usuario.getTipo(), config);
115
setUsuario(db.getUsuario(usuario.getLogin(), usuario.getTipo())); if (config.getFoto() != null) { config.getFoto().delete(); redimTemp.delete(); } } catch (FileNotFoundException e) { // TODO } catch (IOException e) { // TODO } } public void enviarEmailParaUsuario(EscreverEmailDTO email) { try { HtmlEmail msg = new HtmlEmail(); msg.setHostName(LeitorParametros.getInstance().getString( "SMTP_SERVER")); msg.setCharset("iso‐8859‐1"); List<String> emails = email.getDestinatario().getEmails(); if (email.getRemetenteNome() != null && email.getRemetenteEmail() != null) msg .setFrom(email.getRemetenteEmail(), email .getRemetenteNome()); else msg.setFrom(getUsuario().getEmail(), getUsuario().getNome()); if (emails.size() > 1) { for (String i : emails) msg.addBcc(i); msg.addTo(LeitorParametros.getInstance().getString(
116
"FORUM_EMAIL")); } else { try { msg.addTo(emails.get(0)); } catch (Exception e) { } } if (getUsuario().getEmail() != null) msg.addReplyTo(getUsuario().getEmail()); msg.setSentDate(new Date()); msg.setSubject(email.getAssunto()); File modeloEmail = new File(Paths.getPagesPath("modeloEmail.html")); if (email.isHtml()) { Map<String, String> params = new HashMap<String, String>(); params.put("%%texto%%", email.getMensagem()); msg.setHtmlMsg(HtmlGeneratorUtils.anexarModelo(modeloEmail, params)); } msg.setTextMsg(email.getMensagem()); // Processando os Anexos for (File arquivo : email.getAnexos()) msg.attach(new FileDataSource(arquivo), arquivo.getName(), "", EmailAttachment.ATTACHMENT); msg.send(); // Apagando os arquivos anexos if (email.isApagarAnexos()) for (File arquivo : email.getAnexos()) arquivo.delete();
117
} catch (Exception e) { e.printStackTrace(); } } public void enviarRequisicaoCriarTopico(RequisicaoCriarTopicoDTO topico) { try { String smtpServer = LeitorParametros.getInstance().getString( "SMTP_SERVER"); Properties p = new Properties(); p.put("mail.host", smtpServer); Session session = Session.getInstance(p, null); MimeMessage msg = new MimeMessage(session); msg.setFrom(new InternetAddress(getUsuario().getEmail(), getUsuario().getNome())); String emails = topico.getSala().getEmailResponsavel(); InternetAddress[] enderecos; if (emails != null && emails.contains(";")) { String[] emailsArray = emails.split(";"); int nDestinatarios = emailsArray.length; enderecos = new InternetAddress[nDestinatarios]; for (int i = 0; i < nDestinatarios; i++) { enderecos[i] = new InternetAddress(emailsArray[i]); } } else { enderecos = new InternetAddress[1]; enderecos[0] = new InternetAddress(emails); } msg.setRecipients(Message.RecipientType.CC, enderecos);
118
msg.setSentDate(new Date()); msg.setSubject("Criação do Tópico \"" + topico.getTitulo() + "\" em " + topico.getSala().getNome(), "iso‐8859‐1"); msg.setText("O usuário deu o seguinte motivo: \n\n" + topico.getMotivo(), "iso‐8859‐1"); Transport.send(msg); } catch (Exception e) { e.printStackTrace(); } } public void validarParaExcluirMensagem(Mensagem mensagem) throws ExcecaoUsuarioNaoPodeExcluir { boolean resposta = db.usuarioPodeExcluirMensagem(mensagem.getTopico() .getSala().getId(), mensagem.getTopico().getId(), mensagem .getId(), getUsuario().getLogin(), getUsuario().getTipo()); if (!resposta) throw new ExcecaoUsuarioNaoPodeExcluir(getUsuario().getNome() + " não pode excluir em " + mensagem.getTopico().getSala().getNome()); } public void validarParaMandarEmailSala(SalaDiscussao sala) throws ExcecaoUsuarioNaoCadastrado { if (!usuarioFazParte(sala)) throw new ExcecaoUsuarioNaoCadastrado( getUsuario().getNome() + " não faz parte de " + sala.getNome() + ", portanto o mesmo não pode enviar mensagem para seus membros"); } public void validarParaEscreverTopico(SalaDiscussao sala) throws ExcecaoNegacaoPostagem { Usuario usuario = getUsuario();
119
AutorizacaoContainer autorizacao = usuario.getPermissoesCriarTopico() .get(sala.getId()); if (autorizacao == null) { if (!usuarioFazParte(sala)) { autorizacao = new AutorizacaoContainer(false, new ExcecaoUsuarioNaoCadastrado(usuario.getNome() + " não faz parte de " + sala.getNome() + ", portanto o mesmo não pode criar tópicos")); } else if (!sala.isPermissaoGerarTopico() && !db.usuarioPodeCriarTopico(sala.getId(), getUsuario() .getLogin(), getUsuario().getTipo())) { autorizacao = new AutorizacaoContainer(false, new ExcecaoSalaNaoPermiteCriarTopico( "Essa sala não permite a criação de tópicos")); } else { autorizacao = new AutorizacaoContainer(true, null); } usuario.getPermissoesCriarTopico().put(sala.getId(), autorizacao); setUsuario(usuario); } if (!autorizacao.isAutorizado()) throw autorizacao.getErro(); } public void validarParaEscreverMensagem(SalaDiscussao sala) throws ExcecaoNegacaoPostagem { Usuario usuario = getUsuario(); AutorizacaoContainer autorizacao = usuario .getPermissoesPostarMensagem().get(sala.getId()); if (autorizacao == null || !usuario.isAtivo()) {
120
if (!usuarioFazParte(sala)) { autorizacao = new AutorizacaoContainer( false, new ExcecaoUsuarioNaoCadastrado( usuario.getNome() + " não faz parte dessa sala, portanto o mesmo não pode escrever mensagens")); } else { autorizacao = new AutorizacaoContainer(true, null); } usuario.getPermissoesPostarMensagem() .put(sala.getId(), autorizacao); setUsuario(usuario); } if (!autorizacao.isAutorizado()) throw autorizacao.getErro(); } public void excluirMensagem(Mensagem mensagem) { String path = LeitorParametros.getInstance().getString( "USER_FILES_PATH") + File.separator + "salas" + File.separator + mensagem.getTopico().getSalaId() + File.separator + mensagem.getTopico().getId(); deleteDir(new File(path + File.separator + mensagem.getId())); File dirTopico = new File(path); if (dirTopico != null && dirTopico.list() == null) dirTopico.delete(); db.excluirMensagem(mensagem.getId(), getUsuario().getId()); } public List<SalaDiscussao> getSalasDiscussao(Usuario usuario) { return db.getSalasDiscussao(usuario.getLogin(), usuario.getTipo()); }
121
public List<SalaDiscussao> getSalasDiscussao() { return SessionContextContainer.getSalasUsuario().getSalas(); } public List<Topico> buscarTopicos(CriterioBuscaTopico criterio) { criterio.setUsuario(getUsuario()); return db.buscarTopicos(criterio); } public List<Usuario> buscarUsuarios(CriterioBuscaUsuario criterio) { return db.buscarUsuarios(criterio); } public List<SalaDiscussao> buscarSalasDiscussao(CriterioBuscaSala criterio) { criterio.setUsuario(getUsuario()); return db.buscarSalasDiscussao(criterio); } public SalaDiscussao getSalaDiscussao(Integer id) { SalaDiscussao sala = null; SalasUsuario salas = SessionContextContainer.getSalasUsuario(); Map<Integer, SalaDiscussao> mapaSalas = salas.getMapaSalas(); sala = mapaSalas.get(id); if (sala == null) { sala = db.getSalaDiscussao(id); mapaSalas.put(sala.getId(), sala); salas.setMapaSalas(mapaSalas); SessionContextContainer.setSalasUsuario(salas); } return sala; }
122
public List<Usuario> getUsuarios(SalaDiscussao sala) { return db.getUsuarios(getUsuario().getId(), sala.getId()); } public Topico getTopico(Integer id) { return db.getTopico(id); } public List<Topico> getTopicos(SalaDiscussao sala) { return db.getTopicos(sala.getId()); } public Topico visitarTopico(Integer id) { Topico topico = db.getTopico(id); if (topico != null) { topico.setSala(getSalaDiscussao(topico.getSalaId())); topico.setVisitas(topico.getVisitas() + 1); db.atualizarTopico(topico); } return topico; } public Mensagem getMensagem(Integer id) { return db.getMensagem(id); } public MensagensPaginadas getMensagens(Topico topico, Integer paginaAtual, boolean ultimaPagina) { MensagensPaginadas retorno = new MensagensPaginadas(); Integer totalPaginas = db.getTotalPaginasMensagens(topico.getId()); if (ultimaPagina) paginaAtual = totalPaginas;
123
retorno.setLinksPagina(HtmlGeneratorUtils.getMensagemPaginaLinks(topico .getId(), paginaAtual, totalPaginas)); retorno.setTotalDePaginas(totalPaginas); // Verifica se as mensagens possuem anexos List<Mensagem> mensagens = db.getMensagens(topico.getId(), paginaAtual); Iterator<Mensagem> itMensagem = mensagens.iterator(); while (itMensagem.hasNext()) { Mensagem proximo = itMensagem.next(); proximo.setTexto(proximo.getTexto() + HtmlGeneratorUtils .getMensagemArquivosAnexos(listMessageFiles((topico .getSalaId()), topico.getId(), proximo .getId()))); } retorno.setMensagensPagina(mensagens); return retorno; } public void mudarStatusMonitoracaoTopico(Topico topico, boolean ativo) { Usuario usuario = getUsuario(); if (ativo) { db.alterarStatusMonitoracaoTopico(topico.getId(), getUsuario() .getId(), getUsuario().getTipo(), 1); usuario.getTopicosMonitorados().put(topico.getId(), topico); } else { db.alterarStatusMonitoracaoTopico(topico.getId(), usuario.getId(), usuario.getTipo(), 0); usuario.getTopicosMonitorados().remove(topico.getId()); } setUsuario(usuario);
124
} public Integer escreverMensagem(EscreverMensagemDTO msg) throws ExcecaoNegacaoPostagem { Integer mensagemId; Usuario usuario = getUsuario(); Topico topico = db.getTopico(msg.getTopicoId()); SalaDiscussao sala = topico.getSala(); validarParaEscreverMensagem(sala); Mensagem mensagemTopico = new Mensagem(); mensagemTopico.setTitulo(msg.getTitulo()); mensagemTopico.setDataPostagem(new Date()); mensagemTopico.setTexto(msg.getTexto()); mensagemTopico.setAutor(usuario); mensagemTopico.setTopico(topico); mensagemTopico.setNumeroIp(msg.getNumeroIp()); mensagemTopico.setDataPostagem(new Date()); mensagemId = db.inserirMensagem(mensagemTopico); String path = LeitorParametros.getInstance().getString( "USER_FILES_PATH") + File.separator + "salas" + File.separator + topico.getSalaId() + File.separator + topico.getId() + File.separator + mensagemId; UploadUtils.processar(msg.getRequest(), path); String mensagemTexto = mensagemTopico.getTextoHtml() + HtmlGeneratorUtils .getMensagemArquivosAnexos(listMessageFiles((topico .getSalaId()), topico.getId(), mensagemId));
125
if (msg.isMandarEmailMembros()) { EscreverEmailDTO email = new EscreverEmailDTO(); email.setRemetenteNome(getUsuario().getNome() + " (Fórum da Graduação UFSC)"); email.setRemetenteEmail(LeitorParametros.getInstance().getString( "FORUM_EMAIL")); email.setHtml(true); email.setAssunto("Tópico respondido em " + "\"" + topico.getTitulo() + "\" na sala " + sala.getNome()); email.setMensagem(HtmlGeneratorUtils.getEmailCriacaoTopico(topico, usuario, mensagemTexto)); Iterator<Usuario> itUsuarios = getUsuarios(sala).iterator(); email.setDestinatario(new DestinatarioEmail()); while (itUsuarios.hasNext()) { Usuario proximo = itUsuarios.next(); if (!proximo.isBloquearEmailSala() && proximo.getEmail() != null && !proximo.getEmail().equalsIgnoreCase("") && EmailValidator.checar(proximo.getEmail())) email.getDestinatario().getEmails().add(proximo.getEmail()); } enviarEmailParaUsuario(email); } // Monitoramento List<String> emails = db.getEmailsMonitorandosTopico(topico.getId()); if (!emails.isEmpty()) { EscreverEmailDTO emailDTO = new EscreverEmailDTO();
126
DestinatarioEmail destino = new DestinatarioEmail(); destino.setEmails(emails); emailDTO.setRemetenteNome("Fórum da Graduação UFSC"); emailDTO.setRemetenteEmail(LeitorParametros.getInstance() .getString("FORUM_EMAIL")); emailDTO.setAssunto("Tópico \"" + topico.getTitulo() + "\" respondido na sala " + sala.getNome()); emailDTO.setDestinatario(destino); emailDTO .setMensagem(HtmlGeneratorUtils .getEmailMonitoramentoTopico(topico, usuario, mensagemTexto)); emailDTO.setHtml(true); enviarEmailParaUsuario(emailDTO); } return mensagemId; } public Integer escreverTopico(EscreverTopicoDTO topic) throws ExcecaoNegacaoPostagem { Usuario usuario = getUsuario(); SalaDiscussao sala = db.getSalaDiscussao(topic.getSalaId()); validarParaEscreverTopico(sala); Topico topico = new Topico(); topico.setTitulo(topic.getTitulo()); topico.setSala(sala); topico.setVisitas(0); topico.setAutor(usuario); topico.setNumeroIp(topic.getNumeroIp()); topico.setDataPostagem(new Date()); Mensagem mensagemTopico = new Mensagem();
127
mensagemTopico.setTitulo(topico.getTitulo()); mensagemTopico.setDataPostagem(new Date()); mensagemTopico.setTexto(topic.getTexto()); mensagemTopico.setAutor(topico.getAutor()); mensagemTopico.setTopico(topico); mensagemTopico.setNumeroIp(topic.getNumeroIp()); Integer topicoId = db.inserirTopico(topico); topico.setId(topicoId); Integer mensagemId = db.inserirMensagem(mensagemTopico); List<File> arquivos = null; String path = LeitorParametros.getInstance().getString( "USER_FILES_PATH") + File.separator + "salas" + File.separator + topic.getSalaId() + File.separator + topicoId + File.separator + mensagemId; if (topic.getRequest() != null) arquivos = UploadUtils.processar(topic.getRequest(), path); if (topic.getArquivosAnexos() != null) { for (File arq : topic.getArquivosAnexos()) { copyFile(arq, new File(path + File.separator + arq.getName())); arq.delete(); } } if (topic.getEmailDTO() != null) topic.getEmailDTO().setAnexos(arquivos); if (topic.isMandarEmailMembros()) { EscreverEmailDTO email = new EscreverEmailDTO(); email.setRemetenteNome("Fórum da Graduação UFSC"); email.setRemetenteEmail(LeitorParametros.getInstance().getString( "FORUM_EMAIL"));
128
email.setHtml(true); email.setAssunto("Tópico " + "\"" + topico.getTitulo() + "\" criado em " + sala.getNome()); String mensagemTexto = mensagemTopico.getTextoHtml() + HtmlGeneratorUtils .getMensagemArquivosAnexos(listMessageFiles((topico .getSalaId()), topico.getId(), mensagemId)); email.setMensagem(HtmlGeneratorUtils.getEmailCriacaoTopico(topico, usuario, mensagemTexto)); Iterator<Usuario> itUsuarios = getUsuarios(sala).iterator(); email.setDestinatario(new DestinatarioEmail()); while (itUsuarios.hasNext()) { Usuario proximo = itUsuarios.next(); if (!proximo.isBloquearEmailSala() && proximo.getEmail() != null && !proximo.getEmail().equalsIgnoreCase("") && EmailValidator.checar(proximo.getEmail())) email.getDestinatario().getEmails().add(proximo.getEmail()); } enviarEmailParaUsuario(email); } return topicoId; } public boolean usuarioFazParte(SalaDiscussao sala) { boolean parte = SessionContextContainer.getSalasUsuario().contem( sala.getId());
129
return parte; } public Usuario carregarUsuario(String login, String usuarioTipo) { Usuario usuario = db.getUsuario(login, usuarioTipo); return usuario; } public void setUsuario(Usuario usuario) { SessionContextContainer.setUsuario(usuario); } public Usuario getUsuario() { Usuario usuario = SessionContextContainer.getUsuario(); return usuario; } public Usuario getUsuario(String login, String tipo) { return db.getUsuario(login, tipo); } private List<Arquivo> listMessageFiles(Integer salaId, Integer topicoId, Integer mensagemId) { String path = LeitorParametros.getInstance().getString( "USER_FILES_PATH") + File.separator + "salas" + File.separator + salaId + File.separator + topicoId + File.separator + mensagemId; List<Arquivo> arquivos = new ArrayList<Arquivo>(); File[] arqs = new File(path).listFiles(); if (arqs != null) { for (int i = 0; i < arqs.length; i++) {
130
Arquivo arq = new Arquivo(); arq.setNome(arqs[i].getName()); arq.setTamanho(arqs[i].length()); arq.setLink(RedirectFacade.getInstance().getArquivoLink(salaId, topicoId, mensagemId, arq.getNome())); arquivos.add(arq); } } return arquivos; } private boolean deleteDir(File dir) { if (dir.isDirectory()) { String[] children = dir.list(); for (int i = 0; i < children.length; i++) { boolean success = deleteDir(new File(dir, children[i])); if (!success) { return false; } } } // The directory is now empty so delete it return dir.delete(); } public void copyFile(File in, File out) { FileInputStream fis; try { fis = new FileInputStream(in); FileOutputStream fos = new FileOutputStream(out); byte[] buf = new byte[1024]; int i = 0; while ((i = fis.read(buf)) != ‐1) { fos.write(buf, 0, i); } fis.close(); fos.close(); } catch (FileNotFoundException e) {
131
// TODO Auto‐generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto‐generated catch block e.printStackTrace(); } } }
132
DatabaseFacadeSybase.java package br.ufsc.cagr.listaDiscussao.persistencia.sybase; import br.ufsc.cagr.CursoGraduacao; import br.ufsc.cagr.Departamento; import br.ufsc.cagr.listaDiscussao.modelo.CriterioBuscaSala; import br.ufsc.cagr.listaDiscussao.modelo.CriterioBuscaTopico; import br.ufsc.cagr.listaDiscussao.modelo.CriterioBuscaUsuario; import br.ufsc.cagr.listaDiscussao.modelo.Mensagem; import br.ufsc.cagr.listaDiscussao.modelo.SalaDiscussao; import br.ufsc.cagr.listaDiscussao.modelo.Topico; import br.ufsc.cagr.listaDiscussao.modelo.Usuario; import br.ufsc.cagr.listaDiscussao.modelo.dto.ConfiguracoesDTO; import br.ufsc.cagr.listaDiscussao.persistencia.DBUtils; import br.ufsc.cagr.listaDiscussao.persistencia.IDatabaseFacade; import java.sql.Connection; import java.util.List; public class DatabaseFacadeSybase implements IDatabaseFacade { private static IDatabaseFacade instance; public static IDatabaseFacade getInstance() { if (instance == null) { instance = new DatabaseFacadeSybase(); } return instance; } private DatabaseFacadeSybase() { } public boolean salaPossuiUsuario(Integer salaId, Integer usuarioId, String usuarioTipo) { Connection con = DBUtils.openConnection(); boolean retorno = SalaDiscussaoDAO.getInstance().salaPossuiUsuario(con, salaId, usuarioId, usuarioTipo);DBUtils.closeConnection(con, null, null); return retorno;
133
} public Usuario getUsuario(String usuarioLogin, String tipo) { Connection con = DBUtils.openConnection(); Usuario retorno = UsuarioDAO.getInstance().getUsuario(con, usuarioLogin, tipo); DBUtils.closeConnection(con, null, null); return retorno; } public List<Usuario> getUsuarios(Integer usuarioId, Integer salaId) { Connection con = DBUtils.openConnection(); List<Usuario> retorno = UsuarioDAO.getInstance().getUsuarios(con, usuarioId, salaId); DBUtils.closeConnection(con, null, null); return retorno; } public Integer inserirMensagem(Mensagem mensagem) { Connection con = DBUtils.openConnection(); Integer retorno = MensagemDAO.getInstance().inserirMensagem(con, mensagem);DBUtils.closeConnection(con, null, null); return retorno; } public Mensagem getMensagem(Integer mensagemId) { Connection con = DBUtils.openConnection(); Mensagem retorno = MensagemDAO.getInstance().getMensagem(con, mensagemId);DBUtils.closeConnection(con, null, null); return retorno; } public List<Mensagem> getMensagens(Integer topicoId, Integer paginaAtual) { Connection con = DBUtils.openConnection(); List<Mensagem> retorno = MensagemDAO.getInstance().getMensagens(con, topicoId, paginaAtual); DBUtils.closeConnection(con, null, null); return retorno; } public SalaDiscussao getSalaDiscussao(Integer salaId) { Connection con = DBUtils.openConnection(); SalaDiscussao retorno = SalaDiscussaoDAO.getInstance().getSalaDiscussao(con, salaId); DBUtils.closeConnection(con, null, null);
134
return retorno; } public List<SalaDiscussao> getSalasDiscussao(String usuarioLogin, String usuarioTipo) { Connection con = DBUtils.openConnection(); List<SalaDiscussao> retorno = SalaDiscussaoDAO.getInstance().getSalasDiscussao(con, usuarioLogin, usuarioTipo);DBUtils.closeConnection(con, null, null); return retorno; } public List<SalaDiscussao> buscarSalasDiscussao(CriterioBuscaSala criterio) { Connection con = DBUtils.openConnection(); List<SalaDiscussao> retorno = SalaDiscussaoDAO.getInstance().buscarSalasDiscussao(con, criterio); DBUtils.closeConnection(con, null, null); return retorno; } public List<Usuario> buscarUsuarios(CriterioBuscaUsuario criterio) { Connection con = DBUtils.openConnection(); List<Usuario> retorno = UsuarioDAO.getInstance().buscarUsuarios(con, criterio); DBUtils.closeConnection(con, null, null); return retorno; } public Topico getTopico(Integer topicoId) { Connection con = DBUtils.openConnection(); Topico retorno = TopicoDAO.getInstance().getTopico(con, topicoId); DBUtils.closeConnection(con, null, null); return retorno; } public List<Topico> getTopicos(Integer salaId) { Connection con = DBUtils.openConnection(); List<Topico> retorno = TopicoDAO.getInstance().getTopicos(con, salaId); DBUtils.closeConnection(con, null, null); return retorno; } public Integer inserirTopico(Topico topico) { Connection con = DBUtils.openConnection(); Integer retorno = TopicoDAO.getInstance().inserirTopico(con, topico);
135
DBUtils.closeConnection(con, null, null); return retorno; } public void atualizarTopico(Topico topico) { Connection con = DBUtils.openConnection(); TopicoDAO.getInstance().atualizarTopico(con, topico); DBUtils.closeConnection(con, null, null); } public void excluirMensagem(Integer mensagemId, Integer usuarioExclusorId) { Connection con = DBUtils.openConnection(); MensagemDAO.getInstance().excluirMensagem(con, mensagemId, usuarioExclusorId);DBUtils.closeConnection(con, null, null); } public Integer getTotalPaginasMensagens(Integer topicoId) { Connection con = DBUtils.openConnection(); Integer retorno = MensagemDAO.getInstance().getTotalPaginas(con, topicoId);DBUtils.closeConnection(con, null, null); return retorno; } public List<Topico> buscarTopicos(CriterioBuscaTopico criterio) { Connection con = DBUtils.openConnection(); List<Topico> retorno = TopicoDAO.getInstance().buscarTopicos(con, criterio);DBUtils.closeConnection(con, null, null); return retorno; } public boolean usuarioPodeExcluirMensagem(Integer salaId, Integer topicoId, Integer mensagemId, String usuarioLogin, String usuarioTipo) { Connection con = DBUtils.openConnection(); boolean retorno = MensagemDAO.getInstance().permissaoExcluirMensagem(con, salaId, topicoId, mensagemId, usuarioLogin, usuarioTipo);DBUtils.closeConnection(con, null, null);
136
return retorno; } public boolean usuarioPodeCriarTopico(Integer salaId, String usuarioLogin, String usuarioTipo) { Connection con = DBUtils.openConnection(); boolean retorno = TopicoDAO.getInstance().permissaoCriarTopico(con, salaId, usuarioLogin, usuarioTipo);DBUtils.closeConnection(con, null, null); return retorno; } public void atualizarDadosUsuario(String usuarioLogin, String usuarioTipo, ConfiguracoesDTO config) { Connection con = DBUtils.openConnection(); UsuarioDAO.getInstance().atualizarDados(con, usuarioLogin, usuarioTipo, config); DBUtils.closeConnection(con, null, null); } public List<String> getEmailsMonitorandosTopico(Integer topicoId) { Connection con = DBUtils.openConnection(); List<String> retorno = TopicoDAO.getInstance().obterEmailsMonitorandos(con, topicoId); DBUtils.closeConnection(con, null, null); return retorno; } public void alterarStatusMonitoracaoTopico(Integer topicoId, Integer usuarioId, String usuarioTipo, Integer status) { Connection con = DBUtils.openConnection(); TopicoDAO.getInstance().alterarStatusMonitoracao(con, topicoId, usuarioId, usuarioTipo, status); DBUtils.closeConnection(con, null, null); } public byte[] getUsuarioImagem(String matricula, String usuarioTipo) {
137
Connection con = DBUtils.openConnection(); byte[] retorno = UsuarioDAO.getInstance().getImagem(con, matricula, usuarioTipo);DBUtils.closeConnection(con, null, null); return retorno; } public List<CursoGraduacao> getCAGRCursos() { Connection con = DBUtils.openConnection(); List<CursoGraduacao> retorno = CagrDAO.getInstance().getCursos(con); DBUtils.closeConnection(con, null, null); return retorno; } public List<Departamento> getCAGRDepartamentos() { Connection con = DBUtils.openConnection(); List<Departamento> retorno = CagrDAO.getInstance().getDepartamentos(con); DBUtils.closeConnection(con, null, null); return retorno; } }
138
CagrDAO.java package br.ufsc.cagr.listaDiscussao.persistencia.sybase; import br.ufsc.cagr.CursoGraduacao; import br.ufsc.cagr.Departamento; import br.ufsc.cagr.listaDiscussao.persistencia.DBUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class CagrDAO { private static CagrDAO instance; protected static CagrDAO getInstance() { if (instance == null) { instance = new CagrDAO(); } return instance; } private CagrDAO() { } public List<CursoGraduacao> getCursos(Connection con) { List<CursoGraduacao> retorno = new ArrayList<CursoGraduacao>(); PreparedStatement stmt = null; ResultSet rs = null; try { stmt = con.prepareStatement("select cd_curso_cur,nm_curso_cur from cagr..vi_cursograduacao_cur where cd_situacao_stc not in (2,3) order by 2"); rs = stmt.executeQuery();
139
while (rs.next()) { CursoGraduacao curso = new CursoGraduacao(); curso.setCodigoCurso(rs.getString("cd_curso_cur")); curso.setNomeCurso(rs.getString("nm_curso_cur")); retorno.add(curso); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, null, null); } return retorno; } public List<Departamento> getDepartamentos(Connection con) { List<Departamento> retorno = new ArrayList<Departamento>(); PreparedStatement stmt = null; ResultSet rs = null; try { stmt = con.prepareStatement("select cd_departamento_dpt,nm_departamento_dpt from cagr..vi_departamento_dpt where cd_situacao_scd not in (2,3) order by 2"); rs = stmt.executeQuery(); while (rs.next()) { Departamento departamento = new Departamento(); departamento.setCodigoDepartamento(rs.getString("cd_departamento_dpt")); departamento.setNomeDepartamento(rs.getString("nm_departamento_dpt")); retorno.add(departamento); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, null, null); } return retorno;
140
} } MensagemDAO.java package br.ufsc.cagr.listaDiscussao.persistencia.sybase; import br.ufsc.cagr.listaDiscussao.modelo.Mensagem; import br.ufsc.cagr.listaDiscussao.modelo.TiposUsuario; import br.ufsc.cagr.listaDiscussao.modelo.Usuario; import br.ufsc.cagr.listaDiscussao.persistencia.DBUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class MensagemDAO { private static MensagemDAO instance; protected static MensagemDAO getInstance() { if (instance == null) { instance = new MensagemDAO(); } return instance; } private MensagemDAO() { } public boolean permissaoExcluirMensagem(Connection con, Integer salaId, Integer topicoId, Integer mensagemId, String usuarioLogin, String usuarioTipo) { boolean retorno = false;
141
PreparedStatement stmt = null; ResultSet rs = null; try { if (usuarioTipo.equalsIgnoreCase(TiposUsuario.ALUNO) || usuarioTipo.equalsIgnoreCase(TiposUsuario.FORMANDO)) { stmt = con.prepareStatement("exec sp_cafor007 'aluno',?,?,?,?"); stmt.setInt(1, new Integer(usuarioLogin)); stmt.setInt(2, salaId); stmt.setInt(3, topicoId); stmt.setInt(4, mensagemId); } else if (usuarioTipo.equalsIgnoreCase(TiposUsuario.PROFESSOR)) { stmt = con.prepareStatement("exec sp_cafor007 'cagrprf1',?,?,?,?"); stmt.setInt(1, new Integer(usuarioLogin)); stmt.setInt(2, salaId); stmt.setInt(3, topicoId); stmt.setInt(4, mensagemId); } else if (usuarioTipo.equalsIgnoreCase(TiposUsuario.CURSO) || usuarioTipo.equalsIgnoreCase(TiposUsuario.DEPARTAMENTO)) { stmt = con.prepareStatement("exec sp_cafor007 'cagrcur1',null,?,?,?,?"); stmt.setInt(1, salaId); stmt.setInt(2, topicoId); stmt.setInt(3, mensagemId); stmt.setString(4, usuarioLogin); } rs = stmt.executeQuery(); rs.next(); if (rs.getString("validaUsuario").equals("sim")) retorno = true; } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs);
142
} return retorno; } public Integer getTotalPaginas(Connection con, Integer topicoId) { Integer retorno = 0; PreparedStatement stmt = null; ResultSet rs = null; try { stmt = con.prepareStatement("exec sp_cafor004 10,?"); stmt.setInt(1, topicoId); rs = stmt.executeQuery(); rs.next(); retorno = rs.getInt("paginas"); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); } return retorno; } public Mensagem getMensagem(Connection con, Integer mensagemId) { Mensagem mensagem = null; PreparedStatement stmt = null; ResultSet rs = null; try { stmt = con.prepareStatement("SELECT * FROM mensagemForum_msf WHERE nu_mensagemForum_msf = ?"); stmt.setInt(1, mensagemId); rs = stmt.executeQuery(); rs.next();
143
mensagem = new Mensagem(); mensagem.setId(rs.getInt("nu_mensagemForum_msf")); mensagem.setTitulo(rs.getString("dc_tituloMensagem_msf")); mensagem.setTexto(rs.getString("dc_mensagemForum_msf")); mensagem.setDataPostagem(rs.getTimestamp("dt_postagem_msf")); mensagem.setNumeroIp(rs.getString("nu_ipMicro_msf")); // mapearParaModelo(con, rs); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); } return mensagem; } public List<Mensagem> getMensagens(Connection con, Integer topicoId, Integer paginaAtual) { List<Mensagem> retorno = new ArrayList<Mensagem>(); PreparedStatement stmt = null; ResultSet rs = null; try { stmt = con.prepareStatement("exec sp_cafor004 11,?,?"); stmt.setInt(1, topicoId); stmt.setInt(2, paginaAtual); rs = stmt.executeQuery(); while (rs.next()) { retorno.add(mapearParaModelo(con, rs)); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); } return retorno; }
144
public void excluirMensagem(Connection con, Integer mensagemId, Integer usuarioExclusorId) { PreparedStatement stmt = null; try { stmt = con.prepareStatement("UPDATE mensagemForum_msf SET cd_situacao_msf = 0, nu_usuarioExc_msf = ? WHERE nu_mensagemForum_msf = ?"); stmt.setInt(1, usuarioExclusorId); stmt.setInt(2, mensagemId); stmt.executeQuery(); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, null); } } public Integer inserirMensagem(Connection con, Mensagem mensagem) { int retorno = 0; PreparedStatement stmt = null; ResultSet rs = null; try { stmt = con.prepareStatement("INSERT INTO mensagemForum_msf (nu_TopicoForum_tof, nu_salaDiscussao_msf, " + "dc_tituloMensagem_msf, dc_mensagemForum_msf, " + "cd_tipoUsuario_msf, nu_usuarioForum_msf, dt_postagem_msf, nu_ipMicro_msf,cd_situacao_msf) " + "VALUES (?,?,?,?,?,?,?,?,1) \n SELECT @@IDENTITY"); stmt.setInt(1, mensagem.getTopico().getId()); stmt.setInt(2, mensagem.getTopico().getSala().getId()); stmt.setString(3, mensagem.getTitulo()); stmt.setString(4, mensagem.getTexto()); stmt.setString(5, mensagem.getAutor().getTipo()); stmt.setInt(6, mensagem.getAutor().getId()); stmt.setString(7, DBUtils.convertToDateTime(mensagem.getDataPostagem()));
145
stmt.setString(8, mensagem.getNumeroIp()); rs = stmt.executeQuery(); rs.next(); retorno = rs.getInt(1); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); } return retorno; } private Mensagem mapearParaModelo(Connection con, ResultSet rs) { Mensagem mensagem = new Mensagem(); try { mensagem.setId(rs.getInt("nu_mensagemForum_msf")); mensagem.setTitulo(rs.getString("dc_tituloMensagem_msf")); mensagem.setTexto(rs.getString("mensagem")); mensagem.setDataPostagem(rs.getTimestamp("dataPostagem")); mensagem.setNumeroIp(rs.getString("ipMicro")); Usuario autor = new Usuario(); autor.setId(rs.getInt("usuario")); autor.setTotalDeMensagens(rs.getInt("qtdMensagem")); autor.setNome(rs.getString("autor")); autor.setNomeAbreviado(rs.getString("autor")); autor.setAlocacao(rs.getString("curso")); autor.setTipo(rs.getString("tipoUsuario")); mensagem.setAutor(autor); //// mensagem //// .setAutor(UsuarioDAO.getInstance().getUsuario(con, rs.getInt("nu_usuarioForum_msf"),
146
//// rs // .getString("cd_tipoUsuario_msf"))); // TODO: // mensagem // .setTopico(TopicoDAO.getInstance().getTopico(con, rs.getInt("nu_topicoForum_tof"))); } catch (SQLException e) { e.printStackTrace(); } return mensagem; } }
147
SalaDiscussaoDAO.java package br.ufsc.cagr.listaDiscussao.persistencia.sybase; import br.ufsc.cagr.listaDiscussao.modelo.CriterioBuscaSala; import br.ufsc.cagr.listaDiscussao.modelo.SalaDiscussao; import br.ufsc.cagr.listaDiscussao.modelo.TiposUsuario; import br.ufsc.cagr.listaDiscussao.persistencia.DBUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class SalaDiscussaoDAO { private static SalaDiscussaoDAO instance; protected static SalaDiscussaoDAO getInstance() { if (instance == null) { instance = new SalaDiscussaoDAO(); } return instance; } private SalaDiscussaoDAO() { } public boolean salaPossuiUsuario(Connection con, Integer salaId, Integer usuarioId, String usuarioTipo) { boolean retorno = false; PreparedStatement stmt = null; ResultSet rs = null; try { if (usuarioTipo.equalsIgnoreCase(TiposUsuario.ALUNO) || usuarioTipo.equalsIgnoreCase(TiposUsuario.FORMANDO))
148
// TODO: exec sp_cafor003 8,'cagrgr01',04132440,null,200223447,null,null stmt = con.prepareStatement("exec sp_cafor001 8,'aluno',?,null,?"); else if (usuarioTipo.equalsIgnoreCase(TiposUsuario.PROFESSOR)) stmt = con.prepareStatement("exec sp_cafor003 8,'cagrprf1',?,null,?,null,null "); else if (usuarioTipo.equalsIgnoreCase(TiposUsuario.CURSO) || usuarioTipo.equalsIgnoreCase(TiposUsuario.DEPARTAMENTO)) stmt = con.prepareStatement("exec sp_cafor003 8,'cagrcur1',?,null,?,null,null "); stmt.setInt(1, usuarioId); stmt.setInt(2, salaId); rs = stmt.executeQuery(); rs.next(); if (rs.getString("validaUsuario").equals("sim")) retorno = true; } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); } return retorno; } public List<SalaDiscussao> buscarSalasDiscussao(Connection con, CriterioBuscaSala criterio) { List<SalaDiscussao> retorno = new ArrayList<SalaDiscussao>(); PreparedStatement stmt = null; ResultSet rs = null; String salaNome = null; String salaCodigo = null; String salaTurma = null; String salaSemestre = null; if (criterio.getSalaNome() != null && !criterio.getSalaNome().equalsIgnoreCase(""))
149
salaNome = criterio.getSalaNome(); if (criterio.getSalaCodigo() != null && !criterio.getSalaCodigo().equalsIgnoreCase("")) salaCodigo = criterio.getSalaCodigo(); if (criterio.getSalaTurma() != null && !criterio.getSalaTurma().equalsIgnoreCase("")) salaTurma = criterio.getSalaTurma(); if (criterio.getSalaSemestre() != null) salaSemestre = criterio.getSalaSemestre().toString(); try { if (criterio.getSalaTipo().equalsIgnoreCase("disciplinas")) { stmt = con.prepareStatement("exec sp_cafor006 22,null,null,null,null,null,?,?,?,?,null"); stmt.setString(1, salaNome); stmt.setString(2, salaCodigo); stmt.setString(3, salaTurma); stmt.setString(4, salaSemestre); } else if (criterio.getSalaTipo().equalsIgnoreCase("graduandos")) { stmt = con.prepareStatement("exec sp_cafor006 22,null,null,null,null,null,'graduandos',null,null,null,null"); } else if (criterio.getSalaTipo().equalsIgnoreCase("formandos")) { stmt = con.prepareStatement("exec sp_cafor006 22,null,null,null,null,null,'formandos',null,null,null,null"); } else if (criterio.getSalaTipo().equalsIgnoreCase("curso") && criterio.getUsuario().getTipo().equalsIgnoreCase(TiposUsuario.CURSO)) { stmt = con.prepareStatement("exec sp_cafor006 22,null,null,null,null,null,'coordenadoria',null,null,null,?"); stmt.setString(1, criterio.getUsuario().getLogin()); } else if (criterio.getSalaTipo().equalsIgnoreCase("curso") && !criterio.getUsuario().getTipo().equalsIgnoreCase(TiposUsuario.CURSO)) {
150
stmt = con.prepareStatement("exec sp_cafor006 22,null,null,null,null,?,'curso'"); stmt.setInt(1, criterio.getUsuario().getId()); } rs = stmt.executeQuery(); while (rs.next()) { retorno.add(mapearParaModelo(con, rs)); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); } return retorno; } public SalaDiscussao getSalaDiscussao(Connection con, Integer salaId) { SalaDiscussao sala = null; PreparedStatement stmt = null; ResultSet rs = null; try { stmt = con.prepareStatement("exec sp_cafor001 5,null,null,null,?"); stmt.setInt(1, salaId); rs = stmt.executeQuery(); while (rs.next()) { sala = mapearParaModelo(con, rs); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); } return sala; } public List<SalaDiscussao> getSalasDiscussao(Connection con,
151
String usuarioLogin, String usuarioTipo) { List<SalaDiscussao> retorno = new ArrayList<SalaDiscussao>(); PreparedStatement stmt = null; ResultSet rs = null; try { if (usuarioTipo.equalsIgnoreCase(TiposUsuario.ALUNO) || usuarioTipo.equalsIgnoreCase(TiposUsuario.FORMANDO) || usuarioTipo.equalsIgnoreCase(TiposUsuario.MONITOR)) { stmt = con.prepareStatement("exec sp_cafor001 1,'aluno',?"); stmt.setInt(1, new Integer(usuarioLogin)); } else if (usuarioTipo.equalsIgnoreCase(TiposUsuario.PROFESSOR)) { stmt = con.prepareStatement("exec sp_cafor001 4,'professor',?"); stmt.setInt(1, new Integer(usuarioLogin)); } else if (usuarioTipo.equalsIgnoreCase(TiposUsuario.CURSO)) { stmt = con.prepareStatement("exec sp_cafor001 3,null,null,'coord', null, null,?"); stmt.setString(1, usuarioLogin); } else if (usuarioTipo.equalsIgnoreCase(TiposUsuario.DEPARTAMENTO)) { stmt = con.prepareStatement("exec sp_cafor001 3,null,null,'depto', null, null,?"); stmt.setString(1, usuarioLogin); } else if (usuarioTipo.equalsIgnoreCase(TiposUsuario.ESPECIAL) || usuarioTipo.equalsIgnoreCase(TiposUsuario.ESPECIAL1)) { stmt = con.prepareStatement("exec sp_cafor010 4,null,?,'especial'"); stmt.setInt(1, new Integer(usuarioLogin)); } rs = stmt.executeQuery();
152
while (rs.next()) { retorno.add(mapearParaModelo(con, rs)); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); } return retorno; } private SalaDiscussao mapearParaModelo(Connection con, ResultSet rs) { SalaDiscussao sala = new SalaDiscussao(); try { sala.setId(rs.getInt("salaDiscussao")); sala.setAtiva(true); sala.setDescricao(rs.getString("tituloSala")); sala.setDisciplina(rs.getString("disciplina")); sala.setTurma(rs.getString("turma")); sala.setSemestre(rs.getInt("semestre")); if (rs.getString("geraTopico").equalsIgnoreCase("S")) sala.setPermissaoGerarTopico(true); else sala.setPermissaoGerarTopico(false); sala.setNome(rs.getString("tituloSala")); sala.setVisitas(rs.getInt("visitas")); sala.setTotalTopicos(rs.getInt("topicos")); sala.setEmailResponsavel(rs.getString("email")); } catch (SQLException e) { e.printStackTrace(); } return sala; }
153
} TopicoDAO.java package br.ufsc.cagr.listaDiscussao.persistencia.sybase; import br.ufsc.cagr.listaDiscussao.modelo.CriterioBuscaTopico; import br.ufsc.cagr.listaDiscussao.modelo.Mensagem; import br.ufsc.cagr.listaDiscussao.modelo.SalaDiscussao; import br.ufsc.cagr.listaDiscussao.modelo.TiposUsuario; import br.ufsc.cagr.listaDiscussao.modelo.Topico; import br.ufsc.cagr.listaDiscussao.modelo.Usuario; import br.ufsc.cagr.listaDiscussao.persistencia.DBUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; public class TopicoDAO { private static TopicoDAO instance; private static final String QUERY_STRING_SELECT_ALL = "exec sp_cafor009 1,null,?,null"; private static final String QUERY_STRING_SELECT_ID = "exec sp_cafor009 1, null, null,?"; private static final String INSERT_QUERY = "INSERT INTO topicoForum_tof (nu_SalaDiscussao_tof, " + "dc_tituloTopico_tof, nu_visitaTopico_tof, " + "cd_tipoUsuario_tof, nu_usuarioForum_tof, dt_atualizacao_tof, nu_ipMicro_tof) " +
154
"VALUES (?,?,?,?,?,?,?)\n SELECT @@IDENTITY"; private static final String UPDATE_QUERY = "UPDATE topicoForum_tof SET nu_visitaTopico_tof = ? " + "WHERE nu_topicoForum_tof = ?"; protected static TopicoDAO getInstance() { if (instance == null) { instance = new TopicoDAO(); } return instance; } private TopicoDAO() { } public void alterarStatusMonitoracao(Connection con, Integer topicoId, Integer usuarioId, String usuarioTipo, Integer status) { PreparedStatement stmt = null; try { if (status == 1) stmt = con.prepareStatement("exec sp_cafor010 2,?,?,?"); else if (status == 0) { stmt = con.prepareStatement("exec sp_cafor010 3,?,?,?"); } stmt.setInt(1, topicoId); stmt.setInt(2, usuarioId); stmt.setString(3, usuarioTipo); stmt.execute(); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, null);
155
} } public List<String> obterEmailsMonitorandos(Connection con, Integer topicoId) { List<String> retorno = new ArrayList<String>(); PreparedStatement stmt = null; ResultSet rs = null; try { stmt = con.prepareStatement("exec sp_cafor010 1,?"); stmt.setInt(1, topicoId); rs = stmt.executeQuery(); while (rs.next()) { if (rs.getString("email") !=null) retorno.add(rs.getString("email")); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); } return retorno; } public boolean permissaoCriarTopico(Connection con, Integer salaId, String usuarioLogin, String usuarioTipo) { boolean retorno = false; PreparedStatement stmt = null; ResultSet rs = null; try { if (usuarioTipo.equalsIgnoreCase(TiposUsuario.ALUNO) || usuarioTipo.equalsIgnoreCase(TiposUsuario.FORMANDO)) { stmt =
156
con.prepareStatement("exec sp_cafor005 'aluno',?,?,null"); stmt.setInt(1, new Integer(usuarioLogin)); stmt.setInt(2, salaId); } else if (usuarioTipo.equalsIgnoreCase(TiposUsuario.PROFESSOR)) { stmt = con.prepareStatement("exec sp_cafor005 'cagrprf1',?,?,null "); stmt.setInt(1, new Integer(usuarioLogin)); stmt.setInt(2, salaId); } else if (usuarioTipo.equalsIgnoreCase(TiposUsuario.CURSO) || usuarioTipo.equalsIgnoreCase(TiposUsuario.DEPARTAMENTO)) { stmt = con.prepareStatement("exec sp_cafor005 'cagrcur1',null,?,?"); stmt.setInt(1, salaId); stmt.setString(2, usuarioLogin); } rs = stmt.executeQuery(); rs.next(); if (rs.getString("validaUsuario").equals("sim")) retorno = true; } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); } return retorno; } public List<Topico> buscarTopicos(Connection con, CriterioBuscaTopico criterio) { List<Topico> retorno = new ArrayList<Topico>(); PreparedStatement stmt = null; ResultSet rs = null;
157
try { stmt = con.prepareStatement("exec sp_cafor006 21,?,?,?,?,?,null,null,null, ?,null,?,?"); stmt.setString(1, criterio.getPalavraChave()); stmt.setInt(2, criterio.getProcurarEm()); stmt.setString(3, criterio.getOrdenarPor()); stmt.setString(4, criterio.getOrdernarPorOrdem()); stmt.setInt(5, criterio.getUsuario().getId()); Integer semestre = criterio.getSemeste(); if (semestre != null) stmt.setString(6, criterio.getSemeste().toString()); else stmt.setString(6, null); Integer matriculaUsuario = criterio.getMatriculaUsuario(); if (matriculaUsuario != null) stmt.setInt(7, matriculaUsuario); else stmt.setString(7, null); Date dataPostagem = criterio.getData(); if (dataPostagem != null) stmt .setString(8, new SimpleDateFormat("yyyy/mm/dd", Locale.US).format(dataPostagem)); else stmt.setString(8, null); rs = stmt.executeQuery(); while (rs.next()) { SalaDiscussao sala = new SalaDiscussao(); sala.setDisciplina(rs.getString("disciplina")); sala.setTurma(rs.getString("turma")); sala.setSemestre(rs.getInt("semestre"));
158
sala.setNome(rs.getString("tituloSala")); sala.setDescricao(rs.getString("tituloSala")); sala.setId(rs.getInt("salaDiscussao")); sala.setTotalTopicos(rs.getInt("topicos")); Topico topico = new Topico(); topico.setTitulo(rs.getString("tituloTopico")); topico.setVisitas(rs.getInt("visitas")); topico.setId(rs.getInt("topicoForum")); topico.setSala(sala); retorno.add(topico); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); } return retorno; } public Topico getTopico(Connection con, Integer topicoId) { Topico topico = null; PreparedStatement stmt = null; ResultSet rs = null; try { stmt = con.prepareStatement(QUERY_STRING_SELECT_ID); stmt.setInt(1, topicoId); rs = stmt.executeQuery(); while (rs.next()) { topico = mapearParaModelo(con, rs); } } catch (SQLException e) { e.printStackTrace(); } finally {
159
DBUtils.closeConnection(null, stmt, rs); } return topico; } public List<Topico> getTopicos(Connection con, Integer salaId) { List<Topico> retorno = new ArrayList<Topico>(); PreparedStatement stmt = null; ResultSet rs = null; try { stmt = con.prepareStatement(QUERY_STRING_SELECT_ALL); stmt.setInt(1, salaId); rs = stmt.executeQuery(); SalaDiscussao sala = SalaDiscussaoDAO.getInstance().getSalaDiscussao(con, salaId); while (rs.next()) { Topico topico = mapearParaModelo(con, rs); topico.setSala(sala); retorno.add(topico); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); } return retorno; } public Integer inserirTopico(Connection con, Topico topico) { int retorno = 0; PreparedStatement stmt = null; ResultSet rs = null; try { stmt = con.prepareStatement(INSERT_QUERY); stmt.setInt(1, topico.getSala().getId()); stmt.setString(2, topico.getTitulo()); stmt.setInt(3, topico.getVisitas()); stmt.setString(4, topico.getAutor().getTipo());
160
stmt.setInt(5, topico.getAutor().getId()); stmt .setString(6, DBUtils.convertToDateTime(topico.getDataPostagem())); stmt.setString(7, topico.getNumeroIp()); rs = stmt.executeQuery(); rs.next(); retorno = rs.getInt(1); } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); } return retorno; } public void atualizarTopico(Connection con, Topico topico) { PreparedStatement stmt = null; try { stmt = con.prepareStatement(UPDATE_QUERY); // stmt.setInt(1, topico.getSala().getId()); // stmt.setString(2, topico.getTitulo()); stmt.setInt(1, topico.getVisitas()); // stmt.setString(4, topico.getAutor().getTipo()); // stmt.setString(5, topico.getNumeroIp()); stmt.setInt(2, topico.getId()); // stmt.setInt(5, topico.getAutor().getId()); // stmt.setString(6, "Oct 14 2005 12:00AM"); stmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally {
161
DBUtils.closeConnection(null, stmt, null); } } private Topico mapearParaModelo(Connection con, ResultSet rs) { Topico topico = new Topico(); try { topico.setId(rs.getInt("topico")); Usuario autor = new Usuario(); autor.setId(rs.getInt("usuario")); autor.setTipo(rs.getString("tipoUsuario")); autor.setNomeAbreviado(rs.getString("nm_usuarioForumParteAutor")); autor.setNome(rs.getString("nm_usuarioForumParteAutor")); topico.setAutor(autor); Mensagem mensagem = new Mensagem(); mensagem.setDataPostagem(rs.getTimestamp("dataPostagem")); mensagem.setId(rs.getInt("ultimaMensagem")); Usuario autorMensagem = new Usuario(); autorMensagem.setNome(rs.getString("nm_usuarioForumParteMsg")); autorMensagem .setNomeAbreviado(rs.getString("nm_usuarioForumParteMsg")); autorMensagem .setNomeAbreviado(rs.getString("nm_usuarioForumParteMsg")); mensagem.setAutor(autorMensagem); topico.setUltimaMensagem(mensagem); // topico // .setUltimaMensagem(MensagemDAO.getInstance().getMensagem(con, rs // .getInt("ultimaMensagem")));
162
// topico // .setAutor(UsuarioDAO.getInstance().getUsuario(con, rs.getInt("usuario"), // rs // .getString("tipoUsuario"))); // // if (mapearSala) topico .setSala(SalaDiscussaoDAO.getInstance().getSalaDiscussao(con, rs .getInt("salaDiscussao"))); topico.setSalaId(rs.getInt("salaDiscussao")); topico.setTitulo(rs.getString("tituloTopico")); topico.setVisitas(rs.getInt("visitas")); topico.setNumeroIp(rs.getString("ipMicro")); int respostas = rs.getInt("mensagens"); if (respostas > 0) topico.setRespostas(respostas ‐ 1); else topico.setRespostas(respostas); } catch (SQLException e) { e.printStackTrace(); } return topico; } } UsuarioDAO.java package br.ufsc.cagr.listaDiscussao.persistencia.sybase; import br.ufsc.cagr.listaDiscussao.modelo.CriterioBuscaUsuario; import br.ufsc.cagr.listaDiscussao.modelo.TiposUsuario; import br.ufsc.cagr.listaDiscussao.modelo.Topico; import br.ufsc.cagr.listaDiscussao.modelo.Usuario;
163
import br.ufsc.cagr.listaDiscussao.modelo.dto.ConfiguracoesDTO; import br.ufsc.cagr.listaDiscussao.persistencia.DBUtils; import java.io.File; import java.io.FileInputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import java.util.Locale; import javax.activation.FileDataSource; public class UsuarioDAO { private static UsuarioDAO instance; protected static UsuarioDAO getInstance() { if (instance == null) { instance = new UsuarioDAO(); } return instance; } private UsuarioDAO() { } public List<Usuario> buscarUsuarios(Connection con, CriterioBuscaUsuario criterio) { List<Usuario> retorno = new ArrayList<Usuario>(); PreparedStatement stmt = null; ResultSet rs = null; try {
164
if (criterio.getUsuarioTipo().equalsIgnoreCase(TiposUsuario.ALUNO)) { stmt = con.prepareStatement("exec sp_cafor006 24,null,null,null,null,null,null,null,null,null,null,null, null,null,?,?"); if (criterio.getUsuarioCurso() != null) stmt.setInt(1, new Integer(criterio.getUsuarioCurso())); else stmt.setString(1, null); } else if (criterio.getUsuarioTipo().equalsIgnoreCase(TiposUsuario.MONITOR)) { stmt = con.prepareStatement("exec sp_cafor006 25,null,null,null,null,null,null,null,null,null,null,null, null,null,?,?"); if (criterio.getUsuarioCurso() != null) stmt.setInt(1, new Integer(criterio.getUsuarioCurso())); else stmt.setString(1, null); } else if (criterio.getUsuarioTipo().equalsIgnoreCase(TiposUsuario.PROFESSOR)) { stmt = con.prepareStatement("exec sp_cafor006 23,null,null,null,null,null,null,null,null,null,null,null, null,?,null,?"); stmt.setString(1, criterio.getUsuarioDepartamento()); } if (criterio.getUsuarioNome() != null) stmt.setString(2, "%" + criterio.getUsuarioNome().replaceAll(" ", "%") + "%"); else stmt.setString(2, null); rs = stmt.executeQuery(); while (rs.next()) { Usuario usuario = new Usuario(); usuario.setId(rs.getInt("nu_usuarioForum")); usuario.setLogin(rs.getString("nu_usuarioForum")); usuario.setNome(rs.getString("nm_usuarioForum"));
165
usuario.setAlocacao(rs.getString("alocacao")); usuario.setTipo(criterio.getUsuarioTipo()); retorno.add(usuario); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); } return retorno; } public void atualizarDados(Connection con, String usuarioLogin, String usuarioTipo, ConfiguracoesDTO config) { PreparedStatement stmt = null; try { if (usuarioTipo.equalsIgnoreCase(TiposUsuario.ALUNO) || usuarioTipo.equalsIgnoreCase(TiposUsuario.FORMANDO)) { stmt = con.prepareStatement("exec sp_cafor008 'aluno',?,?,?,?,?,?,?"); stmt.setInt(1, new Integer(usuarioLogin)); stmt.setString(2, config.getEmail()); stmt.setString(3, config.getWebsite()); stmt.setBoolean(4, config.isBloquearEmail()); stmt.setBoolean(5, config.isExibirFoto()); stmt.setBoolean(6, config.isBloquearEmailSala()); stmt.setString(7, config.getCurriculo()); stmt.executeUpdate(); setImagem(con, new Integer(usuarioLogin), usuarioTipo, config.getFoto(), config.getNumeroIp()); } else if (usuarioTipo.equalsIgnoreCase(TiposUsuario.PROFESSOR)) {
166
stmt = con.prepareStatement("exec sp_cafor008 'cagrprf1',?,?,?,?,?,?,?"); stmt.setInt(1, new Integer(usuarioLogin)); stmt.setString(2, config.getEmail()); stmt.setString(3, config.getWebsite()); stmt.setBoolean(4, config.isBloquearEmail()); stmt.setBoolean(5, config.isExibirFoto()); stmt.setBoolean(6, config.isBloquearEmailSala()); stmt.setString(7, config.getCurriculo()); stmt.executeUpdate(); setImagem(con, new Integer(usuarioLogin), usuarioTipo, config.getFoto(), config.getNumeroIp()); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, null); } } public Usuario getUsuario(Connection con, String usuarioLogin, String usuarioTipo) { Usuario usuario = null; PreparedStatement stmt = null; ResultSet rs = null; PreparedStatement stmt1 = null; ResultSet rs1 = null;
167
try { if (usuarioTipo.equalsIgnoreCase(TiposUsuario.ALUNO) || usuarioTipo.equalsIgnoreCase(TiposUsuario.FORMANDO) || usuarioTipo.equalsIgnoreCase(TiposUsuario.MONITOR)) { stmt = con.prepareStatement("exec sp_cafor002 6,'aluno',?"); stmt.setInt(1, new Integer(usuarioLogin)); stmt1 = con.prepareStatement("exec sp_cafor010 4,null,?,'aluno'"); stmt1.setInt(1, new Integer(usuarioLogin)); } else if (usuarioTipo.equalsIgnoreCase(TiposUsuario.ESPECIAL) || usuarioTipo.equalsIgnoreCase(TiposUsuario.ESPECIAL1)) { stmt = con.prepareStatement("exec sp_cafor002 6,'especial',?"); stmt.setInt(1, new Integer(usuarioLogin)); stmt1 = con.prepareStatement("exec sp_cafor010 4,null,?,'especial'"); stmt1.setInt(1, new Integer(usuarioLogin)); } else if (usuarioTipo.equalsIgnoreCase(TiposUsuario.PROFESSOR)) { stmt = con.prepareStatement("exec sp_cafor002 6,'professor',?"); stmt.setInt(1, new Integer(usuarioLogin)); stmt1 = con.prepareStatement("exec sp_cafor010 4,null,?,'professor'"); stmt1.setInt(1, new Integer(usuarioLogin)); } else if (usuarioTipo.equalsIgnoreCase(TiposUsuario.CURSO) || usuarioTipo.equalsIgnoreCase(TiposUsuario.DEPARTAMENTO)) { try { Integer matric = new Integer(usuarioLogin); stmt = con.prepareStatement("exec sp_cafor002 6,'cagrcur1',?"); stmt.setInt(1, matric); stmt1 = con.prepareStatement("exec sp_cafor010 4,null,?,'cagrcur1'"); stmt1.setString(1, usuarioLogin);
168
} catch (NumberFormatException e) { stmt = con.prepareStatement("exec sp_cafor002 6,'cagrcur1',null,null,null,null,?"); stmt.setString(1, usuarioLogin); stmt1 = con.prepareStatement("exec sp_cafor010 4,null,null,'cagrcur1',?"); stmt1.setString(1, usuarioLogin); } } rs = stmt.executeQuery(); if (rs.next()) { usuario = new Usuario(); usuario.setId(rs.getInt("nu_UsuarioForum")); // Patch para poder usar o SIAPE if (usuarioTipo.equals(TiposUsuario.PROFESSOR)) { usuario.setLogin(usuario.getId().toString()); } else usuario.setLogin(usuarioLogin); ////////////////////////////////////////////////////////////////////// usuario.setNome(rs.getString("nm_UsuarioForum")); usuario.setNomeAbreviado(rs.getString("nm_UsuarioForumParte")); usuario.setAlocacao(rs.getString("alocacao")); usuario.setEmail(rs.getString("email")); usuario.setTipo((usuarioTipo)); usuario.setWebsite(rs.getString("website")); usuario.setCurriculo(rs.getString("curriculo")); try { usuario.setInfo1(rs.getString("var1")); usuario.setInfo2(rs.getString("var2")); usuario.setInfo3(rs.getString("var3")); usuario.setInfo4(rs.getString("var4")); usuario.setInfo5(rs.getString("var5"));
169
usuario.setInfo6(rs.getString("var6")); } catch (Exception e) { e.printStackTrace(); } usuario.setBloquearEmail(rs.getBoolean("bloqEmail")); usuario.setBloquearEmailSala(rs.getBoolean("monitorarEmail")); usuario.setAtivo(rs.getString("ativo").equalsIgnoreCase("s")); usuario.setTotalDeMensagens(rs.getInt("mensagens")); usuario.setExibirFoto(rs.getBoolean("bloqFoto")); usuario.setPodeMudarFoto(rs.getBoolean("mudaFoto")); rs1 = stmt1.executeQuery(); while (rs1.next()) { Topico topico = TopicoDAO.getInstance().getTopico(con, rs1.getInt("topico")); if (topico != null) { topico.setSala(SalaDiscussaoDAO.getInstance().getSalaDiscussao(con, topico.getSalaId())); usuario.getTopicosMonitorados().put(topico.getId(), topico); } } } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); DBUtils.closeConnection(null, stmt1, rs1); } return usuario; } public List<Usuario> getUsuarios(Connection con, Integer usuarioId, Integer salaId) {
170
List<Usuario> retorno = new ArrayList<Usuario>(); PreparedStatement stmt = null; ResultSet rs = null; try { stmt = con.prepareStatement("exec sp_cafor001 7,null,?,null,?"); stmt.setInt(1, usuarioId); stmt.setInt(2, salaId); rs = stmt.executeQuery(); while (rs.next()) { Usuario usuario = new Usuario(); usuario.setId(rs.getInt("matricula")); usuario.setLogin(rs.getString("matricula")); usuario.setNome(rs.getString("nome")); usuario.setTipo(rs.getString("participantes")); usuario.setAlocacao(rs.getString("curso")); usuario.setEmail(rs.getString("email")); // usuario.setBloquearEmail(rs.getBoolean("bloqEmail")); usuario.setBloquearEmailSala(rs.getBoolean("monitorarEmail")); retorno.add(usuario); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); } return retorno; } private void setImagem(Connection con, int matricula, String usuarioTipo,
171
File imagem, String ip) { PreparedStatement stmt = null; String selectSQL = ""; String updateSQL = ""; String insertSQL = ""; boolean continuar = false; try { if (usuarioTipo.equalsIgnoreCase(TiposUsuario.ALUNO) || usuarioTipo.equalsIgnoreCase(TiposUsuario.FORMANDO)) { selectSQL = "SELECT nu_matric_aln FROM vi_fotoGraduacao_fot WHERE nu_matric_aln = ?"; updateSQL = "UPDATE fotoGraduacao_fot SET lt_foto_fot = ?, lt_formato_fot = ?, nu_ipMicro_fot = ?, dt_atualizacao_fot = ? WHERE nu_matric_aln = ?"; insertSQL = "INSERT INTO fotoGraduacao_fot (nu_matric_aln, lt_foto_fot, lt_formato_fot,nu_ipMicro_fot,dt_atualizacao_fot) VALUES (?,?,?,?,?)"; continuar = true; } else if (usuarioTipo.equalsIgnoreCase(TiposUsuario.PROFESSOR)) { selectSQL = "SELECT nu_matric_pss FROM vi_fotoProfessor_fop WHERE nu_matric_pss = ?"; updateSQL = "UPDATE fotoProfessor_fop SET lt_foto_fop = ?, lt_formato_fop = ?, nu_ipMicro_fop = ?, dt_atualizacao_fop = ? WHERE nu_matric_pss = ?"; insertSQL = "INSERT INTO fotoProfessor_fop (nu_matric_pss, lt_foto_fop, lt_formato_fop,nu_ipMicro_fop,dt_atualizacao_fop) VALUES (?,?,?,?,?)"; continuar = true; } if (continuar && imagem != null) { FileInputStream streamObject = new FileInputStream(imagem); stmt = con.prepareStatement(selectSQL); stmt.setInt(1, matricula);
172
boolean atualizacao = stmt.executeQuery().next(); stmt.close(); FileDataSource fds = new FileDataSource(imagem); // lt_formato_fot if (atualizacao) { stmt = con.prepareStatement(updateSQL); stmt.setBinaryStream(1, streamObject, (int)imagem.length()); stmt.setString(2, fds.getContentType()); stmt.setString(3, ip); stmt.setString(4, new SimpleDateFormat("MMM dd yyyy hh:mma", Locale.US).format(imagem.lastModified())); stmt.setInt(5, matricula); } else { stmt = con.prepareStatement(insertSQL); stmt.setInt(1, matricula); stmt.setBinaryStream(2, streamObject, (int)imagem.length()); stmt.setString(3, fds.getContentType()); stmt.setString(4, ip); stmt.setString(5, new SimpleDateFormat("MMM dd yyyy hh:mma", Locale.US).format(imagem.lastModified())); } stmt.executeUpdate(); } } catch (Exception e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, null); }
173
} public byte[] getImagem(Connection con, String matricula, String usuarioTipo) { byte[] retorno = null; PreparedStatement stmt = null; ResultSet rs = null; try { if (usuarioTipo.equalsIgnoreCase(TiposUsuario.ALUNO) || usuarioTipo.equalsIgnoreCase(TiposUsuario.FORMANDO) || usuarioTipo.equalsIgnoreCase(TiposUsuario.MONITOR)) { stmt = con.prepareStatement("exec sp_cafor011 'aluno',?"); stmt.setInt(1, new Integer(matricula)); } else if (usuarioTipo.equalsIgnoreCase(TiposUsuario.PROFESSOR) || usuarioTipo.equalsIgnoreCase(TiposUsuario.CURSO)) { stmt = con.prepareStatement("exec sp_cafor011 'professor',?"); stmt.setInt(1, new Integer(matricula)); } else { return null; // TODO: } rs = stmt.executeQuery(); if (rs.next()) { retorno = rs.getBytes("lt_foto_fot"); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtils.closeConnection(null, stmt, rs); } return retorno; } }
174
10.4 Artigo
Sistema de Lista de Discussão (fórum) para os Cursos de Graduação da UFSC
Roque Oliveira Bezerra
Bacharelado em Ciências da Computação, 2007 Departamento de Informática e Estatística
Universidade Federal de Santa Catarina (UFSC), Brasil, 88040-900 [email protected]
Resumo Nesse trabalho propôs-se a implementação de um sistema de fórum para ser usado pela
Graduação da Universidade Federal de Santa Catarina. Para tanto, procurou-se entender como
funciona um sistema de fórum, fazendo uma pesquisa sobre suas principais características e
funcionalidades. Logo em seguida, foi analisada a estrutura acadêmica da Universidade, bem
como o estudo das soluções de comunicação já utilizadas por ela. Após isso, foi feita a análise dos
requisitos necessários a elaboração de um protótipo, levando-se em conta as necessidades dos
seus usuários e das características técnicas disponíveis. Por fim, começou-se a implementação do
protótipo do sistema, que foi sendo incrementalmente modificado com base nos testes de
aceitação do mesmo e das funcionalidades sugeridas.
Palavras-Chave: Fórum, Listas de Discussão, Graduação, Universidade, JaveEE, JBoss, Java
Server Faces.
Abstract In this project, it was suggested a forum system implementation, which will be used in the
graduation of Universidade Federal de Santa Catarina. For this, it was tried to understand how a
forum system works, doing a research about its main features and functionalities. Then, the
academic structure of the graduation was analyzed, in addition to the current communication
solutions used by it. After that, it has been made a requisite analysis, thinking about the user
necessities and the necessary technical characteristics. Finally, a system prototype was
implemented, which was gradually modified based on acceptation tests and the suggested
functionalities.
Keywords: Forum, Discussion Lists, Graduation, University, JaveEE, JBoss, Java Server Faces.
175
Introdução A UFSC conta atualmente com mais
de quarenta cursos de Graduação e vinte e seis mil alunos. Apesar dessa magnitude, não possui um sistema que torne possível a integração da informação entre seus alunos, professores e coordenadorias. A difusão da informação não encontra um meio fácil para se propagar, pois não existe uma ferramenta que centralize o universo dos alunos e professores do meio acadêmico. A principal maneira, até então, de se atingir o grande público, é através das listas de discussão por email, que apesar de cumprirem em parte o seu papel de propagar a informação, são de uso restrito e reguladas por moderadores. A Universidade, através de seu Sistema de Controle Acadêmico (CAGR), possui uma base de dados extremamente rica, contendo todos os dados referentes à Graduação. Através dela, poder-se-ia criar um sistema de Listas de Discussão, integrado ao CAGR e contemplando todos os cursos de graduação da UFSC.
O Sistema de Fórum Um fórum é um recurso oferecido na Internet para lidar com discussão e conteúdo postado pelos usuários. É basicamente composto por um número de tópicos escritos por seus usuários. Em cada tópico, existe uma discussão que é composta por uma série de mensagens. Os tópicos permanecem gravados no site para leitura futura indefinidamente, ou até que sejam excluídos por um moderador. Os usuários podem, portanto, consultar e responder os tópicos. A função básica de um sistema de fórum é essa. Porém, um software de fórum pode ser bem mais complexo.
Sistema de Controle Acadêmico (CAGR) O Controle Acadêmico do Ensino da Graduação é uma tarefa auferida ao Departamento de Administração Escolar – DAE. Trata-se de uma das tarefas mais importantes da Universidade, e também uma das mais onerosas, já que cerca de 80% da população estudantil da Instituição é formado por alunos graduandos O gerenciamento do CAGR é uma tarefa auferida ao Núcleo de Processamento de Dados (NPD), que tem entre suas funções:
• Agilizar e otimizar as atividades de
controle acadêmico; • Disponibilizar as bases de dados por
tempo integral; • Diminuir os custos envolvidos; • Fornecer informações para a tomada
de decisão a nível gerencial; • Melhorar a eficiência.
Soluções aplicadas na UFSC atualmente Efetuou-se um estudo para se identificar as soluções utilizadas na UFSC atualmente. As listas de discussão por email são o principal meio de comunicação. Essas por sua vez podem ser da Universidade, como as do Departamento de Informática e Estatística (INE), como terceirizadas. A primeira opção é utilizada pelos alunos de Ciências da Computação e Sistemas de Informação e é administrada pelo Departamento. A segunda opção é administrada geralmente pelos próprios alunos. Nesse caso, uma lista de emails é cadastrada em algum serviço externo como o Grupos19 ou o Yahoo Grupos20. Outra facilidade é o Sistema de Fórum aplicado pelo INE. Esse, porém, é restrito aos alunos e professores do curso, não
19 http://www.grupos.com 20 http://br.groups.yahoo.com
176
sendo abertos aos demais membros da Universidade.
Soluções aplicadas na UFSC atualmente Após ter-se efetuado a análise das soluções existentes, buscou-se definir os requisitos do sistema. Entre eles estão a disponibilidade aos membros da graduação, a integração do sistema com o CAGR, os níveis de hierarquia e segurança de seus usuários, a concepção em JAVA e aspectos referentes a usabilidade básica de um fórum.
Análise de Soluções Existentes A análise de soluções existentes visa decidir a viabilidade de sua aplicação no projeto do fórum. O phpBB21 é a solução com mais popularidade atualmente. Por ser um software com mais de sete anos, é bastante maduro e confiável. Apesar de todas essas qualidades, o mesmo não pode ser utilizado, por não ser feito em Java, que era um dos requisitos do sistema. O JForum22 é um sistema de fórum desenvolvido em Java e muito semelhante ao MVC. Sua arquitetura é bem modular, o que torna possível futuras expansões. Infelizmente, a maneira pela qual a solução do JForum foi implementada em termos de banco de dados, tornaria muito difícil a integração com a base de dados do CAGR. Chegou-se a conclusão, portanto, que seria mais fácil criar um sistema original, buscando inspiração nessas soluções já existentes.
Desenvolvimento O desenvolvimento do fórum começou com a definição de um primeiro protótipo, que foi feito com base na definição dos requisitos, dos casos de uso e da modelagem arquitetural e do banco de dados. Procurou-se fazer um estudo das ferramentas e tecnologias que seriam utilizadas no desenvolvimento do sistema.
21 http://www.phpbb.net 22 http://www.jforum.net
Optou-se por utilizar a IDE Oracle JDeveloper23, o framework de interface gráfica Java Server Faces24, a tecnologia JavaEE25 e o servidor de aplicação JBoss26. A camada de persistência foi feita utilizando-se stored procedures. Após o desenvolvimento do primeiro protótipo, o mesmo foi publicado para que se pudesse obter um feedback dos usuários. Nessa etapa, chegou-se a conclusão de que o fórum estava agradando ao público. Porém, possuía alguns problemas, entre eles a baixa velocidade, a falta de funcionalidades importantes, e integração somente parcial com o CAGR. A próxima etapa foi reunir esforços para se definir uma versão final do sistema. Os principais trabalhos nessa etapa foram:
• Inclusão da listagem de membros; • Envio de mensagens; • Sistema de busca; • Perfil do usuário; • Monitoramento e Notificação de
Postagens; • Sistema de Autenticação; • Otimização de Velocidade.
As funcionalidades e aperfeiçoamentos efetuados foram suficientes para definir o fórum como sendo uma versão final. O sistema foi, portanto, implantado para ser utilizado pelos seus usuários. À medida que eles iam utilizando o fórum, sugestões de inclusão de funcionalidades foram sendo feitas. Procurou-se analisar essas propostas de funcionalidades e decidir se seriam relevantes ao fórum. Optou-se por implementar aquelas que teriam um maior impacto na usabilidade e que contribuiriam para uma melhor interação entre os usuários. Entre elas destacam-se:
• Repositório Individual de Arquivos; • Exibição de Fotos dos Usuários; • Inclusão de Arquivos Anexos nos
Tópicos e Mensagens; 23 http://www.oracle.com/technology/software/products/ 24 http://java.sun.com/javaee/javaserverfaces 25 http://java.sun.com/javaee/ 26 http://www.jboss.com
177
• Inclusão de Alunos Especiais e Monitores;
• Busca por Usuários.
Considerações Finais Na concepção e desenvolvimento desse trabalho, conseguiu-se alcançar os objetivos propostos inicialmente. O estudo da estrutura acadêmica, e de que forma ela é organizada em termos tecnológicos e conceituais, permitiu obter o conhecimento necessário para a concepção do sistema. Na etapa em que a análise e o projeto do sistema foram desenvolvidos, conseguiu-se chegar a um consenso quanto as funcionalidades que o sistema deveria oferecer e de que forma elas deveriam ser organizadas, em termos de usabilidade e apresentação do sistema. A participação do público da Graduação, nas figuras dos alunos, professores e coordenadores de curso, foi fundamental nesse processo. Algumas sugestões para trabalhos futuros podem ser feitas. Uma delas é o fato de o sistema ter sido baseado nas tecnologias vigentes na época do desenvolvimento do Sistema Acadêmico da Graduação. Novas tecnologias, porém, foram desenvolvidas em períodos posteriores e com certeza poderiam ser implementadas em novas versões do sistema. Os recursos de comunicação do fórum podem ser aprimorados à medida que seja necessário aumentar a interação entre os usuários e seus conteúdos. Pode-se buscar inspiração em serviços já existentes, como o Orkut27 e o MySpace28. A divulgação do fórum à comunidade acadêmica também é muito importante. No presente momento em que esse trabalho é escrito, grande parte do público do fórum é composto pelos alunos e professores do curso de Engenharia e Aqüicultura, os cursos
27 http://www.orkut.com 28 http://www.myspace.com
do Centro Tecnológico e alguns cursos do Centro de Ciências da Educação. Nota-se que uma grande parcela do público potencial ainda está inerte quanto a utilização do fórum. Um trabalho bem feito de divulgação, com o intuito de tornar o fórum uma “cultura” universitária com certeza é muito bem vindo. Referências Bibliográficas [1] SUN MICROSYSTEMS. The Source for Java Developers. Disponível em: <http://java.sun.com>. Acesso em: 23 de maio de 2007 [2] SUN MICROSYSTEMS. Java Server Faces Technology. Disponível em: http://java.sun.com/javaee/javaserverfaces>. Acesso em: 18 de maio de 2007 [3] JBOSS GROUP. JBoss Application Server. Disponível em: <http://labs.jboss.com/jbossas >. Acesso em: 20 de abril de 2007 [4] PHPBB GROUP. phpBB. Disponível em: <http://www.phpbb.com>. Acesso em: 10 de abril de 2007 [5] WIKIPEDIA. Internet Forum. Disponível em: <http://en.wikipedia.org/wiki/Internet_forum>. Acesso em: 30 de março de 2007 [6] WIKIPEDIA. Electronic Mailing List. Disponível em: <http://en.wikipedia.org/wiki/Electronic_mailing_list>. Acesso em: 28 de março de 2007 [7] WIKIPEDIA. Apache Struts. Disponível em: <http://en.wikipedia.org/wiki/Struts>. Acesso em: 25 de abril de 2007 [8] WIKIPEDIA. Stored Procedure. Disponível em: <http://en.wikipedia.org/wiki/Stored_procedure>. Acesso em: 10 de maio de 2007 [9] WIKIPEDIA. Java Plataform, Enterprise Edition. Disponível em: <http://en.wikipedia.org/wiki/Java_ee >. Acesso em: 10 de abril de 2007
178
[10] UNIVERSIDADE FEDERAL DE SANTA CATARINA. Guia Acadêmico da Graduação. Santa Catarina. Disponível em: <http://notes.ufsc.br/aplic/guiaAcad.nsf>. Acesso em: 15 de abril de 2007. [11] UNIVERSIDADE FEDERAL DE SANTA CATARINA. Sistema Acadêmico da Graduação: Manual do Usuário. Santa Catarina, outubro 2006. [12] BODOFF, S. The J2EE Tutorial. Boston: Addison-Wesley, 2002. [13] LEMAY, L.; CADENHEAD, R. Sams teach yourself Java 2 in 21 days. Indianapolis, IN: Sams Publishing, 1999.