terça-feira, 25 de janeiro de 2011

Alterar titlebar do panel no primefaces

Algumas vezes, gostaríamos de dar outra cor à barra de título do painel no primefaces.

Para fazer isso, precisamos alterar o css do painel, assim:


.ocupada .ui-panel-titlebar {
background: #993333;
color:#CCCCCC;
}


E a declaração do componente fica assim:

<p:panel header="Título" styleClass="ocupada">
</p:panel>


Desta forma, apenas o painel onde você aplicar o style sofrerá alteração.

segunda-feira, 17 de janeiro de 2011

Assinatura Digital de Documentos

Fiz este pequeno projeto para auxiliar na tarefa de assinatura digital de documentos.

O projeto consiste de DispatchActions, Servlets e Applets.

Os testes foram feitos com o token EPASS2000 da Pronova. Onde o funcionamento depende de dois arquivos principais: pkcs11.cfg (arquivo de configuração) e ngp11v211.dll.

Aqui eu separo os elementos do projeto em várias partes, caso o link de download fique quebrado.

Applet
O módulo de applet está com as classes SignatureManager e TokenSignerApplet.

package br.com.certificacao;

import java.applet.Applet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Security;
import java.security.cert.Certificate;
import java.util.Enumeration;

/**
 * Classe responsável por gerenciar a assinatura contida em 
 * um token. É necessário efetuar o login no dispositivo
 * antes de utilizá-lo.
 */
public class SignatureManager {
 private KeyStore keyStore;
 private char[] PIN;
  
 private final String CONFIG_DIR_NAME = "C:\\assinatura\\";
 private final String CONFIG_FILE_NAME = "pkcs11.cfg";
 private final String WINDOWS_DIR_NAME = "C:\\Windows\\System32\\";
 private final String DLL_FILE_NAME = "ngp11v211.dll";
 
 private String arquivoDLLApp = "";
  
 
 public void createTokenFiles(String urlApp){
  criarDiretorio();
  criarDLL(urlApp);
  createConfigFile();
 }
 
 private void criarDiretorio(){
  try {
   File dir = new File(CONFIG_DIR_NAME);
   if (!dir.exists()){
    dir.mkdirs();
   }
  }catch (Exception e) {
  }
 }
 
