1 /* 2 * To change this template, choose Tools | Templates 3 * and open the template in the editor. 4 */ 5 6 package complex.sfx2; 7 8 import com.sun.star.document.DocumentEvent; 9 import com.sun.star.document.XDocumentEventBroadcaster; 10 import com.sun.star.document.XDocumentEventListener; 11 import com.sun.star.lang.EventObject; 12 import com.sun.star.lang.XEventListener; 13 import com.sun.star.uno.Exception; 14 import com.sun.star.uno.UnoRuntime; 15 import com.sun.star.util.CloseVetoException; 16 import com.sun.star.util.XCloseListener; 17 import com.sun.star.util.XCloseable; 18 import java.util.Vector; 19 import java.util.logging.Level; 20 import java.util.logging.Logger; 21 import org.junit.After; 22 import org.junit.Before; 23 import org.junit.Test; 24 import static org.junit.Assert.*; 25 import org.openoffice.test.tools.OfficeDocument; 26 27 /** 28 * 29 * @author frank.shoenheit@oracle.com 30 */ 31 public class DocumentEvents extends JUnitBasedTest 32 { 33 @Before 34 public void beforeTest() throws Exception 35 { 36 m_document = OfficeDocument.blankTextDocument( this.getORB() ); 37 } 38 39 @After 40 public void afterTest() 41 { 42 if ( m_document != null ) 43 { 44 assertTrue( "closing the test document failed", m_document.close() ); 45 m_document = null; 46 } 47 } 48 49 /** 50 * sets up the environment for a test which checks the behavior upon closing a doc 51 */ 52 private void impl_setupDocCloseTest() 53 { 54 m_observedCloseEvents.clear(); 55 56 final XDocumentEventBroadcaster docEventBroadcaster = UnoRuntime.queryInterface( 57 XDocumentEventBroadcaster.class, m_document.getDocument() ); 58 docEventBroadcaster.addDocumentEventListener( new DocumentEventListener() ); 59 60 final XCloseable docCloseable = UnoRuntime.queryInterface( XCloseable.class, 61 m_document.getDocument() ); 62 docCloseable.addCloseListener( new CloseListener() ); 63 64 m_document.getDocument().addEventListener( new DocDisposeListener() ); 65 } 66 67 /** 68 * sets up the environment for a test which checks the behavior upon closing a doc 69 */ 70 private void impl_tearDownDocCloseTest( final String i_docCloseMethod ) 71 { 72 synchronized( m_document ) 73 { 74 try 75 { 76 m_document.wait(10000); 77 } 78 catch (InterruptedException ex) 79 { 80 // don't continue the test if somebody interrupted us ... 81 return; 82 } 83 } 84 85 m_document = null; 86 synchronized( m_observedCloseEvents ) 87 { 88 assertArrayEquals( 89 "wrong order of events when closing a doc " + i_docCloseMethod, 90 new CloseEventType[] { CloseEventType.OnUnload, CloseEventType.NotifyClosing, CloseEventType.Disposing }, 91 m_observedCloseEvents.toArray( new CloseEventType[0] ) 92 ); 93 } 94 } 95 96 @Test 97 public void testCloseWinEvents() throws Exception 98 { 99 impl_setupDocCloseTest(); 100 m_document.getCurrentView().dispatch( ".uno:CloseWin" ); 101 impl_tearDownDocCloseTest( "via .uno:CloseWin" ); 102 } 103 104 //@Test 105 public void testCloseDocEvents() throws Exception 106 { 107 impl_setupDocCloseTest(); 108 m_document.getCurrentView().dispatch( ".uno:CloseDoc" ); 109 impl_tearDownDocCloseTest( "via .uno:CloseDoc" ); 110 } 111 112 //@Test 113 public void testCloseByAPI() throws Exception 114 { 115 impl_setupDocCloseTest(); 116 // closing the doc by API is synchronous, so do this in a separate thread, else we will get a deadlock 117 // when the document tries to call back our listener (well, I admit I didn't understand *why* we get this 118 // deadlock ... :-\ ) 119 (new DocCloser()).start(); 120 impl_tearDownDocCloseTest( "by API" ); 121 } 122 123 private class DocumentEventListener implements XDocumentEventListener 124 { 125 126 public void documentEventOccured( DocumentEvent i_documentEvent ) 127 { 128 if ( i_documentEvent.EventName.equals( "OnUnload" ) ) 129 { 130 synchronized( m_observedCloseEvents ) 131 { 132 m_observedCloseEvents.add( CloseEventType.OnUnload ); 133 } 134 } 135 } 136 137 public void disposing(EventObject eo) 138 { 139 // not interested in 140 } 141 }; 142 143 private class CloseListener implements XCloseListener 144 { 145 146 public void queryClosing(EventObject eo, boolean bln) throws CloseVetoException 147 { 148 // not interested in 149 } 150 151 public void notifyClosing(EventObject eo) 152 { 153 synchronized( m_observedCloseEvents ) 154 { 155 m_observedCloseEvents.add( CloseEventType.NotifyClosing ); 156 } 157 } 158 159 public void disposing(EventObject eo) 160 { 161 // not interested in 162 } 163 }; 164 165 private class DocDisposeListener implements XEventListener 166 { 167 public void disposing(EventObject eo) 168 { 169 synchronized( m_observedCloseEvents ) 170 { 171 m_observedCloseEvents.add( CloseEventType.Disposing ); 172 } 173 synchronized ( m_document ) 174 { 175 m_document.notifyAll(); 176 } 177 } 178 }; 179 180 private class DocCloser extends Thread 181 { 182 @Override 183 public void run() 184 { 185 try 186 { 187 final XCloseable docCloseable = UnoRuntime.queryInterface(XCloseable.class, m_document.getDocument()); 188 docCloseable.close(true); 189 } 190 catch (CloseVetoException ex) 191 { 192 Logger.getLogger(DocumentEvents.class.getName()).log(Level.SEVERE, null, ex); 193 } 194 } 195 }; 196 197 private enum CloseEventType 198 { 199 OnUnload, 200 NotifyClosing, 201 Disposing 202 }; 203 204 private OfficeDocument m_document = null; 205 final private Vector< CloseEventType > m_observedCloseEvents = new Vector<DocumentEvents.CloseEventType>(); 206 } 207