BlogBlogs.Com.Br

sexta-feira, 31 de julho de 2009

Java ScriptEngine

Estava eu pensando esses dias, se posso executar código java via Jruby por que não o contrário? Quais as minhas chances de usar Jruby dentro do Java?
Então la fui eu ao oraculo, e começei a buscar, ouvi falar de um JSR XXX (preencha com o número que quiser, nunca me lembro desses números, que pra mim são irrelevantes), que define o Java ScriptEngine, que nada mais é do que usar scripts dentro do Java, no Java 6, já vem com superte a Rhino (JavaScript), embutido, mas exemplos usando JavaScript tem de monte, vou lhes mostrar como instanciar uma classe via JRuby e chamar alguns metodos dessa classe no java. Não vou dizer que isso vai ficar bom, mas enfim, quem sabe melhorem futuramente essas engines, Mesmo assim você não precisa massacrar seu codigo java para migra-lo para JRuby, pode simplemente adaptar o codigo do JRuby no Java. Vamos ao exemplo, primeiramente vejamos quais nossas engines disponiveis na nossa versão.


import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;

public class Main {

public static void main(String[] args) throws Exception{
ScriptEngineManager manager = new ScriptEngineManager();
for(ScriptEngineFactory factory : manager.getEngineFactories()){
System.out.println(factory.getEngineName());
}
}
}


A saida deve ser Mozilla Rhino, lembre-se java 6, eu não tenho bem certeza, mas acho que o ScriptEngine está disponivel na versão 5, porém sem nenhuma engine disponivel.
E ai tio e agora como que nos faz?
Vamos adicionar o Jruby, no site do projeto baixem os script-engines, com isso temos as libs de diversas linguagens suportadas que podemos utilizar, para nos interessa, o que esta dentro da pasta jruby/build, o jruby-engine.jar deve ser adicionado ao seu classpath, ainda existem outro jar a ser adicionado, se você olhar outros tutoriais, ele vai passar diversos jar que não estão mais no $JRUBY_HOME/lib, ignore :), adicione ao classpath do seu projeto somente o jruby.jar, e agora sim. Se executar o programinha de antes deve aparecer agora


Mozilla Rhino
Jruby Engine


Vamos para o nosso querido Hello World (eu sei, eu sei, todos vocês amam o Hello World (: )


import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class Main {

public static void main(String[] args) throws Exception{
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");//Buscamos a Engine do Jruby
engine.eval("puts 'Hello World'");//Codigo JRuby
}
}


ao executar temos a mesma saida do Println, não é magico? Heeheh, um puts executado via java. Sei exatamente o que a maioria pensou, vou ter que por todo o codigo Jruby num String? A reposta é não :), a não ser que você queira fazer isso, mas eu não aconselho.
Existem outros metodos para recuperar as engines, e um deles é por extensão, poderiamos ter usado o metodo getEngineByExtension e passar como parametro o “rb”, e teriamos o Jruby.
Vamos criar então uma classe bem bunito um arquivo .rb

class Teste
attr_accessor :name, :age

def set_name(name)
self.name = name
end

def set_age(age)
self.age = age
end

def toString
self.name+" "+self.age.to_s
end
end


Lembrando que o toString sobrescreve o metodo toString do java sem problemas algum, os metodos set_ foram definidos para seguir as convensões do ruby, e isso vai tornar nosso codigo java feio, e não digam que não avisei. Vamos criar uma pequena interface


public interface Teste {
String name();
void set_name(String name);
Integer age();
void set_age(Integer age);
}


notem o estilo que foi declarado os metodos set_ na interface tbm, deve haver alguma maneira de fazer isso automatico, se alguem souber me avisa :)

E agora tio? Vamos brincar um pouco de ScriptEngine?


public static void main(String[] args) throws Exception{
ScriptEngineManager manager = new ScriptEngineManager();
for(ScriptEngineFactory factory : manager.getEngineFactories()){
System.out.println(factory.getEngineName());
}
ScriptEngine engine = manager.getEngineByName("jruby");
engine.eval(new FileReader("src/com/rollingwithcode/testejruby/teste.rb"));//arquivo .rb
Object instance = engine.eval("@teste = Teste.new");//crio a instancia
Invocable inv = (Invocable) engine;
Teste teste = inv.getInterface(instance, Teste.class); //converto a classe em uma Interface Java
teste.set_name("Rafael");
teste.set_age(21);
System.out.println(teste.toString());
System.out.println(teste.name());
}


E adivinhem a saida:

Rafael 21
Rafael


Tudo isso só pra misturar um pouco de Ruby com java, credo, parece coisa de loco :)

vou investigar mais algo, e ver se existem maneiras de melhorar isso.

