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 package org.openoffice.test.tools;
24 
25 import com.sun.star.beans.PropertyState;
26 import com.sun.star.beans.PropertyValue;
27 import com.sun.star.document.MacroExecMode;
28 import com.sun.star.drawing.XDrawPage;
29 import com.sun.star.drawing.XDrawPageSupplier;
30 import com.sun.star.drawing.XDrawPages;
31 import com.sun.star.drawing.XDrawPagesSupplier;
32 import com.sun.star.frame.XComponentLoader;
33 import com.sun.star.frame.XController;
34 import com.sun.star.frame.XFrame;
35 import com.sun.star.frame.XModel;
36 import com.sun.star.lang.XComponent;
37 import com.sun.star.lang.XMultiServiceFactory;
38 import com.sun.star.lang.XServiceInfo;
39 import com.sun.star.uno.UnoRuntime;
40 import com.sun.star.uno.XInterface;
41 import com.sun.star.util.CloseVetoException;
42 import com.sun.star.util.XCloseable;
43 import com.sun.star.util.XModifiable;
44 import java.util.logging.Level;
45 import java.util.logging.Logger;
46 
47 /**************************************************************************/
48 
49 /**************************************************************************/
50 /** provides a small wrapper around a document
51 */
52 public class OfficeDocument
53 {
54     /* ================================================================== */
55     /* ------------------------------------------------------------------ */
OfficeDocument( XMultiServiceFactory orb, XComponent document )56     public OfficeDocument( XMultiServiceFactory orb, XComponent document )
57     {
58         m_orb = orb;
59         m_documentComponent = document;
60     }
61 
62     /* ------------------------------------------------------------------ */
implLoadAsComponent( XMultiServiceFactory orb, String documentOrFactoryURL )63     protected static XComponent implLoadAsComponent( XMultiServiceFactory orb, String documentOrFactoryURL ) throws com.sun.star.uno.Exception
64     {
65 		return implLoadAsComponent( orb, documentOrFactoryURL, new PropertyValue[0] );
66 	}
67 
68     /* ------------------------------------------------------------------ */
implLoadAsComponent( XMultiServiceFactory orb, String documentOrFactoryURL, final PropertyValue[] i_args )69     protected static XComponent implLoadAsComponent( XMultiServiceFactory orb, String documentOrFactoryURL, final PropertyValue[] i_args ) throws com.sun.star.uno.Exception
70     {
71         XComponentLoader aLoader = UnoRuntime.queryInterface( XComponentLoader.class,
72             orb.createInstance( "com.sun.star.frame.Desktop" ) );
73 
74         XComponent document = UnoRuntime.queryInterface( XComponent.class,
75             aLoader.loadComponentFromURL( documentOrFactoryURL, "_blank", 0, i_args )
76         );
77         return document;
78     }
79 
80     /* ------------------------------------------------------------------ */
implLoadDocument( XMultiServiceFactory orb, String documentOrFactoryURL )81     private static OfficeDocument implLoadDocument( XMultiServiceFactory orb, String documentOrFactoryURL ) throws com.sun.star.uno.Exception
82     {
83 		return implLoadDocument( orb, documentOrFactoryURL, new PropertyValue[0] );
84 	}
85 
86     /* ------------------------------------------------------------------ */
implLoadDocument( XMultiServiceFactory orb, String documentOrFactoryURL, final PropertyValue[] i_args )87     private static OfficeDocument implLoadDocument( XMultiServiceFactory orb, String documentOrFactoryURL, final PropertyValue[] i_args ) throws com.sun.star.uno.Exception
88     {
89         XComponent document = implLoadAsComponent( orb, documentOrFactoryURL, i_args );
90 
91         XServiceInfo xSI = UnoRuntime.queryInterface( XServiceInfo.class, document );
92         if ( xSI.supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) )
93             return new SpreadsheetDocument( orb, document );
94         return new OfficeDocument( orb, document );
95     }
96 
97     /* ------------------------------------------------------------------ */
loadDocument( XMultiServiceFactory orb, String documentURL )98     public static OfficeDocument loadDocument( XMultiServiceFactory orb, String documentURL ) throws com.sun.star.uno.Exception
99     {
100         return implLoadDocument( orb, documentURL );
101     }
102 
103     /* ------------------------------------------------------------------ */
blankTextDocument( XMultiServiceFactory orb )104     public static OfficeDocument blankTextDocument( XMultiServiceFactory orb ) throws com.sun.star.uno.Exception
105     {
106         return blankDocument( orb, DocumentType.WRITER );
107     }
108 
109     /* ------------------------------------------------------------------ */
blankXMLForm( XMultiServiceFactory orb )110     public static OfficeDocument blankXMLForm( XMultiServiceFactory orb ) throws com.sun.star.uno.Exception
111     {
112         return blankDocument( orb, DocumentType.XMLFORM );
113     }
114 
115     /* ------------------------------------------------------------------ */
blankDocument( XMultiServiceFactory orb, DocumentType eType )116     public static OfficeDocument blankDocument( XMultiServiceFactory orb, DocumentType eType ) throws com.sun.star.uno.Exception
117     {
118 		final PropertyValue[] args = new PropertyValue[] {
119 			new PropertyValue( "MacroExecutionMode", -1, MacroExecMode.ALWAYS_EXECUTE, PropertyState.DIRECT_VALUE )
120 		};
121         return implLoadDocument( orb, getDocumentFactoryURL( eType ), args );
122     }
123 
124     /* ------------------------------------------------------------------ */
close()125     public boolean close()
126     {
127         try
128         {
129             XCloseable closeDoc = UnoRuntime.queryInterface( XCloseable.class, m_documentComponent );
130             closeDoc.close( true );
131             return true;
132         }
133         catch ( CloseVetoException e )
134         {
135             Logger.getLogger( OfficeDocument.class.getName() ).log( Level.SEVERE, "closing the document was vetoed", e );
136         }
137         return false;
138     }
139 
140     /* ================================================================== */
141     /* ------------------------------------------------------------------ */
getDocument( )142     public XComponent getDocument( )
143     {
144         return m_documentComponent;
145     }
146 
147     /* ------------------------------------------------------------------ */
isModified()148     public boolean isModified()
149     {
150         XModifiable modify = (XModifiable)query( XModifiable.class );
151         return modify.isModified();
152     }
153 
154     /* ------------------------------------------------------------------ */
query( Class aInterfaceClass )155     public Object query( Class aInterfaceClass )
156     {
157         return UnoRuntime.queryInterface( aInterfaceClass, m_documentComponent );
158     }
159 
160     /* ------------------------------------------------------------------ */
getOrb( )161     public XMultiServiceFactory getOrb( )
162     {
163         return m_orb;
164     }
165 
166     /* ------------------------------------------------------------------ */
167     /** retrieves the current view of the document
168         @return
169             the view component, queried for the interface described by aInterfaceClass
170     */
getCurrentView( )171     public OfficeDocumentView getCurrentView( )
172     {
173         // get the model interface for the document
174         XModel xDocModel = UnoRuntime.queryInterface( XModel.class, m_documentComponent );
175         // get the current controller for the document - as a controller is tied to a view,
176         // this gives us the currently active view for the document.
177         XController xController = xDocModel.getCurrentController();
178 
179         if ( classify() == DocumentType.CALC )
180             return new SpreadsheetView( m_orb, this, xController );
181 
182         return new OfficeDocumentView( m_orb, this, xController );
183     }
184 
185     /* ------------------------------------------------------------------ */
186     /** reloads the document
187      *
188      *  The reload is done by dispatching the respective URL at a frame of the document.
189      *  As a consequence, if you have references to a view of the document, or any interface
190      *  of the document, they will become invalid.
191      *  The Model instance itself, at which you called reload, will still be valid, it will
192      *  automatically update its internal state after the reload.
193      *
194      *  Another consequence is that if the document does not have a view at all, it cannot
195      *  be reloaded.
196      */
reload()197     public void reload() throws Exception
198     {
199         OfficeDocumentView view = getCurrentView();
200         XFrame frame = view.getController().getFrame();
201         XModel oldModel = frame.getController().getModel();
202 
203         getCurrentView().dispatch( ".uno:Reload" );
204 
205         m_documentComponent = UnoRuntime.queryInterface( XComponent.class, frame.getController().getModel() );
206 
207         XModel newModel = getCurrentView().getController().getModel();
208         if ( UnoRuntime.areSame( oldModel, newModel ) )
209             throw new java.lang.IllegalStateException( "reload failed" );
210     }
211 
212     /* ------------------------------------------------------------------ */
213     /** returns a URL which can be used to create a document of a certain type
214     */
getDocumentFactoryURL( DocumentType eType )215     public static String getDocumentFactoryURL( DocumentType eType )
216     {
217         if ( eType == DocumentType.WRITER )
218             return "private:factory/swriter";
219         if ( eType == DocumentType.CALC )
220             return "private:factory/scalc";
221         if ( eType == DocumentType.DRAWING )
222             return "private:factory/sdraw";
223         if ( eType == DocumentType.XMLFORM )
224             return "private:factory/swriter?slot=21053";
225         if ( eType == DocumentType.PRESENTATION )
226             return "private:factory/simpress";
227         if ( eType == DocumentType.FORMULA )
228             return "private:factory/smath";
229         return "private:factory/swriter";
230     }
231 
232     /* ------------------------------------------------------------------ */
233     /** classifies a document
234     */
classify( )235     public DocumentType classify( )
236     {
237         XServiceInfo xSI = UnoRuntime.queryInterface( XServiceInfo.class, m_documentComponent );
238 
239         if ( xSI.supportsService( "com.sun.star.text.TextDocument" ) )
240             return DocumentType.WRITER;
241         else if ( xSI.supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) )
242             return DocumentType.CALC;
243         else if ( xSI.supportsService( "com.sun.star.drawing.DrawingDocument" ) )
244             return DocumentType.DRAWING;
245         else if ( xSI.supportsService( "com.sun.star.presentation.PresentationDocument" ) )
246             return DocumentType.PRESENTATION;
247         else if ( xSI.supportsService( "com.sun.star.formula.FormulaProperties" ) )
248             return DocumentType.FORMULA;
249 
250         return DocumentType.UNKNOWN;
251     }
252 
253     /* ------------------------------------------------------------------ */
254     /** retrieves a com.sun.star.drawing.DrawPage of the document, denoted by index
255      *  @param index
256      *      the index of the draw page
257      *  @throws
258      *      com.sun.star.lang.IndexOutOfBoundsException
259      *      com.sun.star.lang.WrappedTargetException
260      */
getDrawPage( int index )261     protected XDrawPage getDrawPage( int index ) throws com.sun.star.lang.IndexOutOfBoundsException, com.sun.star.lang.WrappedTargetException
262     {
263         XDrawPagesSupplier xSuppPages = UnoRuntime.queryInterface( XDrawPagesSupplier.class, getDocument() );
264         XDrawPages xPages = xSuppPages.getDrawPages();
265 
266         return UnoRuntime.queryInterface( XDrawPage.class, xPages.getByIndex( index ) );
267     }
268 
269     /* ------------------------------------------------------------------ */
270     /** retrieves the <type scope="com.sun.star.drawing">DrawPage</type> of the document
271     */
getMainDrawPage( )272     protected XDrawPage getMainDrawPage( ) throws com.sun.star.uno.Exception
273     {
274         XDrawPage xReturn;
275 
276         // in case of a Writer document, this is rather easy: simply ask the XDrawPageSupplier
277         XDrawPageSupplier xSuppPage = UnoRuntime.queryInterface( XDrawPageSupplier.class, getDocument() );
278         if ( null != xSuppPage )
279             xReturn = xSuppPage.getDrawPage();
280         else
281         {   // the model itself is no draw page supplier - okay, it may be a Writer or Calc document
282             // (or any other multi-page document)
283             XDrawPagesSupplier xSuppPages = UnoRuntime.queryInterface( XDrawPagesSupplier.class, getDocument() );
284             XDrawPages xPages = xSuppPages.getDrawPages();
285 
286             xReturn = UnoRuntime.queryInterface( XDrawPage.class, xPages.getByIndex( 0 ) );
287 
288             // Note that this is no really error-proof code: If the document model does not support the
289             // XDrawPagesSupplier interface, or if the pages collection returned is empty, this will break.
290         }
291 
292         return xReturn;
293     }
294 
295     /* ------------------------------------------------------------------ */
296     /** creates a component at the service factory provided by the document
297     */
createInstance( String serviceSpecifier )298     public XInterface createInstance( String serviceSpecifier ) throws com.sun.star.uno.Exception
299     {
300         XMultiServiceFactory xORB = UnoRuntime.queryInterface( XMultiServiceFactory.class, m_documentComponent );
301         return (XInterface)xORB.createInstance( serviceSpecifier );
302     }
303 
304     /* ------------------------------------------------------------------ */
305     /** creates a component at the service factory provided by the document, queried for a given interface type
306     */
createInstance( String i_serviceSpecifier, Class<T> i_interfaceClass )307     public <T> T createInstance( String i_serviceSpecifier, Class<T> i_interfaceClass ) throws com.sun.star.uno.Exception
308     {
309         return UnoRuntime.queryInterface( i_interfaceClass, createInstance( i_serviceSpecifier ) );
310     }
311 
312     /* ------------------------------------------------------------------ */
313     /** creates a component at the service factory provided by the document
314     */
createInstanceWithArguments( String serviceSpecifier, Object[] arguments )315     public XInterface createInstanceWithArguments( String serviceSpecifier, Object[] arguments ) throws com.sun.star.uno.Exception
316     {
317         XMultiServiceFactory xORB = UnoRuntime.queryInterface( XMultiServiceFactory.class, m_documentComponent );
318         return (XInterface) xORB.createInstanceWithArguments( serviceSpecifier, arguments );
319     }
320 
321     private XMultiServiceFactory    m_orb;
322     private XComponent              m_documentComponent;
323 };
324 
325