quarta-feira, 21 de dezembro de 2011

Instalando features do Eclipse via linha de comando com Provision Platform, p2

O Eclipse é a minha IDE favorita, por algumas razões:
  • OpenSource: sendo uma ferramenta de código livre, além de ser possível contribuir, analisar, reutilizar o código-fonte e aprender com o mesmo, a comunidade de desenvolvedores ao redor do mundo pode ampliar os horizontes da plataforma com suas contribuições.
  • Multi-plataforma: assim como a maior parte das ferramentas open-source, o Eclipse também é multi-plataforma, oferecendo assim ainda mais liberdade para que você trabalhe no ambiente que lhe proporciona mais segurança e mais recursos.
  • Multi-linguagem: como todo bom programador, eu não sou viciado em uma única linguagem, e procuro sempre utilizar a linguagem apenas como ferramenta. Apesar de ter trabalhando recentemente mais com a linguagem Java, Python, C e C++, PHP são outros sabores que eu aprecio. Claro, um pouco de shell script para automatizar tarefas corriqueiras são uma boa pedida. O Eclipse lhe oferece um ambiente uniforme para trabalhar com as linguagens, o que para mim é um fator importante, evitando atritos ao programar em mais de uma linguagem em curtos intervalos de tempo.
Por estes e outros motivos, me tornei um Amigo do Eclipse, e fiz uma modesta contribuição para o projeto. Recentemente, descobri um recurso da plataforma que facilita automatizar a instalação de plugins via linha de comando. Este recurso permite que você faça a instalação de uma série de plugins de uma única vez, realize deploys ou até mesmo, construa a partir de sua própria seleção de plugins, uma versão customizada da IDE.

Background
O processo faz uso de um recurso da plataforma do Eclipse chamado Provisioning Platform (p2). Especificamente, uma aplicação do p2 chamada Director [1]. Com esta aplicação, é possível automatizar o processo via linha de comando.

Basicamente, tudo que você tem a fazer é executar a aplicação org.eclipse.equinox.p2.director, e informar as features a serem instaladas, bem como os repositórios a serem consultados para resolução de dependências.

Tecnicamente, este é o mesmo processo que a interface gráfica realiza, com exceção de que você está automaticamente concordando com as licenças dos softwares que está instalando, uma vez que a tela de confirmação não é exibida.

Passo a passo
Terminologia básica para o processo de instalação:
  • Director: a aplicação do Eclipse que está realizando a instalação ou remoção de software. Ela está no bundle org.eclipse.equinox.p2.director.app.
  • Builder: uma aplicação baseada na plataforma do Eclipse que contém o bundle do Director e suas dependências. Pode ser utilizado, por exemplo, para criar uma nova instalação de plugins (modo shared) ou da IDE completa em um diretório diferente.
  • Produto alvo: uma aplicação alvo onde o software será instalado. Pode ser o mesmo do Builder, quando você quer instalar plugins e features em uma versão da IDE, como o Java EE.
Tudo que precisamos é do p2 Director para começar. O modo mais fácil é você já ter baixado o Eclipse para Java, Java EE ou qualquer outro de sua preferência, e começar a adicionar um conjunto de plugins. Você também pode, por exemplo, criar também uma aplicação mínima do eclipse que tenha apenas o Director e então, criar um instalador para baixar um pacote completo.

Vamos supor que você tenha baixado o Eclipse for Java EE Developers, e queira adicionar o Mobile Tools For Java (MTJ). Para isso, você precisará utilizar o seguinte comando (supondo que o binário ou script launcher do Eclipse esteja em seu PATH):


$ eclipse -nosplash -application org.eclipse.equinox.p2.director -repository http://download.eclipse.org/releases/indigo/ -installIU org.eclipse.mtj.feature.group -tag “Added-org.eclipse.mtj.feature.group”

O parâmetro -nosplash evita que a tela de splash seja exibida e fique congelada, já que não precisamos de interface gráfica. Com o parâmetro -application indicamos que o Director deve ser iniciado e não a Workbench. Os parâmetros seguintes, -repository e -installIU, permitem configurar, respectivamente, de onde os plugins e features serão baixados e quais instalation units devem ser adicionadas (plugins, features ou feature-groups). Esses dois parâmetros recebem uma lista separada por vírgulas, o que permite instalar vários plugins de diferentes fontes ao mesmo tempo. O parãmetro -tag permite marcar o que foi feito nesta operação, assim fica fácil “reverter” pela itnerface gráfica do Eclipse (ou mesmo pelo director) para uma tag mais antiga caso a instalação falhe.

Depois de rodar este comando, você vai ver algumas linhas no prompt:

Installing org.eclipse.mtj.feature.group 1.1.2.201109111413.
Operation completed in 337201 ms.

Ao iniciar novamente o Eclipse, você vai poder confirmar que o MTJ foi adicionado com sucesso ao sistema:

Você pdoe conferir nossa tag clicando em Help → About Eclipse, depois no botão Instalation Details. Na aba Instalation History, você vai ver:


Apesar dos parâmetros -repository e -feature aceitarem multiplas opções separadas por vírgula, eu notei que ao tentar instalar muitos plugins em uma única vez pode resultar em conflitos. Eu acredito que o resolvedor de dependências começa a ficar confuso. Eu também notei isso na própria interface gráfica, via Eclipse Marketplace ao tentar instalar o Google Plugin + SDKs, Apache Ivy e Pydev ao mesmo tempo.