Abraços até a próxima







sábado, 4 de julho de 2009

Java e LDAP

É engraçado ver como os servidores LDAP não vem sendo aproveitados. Na verdade são poucas as linguagens onde a comunidade tem algo para usar com servidores LDAP. No caso do Java existe uma biblioteca o JLDAP, distribuida pela Novell que ajuda o trabalho. É uma biblitoeca bem sfemples e mais facil de utilizar que usar JNDI para comunicar com o servidor LDAP.
Porém muita gente tem dificuldade em criar o servidor e efetuar ações dentro de um servidor LDAP, vou utilizar aqui nesse exemplo o Apache Directory Server como servidor LDAP, então as strings de acesso vão depender muito do servidor que você estará utilizando. Existem ferramentas para explorar os servidores então pode não ser tão dificil assim, basta dar uma espiada no senhor da internet (Google) e acharás o que procuras :).
Começando com o JLDAP:
A base de uma conexão com o servidor LDAP é baseada na classe LDAPConnection, e diferente dos banco de dados, não é a conexão que importa e sim o bind dela. Atraves desse bind o servidor disponibiliza os recursos de acordo com as permissoes do usuário que fez o bind. Exemplo:

LDAPConnection conn = new LDAPConnection();
conn.connect(“localhost”, 37); //Esses dois parametros são servidor (IP ou Nome) e a porta de conexão
conn.bind(LDAPConnection.LDAP_V3, “uid=admin,ou=system”, “secret”.getBytes());

Percebam o bind, ele é composto por versão do servidor LDAP, o DN do usuário a ser logado, lembrem-se o LDAP não funciona como usuário e senha, e talvez precisem ler mais sobre ele e suas siglas, DN, CN, RDN etc. E o ultimo parametro e a senha em um array de byte.
Após esse código existe uma conexão com o servidor LDAP. E podemos manipula-la.
Vamos criar uma nova entidade dentro do servidor LDAP. Vou utilizar a classe Person (Os servidores LDAP também são divididos em classes, são chamadas de objectClass, e essas classes identificam o tipo do registro no servidor), responsavel por cadastrar usuários no servidor LDAP.

LDAPAttributeSet attributes = new LDAPAttributeSet();//Um Set de atributos para o servidor, funciona no formato chave => valor.
attributes.add(new LDAPAttribute("objectClass", "person"));
attributes.add(new LDAPAttribute("cn", "felix"));
attributes.add(new LDAPAttribute("sn", "felix"));
attributes.add(new LDAPAttribute("userpassword", "teste"));
attributes.add(new LDAPAttribute("telephonenumber", "11111111"));
attributes.add(new LDAPAttribute("description", "Eu"));
//Definimos o DN, lembrem-se ele sempre é único e tera uma exception caso não seja único
String dn = "cn=felix,ou=users,ou=system";//Isso pode variar de acordo com o servidor LDAP que você estiver utilizando.
LDAPEntry entry = new LDAPEntry(dn, attributes);
conn.add(entry);//insere a entidade.


bacana Não é? E o mais legal, funciona :). Levei algum tempo para conseguir isso, mas assim é mais simples. Lembrando que deve-se ter um conhecimento básico em LDAP. O dn é formado normalmente pelo cn do usuário e o restante compreende a hierarquia de arvore do LDAP. Vendo como um diretorio seria um arquivo chamado felix dentro da pasta users que esta dentro da pasta system, simple não? E ainda por cima vc pode usar esse DN recem inserido para fazer login no servidor LDAP.
Vamos para a segunda parte. Pesquisar registros.
A pesquisa é baseada na classe LDAPSearchResults, e se basea na busca atraves da arvore de diretorios ou de um DN. A pesquisa aqui vai ser baseada na árvore que acabamos de inserir um registro (ou=users,ou=system), e vamos ver todos os usuários do sistema.

LDAPSearchResults search = conn.search(“ou=users,ou=system”, LDAPConnection.SCOPE_ONE, null, null, false); //não to lembrado do por que desses parametros :P
while(search.hasMore()){//Auto explicativo
LDAPEntry entry = search.next()://Recuperamos a entidade. Cada uma dessas entidades é um usuário do servidor LDAP.
//Vamos carregar e imprimir os atributos desse usuário
LDAPAttributeSet attribute = entry.getAttributeSet();
Iterator it = attribute.iterator();
while(it.hasNext()){
LDAPAttribute att = (LDAPAttribute) it.next();
System.out.println(att.getName() + “ => “ + att.getStringValue());
}
System.out.println();
}

Simples não? E ainda tem gente que acha dificil acessar servidor LDAP via Java :)

Espero que esse post seja util a quem está buscando algo como acessar servidores LDAP.