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