quinta-feira, 15 de julho de 2010

ClassNotFoundException em Applet

Algumas vezes, nos deparamos com o seguinte erro ao abrir um applet em um navegador:

load: class br.com.certificacao.TokenSignerApplet.class not found.
java.lang.ClassNotFoundException: br.com.certificacao.TokenSignerApplet.class
at sun.plugin2.applet.Applet2ClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader.loadCode(Unknown Source)
at sun.plugin2.applet.Plugin2Manager.createApplet(Unknown Source)
at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.io.IOException: open HTTP connection failed:http://192.168.0.5:8082/certificaApp/br/com/certificacao/TokenSignerApplet/class.class
at sun.plugin2.applet.Applet2ClassLoader.getBytes(Unknown Source)
at sun.plugin2.applet.Applet2ClassLoader.access$000(Unknown Source)
at sun.plugin2.applet.Applet2ClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
... 7 more
Exception: java.lang.ClassNotFoundException: br.com.certificacao.TokenSignerApplet.class
load: class br.com.certificacao.TokenSignerApplet.class not found.
java.lang.ClassNotFoundException: br.com.certificacao.TokenSignerApplet.class
at sun.plugin2.applet.Applet2ClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.plugin2.applet.Plugin2ClassLoader.loadCode(Unknown Source)
at sun.plugin2.applet.Plugin2Manager.createApplet(Unknown Source)
at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.io.IOException: open HTTP connection failed:http://192.168.0.5:8082/certificaApp/br/com/certificacao/TokenSignerApplet/class.class
at sun.plugin2.applet.Applet2ClassLoader.getBytes(Unknown Source)
at sun.plugin2.applet.Applet2ClassLoader.access$000(Unknown Source)
at sun.plugin2.applet.Applet2ClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
... 7 more
Exception: java.lang.ClassNotFoundException: br.com.certificacao.TokenSignerApplet.class



No meu caso, sofri com isso usando o Internet Explorer. Se isso acontecer com você, tente as seguintes situações:
  1. Utilizar outro browser ( ou outra versão do seu browser);
  2. Tentar desabilitar o uso de proxy (pode ser que o proxy esteja barrando alguma coisa relacionada ao uso de applets, neste caso, você terá que solicitar ao gerente da rede um ajuste no proxy);
  3. Trocar a ordem dos parâmetros java_code e java_archive , deixando o java_archive antes.
    <param name="java_archive" value="TokenSignerApplet.jar, bcprov-jdk14-138.jar, iText-2.0.8.jar">

    <param name="java_code" value="br.com.certificacao.TokenSignerApplet.class">

    <param name="java_codebase" value="<%="http://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()%>">

terça-feira, 13 de julho de 2010

Código de applet para assinatura digital

Este simples código demonstra como disponibilizar uma applet que lê um token para assinar um documento digitalmente.
Merecem destaque as seguintes informações:

  • Os arquivos bcprov-jdk14-138.jar e iText-2.0.8.jar são utilizados para assinar o pdf gerado.
  • O arquivo TokenSignerApplet.jar contem a classe da applet
  • O parâmetro java_codebase é importante de configurar para não dar erro na localização dos arquivos com as classes.
<object
classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
codebase="" width="130" height="25" name="TokenSignerApplet">
<param name="java_code" value="br.com.certificacao.TokenSignerApplet.class">
<param name="java_codebase" value="<%="http://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()%>">
<param name="java_archive" value="TokenSignerApplet.jar , bcprov-jdk14-138.jar , iText-2.0.8.jar">
<param name="mayscript" value="true">
<param name="type" value="application/x-java-applet;version=1.5">
<param name="scriptable" value="false">
<param name="signButtonCaption" value="Assinar Documento">
<param name="pinCodeField" value="pinCode">
<comment>
<embed
type="application/x-java-applet;version=1.5"
java_code="br.com.ebiz.funasawf.web.certificacao.TokenSignerApplet.class"
java_codebase="<%="http://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()%>"
java_archive="TokenSignerApplet.jar , bcprov-jdk14-138.jar , iText-2.0.8.jar"
width="130" height="25" scriptable="true"
pluginspage="http://java.sun.com/products/plugin/index.html#download"
pinCodeField="pinCode"
signButtonCaption="Assinar Documento"
</embed>
<noembed>
Smart card signing applet can not be started because
Java Plugin 1.5 or newer is not installed.
</noembed>
</comment>
</object>

