/*
 * Copyright (c) 2015, 2024, 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.
 */

import java.security.Security;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;

/**
 * @test
 * @bug 8076359 8133151 8150512
 * @summary Test for jdk.security.provider.preferred security property
 * @run main/othervm  PreferredProviderNegativeTest preSet AES false
 * @run main/othervm  PreferredProviderNegativeTest preSet AES:SunNegative true
 * @run main/othervm  PreferredProviderNegativeTest afterSet AES:SunJGSS
 * @run main/othervm  PreferredProviderNegativeTest afterSet AES:SunECNegative
 * @run main/othervm  PreferredProviderNegativeTest invalidAlg AESInvalid:SunJCE
 */
public class PreferredProviderNegativeTest {

    static final String SEC_PREF_PROP = "jdk.security.provider.preferred";

    /*
     * Test security property could be set by valid and invalid provider
     * before JCE was loaded
     */
    public static void preJCESet(String value, boolean negativeProvider)
            throws NoSuchAlgorithmException, NoSuchPaddingException {

        Security.setProperty(SEC_PREF_PROP, value);

        if (!Security.getProperty(SEC_PREF_PROP).equals(value)) {
            throw new RuntimeException("Test Failed:The property wasn't set");
        }

        String[] arrays = value.split(":");
        Cipher cipher = Cipher.getInstance(arrays[0]);
        if (negativeProvider) {
            if (cipher.getProvider().getName().equals(arrays[1])) {
                throw new RuntimeException(
                        "Test Failed:The provider shouldn't be set.");
            }
        } else {
            if (!cipher.getProvider().getName().equals(arrays[1])) {
                throw new RuntimeException("Test Failed:The provider could be "
                        + "set by valid provider.");
            }
        }
        System.out.println("Test Pass.");
    }

    /*
     * Test that the setting of the security property after Cipher.getInstance()
     * does not influence previously loaded instances
     */
    public static void afterJCESet(String value, String expected)
            throws NoSuchAlgorithmException, NoSuchPaddingException {
        String[] arrays = value.split(":");
        Cipher cipher = Cipher.getInstance(arrays[0]);

        Security.setProperty(SEC_PREF_PROP, value);
        if (!cipher.getProvider().getName().equals(expected)) {
            throw new RuntimeException("Test Failed:The security property can't"
                    + " be updated after JCE load.");
        }
        System.out.println("Test Pass");
    }

    /* Test the security property with negative algorithm */
    public static void invalidAlg(String value) throws NoSuchPaddingException {
        String[] arrays = value.split(":");

        try {
            Security.setProperty(SEC_PREF_PROP, value);
            Cipher.getInstance(arrays[0]);
        } catch (NoSuchAlgorithmException e) {
            System.out.println(
                    "Test Pass:Got NoSuchAlgorithmException as expired");
            return;
        }
        throw new RuntimeException(
                "Test Failed:Expected NoSuchAlgorithmException was not thrown");
    }

    public static void main(String[] args)
            throws NoSuchAlgorithmException, NoSuchPaddingException {

        String expected;
        String value = args[1];
        expected = System.getProperty("test.provider.name", "SunJCE");

        if (args.length >= 2) {
            switch (args[0]) {
                case "preSet":
                    boolean negativeProvider = Boolean.valueOf(args[2]);
                    if (!args[1].contains(":")) {
                        value += ":" + expected;
                    }
                    PreferredProviderNegativeTest.preJCESet(
                            value, negativeProvider);
                    break;
                case "afterSet":
                    PreferredProviderNegativeTest.afterJCESet(args[1],
                            expected);
                    break;
                case "invalidAlg":
                    PreferredProviderNegativeTest.invalidAlg(args[1]);
                    break;
            }
        } else {
            throw new RuntimeException(
                    "Test Failed:Please pass the correct args");
        }
    }
}