/*
 * The MIT License
 *
 * Copyright (c) 2015, CloudBees, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.jenkinsci.plugins.docker.commons.credentials;

import com.cloudbees.plugins.credentials.Credentials;
import hudson.remoting.Callable;
import hudson.remoting.VirtualChannel;
import jenkins.authentication.tokens.api.AuthenticationTokens;
import net.sf.json.JSONObject;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.net.URL;

/**
 * Represents an authentication token that docker(1) understands when pushing/pulling
 * from a docker registry. Obtained from various {@link Credentials} implementations via {@link AuthenticationTokens}.
 *
 * @author Kohsuke Kawaguchi
 * @see AuthenticationTokens
 */
public final class DockerRegistryToken implements Serializable {
    private final String email;
    private final String token;

    public DockerRegistryToken(String email, String token) {
        this.email = email;
        this.token = token;
    }

    public String getEmail() {
        return email;
    }

    public String getToken() {
        return token;
    }

    /**
     * Makes the credentials available locally and returns {@link KeyMaterialFactory} that gives you the parameters
     * needed to access it.
     *
     * <p>
     * This is done by inserting the token into {@code ~/.dockercfg}
     */
    public KeyMaterialFactory newKeyMaterialFactory(final URL endpoint, VirtualChannel target) throws InterruptedException, IOException {
        target.call(new Callable<Void, IOException>() {
            /**
             * Insert the token into {@code ~/.dockercfg}
             */
            @Override
            public Void call() throws IOException {
                // TODO: TF: Should this not be done via docker login (possibly preceded by a logout) ?               

                File f = new File(System.getProperty("user.home"), ".dockercfg");
                JSONObject json = new JSONObject();

                synchronized (DockerRegistryToken.class) {// feeble attempt at serializing access to ~/.dockercfg
                    if (f.exists())
                        json = JSONObject.fromObject(FileUtils.readFileToString(f, "UTF-8"));

                    json.put(endpoint.toString(), new JSONObject()
                            .accumulate("auth", getToken())
                            .accumulate("email", getEmail()));

                    FileUtils.writeStringToFile(f, json.toString(2), "UTF-8");
                }

                return null;
            }
        });

        // risky to clean up ~/.dockercfg as multiple builds might try to use the same credentials
        return KeyMaterialFactory.NULL;
    }

    private static final long serialVersionUID = 1L;
}

@@ -2949,14 +2949,206 @@
     
-File f
+JSONObject json;%0A                JSONObject auths;%0A%0A                synchronized (DockerRegistryToken.class) %7B// feeble attempt at serializing access to ~/.dockercfg%0A%0A                    File config
  = n
@@ -3196,19 +3196,28 @@
 %22.docker
-cfg
+/config.json
 %22);%0A    
@@ -3232,148 +3232,308 @@
     
+  
-JSONObject json = new JSONObject();%0A%0A                synchronized (DockerRegistryToken.class) %7B// feeble attempt at serializing access to ~/
+  if (config.exists()) %7B%0A                        json = JSONObject.fromObject(FileUtils.readFileToString(config, %22UTF-8%22));%0A                        auths = json.getJSONObject(%22auths%22);%0A                    %7D else %7B%0A                        File dockercfg = new File(System.getProperty(%22user.home%22), %22
 .doc
@@ -3538,17 +3538,24 @@
 ockercfg
-%0A
+%22);%0A    
         
@@ -3570,17 +3570,25 @@
     if (
-f
+dockercfg
 .exists(
@@ -3589,16 +3589,18 @@
 xists())
+ %7B
 %0A       
@@ -3607,32 +3607,92 @@
                 
+     config = dockercfg;%0A                            auths =
  json = JSONObje
@@ -3732,17 +3732,25 @@
 oString(
-f
+dockercfg
 , %22UTF-8
@@ -3758,33 +3758,382 @@
 ));%0A
-%0A                    json
+                        %7D else %7B%0A                            // Use legacy .dockercfg to ensure this works well with pre-1.7 docker client%0A                            // client will pick this one if .docker/config.json does not yet exists%0A                            auths = json = new JSONObject();%0A                        %7D%0A                    %7D%0A%0A                    auths
 .put
@@ -4343,17 +4343,22 @@
 gToFile(
-f
+config
 , json.t

Support Docker 1.7+ .docker/config.json