quinta-feira, 17 de junho de 2010

Recuperar os parametros de uma requisição HTTP

Segue um exemplo de um método que recupera um enumeration dos parametros de uma requisição:

private void getParameters(HttpServletRequest request){
Enumeration e = request.getParameterNames();

while (e.hasMoreElements()) {
String parameterName = (String) e.nextElement();

String[] parametervalues = request.getParameterValues(parameterName);
}
}

terça-feira, 8 de junho de 2010

Merge de propriedades

Olá pessoal,

Fiz esse pequeno utilitário para sincronizar os métodos get e set de dois objetos.

Fiz isso objetivando atender um caso de atualização de cadastro, evitando fazer cansativos get de um objeto seguido do set para outro objeto destino do valor.

Vocês podem usar a vontade e se houver algum melhoramento, por favor comuniquem.

Código da classe


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
*
* @author Marcelo Garcia
*
*/
public class MergeProperties {

/**
* Realiza o merge dos valores do objeto origem para o objeto destino.
*
* Os metodos que sao capturados pelo algoritmo sao metodos GET e
* que nao possuem parametro.
*
* Os valores sao capturados a partir dos metodos GET existentes na
* classe origem. Isso quer dizer que caso o destino seja uma subclasse
* de origem, os seus metodos nao serao reconhecidos.

* Somente valores nao nulos sao passados de origem para destino.
* Campos string vazios e numericos zerados sao permitidos.
*
* @param
* @param destino: Recebera os valores de origem
* @param origem: Objeto cujas propriedades serao transferidas para o destino
* @return o objeto modificado
*/
public static C mergeProperties(C destino, C origem) {
Method[] metodos = origem.getClass().getMethods();
String nomeMetodo;
String nomeMetodoSemGet;

try {
for (Method metodo : metodos) {
nomeMetodo = metodo.getName();
nomeMetodoSemGet = nomeMetodo.substring(3,nomeMetodo.length());
//Testa se é um método get
if (!nomeMetodo.substring(0,3).equals("get"))
continue;
if (metodo.getParameterTypes().length != 0)
continue;
Object valor = metodo.invoke(origem);
if (valor == null)
continue;
//Captura o metodo SET de acordo com o tipo de retorno do metodo GET
Method metodoSET = destino.getClass().getMethod("set"+nomeMetodoSemGet, metodo.getReturnType());
if (metodo != null)
metodoSET.invoke(destino, valor);
}
}
catch (NoSuchMethodException e) {
System.out.println("Metodo nao encontrado.");
}
catch (InvocationTargetException e) {
System.out.println("Chamada de metodo incorreta.");
}
catch (IllegalAccessException e) {
System.out.println("Metodo inacessivel.");
}
catch (IllegalArgumentException e) {
System.out.println("Argumentos incorretos.");
}

return destino;
}
}

sexta-feira, 28 de maio de 2010

Assinatura de Applets

Primeiramente, é preciso gerar o arquivo com o applet que será assinado digitalmente. Para isso, use o comando:

jar -cvf TokenSignerApplet.jar br\com\certificacao\*.class

O próximo passo é gerar o arquivo de assinatura para o applet. Use o comando:

keytool -genkey -alias signFiles -keystore certificado.jks -keypass !secret -dname "CN=Company Name" -storepass !secret

Finalmente, assine o applet com o comando:

jarsigner -keystore certificado.jks -storepass !secret -keypass !secret TokenSignerApplet.jar signFiles

quinta-feira, 7 de janeiro de 2010

Configurar JBoss como serviço através do JavaServiceWrapper


Despois de descompactar o arquivo, faça o seguinte:
  • Configurar os seguintes arquivos e diretórios. Onde YOURCONFIG, normalmente será default
