/*
 * Copyright (c) 2002, 2025, 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 4638351
 * @summary tests that HTML transfer doesn't cause console output
 * @key headful
 * @library /test/lib
 * @run main HTMLTransferConsoleOutputTest
 */

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;

public class HTMLTransferConsoleOutputTest implements ClipboardOwner {
    static final Clipboard clipboard =
            Toolkit.getDefaultToolkit().getSystemClipboard();
    static final DataFlavor dataFlavor =
            new DataFlavor("text/html; class=java.lang.String", null);
    static final String magic = "TESTMAGICSTRING";
    static final Transferable transferable = new Transferable() {
        final DataFlavor[] flavors = new DataFlavor[]{dataFlavor};
        final String data = "<html><body>" + magic + "</html></body>";

        public DataFlavor[] getTransferDataFlavors() {
            return flavors;
        }

        public boolean isDataFlavorSupported(DataFlavor df) {
            return dataFlavor.equals(df);
        }

        public Object getTransferData(DataFlavor df)
                throws UnsupportedFlavorException {
            if (!isDataFlavorSupported(df)) {
                throw new UnsupportedFlavorException(df);
            }
            return data;
        }
    };
    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    public static final int CLIPBOARD_DELAY = 1000;

    public static void main(String[] args) throws Exception {
        if (args.length == 0) {
            HTMLTransferConsoleOutputTest htmlTransferConsoleOutputTest = new HTMLTransferConsoleOutputTest();
            htmlTransferConsoleOutputTest.initialize();
            return;
        }
        final ClipboardOwner clipboardOwner = new ClipboardOwner() {
            public void lostOwnership(Clipboard clip,
                                      Transferable contents) {
                System.exit(0);
            }
        };
        clipboard.setContents(transferable, clipboardOwner);
        final Object o = new Object();
        synchronized (o) {
            try {
                o.wait();
            } catch (InterruptedException ie) {
                ie.printStackTrace();
            }
        }
        System.out.println("Test Pass!");
    }

    public void initialize() throws Exception {
        clipboard.setContents(transferable, this);
        ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(
                HTMLTransferConsoleOutputTest.class.getName(),
                "child"
        );

        Process process = ProcessTools.startProcess("Child", pb);
        OutputAnalyzer outputAnalyzer = new OutputAnalyzer(process);

        if (!process.waitFor(15, TimeUnit.SECONDS)) {
            process.destroyForcibly();
            throw new TimeoutException("Timed out waiting for Child");
        }

        byte[] bytes = baos.toByteArray();
        String string = null;
        try {
            string = new String(bytes, "ASCII");
        } catch (UnsupportedEncodingException uee) {
            uee.printStackTrace();
        }
        if (string.lastIndexOf(magic) != -1) {
            throw new RuntimeException("Test failed. Output contains:" +
                    string);
        }

        outputAnalyzer.shouldHaveExitValue(0);
    }


    static class ForkOutputStream extends OutputStream {
        final OutputStream outputStream1;
        final OutputStream outputStream2;

        public ForkOutputStream(OutputStream os1, OutputStream os2) {
            outputStream1 = os1;
            outputStream2 = os2;
        }

        public void write(int b) throws IOException {
            outputStream1.write(b);
            outputStream2.write(b);
        }

        public void flush() throws IOException {
            outputStream1.flush();
            outputStream2.flush();
        }

        public void close() throws IOException {
            outputStream1.close();
            outputStream2.close();
        }
    }

    public void lostOwnership(Clipboard clip, Transferable contents) {
        final Runnable r = () -> {
            try {
                Thread.sleep(CLIPBOARD_DELAY);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            final PrintStream oldOut = System.out;
            final PrintStream newOut =
                    new PrintStream(new ForkOutputStream(oldOut, baos));
            Transferable t = clipboard.getContents(null);
            try {
                System.setOut(newOut);
                t.getTransferData(dataFlavor);
                System.setOut(oldOut);
            } catch (IOException | UnsupportedFlavorException ioe) {
                ioe.printStackTrace();
            }
            clipboard.setContents(transferable, null);
        };
        final Thread t = new Thread(r);
        t.start();
    }
}
