viernes, 3 de febrero de 2012

Gifs with Swing

If you set a gif in an ImageIcon, it will stay static and only show you one frame. For a gif to show animated, you have to asign an ImageObserver(JLabel implements ImageObserver)
ImageIcon i = new ImageIcon(new File("image");
JLabel thumbnail=new JLabel();
thumbnail.setIcon(i);
if(s.toLowerCase().endsWith(".gif")){
     i.setImageObserver(thumbnail);
} 

domingo, 29 de enero de 2012

Create a connection with an uncertified ssl connection in Java.

If you try to connect to an uncertified ssl server, Java will launch the following exception(or a very similar depending on which version you are using):


sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target.

An Oracle employee created a simple class that creates an exception and allows connections to the server you are trying to connect. The blog where it was posted has been deleted and I've lost the source code(Source code at the end of the page), so I only have the .jar, which you can download here (http://dl.dropbox.com/u/14715355/sslCert.jar). Once you have the .Jar, follow these steps:

-In your console, type:
java -jar sslCert.jar <url>**
-It will create a file named jssecacerts, rename it to cacerts and replace it with the file  in the following directory: <java-location>/java/jre/lib/security
-If you are developing, you have to add it in the jdk too: java/jdk<version>/jre/lib/security

**You must put the parent domain. if you're trying to access https://subdomain.domain.com/folder1/folder2/file, the url must be domain.com or subdomain.domain.com (with no https://)



/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sslcert;


 
 /*
  * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *
  *   - Redistributions of source code must retain the above copyright
  *     notice, this list of conditions and the following disclaimer.
  *
  *   - Redistributions in binary form must reproduce the above copyright
  *     notice, this list of conditions and the following disclaimer in the
  *     documentation and/or other materials provided with the distribution.
  *
  *   - Neither the name of Sun Microsystems nor the names of its
  *     contributors may be used to endorse or promote products derived
  *     from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 /**
  * http://blogs.sun.com/andreas/resource/InstallCert.java
  * Use:
  * java InstallCert hostname
  * Example:
  *% java InstallCert ecc.fedora.redhat.com
  */

 import javax.net.ssl.*;
 import java.io.*;
 import java.security.KeyStore;
 import java.security.MessageDigest;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;

 /**
  * Class used to add the server's certificate to the KeyStore
  * with your trusted certificates.
  */
 public class InstallCert {

  public static void main(String[] args) throws Exception {
   String host;
   int port;
   char[] passphrase;                       
   if ((args.length == 1) || (args.length == 2)) {
    String[] c = args[0].split(":");
    host = c[0];
    port = (c.length == 1) ? 443 : 443;
    String p = (args.length == 1) ? "changeit" : args[1];
    passphrase = p.toCharArray();
   } else {
    System.out.println("Usage: java InstallCert [:port] [passphrase]");
    return;
                            
   }

   File file = new File("jssecacerts");
   if (file.isFile() == false) {
    char SEP = File.separatorChar;
    File dir = new File(System.getProperty("java.home") + SEP
      + "lib" + SEP + "security");
    file = new File(dir, "jssecacerts");
    if (file.isFile() == false) {
     file = new File(dir, "cacerts");
    }
   }
   System.out.println("Loading KeyStore " + file + "...");
   InputStream in = new FileInputStream(file);
   KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
   ks.load(in, passphrase);
   in.close();

   SSLContext context = SSLContext.getInstance("TLS");
   TrustManagerFactory tmf =
     TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
   tmf.init(ks);
   X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
   SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
   context.init(null, new TrustManager[]{tm}, null);
   SSLSocketFactory factory = context.getSocketFactory();

   System.out.println("Opening connection to " + host + ":" + port + "...");
   SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
   socket.setSoTimeout(10000);
   try {
    System.out.println("Starting SSL handshake...");
    socket.startHandshake();
    socket.close();
    System.out.println();
    System.out.println("No errors, certificate is already trusted");
   } catch (SSLException e) {
    System.out.println();
    e.printStackTrace(System.out);
   }

   X509Certificate[] chain = tm.chain;
   if (chain == null) {
    System.out.println("Could not obtain server certificate chain");
    return;
   }

   BufferedReader reader =
     new BufferedReader(new InputStreamReader(System.in));

   System.out.println();
   System.out.println("Server sent " + chain.length + " certificate(s):");
   System.out.println();
   MessageDigest sha1 = MessageDigest.getInstance("SHA1");
   MessageDigest md5 = MessageDigest.getInstance("MD5");
   for (int i = 0; i < chain.length; i++) {
    X509Certificate cert = chain[i];
    System.out.println
      (" " + (i + 1) + " Subject " + cert.getSubjectDN());
    System.out.println("   Issuer  " + cert.getIssuerDN());
    sha1.update(cert.getEncoded());
    System.out.println("   sha1    " + toHexString(sha1.digest()));
    md5.update(cert.getEncoded());
    System.out.println("   md5     " + toHexString(md5.digest()));
    System.out.println();
   }

   System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
   String line = reader.readLine().trim();
   int k;
   try {
    k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
   } catch (NumberFormatException e) {
    System.out.println("KeyStore not changed");
    return;
   }

   X509Certificate cert = chain[k];
   String alias = host + "-" + (k + 1);
   ks.setCertificateEntry(alias, cert);

   OutputStream out = new FileOutputStream("jssecacerts");
   ks.store(out, passphrase);
   out.close();

   System.out.println();
   System.out.println(cert);
   System.out.println();
   System.out.println
     ("Added certificate to keystore 'jssecacerts' using alias '"
       + alias + "'");
  }

  private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();

  private static String toHexString(byte[] bytes) {
   StringBuilder sb = new StringBuilder(bytes.length * 3);
   for (int b : bytes) {
    b &= 0xff;
    sb.append(HEXDIGITS[b >> 4]);
    sb.append(HEXDIGITS[b & 15]);
    sb.append(' ');
   }
   return sb.toString();
  }

  private static class SavingTrustManager implements X509TrustManager {

   private final X509TrustManager tm;
   private X509Certificate[] chain;

   SavingTrustManager(X509TrustManager tm) {
    this.tm = tm;
   }

   public X509Certificate[] getAcceptedIssuers() {
    throw new UnsupportedOperationException();
   }

   public void checkClientTrusted(X509Certificate[] chain, String authType)
     throws CertificateException {
    throw new UnsupportedOperationException();
   }

   public void checkServerTrusted(X509Certificate[] chain, String authType)
     throws CertificateException {
    this.chain = chain;
    tm.checkServerTrusted(chain, authType);
   }
  }

 }


lunes, 23 de enero de 2012

Working with webservices in Java

I've recently been working with some webservices in Java and they can be a bit of a pain in the ass to configure and get started.

The first step is to generate all the classes. Java has a tool called wsimport that generates all the classes given the webservice definition (The url of the definitions normally finishes with ?wsdl). You can find all the documentation here. Here is an example:
wsimport -d ./build -s ./src -p com.your.package <webservice definition url>

It builds the classes in the folder "build" and the source code at the folder "src". With -p you can specify the package where you want the classes to be generated and finally the url.

To start using them, you have to follow 3 simple steps:

WebService ws=new WebService();//The class that extends Service
PortType pt=ws.getPortType(); //The port you are going to use, normally httpPort
Object response= pt.method();//Invoke the method you want to use with the port

Tips & Tricks
-Every time you create an instance of the webservice, the webservice definition is called. Sometimes java isn't capable of bringing it and throws Exception. A workoround to this problem is to copy the definition and host it on your computer/server and change the reference in the class that extends Service. The only problem with this is that if the webservice changes it's methods, your calls will not work, but it's not going work anyway since the classes do not auto generate every time they are called.

-If the Webservice is hosted on a secure server (https) you will probably have to create and exception so that Java doesn't refuse the connection with the server. I will explain how to do this in a future post

-It's rather complicated to view the soap envelopes(the information you send and recieve from the webservice)  in Java with the classes generated by wsimport. A very easy solution is to install Wireshark and filter by XML(Soap messages are xml).

domingo, 22 de enero de 2012

Printing PDF's and more in Java

The code we had in Java to print, used to be a system invoke and send the files to the spool but we had to start printing in 3 different printers and two of them had to recieve special strings but we saw that what we had, didn't work. After some research, we found the PrintService class. Here is the code that will allow you to print PDF's, strings, images or whatever you need:

private static void print(InputStream is, String printerName) throws Exception{
        PrintService printerService = null;
        DocFlavor df = new DocFlavor("application/octet-stream", "java.io.InputStream");
        PrintService[] lookupPrintServices = PrintServiceLookup.lookupPrintServices(null, null);
        //Iterates through all the printers of the sistem
        for (PrintService pss2 : lookupPrintServices) {
            if (pss2.getName().equals(printerName)) {
                printerService = pss2;
                break;
            }
        }
        if(printerService==null){
            throw new Exception("Printer not found");
        }
        DocPrintJob createPrintJob = printerService.createPrintJob();
        SimpleDoc sc = new SimpleDoc(is, df, null);
        PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
        createPrintJob.print(sc, aset);
    }

Requirements:
-You have to put the exact name of the printer. If it has a strange name, it's very easy to change, especially in windows 7. It also works for printers connected to the network.
-You have to transform what you want to print into an InputStream.

The PrinterService classes are very complex and allow you to do plenty of things but the code above should be enough to cover all your needs. If you only have one printer, you could use the method PrintServiceLookup.lookupDefaultPrintService() to avoid the iteration through all the printers.

Hello

The idea for this blog is to publish code that I have written that I find interesting or "out of the ordinary". Right now I'm working with java and php, so nearly all the samples are going to be of those two languages.