/*
 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @bug 6659990 8147772
 * @summary test the immutability of the Date fields in KerberosTicket class,
 *          serialization, and behavior after being destroyed.
 * @ignore Must set up KDC and setup Kerberos configuration file
 */

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Date;
import java.io.*;
import javax.security.auth.RefreshFailedException;
import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.auth.kerberos.KerberosTicket;
import java.util.Base64;

public class KerberosTixDateTest {

    // Serialized KerberosTicket from JDK6 (encoded in BASE64)
    // Note: the KerberosTicket object is created using the same values as
    // the KerberosTicket 't' in main(). Deserialization should succeed
    // and the deserialized object should equal to 't'.
    static String serializedKerberosTix =
"rO0ABXNyACtqYXZheC5zZWN1cml0eS5hdXRoLmtlcmJlcm9zLktlcmJlcm9zVGlja2V0ZqGBbXB3" +
"w7sCAApbAAxhc24xRW5jb2Rpbmd0AAJbQkwACGF1dGhUaW1ldAAQTGphdmEvdXRpbC9EYXRlO0wA" +
"BmNsaWVudHQAMExqYXZheC9zZWN1cml0eS9hdXRoL2tlcmJlcm9zL0tlcmJlcm9zUHJpbmNpcGFs" +
"O1sAD2NsaWVudEFkZHJlc3Nlc3QAF1tMamF2YS9uZXQvSW5ldEFkZHJlc3M7TAAHZW5kVGltZXEA" +
"fgACWwAFZmxhZ3N0AAJbWkwACXJlbmV3VGlsbHEAfgACTAAGc2VydmVycQB+AANMAApzZXNzaW9u" +
"S2V5dAAmTGphdmF4L3NlY3VyaXR5L2F1dGgva2VyYmVyb3MvS2V5SW1wbDtMAAlzdGFydFRpbWVx" +
"AH4AAnhwdXIAAltCrPMX+AYIVOACAAB4cAAAAARhc24xc3IADmphdmEudXRpbC5EYXRlaGqBAUtZ" +
"dBkDAAB4cHcIAAAAAAC8YU54c3IALmphdmF4LnNlY3VyaXR5LmF1dGgua2VyYmVyb3MuS2VyYmVy" +
"b3NQcmluY2lwYWyZp31dDx4zKQMAAHhwdXEAfgAIAAAAEzARoAMCAQGhCjAIGwZjbGllbnR1cQB+" +
"AAgAAAAVGxNKTEFCUy5TRkJBWS5TVU4uQ09NeHBxAH4AC3VyAAJbWlePIDkUuF3iAgAAeHAAAAAg" +
"AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxAH4AC3NxAH4ADHVxAH4ACAAAABMwEaAD" +
"AgEBoQowCBsGc2VydmVydXEAfgAIAAAAFRsTSkxBQlMuU0ZCQVkuU1VOLkNPTXhzcgAkamF2YXgu" +
"c2VjdXJpdHkuYXV0aC5rZXJiZXJvcy5LZXlJbXBskoOG6DyvS9cDAAB4cHVxAH4ACAAAABUwE6AD" +
        "AgEBoQwECnNlc3Npb25LZXl4cQB+AAs=";

    public static void main(String[] args) throws Exception {
        byte[] asn1Bytes = "asn1".getBytes();
        KerberosPrincipal client = new KerberosPrincipal("client");
        KerberosPrincipal server = new KerberosPrincipal("server");
        byte[] keyBytes = "sessionKey".getBytes();
        long originalTime = 12345678L;
        Date inDate = new Date(originalTime);
        boolean[] flags = new boolean[9];
        flags[8] = true; // renewable
        KerberosTicket t = new KerberosTicket(asn1Bytes, client, server,
                keyBytes, 1 /*keyType*/, flags, inDate /*authTime*/,
                inDate /*startTime*/, inDate /*endTime*/,
                inDate /*renewTill*/, null /*clientAddresses*/);
        inDate.setTime(0); // for testing the constructor

        testDateImmutability(t, originalTime);
        testS11nCompatibility(t); // S11n: Serialization
        testDestroy(t);
    }

    private static void checkTime(KerberosTicket kt, long timeValue) {
        if (kt.getAuthTime().getTime() != timeValue) {
            throw new RuntimeException("authTime check fails!");
        }
        if (kt.getStartTime().getTime() != timeValue) {
            throw new RuntimeException("startTime check fails!");
        }
        if (kt.getEndTime().getTime() != timeValue) {
            throw new RuntimeException("endTime check fails!");
        }
        if (kt.getRenewTill().getTime() != timeValue) {
            throw new RuntimeException("renewTill check fails!");
        }
    }

    private static void testDateImmutability(KerberosTicket t, long origTime)
        throws Exception {
        // test the constructor
        System.out.println("Testing constructor...");
        checkTime(t, origTime);

        // test the getAuth/Start/EndTime() & getRenewTill() methods
        System.out.println("Testing getAuth/Start/EndTime() & getRenewTill()...");
        t.getAuthTime().setTime(0);
        t.getStartTime().setTime(0);
        t.getEndTime().setTime(0);
        t.getRenewTill().setTime(0);
        checkTime(t, origTime);

        System.out.println("DateImmutability Test Passed");
    }

    private static void checkEqualsAndHashCode(byte[] bytes, KerberosTicket t)
        throws IOException, ClassNotFoundException {
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        KerberosTicket deserializedTicket = (KerberosTicket)
                (new ObjectInputStream(bais).readObject());
        if (!deserializedTicket.equals(t)) {
            throw new RuntimeException("equals() check fails!");
        }
        if (deserializedTicket.hashCode() != t.hashCode()) {
            throw new RuntimeException("hashCode() check fails!");
        }
    }

    private static void testS11nCompatibility(KerberosTicket t)
        throws Exception {

        System.out.println("Testing against KerberosTicket from JDK6...");
        byte[] serializedBytes =
            Base64.getMimeDecoder().decode(serializedKerberosTix);
        checkEqualsAndHashCode(serializedBytes, t);

        System.out.println("Testing against KerberosTicket from current rel...");
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        new ObjectOutputStream(baos).writeObject(t);
        checkEqualsAndHashCode(baos.toByteArray(), t);

        System.out.println("S11nCompatibility Test Passed");
    }

    private static void testDestroy(KerberosTicket t) throws Exception {
        t.destroy();
        if (!t.isDestroyed()) {
            throw new RuntimeException("ticket should have been destroyed");
        }
        // Although these methods are meaningless, they can be called
        for (Method m: KerberosTicket.class.getDeclaredMethods()) {
            if (Modifier.isPublic(m.getModifiers())
                    && m.getParameterCount() == 0) {
                System.out.println("Testing " + m.getName() + "...");
                try {
                    m.invoke(t);
                } catch (InvocationTargetException e) {
                    Throwable cause = e.getCause();
                    if (cause instanceof RefreshFailedException ||
                            cause instanceof IllegalStateException) {
                        // this is OK
                    } else {
                        throw e;
                    }
                }
            }
        }
        System.out.println("Destroy Test Passed");
    }
}