copy WRAPPER_HOME\bin\Wrapper.exe %JBOSS_HOME%\bin\Wrapper.exe
copy WRAPPER_HOME\lib\Wrapper.DLL %JBOSS_HOME%\lib\Wrapper.DLL
copy WRAPPER_HOME\lib\wrapper.jar %JBOSS_HOME%\lib\wrapper.jar
mkdir %JBOSS_HOME%\server\YOURCONFIG\wrapper
  • Criar o arquivo wrapper.conf em %JBOSS_HOME%\server\YOURCONFIG\wrapper com o seguinte conteúdo. Edite e/ou comente o que for necessário.
wrapper.java.command=D:/Java/jdk1.5.0_14/bin/java

wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp

wrapper.java.classpath.1=%JBOSS_HOME%/lib/wrapper.jar
wrapper.java.classpath.2=%JAVA_HOME%/bin/java/lib/tools.jar
wrapper.java.classpath.3=./run.jar

wrapper.java.library.path.1=%JBOSS_HOME%/lib

# these are the JAVA_OPTS
wrapper.java.additional.1=-server
# enviroment variables - define the ones that match your desired environment
wrapper.java.additional.2=-Denviromnment.variable=value
# memory parameters - define the ones that match your desired environment
wrapper.java.additional.3=-Xms64m
wrapper.java.additional.4=-Xmx96m
# If you need serialization suppport
wrapper.java.additional.5=-Dsession.serialization.jboss=true

wrapper.app.parameter.1=org.jboss.Main
# Parameters to be passed to the application (Jboss)
# Define server name (configuration) - If you need a config that is different than the "default" or need to run multiple configs
wrapper.app.parameter.2=-c YOURCONFIG
# Define listening IP - If you have more than one IP or want to indicate to listen on a specific IP
wrapper.app.parameter.3=-b aaa.bbb.ccc.ddd
# wrapper log location
wrapper.logfile=%JBOSS_HOME%/server/YOURCONFIG/log/wrapper.log

# You must not change below parameters without first uninstall the service
# service name
wrapper.ntservice.name=JbossYOURCONFIG
# service display name
wrapper.ntservice.displayname=JBoss Server YOURCONFIG

  • Teste o serviço:
cd %JBOSS_HOME%\bin\
wrapper.exe -c %JBOSS_HOME%\server\YOURCONFIG\wrapper\wrapper.conf
  • Instale o serviço:
cd %JBOSS_HOME%\bin\

wrapper.exe -i %JBOSS_HOME%\server\YOURCONFIG\wrapper\wrapper.conf

  • Desinstale o serviço: 

cd %JBOSS_HOME%\bin\
wrapper.exe -r %JBOSS_HOME%\server\YOURCONFIG\wrapper\wrapper.conf
 
Aviso: Certifique-se que a variável de ambiente JBOSS_HOME está configurada corretamente. (run.bat faz isto, mas wrapper não!)

sexta-feira, 18 de dezembro de 2009

Serializador Java para JSON - Parte I

JSON é uma forma de transferência de dados que está sendo utilizado bastante atualmente. Possui um formato bastante que deixa o conjunto de dados bastante enxuto.

Desenvolvi estas classes baseadas na biblioteca FlexJson: http://flexjson.sourceforge.net/ . Fiz algumas alterações que deixou a biblioteca bem menor. Mas, minha motivação principal foi que eu pudesse utilizar a biblioteca  na versão 1.4 do Java. Ao todo, a biblioteca ficou com apenas quatro classes: ChainedIterator, ChainedSet, JSONSerializer, ObjectVisitor. Vou colocar o código de todas elas, e também um exemplo de uso.

Código da classse ChainedIterator

import java.util.Iterator;
import java.util.Iterator;
import java.util.Set;

public class ChainedIterator implements Iterator {
Iterator[] iterators;
int current = 0;

public ChainedIterator(Set sets) {
Object[] arraySets = sets.toArray();
iterators = new Iterator[sets.size()];
for( int i = 0; i < sets.size(); i++ ) {
iterators[i] = ((Set)arraySets[i]).iterator();
}
}

public boolean hasNext() {
if( iterators[current].hasNext() ) {
return true;
} else {
current++;
return current < iterators.length && iterators[current].hasNext();
}
}

public Object next() {
return iterators[current].next();
}

public void remove() {
iterators[current].remove();
}
}

Código da classe ChainedSet
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Collection;
import java.util.TreeSet;