p2-install
O que me motivou a descobrir este recurso foi ter que, nas últimas semanas, configurar várias vezes uma mesma instalação do Eclipse padrão com as ferramentas do Google Plugin for Eclipse, SDKs do AppEngine e Google Webtoolkit, Apache Ivy e IvyDE, e o MercurialEclipse. Este conjunto de ferramentas é o mínimo  essencial no meu emprego atual. Como erros intermitentes ao baixar todas de uma vez só pelo Eclipse Marketplace, tive que procurar uma alternativa.

O trabalho rendeu até um pequeno script que eu compartilhei no Bitbucket no projeto ronoaldo-utils. O script já facilita um pouco com alguns defaults, prevê multiplas instalações do Eclipse e permite que você faça também um “discover” pelos feature-groups disponíveis.

Veja o código-fonte aqui. Se tiver alguma sugestão ou melhoria, crie um fork e submita um patch!

Próximos Passos
Além de instalar plugins e feature groups (Uma feature ou grupo de features composta por vários plugins), o Director permite que você instale em um outro diretório: ou seja, instale a partir de uma aplicação, tendo uma aplicação diferente como alvo. O interessante é que você pode baixar e construir a IDE inteira com este recurso. Outra ferramenta interessante do p2 é que você pode também fazer mirror e gerenciar repositório com os plugins. Ao ler isso, imaginei uma forma bem interessante de realizar o deploy de versões já pré-configuradas do Eclipse via linha de comando, para diversas máquinas, como em um laboratório ou departamento de TI. Mas, isso é assunto para outro post...

Happy hacking!

Referências

sábado, 17 de setembro de 2011

Calculando MD5 e SHA1 em Java

Hashes são extremamente úteis para representar em uma pequena cadeia de bits uma outra cadeia de bits que pode ser bem maior. Podemos considerá-lo uma forma de criptografia assimétrica, uma vez que não é possível (a não ser por meio de algoritmos de força bruta) recuperar a cadeia original a partir do hash.

Existem diversos algoritmos para o cálculo de hashes, e em Java utilizamos a classe MessageDigest para recuperar a implementação desejada. Por exemplo, para calcular o MD5 de uma string, podemos utilizar:

MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update("string original".getBytes());
byte[] digest = md5.digest();

Para exibir os dados como string, recurso util quando você pretende utilizar o MD5 para conferir se todos os bytes de um arquivo foram baixados, basta formatá-lo com:

String.format("%1$032x", new BigInteger(1, digest));

O resultado é exatamente o hash MD5 da string:

~$ echo "string original" | md5sum
3ced9d1f470cd18f06a8b6492d3ea94e  -

Neste exemplo, utilizamos a string de formatação "%1$032x", porque queremos o resultado em hexadecimal, alinhado em 32 casas à esquerda. Construímos um BigInteger positivo, com os bits resultantes da soma, e isso nos permite converter os bytes do array para hexadecimal de forma simples.

Podemos fazer de forma semelhante ao calcular o SHA1:

MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
sha1.update("string original".getBytes());
byte[] digest = sha1.digest();
String.format("%1$040x", new BigInteger(1, digest));

Generalizando, você pode também utilizar os seguinte métodos:

public static String computeHash(String data, String algoritm,
        Integer resultSize) {
    try {
        MessageDigest digest = MessageDigest.getInstance(algoritm);
        digest.update(data.getBytes());
        return hexdigits(digest.digest(), resultSize);
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException("Unable to hash with " + algoritm);
    }
}

public static String hexdigits(byte[] data, Integer resultSize) {
    return String
            .format("%1$0" + resultSize + "x", new BigInteger(1, data));
}

Até a próxima dica!

quinta-feira, 25 de agosto de 2011

Coletânea de Soluções do GDD-BR

O Google Developer Day Brasil 2011 teve suas inscrições encerradas na última sexta-feira. Na empresa onde trabalho, eu e meus colegas fizemos uma coletânea de soluções em Java e estamos compartilhando com o mundo hoje!

As soluções são apenas para fins de exercício e oferecem diferentes visões de como podemos resolver o problema. Obviamente, para publicar nossas respostas o mais rápido possível, não otimizamos o código, e resolvemos as questões da primeira forma que nos veio em mente.

Deixem suas opiniões e comentários! E, claro, podem ficar à vontade para clonar o repositório de códigos de exemplo.

Se você gostaria de contribuir com sua solução, deixe um comentário que eu entro em contato para habilitar push no repositório.

terça-feira, 26 de julho de 2011

Pelo mundo (virtual) afora

No ano passado tive um acesso de inspiração e publiquei alguns cliparts no OpenCliparts.org, um portal de hospedagem de ilustrações vetoriais sob domínio público.

Algumas semanas depois, o Google começou a mostrar estes cliparts nos resultados de pesquisa por imagens com meu nome. Dias depois, cada clipart passou a aparecer várias vezes na mesma busca por imagens. Notei que os desenhos estavam se espalhando pela web de portal em portal, e como o OpenClipart adicionou meu nome no nome do arquivo e nos seus meta-dados, eu tive certeza que eram os mesmos.

Tudo bem, publiquei no OpenClipart com esse objetivo mesmo: divulgar os desenhos. Hoje fui até o OpenClipart novamente, e agora eles exibem os top 10 downloads na página de cada artista. Para minha surpresa, alguns cliparts já passaram dos mil downloads! Claro, a maior parte deve ser dos robozinhos dos sites que republicaram o trabalho, mas já é gratificante.

Também achei interessante que alguns dos modelos de documento do Google Docs que eu publiquei já foram utilizados diversas vezes. Agora os templates já não possuem mais a contagem de utilizações, apenas a avaliação dos usuários, que até agora foi de 4 estrelas.