 private void createConfigFile(){
  try {
   File file = new File(CONFIG_DIR_NAME + CONFIG_FILE_NAME);
   file.createNewFile();
   FileWriter writer = new FileWriter(file);
   writer.write("name = PKCS11\n");
   writer.write("library = " + arquivoDLLApp + "\n");
   writer.write("slot = 1\n");
   writer.write("disabledMechanisms = {\n");
   writer.write("    CKM_SHA1_RSA_PKCS\n");
   writer.write("}\n");
   writer.flush();
   writer.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
    
    /**
  * Metodo que verifica a situação da DLL do Token e-Pass da Pronova.
  * Verifica se a DLL já está criada na pasta Windows\System32.
  * Se o arquivo não existir, cria uma cópia na pasta apontada pela variável CONFIG_DIR_NAME.
  * 
  * @param urlApp
  */
 private void criarDLL(String urlApp){
  try {
   File dllWindows = new File(WINDOWS_DIR_NAME + DLL_FILE_NAME);
   if (dllWindows.exists()){
    arquivoDLLApp = WINDOWS_DIR_NAME + DLL_FILE_NAME;
   }else{
    arquivoDLLApp = CONFIG_DIR_NAME + DLL_FILE_NAME;
    
    URL url = new URL(urlApp+ "DLLServlet");
    HttpURLConnection connectionGet = (HttpURLConnection) url.openConnection();
    connectionGet.setRequestProperty("Request-Method", "GET");  
    connectionGet.setDoInput(true);
    connectionGet.setDoOutput(false);
    connectionGet.connect();
    
    // imprime o numero do resultado
    System.out.println("Resultado: "+ connectionGet.getResponseCode()+ "/"+ connectionGet.getResponseMessage());   
    InputStream input = connectionGet.getInputStream();
    File file = new File(arquivoDLLApp);
    file.createNewFile();
    FileOutputStream output = new FileOutputStream(file);
    
    int b = 0;
    while (-1 != ((b = input.read()))) {
     output.write(b);
    }
    output.close();  
   }
  } catch (MalformedURLException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
    
 /**
  * @param password representa o PIN informado pelo usuário
  * @return true se houve sucesso no login ou false se ocorreu 
  * algum erro
  */
 public boolean login(String password, Applet applet)throws Exception{
  boolean status = true;

  try {
   PIN = password.toCharArray();
   
   //A configuracao do provider eh possivel diante de tres opcoes:
   //1.Configuracao do java.security
   //  p. ex:security.provider.10=sun.security.pkcs11.SunPKCS11 D:\\desenvolvimento\\projetos\\funasa\\pkcs11.cfg
   //2.Pedindo para o usuario fornecer o arquivo de configuracao, através de um uploader (argh!!)
   //3.Manualmente, no codigo da applet

   //Foi escolhida a forma manual.
   Provider p = new sun.security.pkcs11.SunPKCS11(CONFIG_DIR_NAME + CONFIG_FILE_NAME);
   Security.addProvider(p);
   
   keyStore = KeyStore.getInstance("PKCS11");
   keyStore.load(null, PIN);
  }catch(Exception e){
   throw new Exception(e);
  }
  return status;
 }

 /**
  * @return chain representa o certificado armazenado no token
  */
 public Certificate[] getCertificate(){
  Certificate[] chain = null;
  try {
   Enumeration aliasesEnum = keyStore.aliases();
   while (aliasesEnum.hasMoreElements()){
    String alias = aliasesEnum.nextElement();
    if(keyStore.isKeyEntry(alias)){
     chain = keyStore.getCertificateChain(alias);
     break;
    }
   }
  } catch (GeneralSecurityException e) {
   e.printStackTrace();
  } 
  return chain;
 }

 /**
  * @return privateKey representa a chave privada armazenada no Token
  */
 public PrivateKey getPrivateKey() {
  PrivateKey privateKey = null;
  try {
   Enumeration aliasesEnum = keyStore.aliases();
   while (aliasesEnum.hasMoreElements()){
    String alias = aliasesEnum.nextElement();
    if(keyStore.isKeyEntry(alias)){
     privateKey = (PrivateKey)keyStore.getKey(alias, PIN);
     
     keyStore.getCertificateChain(alias);
     break;
    }
   }
  } catch (GeneralSecurityException e) {
   e.printStackTrace();
  } 
  return privateKey;
 }
}


package br.com.certificacao;

import java.applet.Applet;
import java.awt.Button;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Calendar;

import javax.swing.JOptionPane;

import netscape.javascript.JSObject;


import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfSignatureAppearance;
import com.lowagie.text.pdf.PdfStamper;

public class TokenSignerApplet extends Applet {
 private static final long serialVersionUID = 4023705496194390163L;

 private static final String PIN_CODE_PARAM = "pinCodeField";
 private static final String NOME_PARAM = "nomeField";
 private static final String APP_URL_PARAM = "appUrlField";
 private static final String SIGN_BUTTON_CAPTION_PARAM = "signButtonCaption"; 
 
 private Button mSignButton;

 private SignatureManager manager = new SignatureManager(); 

    /**
     * Cria e inicializa a interface grafica da applet.
     */
 public void init() {
     criarArquivoToken();
        String signButtonCaption = this.getParameter(SIGN_BUTTON_CAPTION_PARAM);
        mSignButton = new Button(signButtonCaption);
        mSignButton.setLocation(0, 0);
        Dimension appletSize = this.getSize();
        mSignButton.setSize(appletSize);
        
        mSignButton.setBackground(new Color(190, 1, 1));
        mSignButton.setForeground(new Color(255,255,255));
        mSignButton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                assinaStream();
            }
        });
        this.setLayout(null);
        this.add(mSignButton);
    }

    public void assinaStream(){
     JSObject browserWindow = JSObject.getWindow(this);
     JSObject mainForm = (JSObject)browserWindow.eval("document.forms[0]");
     String pinCodeParam = getParameter(PIN_CODE_PARAM);
     JSObject pinCodeField = (JSObject)mainForm.getMember(pinCodeParam);
     String pinCode = (String)pinCodeField.getMember("value");

     String nomeParam = getParameter(NOME_PARAM);
     JSObject nomeField = (JSObject)mainForm.getMember(nomeParam);
     String nome = (String)nomeField.getMember("value");
        
        String appParam = this.getParameter(APP_URL_PARAM);
        JSObject appField = (JSObject) mainForm.getMember(appParam);
        String appUrl = (String) appField.getMember("value");
     
        try{
         //Chama o servlet para leitura do pdf.
         String urlArquivoServlet = appUrl + "/ArquivoServlet";
            URL url = new URL(urlArquivoServlet);
            HttpURLConnection connectionGet = (HttpURLConnection)url.openConnection();
            connectionGet.setRequestProperty("Request-Method", "GET");
            connectionGet.setDoInput(true);
            connectionGet.setDoOutput(false);
            connectionGet.connect();

            //Stream de LEITURA de dados do pdf
            InputStream input = connectionGet.getInputStream();

            SignatureManager manager = new SignatureManager();
            if(manager.login(pinCode, this)){
                java.security.PrivateKey key = manager.getPrivateKey();
                java.security.cert.Certificate certificate[] = manager.getCertificate();
                try{
                    PdfReader pdfReader = new PdfReader(input);
                    //Monta a conexao com o Servlet para escrever o arquivo assinado digitalmente 
                    HttpURLConnection connectionPost = (HttpURLConnection)url.openConnection();
                    connectionPost.setRequestProperty("Content-Type", "application/pdf");
                    connectionPost.setDoOutput(true);
                    connectionPost.connect();
                    OutputStream output = connectionPost.getOutputStream();
                    //Assina PDF
                    PdfStamper stamper = PdfStamper.createSignature(pdfReader, output, '\0');
                    PdfSignatureAppearance signAppearance = stamper.getSignatureAppearance();
                    signAppearance.setCrypto(key, certificate, null, PdfSignatureAppearance.WINCER_SIGNED);
                    signAppearance.setReason("Empresa S/A");
                    signAppearance.setLocation("Sao Paulo - SP");
                    signAppearance.setSignDate(Calendar.getInstance());
                    signAppearance.setCertificationLevel(1);
                    stamper.close();
                    BufferedReader rd = new BufferedReader(new InputStreamReader(connectionPost.getInputStream()));
                    String line;
                    while((line = rd.readLine()) != null){
                        System.out.println(line);
                    }
                    output.close();
                    input.close();
                    rd.close();
                    //chamada de uma funcao javascript no jsp 
                    browserWindow.call("chamaAction", new Object[] {nome});
                }
                catch(Exception e){
                    e.printStackTrace();
                }
            } else{
                JOptionPane.showMessageDialog(this, "Erro ao assinar documento.");
            }
            input.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
 
 private void criarArquivoToken(){
  try {
         JSObject browserWindow = JSObject.getWindow(this);
         JSObject mainForm = (JSObject) browserWindow.eval("document.forms[0]");

         String appParam = this.getParameter(APP_URL_PARAM);
         JSObject appField = (JSObject) mainForm.getMember(appParam);
         String app = (String) appField.getMember("value");
         
         manager.createTokenFiles(app);
  }catch (Exception e) {
   e.printStackTrace();
  }
 } 
}


<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<html>

<head>
    <title>Teste Token Signer Applet</title>
</head>

<body>
 <script type="text/javascript">
  function chamaAction(tarefa){
   var forward = "./certificacao.do?method=doFimCertificacao" + 
    "&idTarefa=" + tarefa;
   doSubmit(forward);
  }
 </script>

    <form>
     <input type="hidden" name="appUrl" value=${pageContext.request.contextPath}>
        Código PIN:
        <input type="text" width="100" size=80 name="pinCode">
        <br>
        Nome:
        <input type="text" width="100" size=80 name="nome" value=${nome_request}>
    </form>

 <object
     classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
     codebase="http://java.sun.com/update/1.5.0/jinstall-1_5-windows-i586.cab#Version=5,0,0,5"
     width="130" height="25" name="TokenSignerApplet">
     <param name="code" value="br.com.certificacao.TokenSignerApplet">
     <param name="archive" value="TokenSignerApplet.jar , ./certificacao/bcprov-jdk14-138.jar , ./certificacao/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="appUrlField" value="appUrl">
     <param name="pinCodeField" value="pinCode">
     <param name="nomeField" value="nome">

     <comment>
   <embed
             type="application/x-java-applet;version=1.5"
             code="br.com.certificacao.TokenSignerApplet" 
             archive="TokenSignerApplet.jar , ./certificacao/bcprov-jdk14-138.jar , ./certificacao/iText-2.0.8.jar"
             width="130" height="25" scriptable="true"
       pluginspage="http://java.sun.com/products/plugin/index.html#download"
             appUrlField="appUrl"
             pinCodeField="pinCode"
             signButtonCaption="Assinar Documento"
             nomeField="nome">
   </embed>
     </comment>
 </object>
</body>
</html>

Servlet
package br.com.servlet;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet que gerencia o armazenamento do arquivo assinado.
 *  
 * @author marcelo.garcia
 *
 */
public class ArquivoServlet extends HttpServlet {
 private static final long serialVersionUID = 4102000674926121528L;

 /**
  * Recupera um arquivo e envia para o cliente (por ex. um applet)
  */
 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  System.out.println("ArquivoServlet - doGet");
  lerArquivo(request, response);
 }

 /**
  * Recebe o arquivo assinado e grava em disco no servidor.
  */
 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  System.out.println("ArquivoServlet - doPost");
  try {
   
   InputStream input = request.getInputStream();

   File file = new File("D:\\temp\\ResumoServletCriado.pdf");
   file.createNewFile();
   FileOutputStream output = new FileOutputStream(file);

   int b = 0;
   while (-1 != ((b = input.read()))) {
    output.write(b);
   }
   output.close();   
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 
 /**
  * Recupera um arquivo pdf
  * 
  * @param request
  * @param response
  * @throws ServletException
  * @throws IOException
  */
 private void lerArquivo (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  System.out.println("ArquivoServlet - lerArquivo");
  try {
   response.setContentType("application/pdf");
   InputStream is = new FileInputStream("D:\\temp\\Resumo.pdf");
   
   geraOutput(response, is);
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
 
 /**
  * Gera saída do arquivo PDF gerado
  * 
  * @param response
  * @param is
  * @throws IOException
  */
 private void geraOutput(HttpServletResponse response, InputStream is) throws IOException {
  BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
  try {
   response.setCharacterEncoding("iso-8859-1");
   int c;
   while ((c = is.read()) != -1) {
              byte[] b = new byte[1];
              b[0] = (byte)c;
              out.write(b);
   }
  } finally {
   if (is != null)
    is.close();
   if (out != null){
    out.flush();
    out.close();
   }
  }
 } 
}


package br.com.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet que controla a DLL do token da pronova. 
 * 
 * @author marcelo.garcia
 */
public class DLLServlet extends HttpServlet {
 private static final long serialVersionUID = -3363073130063055864L;

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  System.out.println("DO-post");
  try {
   
   InputStream url  = this.getServletContext().getResourceAsStream("\\dll\\ngp11v211.dll");
   OutputStream output = response.getOutputStream();

   int b = 0;
   while (-1 != ((b = url.read()))) {
    output.write(b);
   }
   output.close();
   url.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 
 protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
  doGet(request, response);
 }
}


Struts

package br.com.struts;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;

/**
 * 
 * @author marcelo.garcia
 * @version 1.0
 */
public class ActionCertificacao extends DispatchAction {

 public ActionForward doInicioCertificacao(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
  
  System.out.println("Metodo inicial da certificacao");
  
        return mapping.findForward("token");
 }

 /**
  * Metodo que finaliza o processo de assinatura digital.
  * Chamado por uma funcao javascript no token.jsp. 
  * 
  * @param mapping
  * @param actionForm
  * @param request
  * @param response
  * @return
  * @throws IOException
  * @throws ServletException
  */
 public ActionForward doFimCertificacao(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
  
  System.out.println("Metodo final da certificacao ");
  
        return null;
 }
}



          "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">





    
        
         
        
    
    
 

    
                    path="/certificacao"
            type="br.com.struts.ActionCertificacao"
            parameter="method"
            scope="request"
            name="formCertificacao"
            validate="false">
            
   
     
 

sexta-feira, 14 de janeiro de 2011

Descompilação de códigos Java

Uma ferramenta muito útil e simples para descompilar códigos java é conhecida como JAD, que pode ser baixada gratuitamente na Net.

Basicamente, você usará duas formas de descompilação:

1. Para descompliar um único arquivo, use o comando:

jad -sjava Pessoa.class

Com isso, será criado o arquivo Pessoa.java

2. Para descompilar vários arquivos organizados em pacotes, use o comando:

jad -o -r -sjava -dsrc bin/**/*.class

Jad descompilará todos os .class considerando as subpastas de "bin" e criará os respectivos .java organizados em subpastas dentro de "src".
Por exemplo, se você tiver a seguinte hierarquia de pastas "bin/com/br/Pessoa.class" (Uma classe Pessoa em uma pacote "com.br"), então o arquivo descompilado será "src/com/br/Pessoa.java".

quarta-feira, 12 de janeiro de 2011

Inserindo um novo registro numa tabela sem sequence

Algumas vezes, precisamos inserir um novo registro em uma tabela, mas que não possui nenhum esquema de atribuição de valor da chave primária.

Para esses casos, poderemos usar um script semelhante a este:


insert into produto(id, nome, valor) select max(id) + 1, 'Televisor', 450 from produto


Perceba que não usamos a cláusula VALUES no comando INSERT.

sexta-feira, 7 de janeiro de 2011

Exibição de PDF em uma JSP

Neste exemplo, uso um iframe para exibir um relatório em PDF em uma área de uma página JSP. Utilizei Struts como framework Web.

Aqui, não abro um arquivo físico, e sim utilizo o stream de dados para escrever o conteúdo do pdf.

Segue o código do método da DispatchAction do Struts:

public ActionForward geraRelatorio(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) {
try {
Map<String, String> parametros = new HashMap<String, String>();
//recuperacao de imagem para o relatorio
//passagem de parametro
parametros.put("caminhoImagem", request.getSession().getServletContext().getRealPath("/images/relatorio/logo.jpg"));

//recuperacao do arquivo compilado do relatorio
InputStream relatorio = getClass().getResourceAsStream("/br/com/relatorio.jasper");
byte[] pdf = ReportUtil.pdfPrint(relatorio, parametros);
response.setContentType("application/pdf");
response.getOutputStream().write(pdf);
} catch (Exception e) {}

//nao pode fazer forward, uma vez que escreveu no response
return null;
}


E segue o exemplo da página contendo simplesmente um iframe:


quinta-feira, 6 de janeiro de 2011

Recuperando conexão de banco no Tomcat

A configuração de conexão a um banco de dados no Tomcat pode ser feita usando o context.xml. Este arquivo deve ser armazenado na pasta META-INF do projeto web.

Exemplo do arquivo context.xml:







O método para recuperar a conexão é:


private static Connection getConnection() {
try {
InitialContext initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource) envCtx.lookup("jdbc/dataSourceName");

Connection conexao = ds.getConnection();

return conexao;
} catch (Exception e) {}

return null;
}