Sunday, March 23, 2014

Select and copy text within Quick Look previews

I'm a big Apple fan and my first work station was Macbook Air. Now i switched to Macbook pro and recently found a nice solution that allows you to copy text from Quick Look preview - it makes my life way more easier and handy. Here's how you can do it :
  • Open Terminal
  • Paste next command :
defaults write com.apple.finder QLEnableTextSelection -bool TRUE; killall Finder
And that's it! Now you can find any text file, push Space button and you'll get Quick Look preview of it. Now you can select text from it and copy -> paste into another place.

In case if you want to disable this feature , you can always run next command in the Terminal :
defaults delete com.apple.finder QLEnableTextSelection; killall Finder

Thursday, January 9, 2014

InstallCert.java - console app that allows you to get and download ssl keys from webservice you're trying to work with

Recently i was working on one of my Test Frameworks for API and i had to work with https. I faced with :
javax.net.ssl.SSLHandshakeException: 
   sun.security.validator.ValidatorException: PKIX path building failed: 
   sun.security.provider.certpath.SunCertPathBuilderException: 
   unable to find valid certification path to requested target
 
Caused by: sun.security.validator.ValidatorException: 
   PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: 
   unable to find valid certification path to requested target
 
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: 
   unable to find valid certification path to requested target
exception during their execution. The reason was that i was working with dev server that has self signed certificate, which was absent in my local keystore. So, i googled a little bit and found this nice Java console app that allowed you in a very simple manner get a certificate. But in my case i need to use Proxy sometimes and that's why i decided to improve this app and add proxying possibilities to it. Final result can be found here    
Here's how it works : The most simple way is
java InstallCert host=google.com
In this case InstallCert will look for ssl certificates on https://google.com:443. Here's it's output
host = google.com
Connecting to address without enabled proxy settings.
Loading KeyStore C:\Program Files\Java\jre7\lib\security\cacerts...
Opening connection to google.com:443...
Starting SSL handshake...

No errors, certificate is already trusted

Server sent 3 certificate(s):

 1 Subject CN=*.google.com, O=Google Inc, L=Mountain View, ST=California, C=US
   Issuer  CN=Google Internet Authority G2, O=Google Inc, C=US
   sha1    3c 6b de 6c a0 a1 ae 6a e9 d5 bf b3 67 ab 12 4e 1b 98 8b fb
   md5     27 91 da c0 73 30 85 db e3 23 ef 7d 6f aa 7f cd

 2 Subject CN=Google Internet Authority G2, O=Google Inc, C=US
   Issuer  CN=GeoTrust Global CA, O=GeoTrust Inc., C=US
   sha1    d8 3c 1a 7f 4d 04 46 bb 20 81 b8 1a 16 70 f8 18 34 51 ca 24
   md5     9e 4a c9 64 74 24 51 29 d9 76 67 00 41 2a 1f 89

 3 Subject CN=GeoTrust Global CA, O=GeoTrust Inc., C=US
   Issuer  OU=Equifax Secure Certificate Authority, O=Equifax, C=US
   sha1    73 59 75 5c 6d f9 a0 ab c3 06 0b ce 36 95 64 c8 ec 45 42 a3
   md5     2e 7d b2 a3 1d 0e 3d a4 b2 5f 49 b9 54 2a 2e 1a

Enter certificate to add to trusted keystore or 'q' to quit: [1]
You simply press 1 and hit Enter button. As a result, you'll have your certificate added to your default keystore
[
[
  Version: V3
  Subject: CN=*.google.com, O=Google Inc, L=Mountain View, ST=California
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

  Key:  Sun EC public key, 256 bits
  public x coord: 656756547611416355835880201008930358845723006450213197
628251447943028
  public y coord: 396827319974765304927937356957360152389742209992235777
66752587796918
  parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.
  Validity: [From: Wed Dec 11 13:34:50 CET 2013,
               To: Thu Apr 10 02:00:00 CEST 2014]
  Issuer: CN=Google Internet Authority G2, O=Google Inc, C=US
  SerialNumber: [    4445eb4c d2c191ad]

Certificate Extensions: 9
[1]: ObjectId: 1.3.6.1.5.5.7.1.1 Criticality=false
AuthorityInfoAccess [
  [
   accessMethod: caIssuers
   accessLocation: URIName: http://pki.google.com/GIAG2.crt
,
   accessMethod: ocsp
   accessLocation: URIName: http://clients1.google.com/ocsp
]
]
...

[9]: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 4E A2 DC AC DF 9C 45 35   DE A0 F7 C1 0A A6 88 19  N.....E5.......
0010: B7 6B D1 F7                                        .k..
]
]

]
  Algorithm: [SHA1withRSA]
  Signature:
0000: 71 BD 84 65 33 2E 28 65   AB 5D 2A C8 1F 38 47 9A  q..e3.(e.]*..8G
0010: 43 DF BF 49 70 45 56 4C   D9 D8 31 67 53 B5 82 40  C..IpEVL..1gS..
0020: 4B BE D4 61 39 82 A7 25   7A 7F 27 B9 AE F0 1F 32  K..a9..%z.'....
0030: 38 1E 7B 32 C9 8A A1 8E   C6 66 5B 45 96 85 25 FB  8..2.....f[E..%
0040: DB D7 05 9B 40 1B 44 DC   8D 19 2D 94 0F FE 0B 67  ....@.D...-....
0050: E9 7D 8F 2B 93 50 B4 51   DF D0 97 4A A1 73 B3 46  ...+.P.Q...J.s.
0060: 26 A8 E7 21 20 5D 5E 86   5D C2 1B D9 0B B9 E5 95  &..! ]^.]......
0070: FE 87 2F 2A 99 B1 3D 8D   F9 59 A6 B6 0B A4 A4 91  ../*..=..Y.....
0080: 81 4E EA 03 8F 6C 42 18   89 27 2C 88 C6 E9 50 A9  .N...lB..',...P
0090: 45 69 1E 82 BD 22 48 2B   A0 5C E9 37 86 51 CD 57  Ei..."H+.\.7.Q.
00A0: 8B C6 ED 7E FE E7 B6 F8   FC 82 9E AE E5 9D 1E 74  ...............
00B0: 18 5C 34 4C 2B 7A C5 3C   C1 9B D5 AF F3 33 6C E8  .\4L+z.<.....3l
00C0: AE 94 B1 3A 0B CD BD EF   9D 75 46 BD 91 F0 C0 55  ...:.....uF....
00D0: D2 87 46 5B AF 8B A1 9A   0F 8E 06 C4 F1 42 7C AB  ..F[.........B.
00E0: 58 79 59 A5 F3 4D 98 6C   8C 97 93 B0 0E 8E A1 3E  XyY..M.l.......
00F0: BF 11 83 D0 95 22 27 69   6A E8 66 84 8C 59 0D 49  ....."'ij.f..Y.

]

Added certificate to keystore 'cacerts' using alias 'google.com-1'
To check that everything went well you can run this command again and you should see :
Opening connection to google.com:443...
Starting SSL handshake...

No errors, certificate is already trusted
Besides that you can also specify :
  • Host port. If it's not standart 443 then you need to add to your command hostPort=[portNumber]
  • If you would like to address your request through proxy first, then you need to specify proxyHost=[hostName] proxyPort=[portNumber]
  • If your keystore has non-default password then passphrase=[passphrase] should be also added to the command. That's it :)
  • Tuesday, December 17, 2013

    Nice reporting tool for TestNG tests


    Recently came to the point where i needed to get reports for my TestNG reports and to use them in CI. After some googling i found ReportNG . It provides both XML and HTML reports and is very easy to setup.
    On original page there's an instruction for setup with ant, but Maven users can find this article very useful

    Friday, December 6, 2013

    Add Microsoft SQL JDBC driver to Maven

    Found out today that Maven does not directly support some libraries, like Microsoft’s SQL Server JDBC. The reason for that is that this library is not open source and can be stored in global repository. Anyway, i recently was wondering how to add a library to local maven repository to use it in my automation projects. Fast search in Google got me to this blog post. It's really easy :

    1. Visit the MSDN site for SQL Server and download the latest version of the JDBC driver for your operating system. 
    2. Unzip the package 
    3. Open a command prompt and switch into the expanded directory where the jar file is located. 
    4. Execute the following command. Be sure to modify the jar file name and version as necessary:

    mvn install:install-file -Dfile=sqljdbc4.jar -Dpackaging=jar -DgroupId=com.microsoft.sqlserver -DartifactId=sqljdbc4 -Dversion=4.0
    
    Then you'll get this result :
    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building Maven Stub Project (No POM) 1
    [INFO] ------------------------------------------------------------------------
    [INFO]
    [INFO] --- maven-install-plugin:2.4:install-file (default-cli) @ standalone-pom
    ---
    [INFO] Installing C:\sqljdbc4.jar to C:\IDEConfigs\.m2\repository\com\microsoft\
    sqlserver\sqljdbc4\4.0\sqljdbc4-4.0.jar
    [INFO] Installing C:\Users\AF4C0~1.ZAK\AppData\Local\Temp\mvninstall797028335566
    232276.pom to C:\IDEConfigs\.m2\repository\com\microsoft\sqlserver\sqljdbc4\4.0\
    sqljdbc4-4.0.pom
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 0.925s
    [INFO] Finished at: Fri Dec 06 15:59:40 CET 2013
    [INFO] Final Memory: 5M/121M
    [INFO] ------------------------------------------------------------------------
    
    Now you have this library in your local repository. If you want to use it in your project, then just add dependancy to your pom.xml file.
    
        com.microsoft.sqlserver
        sqljdbc4
        4.0
    
    
    That's it. Now you can create connection to SQL Server in your tests

    Tuesday, November 19, 2013

    Nice and simple converter of Java ResultSet into JSONArray or XML

    Right now i'm working with SOAP UI and responce i get in ResultSet format. Since i preffer to work more with JSON rather then ResultSet, i found this nice solution that perfectly fits my needs.
    Here's the code : Thanks to this blog

    Java doesn't resolve remote dns properly and how to deal with it

    I don't think that this story will be short, but it's definitely interesting. So, i got a new project where i need to cover SOAP API with automated tests written on Java. As a start point i have URL to WSDL file to work with. The "tricky" part is the environment configuration. Our test environment is hidden behind SOCKS proxy server. So, if you want to work with test environment, you need to make your requests through that proxy, otherwise you'll "talk" to another environment that we don't need right now. Not usual configuration, but it had it's own reasons in the past for doing so. My first problem was to decide how to work with WSDL and in what direction my future framework would go. After some googling and trials, i've stopped on JAX-WS lib. It's handy because with wsimport maven task it can easily generate all needed classes and objects where your stubs will be held. Here's how it looks like in maven :

    
                        org.jvnet.jax-ws-commons
                        jaxws-maven-plugin
                        ${jaxws.plugin.version}
                        
                            
                                {put_some_id}
                                validate
                                
                                    wsimport
                                
                                
                                    
                                    {your_wsdl_location}
                                    ${project.basedir}\src\main\java\Stubs\oop
                                    
                                        ${project.basedir}\src\main\resources\wsdl\myWSDL.wsdl
                                    
                                    Stubs.oop
                                    
                                    ${project.build.directory}/jaxws/stale/wsdl.done
                                
                            
                            
                                {put_some_id}
                                validate
                                
                                    wsimport
                                
                                
                                    
                                    {your_wsdl_location}
                                    ${project.basedir}\src\main\java\Stubs\wsdl2
                                    
                                        ${project.basedir}\src\main\resources\wsdl\your_wsld2.wsdl
                                    
                                    your_package_name
                                    
                                    ${project.build.directory}/jaxws/stale/wsdl.done
                                
                            
                        
                    
    It was a bit hard for me to get WSDL from URL, so i decided to save it locally and read it from there then. Since changes are not being made frequently in API, i can easily accept this. This configuration allows to add as many WSDL sources as i want and to store stubs for each of them in separate packages in the project. First problem was solved. Now, i had to figure out how to put my requests through Proxy . My first trial was basic and most common in Java world:
    System.getProperties().put("proxySet", "true");
    System.getProperties().put("proxyHost", getProxyHost());
    System.getProperties().put("proxyPort", getProxyPort());
    
    But i kept getting errors and no successful connection. My next guess was that problem could be in SSL , since we are using https. So, i went into the browser, imported security certificate ( they were self-signed since it's a test environment), added them to java cacerts keystore and added next to my code :
    System.setProperty("javax.net.ssl.keyStore", "keystore.jks");
    System.setProperty("javax.net.ssl.trustStrore", "cacerts.jks");
    System.setProperty("javax.net.ssl.keyStorePassword", "changeit");
    
    I tried to debug and to make sure that JVM is using my proxy settings and it was true - everything was there. What would be the next step in debugging for me ? I decided to install local proxy and try to put my requests through it, so i could get more details. I've installed Charles - a fantastic proxy server that helped me a lot in the past with REST API automation. It has a life changing ( for me in this case) "External Proxy" option . I've set it to forward all requests to our SOCKS proxy and then told to my tests to make calls through Charles. And it worked! You can't even believe how happy i was because of it:) But now i got another problem - Charles cost 50$ for one license:)So, there were 2 questions that i needed to solve : * Why my Java calls works fine with Charles and without it they fail? * Where to find free and easy to setup http proxy with forwarding possibility?:) With help from one of our developers we could find out why Java kept getting authentification errors and didn't want to connect to test environment properly. The problem was that java was connecting to SOCKS proxy properly, but it was resolving remote dns to another environment to which i didn't have proper certificates and credentials for authorization! I found only one article on stackoverflow regarding this issue and from that point i new that i need to have local http proxy that is : * free * can forward my requests to SOCKS proxy I've spent whole day trying to find some easy to use and adequate proxy server for Windows ( it's my Workstation that i need to use) , looked over 15 different apps and still couldn't find anything that i could use. In the end of the day i've installed VirtualBox with Ubuntu and installed there squid3 proxy server. It's the most popular and common proxy server for Unix, from what i saw on Google. But, this crazy proxy has configuration file with more then 3000 lines!! It's not that easy to make it run as i want, it's not even that easy to restart it. So, after couple hours i gave up on it and started looking for alternatives. Luckily, i found Polipo - tiny, easy to install and setup proxy server. It has few main options that i had to setup and make everything work as a charm : * proxyAddress - set it to ip address of your local virtual box, or your local machine, if you use linux or mac * allowedClients - list of ip addresses from which polipo will allow to access it and forward requests towards another proxy or web directly * socksParentProxy = "host name and port of your proxy to which i needed to forward my requests" * socksProxyType = socks5 Save changes and restart - that's it! After that i pointed my Java framework to local proxy and got green tests! To set proxy for my tests i used custom MyProxySelector class :
    package Base;
    
    import java.net.*;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.io.IOException;
    
    
    public  class MyProxySelector extends ProxySelector {
        // Keep a reference on the previous default
        public ProxySelector defsel = null;
    
        /**
         * Inner class representing a Proxy and a few extra data
         */
        class InnerProxy {
            Proxy proxy;
            SocketAddress addr;
            // How many times did we fail to reach this proxy?
            int failedCount = 0;
    
            InnerProxy(InetSocketAddress a) {
                addr = a;
                proxy = new Proxy(Proxy.Type.HTTP, a);
            }
    
            SocketAddress address() {
                return addr;
            }
    
            Proxy toProxy() {
                return proxy;
            }
    
            int failed() {
                return ++failedCount;
            }
        }
    
        /**
         * A list of proxies, indexed by their address.
         */
        HashMap proxies = new HashMap();
    
        public MyProxySelector(ProxySelector def, String host, int port) {
            // Save the previous default
            defsel = def;
    
            // Populate the HashMap (List of proxies)
            InnerProxy i = new InnerProxy(new InetSocketAddress(host, port));
            proxies.put(i.address(), i);
        }
    
        /**
         * This is the method that the handlers will call.
         * Returns a List of proxy.
         */
        public java.util.List select(URI uri) {
            // Let's stick to the specs. 
            if (uri == null) {
                throw new IllegalArgumentException("URI can't be null.");
            }
            /**
             * If it's a http (or https) URL, then we use our own
             * list.
             */
            String protocol = uri.getScheme();
            if ("http".equalsIgnoreCase(protocol) ||
                    "https".equalsIgnoreCase(protocol)) {
                ArrayList l = new ArrayList();
                for (InnerProxy p : proxies.values()) {
                    l.add(p.toProxy());
                }
                return l;
            }
            
            /**
             * Not HTTP or HTTPS (could be SOCKS or FTP)
             * defer to the default selector.
             */
            if (defsel != null) {
                return defsel.select(uri);
            } else {
                ArrayList l = new ArrayList();
                l.add(Proxy.NO_PROXY);
                return l;
            }
        }
    
        /**
         * Method called by the handlers when it failed to connect
         * to one of the proxies returned by select().
         */
        public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
            // Let's stick to the specs again.
            if (uri == null || sa == null || ioe == null) {
                throw new IllegalArgumentException("Arguments can't be null.");
            }
            
            /**
             * Let's lookup for the proxy 
             */
            InnerProxy p = proxies.get(sa);
            if (p != null) {
                    /**
                     * It's one of ours, if it failed more than 3 times
                     * let's remove it from the list.
                     */
                if (p.failed() >= 3)
                    proxies.remove(sa);
            } else {
                    /**
                     * Not one of ours, let's delegate to the default.
                     */
                if (defsel != null)
                    defsel.connectFailed(uri, sa, ioe);
            }
        }
    }
    
    And to turn proxy on and off i wrote next switch methods :
    private ProxySelector defaultProxy = ProxySelector.getDefault();
    public void setLocalProxy(){
            MyProxySelector ps = new MyProxySelector(ProxySelector.getDefault(),localProxyName,localProxyPort);
            ProxySelector.setDefault(ps);
    
        }
    
    public void disableProxy(){
        ProxySelector.setDefault(defaultProxy);
    
        }
    
    That's it. Now i can run my tests easily with control of when to use proxy and when not. In the future i'll move my tests to CI ( Jenkins most probably) and will setup on that environment Polipo proxy in 2 minutes. It's always nice to solve such non-ordinary problems. Most probably my solution is not very elegant and "right" , but it works right now and for this moment this what matters for me, since i can start writing automated tests rather then fighting with this configuration issues. *Update* . One of my colleagues proposed me to set next settings for Java :
    System.setProperty("sun.net.spi.nameservice.nameservers", "ip_here");
    System.setProperty("sun.net.spi.nameservice.provider.1", "dns,sun");
     
    But it didn't work for me. So will stick with my current solution for now.