Path: blob/master/test/jdk/java/awt/Clipboard/HTMLTransferTest/HTMLTransferTest.java
41153 views
/*1* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24@test25@key headful26@bug 6392086 801472527@summary tests that HTMLs of all supported native HTML formats are transfered28properly29@run main/othervm HTMLTransferTest30*/3132import java.awt.*;33import java.awt.datatransfer.*;34import java.io.*;3536public class HTMLTransferTest {37public static final int CODE_NOT_RETURNED = 100;38public static final int CODE_CONSUMER_TEST_FAILED = 101;39public static final int CODE_FAILURE = 102;40public static DataFlavor[] HTMLFlavors = null;41public static DataFlavor SyncFlavor = null;42static {43try{44HTMLFlavors = new DataFlavor[] {45new DataFlavor("text/html; document=selection; Class=" + InputStream.class.getName() + "; charset=UTF-8"),46new DataFlavor("text/html; document=selection; Class=" + String.class.getName() + "; charset=UTF-8")47};48SyncFlavor = new DataFlavor(49"application/x-java-serialized-object; class="50+ SyncMessage.class.getName()51+ "; charset=UTF-8"52);53}catch(Exception e){54e.printStackTrace();55}56}5758private THTMLProducer imPr;59private int returnCode = CODE_NOT_RETURNED;6061public static void main(final String[] args) {62HTMLTransferTest app = new HTMLTransferTest();63app.init();64app.start();65}6667public void init() {68initImpl();6970} // init()7172private void initImpl() {73imPr = new THTMLProducer();74imPr.begin();75}767778public void start() {79try {80String stFormats = "";8182String iniMsg = "Testing formats from the list:\n";83for (int i = 0; i < HTMLTransferTest.HTMLFlavors.length; i++) {84stFormats += "\"" + HTMLTransferTest.HTMLFlavors[i].getMimeType() + "\"\n";85}86System.out.println(iniMsg + stFormats);87System.err.println("===>" + iniMsg + stFormats);8889String javaPath = System.getProperty("java.home", "");90String cmd = javaPath + File.separator + "bin" + File.separator91+ "java -cp " + System.getProperty("test.classes", ".") +92//+ "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 "93" THTMLConsumer"94//+ stFormats95;9697Process process = Runtime.getRuntime().exec(cmd);98ProcessResults pres = ProcessResults.doWaitFor(process);99returnCode = pres.exitValue;100101if (pres.stderr != null && pres.stderr.length() > 0) {102System.err.println("========= Child VM System.err ========");103System.err.print(pres.stderr);104System.err.println("======================================");105}106107if (pres.stdout != null && pres.stdout.length() > 0) {108System.err.println("========= Child VM System.out ========");109System.err.print(pres.stdout);110System.err.println("======================================");111}112} catch (Throwable e) {113e.printStackTrace();114//returnCode equals CODE_NOT_RETURNED115}116117switch (returnCode) {118case CODE_NOT_RETURNED:119System.err.println("Child VM: failed to start");120break;121case CODE_FAILURE:122System.err.println("Child VM: abnormal termination");123break;124case CODE_CONSUMER_TEST_FAILED:125throw new RuntimeException("test failed: HTMLs in some " +126"native formats are not transferred properly: " +127"see output of child VM");128default:129boolean failed = false;130String passedFormats = "";131String failedFormats = "";132133for (int i = 0; i < imPr.passedArray.length; i++) {134if (imPr.passedArray[i]) {135passedFormats += HTMLTransferTest.HTMLFlavors[i].getMimeType() + " ";136} else {137failed = true;138failedFormats += HTMLTransferTest.HTMLFlavors[i].getMimeType() + " ";139}140}141if (failed) {142throw new RuntimeException(143"test failed: HTMLs in following "144+ "native formats are not transferred properly: "145+ failedFormats146);147} else {148System.err.println(149"HTMLs in following native formats are "150+ "transferred properly: "151+ passedFormats152);153}154}155156} // start()157158} // class HTMLTransferTest159160class SyncMessage implements Serializable {161String msg;162163public SyncMessage(String sync) {164this.msg = sync;165}166167@Override168public boolean equals(Object obj) {169return this.msg.equals(((SyncMessage)obj).msg);170}171172@Override173public String toString() {174return msg;175}176}177178class ProcessResults {179public int exitValue;180public String stdout;181public String stderr;182183public ProcessResults() {184exitValue = -1;185stdout = "";186stderr = "";187}188189/**190* Method to perform a "wait" for a process and return its exit value.191* This is a workaround for <code>Process.waitFor()</code> never returning.192*/193public static ProcessResults doWaitFor(Process p) {194ProcessResults pres = new ProcessResults();195196InputStream in = null;197InputStream err = null;198199try {200in = p.getInputStream();201err = p.getErrorStream();202203boolean finished = false;204205while (!finished) {206try {207while (in.available() > 0) {208pres.stdout += (char)in.read();209}210while (err.available() > 0) {211pres.stderr += (char)err.read();212}213// Ask the process for its exitValue. If the process214// is not finished, an IllegalThreadStateException215// is thrown. If it is finished, we fall through and216// the variable finished is set to true.217pres.exitValue = p.exitValue();218finished = true;219}220catch (IllegalThreadStateException e) {221// Process is not finished yet;222// Sleep a little to save on CPU cycles223Thread.currentThread().sleep(500);224}225}226if (in != null) in.close();227if (err != null) err.close();228}229catch (Throwable e) {230System.err.println("doWaitFor(): unexpected exception");231e.printStackTrace();232}233return pres;234}235}236237238abstract class HTMLTransferer implements ClipboardOwner {239240static final SyncMessage S_PASSED = new SyncMessage("Y");241static final SyncMessage S_FAILED = new SyncMessage("N");242static final SyncMessage S_BEGIN = new SyncMessage("B");243static final SyncMessage S_BEGIN_ANSWER = new SyncMessage("BA");244static final SyncMessage S_END = new SyncMessage("E");245246247248Clipboard m_clipboard;249250HTMLTransferer() {251m_clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();252}253254255abstract void notifyTransferSuccess(boolean status);256257258static Object createTRInstance(int i) {259try{260String _htmlText =261"The quick <font color='#78650d'>brown</font> <b>mouse</b> jumped over the lazy <b>cat</b>.";262switch(i){263case 0:264return new ByteArrayInputStream(_htmlText.getBytes("utf-8"));265case 1:266return _htmlText;267}268}catch(UnsupportedEncodingException e){ e.printStackTrace(); }269return null;270}271272static byte[] getContent(InputStream is)273{274ByteArrayOutputStream tmp = new ByteArrayOutputStream();275try{276int read;277while( -1 != (read = is.read()) ){278tmp.write(read);279};280} catch( IOException e ) {281e.printStackTrace();282}283return tmp.toByteArray();284}285286static void Dump(byte[] b){287System.err.println( new String(b) );288};289290void setClipboardContents(291Transferable contents,292ClipboardOwner owner293) {294synchronized (m_clipboard) {295boolean set = false;296while (!set) {297try {298m_clipboard.setContents(contents, owner);299set = true;300} catch (IllegalStateException ise) {301try {302Thread.sleep(100);303} catch(InterruptedException e) {304e.printStackTrace();305}306}307}308}309}310311Transferable getClipboardContents(Object requestor)312{313synchronized (m_clipboard) {314while (true) {315try {316Transferable t = m_clipboard.getContents(requestor);317return t;318} catch (IllegalStateException ise) {319try {320Thread.sleep(100);321} catch (InterruptedException e) {322e.printStackTrace();323}324}325}326}327}328329}330331332class THTMLProducer extends HTMLTransferer {333334boolean[] passedArray;335int fi = 0; // next format index336private boolean isFirstCallOfLostOwnership = true;337338THTMLProducer() {339passedArray = new boolean[HTMLTransferTest.HTMLFlavors.length];340}341342void begin() {343setClipboardContents(344new HTMLSelection(345HTMLTransferTest.SyncFlavor,346S_BEGIN347),348this349);350}351352public void lostOwnership(Clipboard cb, Transferable contents) {353System.err.println("{PRODUCER: lost clipboard ownership");354Transferable t = getClipboardContents(null);355if (t.isDataFlavorSupported(HTMLTransferTest.SyncFlavor)) {356SyncMessage msg = null;357// for test going on if t.getTransferData() will throw an exception358if (isFirstCallOfLostOwnership) {359isFirstCallOfLostOwnership = false;360msg = S_BEGIN_ANSWER;361} else {362msg = S_PASSED;363}364try {365msg = (SyncMessage)t.getTransferData(HTMLTransferTest.SyncFlavor);366System.err.println("++received message: " + msg);367} catch (Exception e) {368System.err.println("Can't getTransferData-message: " + e);369}370if( msg.equals(S_PASSED) ){371notifyTransferSuccess(true);372} else if( msg.equals(S_FAILED) ){373notifyTransferSuccess(false);374} else if (!msg.equals(S_BEGIN_ANSWER)) {375throw new RuntimeException("wrong message in " +376"THTMLProducer.lostOwnership(): " + msg +377" (possibly due to bug 4683804)");378}379} else {380throw new RuntimeException(381"DataFlavor.stringFlavor is not "382+ "suppurted by transferable in "383+ "THTMLProducer.lostOwnership()"384);385}386387if (fi < HTMLTransferTest.HTMLFlavors.length) {388System.err.println(389"testing native HTML format \""390+ HTMLTransferTest.HTMLFlavors[fi].getMimeType()391+ "\"..."392);393//leaveFormat( HTMLTransferTest.HTMLFlavors[fi].getMimeType() );394setClipboardContents(395new HTMLSelection(396HTMLTransferTest.HTMLFlavors[fi],397HTMLTransferer.createTRInstance(fi)398),399this400);401} else {402setClipboardContents(403new HTMLSelection(404HTMLTransferTest.SyncFlavor,405S_END406),407null408);409}410System.err.println("}PRODUCER: lost clipboard ownership");411}412413414void notifyTransferSuccess(boolean status) {415passedArray[fi] = status;416fi++;417}418419}420421422class THTMLConsumer extends HTMLTransferer423{424private static final Object LOCK = new Object();425private static boolean failed;426int fi = 0; // next format index427428public void lostOwnership(Clipboard cb, Transferable contents) {429System.err.println("{CONSUMER: lost clipboard ownership");430Transferable t = getClipboardContents(null);431boolean bContinue = true;432if(t.isDataFlavorSupported(HTMLTransferTest.SyncFlavor)) {433try {434SyncMessage msg = (SyncMessage)t.getTransferData(HTMLTransferTest.SyncFlavor);435System.err.println("received message: " + msg);436if(msg.equals(S_END)){437synchronized (LOCK) {438LOCK.notifyAll();439}440bContinue = false;441}442} catch (Exception e) {443System.err.println("Can't getTransferData-message: " + e);444}445}446if(bContinue){447// all HTML formats have been processed448System.err.println( "============================================================");449System.err.println( "Put as " + HTMLTransferTest.HTMLFlavors[fi].getMimeType() );450boolean bSuccess = false;451for(int i = 0; i < HTMLTransferTest.HTMLFlavors.length; ++i) {452System.err.println( "----------------------------------------------------------");453if( t.isDataFlavorSupported(HTMLTransferTest.HTMLFlavors[i]) ){454Object im = null; //? HTML;455try {456im = t.getTransferData(HTMLTransferTest.HTMLFlavors[i]);457if (im == null) {458System.err.println("getTransferData returned null");459} else {460System.err.println( "Extract as " + HTMLTransferTest.HTMLFlavors[i].getMimeType() );461String stIn = "(unknown)", stOut = "(unknown)";462switch( i ){463case 0:464stIn = new String( getContent( (InputStream)HTMLTransferer.createTRInstance(i) ) );465stOut = new String( getContent((InputStream)im) );466bSuccess = stIn.equals(stOut);467break;468case 1:469stIn = (String)HTMLTransferer.createTRInstance(i);470stOut = (String)im;471int head = stOut.indexOf("<HTML><BODY>");472if (head >= 0) {473stOut = stOut.substring(head + 12, stOut.length() - 14);474}475bSuccess = stIn.equals(stOut);476break;477default:478bSuccess = HTMLTransferer.createTRInstance(i).equals(im);479break;480};481System.err.println("in :" + stIn);482System.err.println("out:" + stOut);483};484} catch (Exception e) {485System.err.println("Can't getTransferData: " + e);486}487if(!bSuccess)488System.err.println("transferred DATA is different from initial DATA\n");489} else {490System.err.println("Flavor is not supported by transferable:\n");491DataFlavor[] dfs = t.getTransferDataFlavors();492int ii;493for(ii = 0; ii < dfs.length; ++ii)494System.err.println("Supported:" + dfs[ii] + "\n");495dfs = HTMLTransferTest.HTMLFlavors;496for(ii = 0; ii < dfs.length; ++ii)497System.err.println("Accepted:" + dfs[ii] + "\n" );498}499}500System.err.println( "----------------------------------------------------------");501notifyTransferSuccess(bSuccess);502System.err.println( "============================================================");503++fi;504}505System.err.println("}CONSUMER: lost clipboard ownership");506}507508509void notifyTransferSuccess(boolean status) {510System.err.println(511"format "512+ (status513? "passed"514: "failed"515)516+ "!!!"517);518setClipboardContents(519new HTMLSelection(520HTMLTransferTest.SyncFlavor,521status522? S_PASSED523: S_FAILED524),525this526);527}528529530public static void main(String[] args) {531try {532System.err.println("{CONSUMER: start");533THTMLConsumer ic = new THTMLConsumer();534ic.setClipboardContents(535new HTMLSelection(536HTMLTransferTest.SyncFlavor,537S_BEGIN_ANSWER538),539ic540);541synchronized (LOCK) {542LOCK.wait();543}544System.err.println("}CONSUMER: start");545} catch (Throwable e) {546e.printStackTrace();547System.exit(HTMLTransferTest.CODE_FAILURE);548}549}550551}552553554/**555* A <code>Transferable</code> which implements the capability required556* to transfer an <code>HTML</code>.557*558* This <code>Transferable</code> properly supports559* <code>HTMLTransferTest.HTMLFlavors</code>.560* and all equivalent flavors.561* No other <code>DataFlavor</code>s are supported.562*563* @see java.awt.datatransfer.HTMLTransferTest.HTMLFlavors564*/565class HTMLSelection implements Transferable {566private DataFlavor m_flavor;567private Object m_data;568569/**570* Creates a <code>Transferable</code> capable of transferring571* the specified <code>String</code>.572*/573public HTMLSelection(574DataFlavor flavor,575Object data576){577m_flavor = flavor;578m_data = data;579}580581/**582* Returns an array of flavors in which this <code>Transferable</code>583* can provide the data. <code>DataFlavor.stringFlavor</code>584* is properly supported.585* Support for <code>DataFlavor.plainTextFlavor</code> is586* <b>deprecated</b>.587*588* @return an array of length one, whose element is <code>DataFlavor.589* HTMLTransferTest.HTMLFlavors</code>590*/591public DataFlavor[] getTransferDataFlavors() {592// returning flavors itself would allow client code to modify593// our internal behavior594return new DataFlavor[]{ m_flavor } ;595}596597/**598* Returns whether the requested flavor is supported by this599* <code>Transferable</code>.600*601* @param flavor the requested flavor for the data602* @return true if <code>flavor</code> is equal to603* <code>HTMLTransferTest.HTMLFlavors</code>;604* false if <code>flavor</code>605* is not one of the above flavors606* @throws NullPointerException if flavor is <code>null</code>607*/608public boolean isDataFlavorSupported(DataFlavor flavor) {609System.err.println("Have:" + flavor + " Can:" + m_flavor);610if(flavor.equals(m_flavor))611return true;612return false;613}614615/**616* Returns the <code>Transferable</code>'s data in the requested617* <code>DataFlavor</code> if possible. If the desired flavor is618* <code>HTMLTransferTest.HTMLFlavors</code>, or an equivalent flavor,619* the <code>HTML</code> representing the selection is620* returned.621*622* @param flavor the requested flavor for the data623* @return the data in the requested flavor, as outlined above624* @throws UnsupportedFlavorException if the requested data flavor is625* not equivalent to <code>HTMLTransferTest.HTMLFlavors</code>626* @throws IOException if an IOException occurs while retrieving the data.627* By default, <code>HTMLSelection</code> never throws628* this exception, but a subclass may.629* @throws NullPointerException if flavor is <code>null</code>630*/631public Object getTransferData(DataFlavor flavor)632throws UnsupportedFlavorException, IOException633{634if (flavor.equals(m_flavor)) {635return (Object)m_data;636} else {637throw new UnsupportedFlavorException(flavor);638}639}640641} // class HTMLSelection642643644