public class ChainedSet implements Set {
Set parent;
Set child;

public ChainedSet(Set parent) {
this.parent = parent;
this.child = new HashSet();
}

public int size() {
return this.child.size() + parent.size();
}

public boolean isEmpty() {
return this.child.isEmpty() && parent.isEmpty();
}

public boolean contains(Object o) {
return child.contains(o) || parent.contains(o);
}

public Iterator iterator() {
Set sets = new TreeSet();
sets.add(child);
sets.add(parent);
return new ChainedIterator(sets);
}

public Object[] toArray() {
Object[] carr = child.toArray();
Object[] parr = parent.toArray();
Object[] combined = new Object[ carr.length + parr.length ];
System.arraycopy( carr, 0, combined, 0, carr.length );
System.arraycopy( parr, 0, combined, carr.length, parr.length );
return combined;
}

public Object[] toArray(Object[] a) {
throw new IllegalStateException( "Not implemeneted" );
}

public boolean add(Object o) {
return child.add( o );
}

public boolean remove(Object o) {
return child.remove( o );
}

public boolean containsAll(Collection c) {
return child.containsAll(c) || parent.containsAll(c);
}

public boolean addAll(Collection c) {
return child.addAll( c );
}

public boolean retainAll(Collection c) {
return child.retainAll( c );
}

public boolean removeAll(Collection c) {
return child.removeAll( c );
}

public void clear() {
child.clear();
}

public Set getParent() {
return parent;
}
}
Código da classe JSONSerializer
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JSONSerializer {

public final static char[] HEX = "0123456789ABCDEF".toCharArray();

List pathExpressions = new ArrayList();
Map transformations = new HashMap();

public JSONSerializer() {
}

public String serialize( String rootName, Object target ) {
return new ObjectVisitor().visit( rootName, target );
}

public String serialize( Object target ) {
return new ObjectVisitor().visit( target );
}

public String prettyPrint( Object target ) {
return new ObjectVisitor( true ).visit( target );
}

public String prettyPrint( String rootName, Object target ) {
return new ObjectVisitor( true ).visit( rootName, target );
}
}

Código da classe ObjectVisitor
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;

public class ObjectVisitor {
protected StringBuffer builder;
protected boolean prettyPrint = false;
private int amount = 0;
private boolean insideArray = false;

protected ObjectVisitor() {
builder = new StringBuffer();
}

public ObjectVisitor(boolean prettyPrint) {
this();
this.prettyPrint = prettyPrint;
}

public String visit( Object target ) {
json( target );
return builder.toString();
}

public String visit( String rootName, Object target ) {
beginObject();
string(rootName);
add(':');
json( target );
endObject();
return builder.toString();
}

private void numberToString(Number n) {
if (n != null && testValidity(n)) {
String s = n.toString();
if (s.indexOf('.') > 0 && s.indexOf('e') < 0 && s.indexOf('E') < 0) {
while (s.endsWith("0")) {
s = s.substring(0, s.length() - 1);
}
if (s.endsWith(".")) {
s = s.substring(0, s.length() - 1);
}
}
add(s);
}else{
add("0");
}
}

private boolean testValidity(Object o) {
if (o != null) {
if (o instanceof Double) {
if (((Double)o).isInfinite() || ((Double)o).isNaN()) {
return false;
}
} else if (o instanceof Float) {
if (((Float)o).isInfinite() || ((Float)o).isNaN()) {
return false;
}
}
}
return true;
}


private void json(Object object) {
if (object == null) add("null");
else if (object instanceof Class)
string( ((Class)object).getName() );
else if (object instanceof Boolean)
bool( ((Boolean) object) );
else if (object instanceof String)
string(object);
else if (object instanceof Character)
string(object);
else if (object instanceof Number)
numberToString((Number) object);
else if (object instanceof Map)
map( (Map)object);
else if (object.getClass().isArray())
array( object );
else if( object instanceof Date)
date( (Date)object );
else if (object instanceof Collection)
array(((Collection) object).iterator() );
else
bean( object );
}

private void map(Map map) {
beginObject();
Iterator it = map.keySet().iterator();
boolean firstField = true;
while (it.hasNext()) {
Object key = it.next();
int len = builder.length();
add( key, map.get(key), firstField );
if( len < builder.length() ) {
firstField = false;
}
}
endObject();
}

private void array(Iterator it) {
beginArray();
while (it.hasNext()) {
if( prettyPrint ) {
addNewline();
}
addArrayElement( it.next(), it.hasNext() );
}
endArray();
}

private void array(Object object) {
beginArray();
int length = Array.getLength(object);
for (int i = 0; i < length; ++i) {
if( prettyPrint ) {
addNewline();
}
addArrayElement( Array.get(object, i), i < length - 1 );
}
endArray();
}

private void addArrayElement(Object object, boolean isLast ) {
int len = builder.length();
json( object );
if( len < builder.length() ) { // make sure we at least added an element.
if ( isLast ) add(',');
}
}

private void bool(Boolean b) {
add( b.booleanValue() ? "true" : "false" );
}

private void string(Object obj) {
add('"');
CharacterIterator it = new StringCharacterIterator(obj.toString());
for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
if (c == '"') add("\\\"");
else if (c == '\\') add("\\\\");
else if (c == '\b') add("\\b");
else if (c == '\f') add("\\f");
else if (c == '\n') add("\\n");
else if (c == '\r') add("\\r");
else if (c == '\t') add("\\t");
else if (Character.isISOControl(c)) {
unicode(c);
} else {
add(c);
}
}
add('"');
}

