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