private void date(Date date) {
builder.append( date.getTime());
}

private ChainedSet visits = new ChainedSet( Collections.EMPTY_SET );

protected void bean(Object bean) {
if( !visits.contains( bean ) ) {
visits = new ChainedSet( visits );
visits.add( bean );
beginObject();
try {
Class klass = bean.getClass();

Method[] methods = klass.getMethods();
boolean firstField = true;
for (int i = 0; i < methods.length; i += 1) {
Method method = methods[i];
if (Modifier.isPublic(method.getModifiers())) {
String name = method.getName();
String key = "";
boolean invoke = false;
if (name.startsWith("get")) {
invoke = true;
key = name.substring(3);
} else if (name.startsWith("is")) {
key = name.substring(2);
invoke = true;
}
if (key.length() > 0){
key = String.valueOf(key.charAt(0)).toLowerCase() + key.substring(1);
}

if (invoke) {
Object value = method.invoke(bean, (Object[])null);

if( !visits.contains( value ) ) {
add(key, value, firstField);
firstField = false;
}
}
}
}
} catch( Exception e ) {

}
endObject();
visits = (ChainedSet) visits.getParent();
}
}

protected boolean addComma(boolean firstField) {
if ( !firstField ) {
add(',');
} else {
firstField = false;
}
return firstField;
}

protected void beginObject() {
if( prettyPrint ) {
if( insideArray ) {
indent( amount );
}
amount += 4;
}
add( '{' );
}

protected void endObject() {
if( prettyPrint ) {
addNewline();
amount -= 4;
indent( amount );
}
add( '}' );
}

private void beginArray() {
if( prettyPrint ) {
amount += 4;
insideArray = true;
}
add('[');
}

private void endArray() {
if( prettyPrint ) {
addNewline();
amount -= 4;
insideArray = false;
indent( amount );
}
add(']');
}

protected void add( char c ) {
builder.append( c );
}

private void indent(int amount) {
for( int i = 0; i < amount; i++ ) {
builder.append( " " );
}
}

private void addNewline() {
builder.append("\n");
}

protected void add( Object value ) {
builder.append( value );
}

protected void add(Object key, Object value, boolean prependComma) {
int start = builder.length();
addComma( prependComma );
addAttribute( key );

int len = builder.length();
json( value );
if( len == builder.length() ) {
builder.delete( start, len ); // erase the attribute key we didn't output anything.
}
}

private void addAttribute(Object key) {
if( prettyPrint ) {
addNewline();
indent( amount );
}
builder.append("\"");
builder.append( key );
builder.append( "\"" );
builder.append( ":" );
if( prettyPrint ) {
builder.append(" ");
}
}

private void unicode(char c) {
add("\\u");
int n = c;
for (int i = 0; i < 4; ++i) {
int digit = (n & 0xf000) >> 12;
add(JSONSerializer.HEX[digit]);
n <<= 4;
}
}
}