From 323b26c51adac28e86436bf3f5721cd3d68d56ae Mon Sep 17 00:00:00 2001 From: Oliver Bolte Date: Thu, 16 Oct 2008 06:57:26 +0000 Subject: CWS-TOOLING: integrate CWS odbmacros3 --- dbaccess/inc/documentcontroller.hxx | 21 +- dbaccess/prj/build.lst | 1 + dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java | 11 +- dbaccess/qa/complex/dbaccess/CRMDatabase.java | 2 +- dbaccess/qa/complex/dbaccess/DatabaseDocument.java | 870 ++++++++++ dbaccess/qa/complex/dbaccess/Parser.java | 2 +- dbaccess/qa/complex/dbaccess/QueryInQuery.java | 2 +- .../dbaccess/SingleSelectQueryComposer.java | 2 +- dbaccess/qa/complex/dbaccess/Storable.java | 106 -- dbaccess/qa/complex/dbaccess/TestCase.java | 128 ++ dbaccess/qa/complex/dbaccess/dbaccess.sce | 2 +- dbaccess/source/core/dataaccess/ModelImpl.cxx | 142 +- dbaccess/source/core/dataaccess/ModelImpl.hxx | 115 +- .../source/core/dataaccess/databasecontext.cxx | 60 +- .../source/core/dataaccess/databasecontext.hxx | 7 +- .../source/core/dataaccess/databasedocument.cxx | 896 ++++++---- .../source/core/dataaccess/databasedocument.hxx | 284 ++- dbaccess/source/core/dataaccess/datasource.cxx | 12 +- .../source/core/dataaccess/documentdefinition.cxx | 12 +- .../source/core/dataaccess/documentdefinition.hxx | 2 +- .../core/dataaccess/documenteventexecutor.cxx | 234 +++ .../core/dataaccess/documenteventexecutor.hxx | 81 + .../core/dataaccess/documenteventnotifier.cxx | 315 ++++ .../core/dataaccess/documenteventnotifier.hxx | 147 ++ dbaccess/source/core/dataaccess/documentevents.cxx | 266 +++ dbaccess/source/core/dataaccess/documentevents.hxx | 91 + dbaccess/source/core/dataaccess/makefile.mk | 7 +- dbaccess/source/ext/macromigration/dbmm_global.hrc | 37 +- dbaccess/source/ext/macromigration/dbmm_types.cxx | 66 + dbaccess/source/ext/macromigration/dbmm_types.hxx | 10 +- .../source/ext/macromigration/docerrorhandling.cxx | 91 - .../source/ext/macromigration/docerrorhandling.hxx | 69 - .../source/ext/macromigration/docinteraction.cxx | 157 ++ .../source/ext/macromigration/docinteraction.hxx | 107 ++ .../source/ext/macromigration/macromigration.hrc | 4 +- .../source/ext/macromigration/macromigration.src | 69 +- .../ext/macromigration/macromigrationdialog.cxx | 308 +++- .../ext/macromigration/macromigrationdialog.hxx | 4 +- .../ext/macromigration/macromigrationpages.cxx | 45 +- .../ext/macromigration/macromigrationpages.hxx | 8 +- .../ext/macromigration/macromigrationwizard.cxx | 15 +- dbaccess/source/ext/macromigration/makefile.mk | 9 +- .../source/ext/macromigration/migrationengine.cxx | 1815 +++++++++++++++++--- .../source/ext/macromigration/migrationerror.hxx | 162 ++ .../source/ext/macromigration/migrationlog.cxx | 305 +++- .../source/ext/macromigration/migrationlog.hxx | 16 +- .../ext/macromigration/migrationprogress.hxx | 4 +- .../source/ext/macromigration/progressmixer.cxx | 218 +++ .../source/ext/macromigration/progressmixer.hxx | 103 ++ dbaccess/source/filter/migration/cfgimport.cxx | 9 +- dbaccess/source/filter/xml/dbloader2.cxx | 77 +- dbaccess/source/filter/xml/xmlEnums.hxx | 5 +- dbaccess/source/filter/xml/xmlExport.cxx | 3 +- dbaccess/source/filter/xml/xmlExport.hxx | 2 +- dbaccess/source/filter/xml/xmlfilter.cxx | 28 +- dbaccess/source/filter/xml/xmlfilter.hxx | 4 +- dbaccess/source/ui/app/AppController.cxx | 59 +- dbaccess/source/ui/app/AppControllerDnD.cxx | 2 +- dbaccess/source/ui/app/AppControllerGen.cxx | 2 +- dbaccess/source/ui/app/AppView.cxx | 2 +- dbaccess/source/ui/app/app.src | 9 +- dbaccess/source/ui/browser/brwctrlr.cxx | 2 +- dbaccess/source/ui/browser/dbloader.cxx | 11 +- dbaccess/source/ui/browser/dsbrowserDnD.cxx | 2 +- dbaccess/source/ui/browser/exsrcbrw.cxx | 2 +- dbaccess/source/ui/browser/sbagrid.cxx | 2 +- dbaccess/source/ui/browser/unodatbr.cxx | 5 - dbaccess/source/ui/control/RelationControl.cxx | 2 +- dbaccess/source/ui/control/tabletree.cxx | 2 +- dbaccess/source/ui/control/toolboxcontroller.cxx | 2 +- dbaccess/source/ui/dlg/AdabasStat.cxx | 2 +- dbaccess/source/ui/dlg/ConnectionPage.src | 4 +- dbaccess/source/ui/dlg/ExtensionNotPresent.cxx | 2 +- dbaccess/source/ui/dlg/adminpages.cxx | 2 +- dbaccess/source/ui/dlg/dbwizsetup.cxx | 80 +- dbaccess/source/ui/dlg/directsql.cxx | 2 +- dbaccess/source/ui/dlg/queryorder.cxx | 2 +- dbaccess/source/ui/dlg/tablespage.cxx | 2 +- dbaccess/source/ui/inc/brwctrlr.hxx | 2 +- dbaccess/source/ui/misc/DExport.cxx | 2 +- dbaccess/source/ui/misc/TableCopyHelper.cxx | 2 +- dbaccess/source/ui/misc/TokenWriter.cxx | 2 +- dbaccess/source/ui/misc/controllerframe.cxx | 47 +- dbaccess/source/ui/misc/databaseobjectview.cxx | 2 +- dbaccess/source/ui/misc/documentcontroller.cxx | 13 +- dbaccess/source/ui/misc/dsmeta.cxx | 58 +- dbaccess/source/ui/misc/dsntypes.cxx | 0 dbaccess/source/ui/misc/indexcollection.cxx | 2 +- dbaccess/source/ui/misc/singledoccontroller.cxx | 10 +- dbaccess/source/ui/uno/composerdialogs.cxx | 2 +- dbaccess/source/ui/uno/dbinteraction.cxx | 2 +- dbaccess/source/ui/uno/unoDirectSql.cxx | 2 +- dbaccess/uiconfig/dbapp/menubar/menubar.xml | 1 + dbaccess/util/makefile.mk | 6 +- 94 files changed, 6537 insertions(+), 1384 deletions(-) create mode 100644 dbaccess/qa/complex/dbaccess/DatabaseDocument.java delete mode 100644 dbaccess/qa/complex/dbaccess/Storable.java create mode 100644 dbaccess/qa/complex/dbaccess/TestCase.java create mode 100644 dbaccess/source/core/dataaccess/documenteventexecutor.cxx create mode 100644 dbaccess/source/core/dataaccess/documenteventexecutor.hxx create mode 100644 dbaccess/source/core/dataaccess/documenteventnotifier.cxx create mode 100644 dbaccess/source/core/dataaccess/documenteventnotifier.hxx create mode 100644 dbaccess/source/core/dataaccess/documentevents.cxx create mode 100644 dbaccess/source/core/dataaccess/documentevents.hxx create mode 100644 dbaccess/source/ext/macromigration/dbmm_types.cxx delete mode 100644 dbaccess/source/ext/macromigration/docerrorhandling.cxx delete mode 100644 dbaccess/source/ext/macromigration/docerrorhandling.hxx create mode 100644 dbaccess/source/ext/macromigration/docinteraction.cxx create mode 100644 dbaccess/source/ext/macromigration/docinteraction.hxx create mode 100644 dbaccess/source/ext/macromigration/migrationerror.hxx create mode 100644 dbaccess/source/ext/macromigration/progressmixer.cxx create mode 100644 dbaccess/source/ext/macromigration/progressmixer.hxx delete mode 100644 dbaccess/source/ui/misc/dsntypes.cxx (limited to 'dbaccess') diff --git a/dbaccess/inc/documentcontroller.hxx b/dbaccess/inc/documentcontroller.hxx index 067dac6cbe1d..a16e4c645b06 100644 --- a/dbaccess/inc/documentcontroller.hxx +++ b/dbaccess/inc/documentcontroller.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: documentcontroller.hxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.2 $ * * This file is part of OpenOffice.org. * @@ -84,6 +84,18 @@ namespace dbaui const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& _rxController ); + /** connects the controller to the model + + @param _rxModel + the model to which the controller should be connected + @param _rxController + the controller which should be connected to the model + */ + void connect( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& _rxModel, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& _rxController + ); + /** destroys the object, and disconnects the controller from the model */ ~ModelControllerConnector(); @@ -92,10 +104,6 @@ namespace dbaui */ inline bool empty() const { return !m_xController.is(); } - /** exchanges the content of this and the given ->ModelControllerConnector instance - */ - void swap( ModelControllerConnector& _rSwapWith ); - /** clears the object The controller is disconnected from the model, and references to the model and the controller @@ -103,8 +111,7 @@ namespace dbaui */ inline void clear() { - ModelControllerConnector aEmpty; - swap( aEmpty ); + connect( NULL, NULL ); } public: diff --git a/dbaccess/prj/build.lst b/dbaccess/prj/build.lst index 3c597799245d..756e48e3c4f3 100644 --- a/dbaccess/prj/build.lst +++ b/dbaccess/prj/build.lst @@ -26,3 +26,4 @@ ba dbaccess\source\ui\uno nmake - all ba_uiuno ba_uimisc ba_inc NULL ba dbaccess\source\ui\imagelists nmake - all ba_uiimglst ba_inc NULL ba dbaccess\util nmake - all ba_util ba_uiimglst ba_capi ba_shared ba_uibrowser ba_uiapp ba_uicontrol ba_uidlg ba_uimisc ba_uiquery ba_uitabledesign ba_uirelationdesign ba_uiuno ba_conntools ba_misctools ba_miscres ba_ext_adabasui NULL ba dbaccess\win32\source\odbcconfig nmake - w ba_odbcconfig ba_inc NULL +ba dbaccess\qa\complex\dbaccess nmake - all ba_complex_tests NULL diff --git a/dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java b/dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java index 032b2891eaad..edcb62579aac 100644 --- a/dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java +++ b/dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: CRMBasedTestCase.java,v $ - * $Revision: 1.2 $ + * $Revision: 1.1.6.6 $ * * This file is part of OpenOffice.org. * @@ -35,16 +35,10 @@ import com.sun.star.uno.UnoRuntime; import java.util.logging.Level; import java.util.logging.Logger; -public abstract class CRMBasedTestCase extends complexlib.ComplexTestCase +public abstract class CRMBasedTestCase extends TestCase { protected CRMDatabase m_database; - // -------------------------------------------------------------------------------------------------------- - protected final XMultiServiceFactory getORB() - { - return (XMultiServiceFactory)param.getMSF(); - } - // -------------------------------------------------------------------------------------------------------- protected void createTestCase() { @@ -79,6 +73,7 @@ public abstract class CRMBasedTestCase extends complexlib.ComplexTestCase } } + // -------------------------------------------------------------------------------------------------------- /** creates a SingleSelectQueryComposer for our connection */ protected final XSingleSelectQueryComposer createQueryComposer() throws com.sun.star.uno.Exception diff --git a/dbaccess/qa/complex/dbaccess/CRMDatabase.java b/dbaccess/qa/complex/dbaccess/CRMDatabase.java index 6f24de212cda..057d44e2692a 100644 --- a/dbaccess/qa/complex/dbaccess/CRMDatabase.java +++ b/dbaccess/qa/complex/dbaccess/CRMDatabase.java @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: CRMDatabase.java,v $ - * $Revision: 1.7 $ + * $Revision: 1.6.2.1 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/qa/complex/dbaccess/DatabaseDocument.java b/dbaccess/qa/complex/dbaccess/DatabaseDocument.java new file mode 100644 index 000000000000..0d12fd33b763 --- /dev/null +++ b/dbaccess/qa/complex/dbaccess/DatabaseDocument.java @@ -0,0 +1,870 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: DatabaseDocument.java,v $ + * $Revision: 1.1.2.9 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package complex.dbaccess; + +import com.sun.star.awt.XTopWindow; +import com.sun.star.awt.XTopWindow; +import com.sun.star.beans.PropertyState; +import com.sun.star.document.DocumentEvent; +import com.sun.star.lang.XEventListener; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.script.XStorageBasedLibraryContainer; +import com.sun.star.task.XInteractionRequest; +import com.sun.star.uno.Exception; +import com.sun.star.uno.Type; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.frame.XStorable; +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.XNameContainer; +import com.sun.star.container.XSet; +import com.sun.star.document.XDocumentEventBroadcaster; +import com.sun.star.document.XDocumentEventListener; +import com.sun.star.document.XEmbeddedScripts; +import com.sun.star.document.XEventsSupplier; +import com.sun.star.document.XScriptInvocationContext; +import com.sun.star.frame.DoubleInitializationException; +import com.sun.star.lang.XComponent; +import com.sun.star.frame.XComponentLoader; +import com.sun.star.frame.XDispatch; +import com.sun.star.frame.XDispatchProvider; +import com.sun.star.frame.XFrame; +import com.sun.star.frame.XLoadable; +import com.sun.star.frame.XModel; +import com.sun.star.frame.XModel2; +import com.sun.star.frame.XTitle; +import com.sun.star.lang.EventObject; +import com.sun.star.lang.NotInitializedException; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lang.XSingleComponentFactory; +import com.sun.star.lang.XTypeProvider; +import com.sun.star.script.provider.XScriptProviderSupplier; +import com.sun.star.sdb.XFormDocumentsSupplier; +import com.sun.star.sdb.XOfficeDatabaseDocument; +import com.sun.star.sdb.XReportDocumentsSupplier; +import com.sun.star.task.DocumentMacroConfirmationRequest; +import com.sun.star.task.XInteractionApprove; +import com.sun.star.task.XInteractionContinuation; +import com.sun.star.task.XInteractionHandler; +import com.sun.star.uno.XComponentContext; +import com.sun.star.util.CloseVetoException; +import com.sun.star.util.URL; +import com.sun.star.util.XChangesBatch; +import com.sun.star.util.XCloseable; +import com.sun.star.util.XModifiable; +import com.sun.star.util.XURLTransformer; +import connectivity.tools.*; +import helper.FileTools; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Iterator; +import java.util.Vector; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class DatabaseDocument extends TestCase implements com.sun.star.document.XDocumentEventListener +{ + private XComponent m_callbackFactory = null; + private Vector m_documentEvents = new Vector(); + private Vector m_globalEvents = new Vector(); + + // for those states, see testDocumentEvents + private static short STATE_NOT_STARTED = 0; + private static short STATE_LOADING_DOC = 1; + private static short STATE_MACRO_EXEC_APPROVED = 2; + private static short STATE_ON_LOAD_RECEIVED = 3; + private short m_loadDocState = STATE_NOT_STARTED; + + // ======================================================================================================== + /** a helper class which can be used by the Basic scripts in our test documents + * to notify us of events in this document + */ + private class CallbackComponent implements XDocumentEventListener, XTypeProvider + { + public void documentEventOccured( DocumentEvent _event ) + { + onDocumentEvent( _event ); + } + + public void disposing( com.sun.star.lang.EventObject _Event ) + { + // not interested in + } + + public Type[] getTypes() + { + Class interfaces[] = getClass().getInterfaces(); + Type types[] = new Type[interfaces.length]; + for(int i = 0; i < interfaces.length; ++ i) + { + types[i] = new Type(interfaces[i]); + } + return types; + } + + public byte[] getImplementationId() + { + return getClass().toString().getBytes(); + } + }; + + // ======================================================================================================== + private static String getCallbackComponentServiceName() + { + return "org.openoffice.complex.dbaccess.EventCallback"; + } + + // ======================================================================================================== + /** a factory for a CallbackComponent + */ + private class CallbackComponentFactory implements XSingleComponentFactory, XServiceInfo, XComponent + { + private Vector m_eventListeners = new Vector(); + + public Object createInstanceWithContext( XComponentContext _context ) throws Exception + { + return new CallbackComponent(); + } + + public Object createInstanceWithArgumentsAndContext( Object[] arg0, XComponentContext _context ) throws Exception + { + return createInstanceWithContext( _context ); + } + + public String getImplementationName() + { + return "org.openoffice.complex.dbaccess.CallbackComponent"; + } + + public boolean supportsService( String _service ) + { + return _service.equals( getCallbackComponentServiceName() ); + } + + public String[] getSupportedServiceNames() + { + return new String[] { getCallbackComponentServiceName() }; + } + + public void dispose() + { + EventObject event = new EventObject( this ); + + Vector eventListenersCopy = (Vector)m_eventListeners.clone(); + Iterator iter = eventListenersCopy.iterator(); + while ( iter.hasNext() ) + { + ((XEventListener)iter.next()).disposing( event ); + } + } + + public void addEventListener( XEventListener _listener ) + { + if ( _listener != null ) + m_eventListeners.add( _listener ); + } + + public void removeEventListener( XEventListener _listener ) + { + m_eventListeners.remove( _listener ); + } + }; + + // ======================================================================================================== + private class MacroExecutionApprove implements XInteractionHandler + { + private XInteractionHandler m_defaultHandler = null; + + MacroExecutionApprove( XMultiServiceFactory _factory ) + { + try + { + m_defaultHandler = (XInteractionHandler)UnoRuntime.queryInterface( XInteractionHandler.class, + _factory.createInstance( "com.sun.star.sdb.InteractionHandler" ) ); + } + catch ( Exception ex ) + { + Logger.getLogger( DatabaseDocument.class.getName() ).log( Level.SEVERE, null, ex ); + } + } + + public void handle( XInteractionRequest _request ) + { + Object request = _request.getRequest(); + if ( !( request instanceof DocumentMacroConfirmationRequest ) && ( m_defaultHandler != null ) ) + { + m_defaultHandler.handle( _request ); + return; + } + + assureEquals( "interaction handleer called in wrong state", STATE_LOADING_DOC, m_loadDocState ); + + // auto-approve + XInteractionContinuation continuations[] = _request.getContinuations(); + for ( int i=0; i - * for a copy of the LGPLv3 License. - * - ************************************************************************/ -package complex.dbaccess; - -import com.sun.star.lang.XMultiServiceFactory; -import com.sun.star.uno.UnoRuntime; -import com.sun.star.frame.XStorable; -import com.sun.star.frame.FrameSearchFlag; -import com.sun.star.beans.PropertyValue; -import com.sun.star.lang.XComponent; -import com.sun.star.frame.XComponentLoader; -import com.sun.star.util.XCloseable; -import connectivity.tools.*; - -public class Storable extends complexlib.ComplexTestCase { - - HsqlDatabase m_database; - - // -------------------------------------------------------------------------------------------------------- - public String[] getTestMethodNames() { - return new String[] - { - "testStorable" - }; - } - - // -------------------------------------------------------------------------------------------------------- - public String getTestObjectName() { - return "Storable"; - } - - // -------------------------------------------------------------------------------------------------------- - private void createTestCase() - { - try - { - if ( m_database == null ) - { - CRMDatabase database = new CRMDatabase( getFactory() ); - m_database = database.getDatabase(); - } - } - catch( Exception e ) - { - System.err.println( "could not create the test case, error message:\n" + e.getMessage() ); - e.printStackTrace( System.err ); - assure( "failed to created the test case", false ); - } - } - - // -------------------------------------------------------------------------------------------------------- - private XMultiServiceFactory getFactory() - { - return (XMultiServiceFactory)param.getMSF(); - } - - // -------------------------------------------------------------------------------------------------------- - public void testStorable() - { - createTestCase(); - - try - { - Object object = getFactory().createInstance("com.sun.star.frame.Desktop"); - XComponentLoader xComponentLoader = (XComponentLoader)UnoRuntime.queryInterface(XComponentLoader.class, object); - XComponent xComponent = xComponentLoader.loadComponentFromURL(m_database.getDocumentURL(), "_blank",FrameSearchFlag.ALL, new PropertyValue[0]); - m_database.close(); - XStorable storable = (XStorable)UnoRuntime.queryInterface(XStorable.class,xComponent); - storable.store(); - XCloseable close = (XCloseable)UnoRuntime.queryInterface(XCloseable.class,xComponent); - close.close(true); - } - catch ( AssureException e ) { throw e; } - catch ( Exception e ) - { - assure( "caught an unexpected exception: " + e.getMessage(), false ); - } - } -} diff --git a/dbaccess/qa/complex/dbaccess/TestCase.java b/dbaccess/qa/complex/dbaccess/TestCase.java new file mode 100644 index 000000000000..65774e108247 --- /dev/null +++ b/dbaccess/qa/complex/dbaccess/TestCase.java @@ -0,0 +1,128 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: TestCase.java,v $ + * $Revision: 1.1.2.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package complex.dbaccess; + +import com.sun.star.beans.XPropertySet; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public abstract class TestCase extends complexlib.ComplexTestCase +{ + // -------------------------------------------------------------------------------------------------------- + protected final XMultiServiceFactory getORB() + { + return (XMultiServiceFactory)param.getMSF(); + } + + // -------------------------------------------------------------------------------------------------------- + protected final XComponentContext getComponentContext() + { + XComponentContext context = null; + try + { + XPropertySet orbProps = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, getORB() ); + context = (XComponentContext)UnoRuntime.queryInterface( XComponentContext.class, + orbProps.getPropertyValue( "DefaultContext" ) ); + } + catch ( Exception ex ) + { + failed( "could not retrieve the ComponentContext" ); + } + return context; + } + + // -------------------------------------------------------------------------------------------------------- + public void before() + { + } + + // -------------------------------------------------------------------------------------------------------- + public void after() + { + } + + // -------------------------------------------------------------------------------------------------------- + /** returns the URL of a temporary file which can be used during the test. + * + * The file will be deleted when the process exits + * @return the URL of a temporary file + */ + protected final String createTempFileURL() throws IOException + { + File documentFile = java.io.File.createTempFile( getTestObjectName(), ".odb" ); + documentFile.deleteOnExit(); + return documentFile.getAbsoluteFile().toURL().toString(); + } + + // -------------------------------------------------------------------------------------------------------- + protected void verifyExpectedException( Object _object, Class _unoInterfaceClass, String _methodName, Object[] _methodArgs, + Class _expectedExceptionClass ) + { + verifyExpectedException( UnoRuntime.queryInterface( _unoInterfaceClass, _object ), _methodName, + _methodArgs, _expectedExceptionClass ); + } + + // -------------------------------------------------------------------------------------------------------- + protected void verifyExpectedException( Object _object, String _methodName, Object[] _methodArgs, + Class _expectedExceptionClass ) + { + Class objectClass = _object.getClass(); + Class[] methodArgsClasses = new Class[ _methodArgs.length ]; + for ( int i=0; i<_methodArgs.length; ++i ) + methodArgsClasses[i] = _methodArgs[i].getClass(); + + boolean noExceptionAllowed = _expectedExceptionClass == null; + + boolean caughtExpected = noExceptionAllowed ? true : false; + try + { + Method method = objectClass.getMethod( _methodName, methodArgsClasses ); + method.invoke(_object, _methodArgs ); + } + catch ( InvocationTargetException e ) + { + caughtExpected = noExceptionAllowed + ? false + : ( e.getTargetException().getClass().equals( _expectedExceptionClass ) ); + } + catch( Exception e ) + { + caughtExpected = false; + } + assure( "did not catch the expected exception (" + + ( noExceptionAllowed ? "none" : _expectedExceptionClass.getName() ) + + ") while calling " + _object.getClass().getName() + "." + _methodName, caughtExpected ); + } +} diff --git a/dbaccess/qa/complex/dbaccess/dbaccess.sce b/dbaccess/qa/complex/dbaccess/dbaccess.sce index f5973808b8f4..3e0357af2727 100644 --- a/dbaccess/qa/complex/dbaccess/dbaccess.sce +++ b/dbaccess/qa/complex/dbaccess/dbaccess.sce @@ -3,6 +3,6 @@ -o complex.dbaccess.PropertyBag -o complex.dbaccess.Query -o complex.dbaccess.QueryInQuery --o complex.dbaccess.Storable +-o complex.dbaccess.DatabaseDocument -o complex.dbaccess.DataSource -o complex.dbaccess.Parser diff --git a/dbaccess/source/core/dataaccess/ModelImpl.cxx b/dbaccess/source/core/dataaccess/ModelImpl.cxx index ed285b26b2cc..7638609062d9 100644 --- a/dbaccess/source/core/dataaccess/ModelImpl.cxx +++ b/dbaccess/source/core/dataaccess/ModelImpl.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: ModelImpl.cxx,v $ - * $Revision: 1.32.18.1 $ + * $Revision: 1.25.6.12 $ * * This file is part of OpenOffice.org. * @@ -43,6 +43,7 @@ #include "userinformation.hxx" /** === begin UNO includes === **/ +#include #include #include #include @@ -50,6 +51,7 @@ #include #include #include +#include /** === end UNO includes === **/ #include @@ -127,6 +129,33 @@ void SAL_CALL SharedMutex::release() delete this; } +//============================================================ +//= VosMutexFacade +//============================================================ +//------------------------------------------------------------------------ +VosMutexFacade::VosMutexFacade( ::osl::Mutex& _rMutex ) + :m_rMutex( _rMutex ) +{ +} + +//------------------------------------------------------------------------ +void SAL_CALL VosMutexFacade::acquire() +{ + m_rMutex.acquire(); +} + +//------------------------------------------------------------------------ +sal_Bool SAL_CALL VosMutexFacade::tryToAcquire() +{ + return m_rMutex.tryToAcquire(); +} + +//------------------------------------------------------------------------ +void SAL_CALL VosMutexFacade::release() +{ + m_rMutex.release(); +} + //============================================================ //= DocumentStorageAccess //============================================================ @@ -189,9 +218,9 @@ void DocumentStorageAccess::dispose() { ::osl::MutexGuard aGuard( m_aMutex ); - for ( NamedStorages::iterator loop = m_aExposedStorages.begin(); - loop != m_aExposedStorages.end(); - ++loop + for ( NamedStorages::iterator loop = m_aExposedStorages.begin(); + loop != m_aExposedStorages.end(); + ++loop ) { try @@ -202,7 +231,7 @@ void DocumentStorageAccess::dispose() } catch( const Exception& ) { - OSL_ENSURE( sal_False, "DocumentStorageAccess::dispose: caught an exception!" ); + DBG_UNHANDLED_EXCEPTION(); } } @@ -313,15 +342,17 @@ ODatabaseModelImpl::ODatabaseModelImpl( const Reference< XMultiServiceFactory >& :m_xModel() ,m_xDataSource() ,m_pStorageAccess( NULL ) - ,m_xMutex( new SharedMutex ) + ,m_aMutexFacade( m_xMutex->getMutex() ) ,m_aContainer(4) ,m_aStorages() ,m_aMacroMode( *this ) ,m_nImposedMacroExecMode( MacroExecMode::NEVER_EXECUTE ) ,m_pDBContext( &_rDBContext ) + ,m_refCount(0) ,m_bHasAnyObjectWithMacros( false ) ,m_bHasMacroStorages( false ) ,m_bModificationLock( false ) + ,m_bDocumentInitialized( false ) ,m_aContext( _rxFactory ) ,m_nLoginTimeout(0) ,m_bReadOnly(sal_False) @@ -331,7 +362,6 @@ ODatabaseModelImpl::ODatabaseModelImpl( const Reference< XMultiServiceFactory >& ,m_bDocumentReadOnly(sal_False) ,m_bDisposingSubStorages( sal_False ) ,m_pSharedConnectionManager(NULL) - ,m_refCount(0) ,m_nControllerLockCount(0) { // some kind of default @@ -351,15 +381,17 @@ ODatabaseModelImpl::ODatabaseModelImpl( :m_xModel() ,m_xDataSource() ,m_pStorageAccess( NULL ) - ,m_xMutex( new SharedMutex ) + ,m_aMutexFacade( m_xMutex->getMutex() ) ,m_aContainer(4) ,m_aStorages() ,m_aMacroMode( *this ) ,m_nImposedMacroExecMode( MacroExecMode::NEVER_EXECUTE ) ,m_pDBContext( &_rDBContext ) + ,m_refCount(0) ,m_bHasAnyObjectWithMacros( false ) ,m_bHasMacroStorages( false ) ,m_bModificationLock( false ) + ,m_bDocumentInitialized( false ) ,m_aContext( _rxFactory ) ,m_sName(_rRegistrationName) ,m_nLoginTimeout(0) @@ -370,7 +402,6 @@ ODatabaseModelImpl::ODatabaseModelImpl( ,m_bDocumentReadOnly(sal_False) ,m_bDisposingSubStorages( sal_False ) ,m_pSharedConnectionManager(NULL) - ,m_refCount(0) ,m_nControllerLockCount(0) { DBG_CTOR(ODatabaseModelImpl,NULL); @@ -677,6 +708,37 @@ const Reference< XNumberFormatsSupplier > & ODatabaseModelImpl::getNumberFormats } return m_xNumberFormatsSupplier; } +// ----------------------------------------------------------------------------- +void ODatabaseModelImpl::attachResource( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _rArgs ) +{ + ::comphelper::NamedValueCollection aMediaDescriptor( _rArgs ); + + ::rtl::OUString sDocumentLocation( aMediaDescriptor.getOrDefault( "SalvagedFile", _rURL ) ); + if ( !sDocumentLocation.getLength() ) + // this indicates "the document is being recovered, but _rURL already is the real document URL, + // not the temporary document location" + sDocumentLocation = _rURL; + + if ( aMediaDescriptor.has( "SalvagedFile" ) ) + aMediaDescriptor.remove( "SalvagedFile" ); + + m_aArgs = stripLoadArguments( aMediaDescriptor ); + + switchToURL( sDocumentLocation, _rURL ); +} + +// ----------------------------------------------------------------------------- +Sequence< PropertyValue > ODatabaseModelImpl::stripLoadArguments( const ::comphelper::NamedValueCollection& _rArguments ) +{ + OSL_ENSURE( !_rArguments.has( "Model" ), "ODatabaseModelImpl::stripLoadArguments: this is suspicious (1)!" ); + OSL_ENSURE( !_rArguments.has( "ViewName" ), "ODatabaseModelImpl::stripLoadArguments: this is suspicious (2)!" ); + + ::comphelper::NamedValueCollection aMutableArgs( _rArguments ); + aMutableArgs.remove( "Model" ); + aMutableArgs.remove( "ViewName" ); + return aMutableArgs.getPropertyValues(); +} + // ----------------------------------------------------------------------------- void ODatabaseModelImpl::disposeStorages() SAL_THROW(()) { @@ -694,7 +756,7 @@ void ODatabaseModelImpl::disposeStorages() SAL_THROW(()) } catch( const Exception& ) { - OSL_ENSURE( sal_False, "ODatabaseModelImpl::disposeStorages: caught an exception!" ); + DBG_UNHANDLED_EXCEPTION(); } } m_aStorages.clear(); @@ -780,7 +842,7 @@ DocumentStorageAccess* ODatabaseModelImpl::getDocumentStorageAccess() } // ----------------------------------------------------------------------------- -void ODatabaseModelImpl::modelIsDisposing( ResetModelAccess ) +void ODatabaseModelImpl::modelIsDisposing( const bool _wasInitialized, ResetModelAccess ) { m_xModel = Reference< XModel >(); @@ -789,6 +851,8 @@ void ODatabaseModelImpl::modelIsDisposing( ResetModelAccess ) // So, to not be tempted to do anything with them, again, we reset them. m_xBasicLibraries.clear(); m_xDialogLibraries.clear(); + + m_bDocumentInitialized = _wasInitialized; } // ----------------------------------------------------------------------------- @@ -906,7 +970,7 @@ bool ODatabaseModelImpl::commitStorageIfWriteable_ignoreErrors( const Reference< } catch( const Exception& ) { - OSL_ENSURE( sal_False, "ODatabaseModelImpl::commitStorageIfWriteable_ignoreErrors: caught an exception!" ); + DBG_UNHANDLED_EXCEPTION(); } return bSuccess; } @@ -918,24 +982,24 @@ void ODatabaseModelImpl::setModified( sal_Bool _bModified ) try { - Reference xModi(m_xModel.get(),UNO_QUERY); + Reference< XModifiable > xModi( m_xModel.get(), UNO_QUERY ); if ( xModi.is() ) xModi->setModified( _bModified ); else m_bModified = _bModified; } - catch(Exception) + catch( const Exception& ) { - OSL_ENSURE(0,"ODatabaseModelImpl::setModified: Exception caught!"); + DBG_UNHANDLED_EXCEPTION(); } } // ----------------------------------------------------------------------------- -Reference ODatabaseModelImpl::getDataSource( bool _bCreateIfNecessary ) +Reference ODatabaseModelImpl::getOrCreateDataSource() { Reference xDs = m_xDataSource; - if ( !xDs.is() && _bCreateIfNecessary ) - { // no data source, so we have to create one and register it later on + if ( !xDs.is() ) + { xDs = new ODatabaseSource(this); m_xDataSource = xDs; } @@ -947,7 +1011,7 @@ Reference< XModel> ODatabaseModelImpl::getModel_noCreate() const return m_xModel; } // ----------------------------------------------------------------------------- -Reference< XModel > ODatabaseModelImpl::createNewModel_deliverOwnership() +Reference< XModel > ODatabaseModelImpl::createNewModel_deliverOwnership( bool _bInitialize ) { Reference< XModel > xModel( m_xModel ); OSL_PRECOND( !xModel.is(), "ODatabaseModelImpl::createNewModel_deliverOwnership: not to be called if there already is a model!" ); @@ -955,6 +1019,31 @@ Reference< XModel > ODatabaseModelImpl::createNewModel_deliverOwnership() { xModel = ODatabaseDocument::createDatabaseDocument( this, ODatabaseDocument::FactoryAccess() ); m_xModel = xModel; + + try + { + Reference< XSet > xModelCollection; + if ( m_aContext.createComponent( "com.sun.star.frame.GlobalEventBroadcaster", xModelCollection ) ) + xModelCollection->insert( makeAny( xModel ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + if ( _bInitialize ) + { + try + { + Reference< XLoadable > xLoad( xModel, UNO_QUERY_THROW ); + xLoad->initNew(); + } + catch( RuntimeException& ) { throw; } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } } return xModel; } @@ -1159,7 +1248,7 @@ namespace { void lcl_modifyListening( ::sfx2::IModifiableDocument& _rDocument, const Reference< XStorage >& _rxStorage, ::rtl::Reference< ::sfx2::DocumentStorageModifyListener >& _inout_rListener, - bool _bListen ) + ::vos::IMutex& _rMutex, bool _bListen ) { Reference< XModifiable > xModify( _rxStorage, UNO_QUERY ); OSL_ENSURE( xModify.is() || !_rxStorage.is(), "lcl_modifyListening: storage can't notify us!" ); @@ -1178,15 +1267,12 @@ namespace if ( xModify.is() && _bListen ) { // the listener from sfx2 uses SolarMutex internally - _inout_rListener = new ::sfx2::DocumentStorageModifyListener( _rDocument ); + _inout_rListener = new ::sfx2::DocumentStorageModifyListener( _rDocument, _rMutex ); xModify->addModifyListener( _inout_rListener.get() ); } } -} -// ----------------------------------------------------------------------------- -namespace -{ + // ------------------------------------------------------------------------- static void lcl_rebaseScriptStorage_throw( const Reference< XStorageBasedLibraryContainer >& _rxContainer, const Reference< XStorage >& _rxNewRootStorage ) { @@ -1204,13 +1290,13 @@ namespace Reference< XStorage > ODatabaseModelImpl::impl_switchToStorage_throw( const Reference< XStorage >& _rxNewRootStorage ) { // stop listening for modifications at the old storage - lcl_modifyListening( *this, m_xDocumentStorage.getTyped(), m_pStorageModifyListener, false ); + lcl_modifyListening( *this, m_xDocumentStorage.getTyped(), m_pStorageModifyListener, m_aMutexFacade, false ); // set new storage m_xDocumentStorage.reset( _rxNewRootStorage, SharedStorage::TakeOwnership ); // start listening for modifications - lcl_modifyListening( *this, m_xDocumentStorage.getTyped(), m_pStorageModifyListener, true ); + lcl_modifyListening( *this, m_xDocumentStorage.getTyped(), m_pStorageModifyListener, m_aMutexFacade, true ); // forward new storage to Basic and Dialog library containers lcl_rebaseScriptStorage_throw( m_xBasicLibraries, m_xDocumentStorage.getTyped() ); @@ -1310,7 +1396,7 @@ sal_Bool ODatabaseModelImpl::setCurrentMacroExecMode( sal_uInt16 nMacroMode ) // don't return getURL() (or m_sDocumentURL, which is the same). In case we were recovered // after a previous crash of OOo, m_sDocFileLocation points to the file which were loaded from, // and this is the one we need for security checks. - return getLocation(); + return getDocFileLocation(); } // ----------------------------------------------------------------------------- diff --git a/dbaccess/source/core/dataaccess/ModelImpl.hxx b/dbaccess/source/core/dataaccess/ModelImpl.hxx index f468e0923ca0..9c845c7c171d 100644 --- a/dbaccess/source/core/dataaccess/ModelImpl.hxx +++ b/dbaccess/source/core/dataaccess/ModelImpl.hxx @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +68,7 @@ #include #include #include +#include /** === end UNO includes === **/ #include @@ -78,10 +80,15 @@ #include #include #include -#include +#include #include +namespace comphelper +{ + class NamedValueCollection; +} + //........................................................................ namespace dbaccess { @@ -111,6 +118,9 @@ class OSharedConnectionManager; //============================================================ //= SharedMutex //============================================================ +/** a shared mutex, which deletes itself as soon as the last reference + to it dies. +*/ class SharedMutex { private: @@ -129,6 +139,45 @@ private: ~SharedMutex(); }; +//============================================================ +//= SharedMutexHolder +//============================================================ +/** a base class merely holding a SharedMutex instance. Useful if you + need to ensure the SharedMutex is to be initialized before other + of your members, in this case just derive from SharedMutexHolder. +*/ +class SharedMutexHolder +{ +protected: + SharedMutexHolder() : m_xMutex( new SharedMutex ) { } + ~SharedMutexHolder() { } + +protected: + ::rtl::Reference< SharedMutex > m_xMutex; +}; + +//============================================================ +//= VosMutexFacade +//============================================================ +/** a class which provides an IMutex interface to an OSL-based mutex +*/ +class VosMutexFacade : public ::vos::IMutex +{ +public: + /** beware of life time: the mutex you pass here must live as least as long + as the VosMutexFacade instance lives. + */ + VosMutexFacade( ::osl::Mutex& _rMutex ); + + // IMutex + virtual void SAL_CALL acquire(); + virtual sal_Bool SAL_CALL tryToAcquire(); + virtual void SAL_CALL release(); + +private: + ::osl::Mutex& m_rMutex; +}; + //============================================================ //= ODatabaseModelImpl //============================================================ @@ -139,7 +188,8 @@ typedef ::utl::SharedUNOComponent< ::com::sun::star::embed::XStorage > SharedSt class ODatabaseContext; class DocumentStorageAccess; class OSharedConnectionManager; -class ODatabaseModelImpl :public ::rtl::IReference +class ODatabaseModelImpl :public SharedMutexHolder + ,public ::rtl::IReference ,public ::sfx2::IMacroDocumentAccess ,public ::sfx2::IModifiableDocument { @@ -158,7 +208,7 @@ private: ::com::sun::star::uno::WeakReference< ::com::sun::star::sdbc::XDataSource > m_xDataSource; DocumentStorageAccess* m_pStorageAccess; - ::rtl::Reference< SharedMutex > m_xMutex; + VosMutexFacade m_aMutexFacade; ::std::vector< TContentPtr > m_aContainer; // one for each ObjectType TStorages m_aStorages; ::sfx2::DocumentMacroMode m_aMacroMode; @@ -171,8 +221,11 @@ private: ::rtl::Reference< ::sfx2::DocumentStorageModifyListener > m_pStorageModifyListener; ODatabaseContext* m_pDBContext; + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > m_aArgs; /// the URL the document was loaded from - ::rtl::OUString m_sDocFileLocation; + ::rtl::OUString m_sDocFileLocation; + + oslInterlockedCount m_refCount; /// do we have any object (forms/reports) which contains macros? bool m_bHasAnyObjectWithMacros; @@ -182,6 +235,9 @@ private: /// true if setting the Modified flag of the document is currently locked bool m_bModificationLock; + /// true if and only if a database document existed previously (though meanwhile disposed), and was already initialized + bool m_bDocumentInitialized; + /** the URL which the document should report as it's URL This might differ from ->m_sDocFileLocation in case the document was loaded @@ -220,12 +276,9 @@ public: m_xSettings; ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aTableFilter; ::com::sun::star::uno::Sequence< ::rtl::OUString > m_aTableTypeFilter; - ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > - m_aArgs; OSharedConnectionManager* m_pSharedConnectionManager; ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > m_xSharedConnectionManager; - oslInterlockedCount m_refCount; sal_uInt16 m_nControllerLockCount; void reset(); @@ -269,14 +322,23 @@ public: void dispose(); - inline ::rtl::OUString getURL() const { return m_sDocumentURL; } - inline ::rtl::OUString getLocation() const { return m_sDocFileLocation; } + inline ::rtl::OUString getURL() const { return m_sDocumentURL; } + inline ::rtl::OUString getDocFileLocation() const { return m_sDocFileLocation; } ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage> getStorage(const ::rtl::OUString& _sStorageName,sal_Int32 nMode = ::com::sun::star::embed::ElementModes::READWRITE); // helper const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier >& getNumberFormatsSupplier(); + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& + getResource() const { return m_aArgs; } + + void attachResource( + const ::rtl::OUString& _rURL, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rArgs ); + + static ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > + stripLoadArguments( const ::comphelper::NamedValueCollection& _rArguments ); // other stuff void flushTables(); @@ -315,7 +377,7 @@ public: /** returns the data source. If it doesn't exist it will be created */ - ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDataSource> getDataSource( bool _bCreateIfNecessary = true ); + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDataSource> getOrCreateDataSource(); /** returns the model, if there already exists one */ @@ -323,12 +385,16 @@ public: /** returns a new ->ODatabaseDocument + @param _bInitializeIfNecessary + calls XLoadable::initNew on the newly created model, if necessary + @precond No ->ODatabaseDocument exists so far + @seealso getModel_noCreate */ - ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > createNewModel_deliverOwnership(); + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > createNewModel_deliverOwnership( bool _bInitialize ); struct ResetModelAccess { friend class ODatabaseDocument; private: ResetModelAccess() { } }; @@ -336,7 +402,9 @@ public: Only to be called when the model is being disposed */ - void modelIsDisposing( ResetModelAccess ); + void modelIsDisposing( const bool _wasInitialized, ResetModelAccess ); + + bool hadInitializedDocument() const { return m_bDocumentInitialized; } DocumentStorageAccess* getDocumentStorageAccess(); @@ -459,7 +527,7 @@ public: const ::rtl::OUString& _rDocumentURL ); - /** returns the macro mode imposed by an external instance, by passing it to attachResource + /** returns the macro mode imposed by an external instance, which passed it to attachResource */ sal_Int16 getImposedMacroExecMode() const { @@ -517,7 +585,7 @@ protected: } public: - struct GuardAccess { friend class ModelMethodGuard; friend class ModifyLock; private: GuardAccess() { } }; + struct GuardAccess { friend class ModelMethodGuard; private: GuardAccess() { } }; /** returns the mutex used for thread safety @@ -534,18 +602,19 @@ public: return m_pImpl; } + /// checks whether the component is already disposed, throws a DisposedException if so inline void checkDisposed() const { if ( !m_pImpl.is() ) throw ::com::sun::star::lang::DisposedException( ::rtl::OUString::createFromAscii( "Component is already disposed." ), getThis() ); } - inline void lockModify( GuardAccess ) + inline void lockModify() { m_pImpl->lockModify(); } - inline void unlockModify( GuardAccess ) + inline void unlockModify() { m_pImpl->unlockModify(); } @@ -557,12 +626,12 @@ public: ModifyLock( ModelDependentComponent& _component ) :m_rComponent( _component ) { - m_rComponent.lockModify( ModelDependentComponent::GuardAccess() ); + m_rComponent.lockModify(); } ~ModifyLock() { - m_rComponent.unlockModify( ModelDependentComponent::GuardAccess() ); + m_rComponent.unlockModify(); } private: @@ -574,7 +643,7 @@ private: Just put this guard onto the stack at the beginning of your method. Don't bother yourself with a MutexGuard, checks for being disposed, and the like. */ -class ModelMethodGuard :public ::osl::ResettableMutexGuard +class ModelMethodGuard : public ::osl::ResettableMutexGuard { private: typedef ::osl::ResettableMutexGuard BaseMutexGuard; @@ -594,14 +663,8 @@ public: _component.checkDisposed(); } - inline void clear() - { - BaseMutexGuard::clear(); - } - - inline void reset() + ~ModelMethodGuard() { - BaseMutexGuard::reset(); } }; diff --git a/dbaccess/source/core/dataaccess/databasecontext.cxx b/dbaccess/source/core/dataaccess/databasecontext.cxx index fe4eca44331d..0c333cf0b7be 100644 --- a/dbaccess/source/core/dataaccess/databasecontext.cxx +++ b/dbaccess/source/core/dataaccess/databasecontext.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: databasecontext.cxx,v $ - * $Revision: 1.43 $ + * $Revision: 1.43.4.3 $ * * This file is part of OpenOffice.org. * @@ -190,33 +190,36 @@ Sequence< ::rtl::OUString > ODatabaseContext::getSupportedServiceNames( ) throw } //-------------------------------------------------------------------------- -Reference< XInterface > SAL_CALL ODatabaseContext::createInstance( ) throw (Exception, RuntimeException) +Reference< XInterface > ODatabaseContext::impl_createNewDataSource() { ::rtl::Reference pImpl( new ODatabaseModelImpl( m_aContext.getLegacyServiceFactory(), *this ) ); - Reference< XDataSource > xDataSource( pImpl->getDataSource() ); + Reference< XDataSource > xDataSource( pImpl->getOrCreateDataSource() ); + return xDataSource.get(); } +//-------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL ODatabaseContext::createInstance( ) throw (Exception, RuntimeException) +{ + // for convenience of the API user, we ensure the document is fully initialized (effectively: XLoadable::initNew + // has been called at the DatabaseDocument). + return impl_createNewDataSource(); +} + //-------------------------------------------------------------------------- Reference< XInterface > SAL_CALL ODatabaseContext::createInstanceWithArguments( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException) { - const Any* pIter = _rArguments.getConstArray(); - const Any* pEnd = pIter + _rArguments.getLength(); - NamedValue aValue; - Reference< XInterface > xExistent; - ::rtl::OUString sURL; - for (; pIter != pEnd; ++pIter) - { - if ( (*pIter >>= aValue) && aValue.Name == INFO_POOLURL && (aValue.Value >>= sURL) ) - { - xExistent = getObject(sURL); - break; - } - } - if ( !xExistent.is() ) - xExistent = createInstance(); + ::comphelper::NamedValueCollection aArgs( _rArguments ); + ::rtl::OUString sURL = aArgs.getOrDefault( (::rtl::OUString)INFO_POOLURL, ::rtl::OUString() ); - return xExistent; + Reference< XInterface > xDataSource; + if ( sURL.getLength() ) + xDataSource = getObject( sURL ); + + if ( !xDataSource.is() ) + xDataSource = impl_createNewDataSource(); + + return xDataSource; } // DatabaseAccessContext_Base //------------------------------------------------------------------------------ @@ -233,7 +236,6 @@ void ODatabaseContext::disposing() ++aIter ) { - OSL_ENSURE(aIter->second->m_refCount != 0,"Object is already disposed"); aIter->second->dispose(); } m_aDatabaseObjects.clear(); @@ -333,22 +335,24 @@ Reference< XInterface > ODatabaseContext::loadObjectFromURL(const ::rtl::OUStrin { pExistent.set( new ODatabaseModelImpl( _rName, m_aContext.getLegacyServiceFactory(), *this ) ); + Reference< XModel > xModel( pExistent->createNewModel_deliverOwnership( false ), UNO_SET_THROW ); + Reference< XLoadable > xLoad( xModel, UNO_QUERY_THROW ); + ::comphelper::NamedValueCollection aArgs; aArgs.put( "FileName", _sURL ); aArgs.put( "MacroExecutionMode", MacroExecMode::USE_CONFIG ); aArgs.put( "InteractionHandler", m_aContext.createComponent( "com.sun.star.sdb.InteractionHandler" ) ); - Reference< XModel > xModel = pExistent->createNewModel_deliverOwnership(); - DBG_ASSERT( xModel.is(), "ODatabaseContext::loadObjectFromURL: no model?" ); - - xModel->attachResource( _sURL, aArgs.getPropertyValues() ); + Sequence< PropertyValue > aResource( aArgs.getPropertyValues() ); + xLoad->load( aResource ); + xModel->attachResource( _sURL, aResource ); ::utl::CloseableComponent aEnsureClose( xModel ); } setTransientProperties( _sURL, *pExistent ); - return pExistent->getDataSource().get(); + return pExistent->getOrCreateDataSource().get(); } // ----------------------------------------------------------------------------- void ODatabaseContext::setTransientProperties(const ::rtl::OUString& _sURL, ODatabaseModelImpl& _rDataSourceModel ) @@ -358,7 +362,7 @@ void ODatabaseContext::setTransientProperties(const ::rtl::OUString& _sURL, ODat try { ::rtl::OUString sAuthFailedPassword; - Reference< XPropertySet > xDSProps( _rDataSourceModel.getDataSource(), UNO_QUERY_THROW ); + Reference< XPropertySet > xDSProps( _rDataSourceModel.getOrCreateDataSource(), UNO_QUERY_THROW ); const Sequence< PropertyValue >& rSessionPersistentProps = m_aDatasourceProperties[_sURL]; const PropertyValue* pProp = rSessionPersistentProps.getConstArray(); const PropertyValue* pPropsEnd = rSessionPersistentProps.getConstArray() + rSessionPersistentProps.getLength(); @@ -428,7 +432,7 @@ void ODatabaseContext::registerObject(const rtl::OUString& _rName, const Referen //------------------------------------------------------------------------------ void ODatabaseContext::storeTransientProperties( ODatabaseModelImpl& _rModelImpl) { - Reference< XPropertySet > xSource(_rModelImpl.getDataSource(),UNO_QUERY); + Reference< XPropertySet > xSource( _rModelImpl.getOrCreateDataSource(), UNO_QUERY ); ::comphelper::NamedValueCollection aRememberProps; try @@ -641,7 +645,7 @@ Reference< XInterface > ODatabaseContext::getObject(const ::rtl::OUString& _rNam ObjectCacheIterator aFind = m_aDatabaseObjects.find(_rName); Reference< XInterface > xExistent; if ( aFind != m_aDatabaseObjects.end() ) - xExistent = aFind->second->getDataSource(); + xExistent = aFind->second->getOrCreateDataSource(); return xExistent; } // ----------------------------------------------------------------------------- diff --git a/dbaccess/source/core/dataaccess/databasecontext.hxx b/dbaccess/source/core/dataaccess/databasecontext.hxx index 2d314e43aff7..b164dd644671 100644 --- a/dbaccess/source/core/dataaccess/databasecontext.hxx +++ b/dbaccess/source/core/dataaccess/databasecontext.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: databasecontext.hxx,v $ - * $Revision: 1.17 $ + * $Revision: 1.17.2.2 $ * * This file is part of OpenOffice.org. * @@ -138,6 +138,11 @@ private: */ void setTransientProperties(const ::rtl::OUString& _sURL, ODatabaseModelImpl& _rDataSourceModel ); + /** creates a new data source + */ + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > + impl_createNewDataSource(); + protected: ::osl::Mutex m_aMutex; ::comphelper::ComponentContext m_aContext; diff --git a/dbaccess/source/core/dataaccess/databasedocument.cxx b/dbaccess/source/core/dataaccess/databasedocument.cxx index 015633dbdd6c..a224dff54087 100644 --- a/dbaccess/source/core/dataaccess/databasedocument.cxx +++ b/dbaccess/source/core/dataaccess/databasedocument.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: databasedocument.cxx,v $ - * $Revision: 1.48 $ + * $Revision: 1.40.6.21 $ * * This file is part of OpenOffice.org. * @@ -35,93 +35,49 @@ #include "databasedocument.hxx" #include "dbastrings.hrc" #include "module_dba.hxx" +#include "documentevents.hxx" +#include "documenteventexecutor.hxx" +#include "databasecontext.hxx" +#include "documentcontainer.hxx" -#include -#include -#include -#include #include #include #include -#include -#ifndef _COM_SUN_STAR_EMBED_XTRANSACTEDOBJECT_HPP_ +/** === begin UNO includes === **/ +#include +#include +#include +#include +#include #include -#endif -#ifndef _COM_SUN_STAR_IO_XACTIVEDATASOURCE_HPP_ +#include #include -#endif -#ifndef _COM_SUN_STAR_IO_XSEEKABLE_HPP_ #include -#endif -#ifndef _COM_SUN_STAR_TASK_XSTATUSINDICATOR_HPP_ +#include +#include #include -#endif -#ifndef _COM_SUN_STAR_TASK_XSTATUSINDICATORFACTORY_HPP_ #include -#endif -#ifndef _COM_SUN_STAR_DOCUMENT_XEXPORTER_HPP_ -#include -#endif -#ifndef _COM_SUN_STAR_DOCUMENT_XFILTER_HPP_ -#include -#endif -#ifndef _COM_SUN_STAR_TASK_ERRORCODEIOEXCEPTION_HPP_ -#include -#endif -#ifndef _COM_SUN_STAR_XML_SAX_XDOCUMENTHANDLER_HPP_ -#include -#endif -#ifndef _DBA_COREDATAACCESS_DOCUMENTCONTAINER_HXX_ -#include "documentcontainer.hxx" -#endif -#ifndef _DBA_COREDATAACCESS_DATABASECONTEXT_HXX_ -#include "databasecontext.hxx" -#endif -#ifndef _URLOBJ_HXX -#include -#endif -#ifndef TOOLS_DIAGNOSE_EX_H -#include -#endif -#ifndef _ERRCODE_HXX -#include -#endif -#ifndef _COMPHELPER_MEDIADESCRIPTOR_HXX_ -#include -#endif -#ifndef _COM_SUN_STAR_UI_XUICONFIGURATIONSTORAGE_HPP_ #include -#endif -#ifndef _COM_SUN_STAR_EMBED_XTRANSACTIONBROADCASTER_HPP_ -#include -#endif -#ifndef _COM_SUN_STAR_EMBED_XEMBEDPERSIST_HPP_ -#include -#endif -#ifndef _COM_SUN_STAR_EMBED_ENTRYINITMODES_HPP_ -#include -#endif -#ifndef _COM_SUN_STAR_VIEW_XSELECTIONSUPPLIER_HPP_ #include -#endif -#ifndef _COM_SUN_STAR_DOCUMENT_XIMPORTER_HPP_ -#include -#endif -#ifndef _COM_SUN_STAR_SCRIPT_PROVIDER_XSCRIPTPROVIDERFACTORY_HPP_ -#include -#endif -#ifndef _TOOLS_DEBUG_HXX -#include -#endif -#ifndef _CPPUHELPER_EXC_HLP_HXX_ +#include +/** === end UNO includes === **/ + +#include +#include +#include +#include +#include +#include #include -#endif +#include +#include +#include +#include +#include -#ifndef BOOST_BIND_HPP_INCLUDED #include -#endif #include #include @@ -156,7 +112,35 @@ namespace dbaccess //........................................................................ //============================================================ -//= ODatabaseContext +//= ViewMonitor +//============================================================ +//-------------------------------------------------------------------------- +bool ViewMonitor::onControllerConnected( const Reference< XController >& _rxController ) +{ + bool bFirstControllerEver = ( m_bEverHadController == false ); + m_bEverHadController = true; + + m_xLastConnectedController = _rxController; + m_bLastIsFirstEverController = bFirstControllerEver; + + return bFirstControllerEver; +} + +//-------------------------------------------------------------------------- +void ViewMonitor::onSetCurrentController( const Reference< XController >& _rxController ) +{ + // we interpret this as "loading the document (including UI) is finished", + // if and only if this is the controller which was last connected, and it was the + // first controller ever connected + bool bLoadFinished = ( _rxController == m_xLastConnectedController ) && m_bLastIsFirstEverController; + + // notify the respective events + if ( bLoadFinished ) + m_rEventNotifier.notifyDocumentEventAsync( m_bIsNewDocument ? "OnNew" : "OnLoad" ); +} + +//============================================================ +//= ODatabaseDocument //============================================================ DBG_NAME(ODatabaseDocument) //-------------------------------------------------------------------------- @@ -171,8 +155,13 @@ ODatabaseDocument::ODatabaseDocument(const ::rtl::Reference& ,ODatabaseDocument_OfficeDocument( getMutex() ) ,m_aModifyListeners( getMutex() ) ,m_aCloseListener( getMutex() ) - ,m_aDocEventListeners( getMutex() ) ,m_aStorageListeners( getMutex() ) + ,m_pEventContainer( new DocumentEvents( *this, getMutex() ) ) + ,m_pEventExecutor( NULL ) // initialized below, ref-count-protected + ,m_aEventNotifier( *this, getMutex() ) + ,m_aViewMonitor( m_aEventNotifier ) + ,m_eInitState( NotInitialized ) + ,m_bClosing( false ) { DBG_CTOR(ODatabaseDocument,NULL); @@ -182,8 +171,16 @@ ODatabaseDocument::ODatabaseDocument(const ::rtl::Reference& impl_reparent_nothrow( m_xReports ); impl_reparent_nothrow( m_pImpl->m_xTableDefinitions ); impl_reparent_nothrow( m_pImpl->m_xCommandDefinitions ); + + m_pEventExecutor = new DocumentEventExecutor( m_pImpl->m_aContext, this ); } osl_decrementInterlockedCount( &m_refCount ); + + // if there previously was a document instance for the same Impl which was already initialized, + // then consider ourself initialized, too. + // #i94840# + if ( m_pImpl->hadInitializedDocument() ) + impl_setInitialized(); } //-------------------------------------------------------------------------- @@ -195,6 +192,8 @@ ODatabaseDocument::~ODatabaseDocument() acquire(); dispose(); } + + delete m_pEventContainer, m_pEventContainer = NULL; } // ----------------------------------------------------------------------------- Any SAL_CALL ODatabaseDocument::queryInterface( const Type& _rType ) throw (RuntimeException) @@ -286,12 +285,9 @@ Sequence< sal_Int8 > SAL_CALL ODatabaseDocument::getImplementationId( ) throw ( bool ODatabaseDocument::impl_shouldDisallowScripting_nolck_nothrow() const { ::osl::MutexGuard aGuard( getMutex() ); - // TODO: revert to the disabled code. The current version is just to be able - // to integrate an intermediate version of the CWS, which should behave as - // if no macros in DB docs are allowed -// if ( m_pImpl.is() && m_pImpl->hasAnyObjectWithMacros() ) + if ( m_pImpl.is() && m_pImpl->hasAnyObjectWithMacros() ) return true; -// return false; + return false; } // ----------------------------------------------------------------------------- @@ -299,15 +295,6 @@ bool ODatabaseDocument::impl_shouldDisallowScripting_nolck_nothrow() const // ----------------------------------------------------------------------------- namespace { - static void lcl_stripLoadArguments( ::comphelper::NamedValueCollection& _rArguments, Sequence< PropertyValue >& _rArgs ) - { - OSL_ENSURE( !_rArguments.has( "Model" ), "lcl_stripLoadArguments: this is suspicious (1)!" ); - OSL_ENSURE( !_rArguments.has( "ViewName" ), "lcl_stripLoadArguments: this is suspicious (2)!" ); - _rArguments.remove( "Model" ); - _rArguments.remove( "ViewName" ); - _rArguments >>= _rArgs; - } - // ----------------------------------------------------------------------------- static void lcl_extractAndStartStatusIndicator( const ::comphelper::NamedValueCollection& _rArguments, Reference< XStatusIndicator >& _rxStatusIndicator, Sequence< Any >& _rCallArgs ) @@ -342,6 +329,15 @@ namespace } } +// ----------------------------------------------------------------------------- +void ODatabaseDocument::impl_setInitialized() +{ + m_eInitState = Initialized; + + // start event notifications + m_aEventNotifier.onDocumentInitialized(); +} + // ----------------------------------------------------------------------------- void ODatabaseDocument::impl_reset_nothrow() { @@ -356,6 +352,8 @@ void ODatabaseDocument::impl_reset_nothrow() clearObjectContainer( m_pImpl->m_xTableDefinitions ); clearObjectContainer( m_pImpl->m_xCommandDefinitions ); + m_eInitState = NotInitialized; + m_pImpl->reset(); } catch(const Exception&) @@ -366,140 +364,186 @@ void ODatabaseDocument::impl_reset_nothrow() } // ----------------------------------------------------------------------------- -bool ODatabaseDocument::impl_import_throw( const ::comphelper::NamedValueCollection& _rResource ) +void ODatabaseDocument::impl_import_throw( const ::comphelper::NamedValueCollection& _rResource ) { - try - { - Sequence< Any > aFilterArgs; - Reference< XStatusIndicator > xStatusIndicator; - lcl_extractAndStartStatusIndicator( _rResource, xStatusIndicator, aFilterArgs ); + Sequence< Any > aFilterArgs; + Reference< XStatusIndicator > xStatusIndicator; + lcl_extractAndStartStatusIndicator( _rResource, xStatusIndicator, aFilterArgs ); - Reference< XImporter > xImporter( - m_pImpl->m_aContext.createComponentWithArguments( "com.sun.star.comp.sdb.DBFilter", aFilterArgs ), - UNO_QUERY_THROW ); + Reference< XImporter > xImporter( + m_pImpl->m_aContext.createComponentWithArguments( "com.sun.star.comp.sdb.DBFilter", aFilterArgs ), + UNO_QUERY_THROW ); - Reference< XComponent > xComponent( *this, UNO_QUERY_THROW ); - xImporter->setTargetDocument( xComponent ); + Reference< XComponent > xComponent( *this, UNO_QUERY_THROW ); + xImporter->setTargetDocument( xComponent ); - Reference< XFilter > xFilter( xImporter, UNO_QUERY_THROW ); - xFilter->filter( m_pImpl->m_aArgs ); + Reference< XFilter > xFilter( xImporter, UNO_QUERY_THROW ); + xFilter->filter( ODatabaseModelImpl::stripLoadArguments( _rResource ) ); - if ( xStatusIndicator.is() ) - xStatusIndicator->end(); - } - catch( const RuntimeException& e ) - { - throw e; - } - catch( const Exception& ) - { - return false; - } - return true; + if ( xStatusIndicator.is() ) + xStatusIndicator->end(); } // ----------------------------------------------------------------------------- -// XModel -// ATTENTION: The Application controller attaches the same resource to force a reload. -// TODO: this is a bug. By (API) definition, attachResource is only for notifying the document -// of its resource, *not* for loading it. We should implement an XLoadable, and move all the -// load logic therein. -sal_Bool SAL_CALL ODatabaseDocument::attachResource( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _aArguments ) throw (RuntimeException) +void SAL_CALL ODatabaseDocument::initNew( ) throw (DoubleInitializationException, IOException, Exception, RuntimeException) { - ModelMethodGuard aGuard( *this ); - OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); + // SYNCHRONIZED -> + DocumentGuard aGuard( *this, DocumentGuard::InitMethod ); impl_reset_nothrow(); - ::comphelper::NamedValueCollection aResource( _aArguments ); - lcl_stripLoadArguments( aResource, m_pImpl->m_aArgs ); + impl_setInitializing(); + + // create a temporary storage + Reference< XStorage > xTempStor( ::comphelper::OStorageHelper::GetTemporaryStorage( + m_pImpl->m_aContext.getLegacyServiceFactory() ) ); + + // store therein + impl_storeToStorage_throw( xTempStor, Sequence< PropertyValue >() ); + + // let the impl know we're now based on this storage + m_pImpl->switchToStorage( xTempStor ); + + impl_setInitialized(); + + m_aEventNotifier.notifyDocumentEventAsync( "OnTitleChanged" ); + + impl_setModified_nothrow( sal_False, aGuard ); + // <- SYNCHRONIZED + + m_aEventNotifier.notifyDocumentEvent( "OnCreate" ); + + impl_notifyStorageChange_nolck_nothrow( xTempStor ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::load( const Sequence< PropertyValue >& _Arguments ) throw (DoubleInitializationException, IOException, Exception, RuntimeException) +{ + // SYNCHRONIZED -> + DocumentGuard aGuard( *this, DocumentGuard::InitMethod ); + + impl_reset_nothrow(); + + ::comphelper::NamedValueCollection aResource( _Arguments ); // now that somebody (perhaps) told us an macro execution mode, remember it as // ImposedMacroExecMode m_pImpl->setImposedMacroExecMode( aResource.getOrDefault( "MacroExecutionMode", m_pImpl->getImposedMacroExecMode() ) ); - ::rtl::OUString sDocumentLocation( aResource.getOrDefault( "SalvagedFile", _rURL ) ); - if ( !sDocumentLocation.getLength() ) - // this indicates "the document is being recovered, but _rURL already is the real document URL, - // not the temporary document location" - sDocumentLocation = _rURL; - m_pImpl->switchToURL( sDocumentLocation, _rURL ); + impl_setInitializing(); + try + { + impl_import_throw( aResource ); + } + catch( const Exception& ) + { + impl_reset_nothrow(); + throw; + } + // tell our view monitor that the document has been loaded - this way it will fire the proper + // even (OnLoad instead of OnCreate) later on + m_aViewMonitor.onLoadedDocument(); - bool bSuccess = - ( m_pImpl->getOrCreateRootStorage().is() - && impl_import_throw( aResource ) // TODO: this doesn't belong here, but into an (externally called) XLoadable::load implementation - ); + // note that we do *not* call impl_setInitialized() here: The initialization is only complete + // when the XModel::attachResource has been called, not sooner. + + impl_setModified_nothrow( sal_False, aGuard ); + // <- SYNCHRONIZED +} - if ( !bSuccess ) +// ----------------------------------------------------------------------------- +// XModel +sal_Bool SAL_CALL ODatabaseDocument::attachResource( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); + + if ( ( _rURL == getURL() ) + && ( _rArguments.getLength() == 1 ) + && ( _rArguments[0].Name.compareToAscii( "BreakMacroSignature" ) == 0 ) + ) { - m_pImpl->revokeDataSource(); + // this is a BAD hack of the Basic importer code ... there should be a dedicated API for this, + // not this bad mis-using of existing interfaces return sal_False; + // (we do not support macro signatures, so we can ignore this call) + } + + m_pImpl->attachResource( _rURL, _rArguments ); + + if ( impl_isInitializing() ) + { // this means we've just been loaded, and this is the attachResource call which follows + // the load call. + impl_setInitialized(); + m_aEventNotifier.notifyDocumentEvent( "OnLoadFinished" ); } - impl_setModified_throw( sal_False, aGuard ); return sal_True; } + // ----------------------------------------------------------------------------- ::rtl::OUString SAL_CALL ODatabaseDocument::getURL( ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); return m_pImpl->getURL(); } + // ----------------------------------------------------------------------------- Sequence< PropertyValue > SAL_CALL ODatabaseDocument::getArgs( ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); - return m_pImpl->m_aArgs; + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); + return m_pImpl->getResource(); } + // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::connectController( const Reference< XController >& _xController ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this ); m_aControllers.push_back( _xController ); - if ( m_aControllers.size() != 1 ) + m_aEventNotifier.notifyDocumentEventAsync( "OnViewCreated", Reference< XController2 >( _xController, UNO_QUERY ) ); + + bool bFirstControllerEver = m_aViewMonitor.onControllerConnected( _xController ); + if ( !bFirstControllerEver ) return; - // it's the first controller - - // check/adjust our macro mode. Note: This is only temporary. When we fully support the - // XEmbeddedScripts interface, plus related functionality, then the controller is able - // to do this itself, since we'll then have a UNO method for this. - // - // Also, the same has to happen in the loader then, since the checks must be made - // *before* OnLoad events are triggered - finally, the user can bind events to OnLoad ... - // (This, at the latest, implies we need a UNO equivalent for checkMacrosOnLoading, else - // the loader can't call it.) - // - // For now, as long as we do not have own macros, but only those in the embedded - // forms/reports, it's sufficient to do the check here. - // + // check/adjust our macro mode. m_pImpl->checkMacrosOnLoading(); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::disconnectController( const Reference< XController >& _xController ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); - OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); + bool bNotifyViewClosed = false; + bool bLastControllerGone = false; + bool bIsClosing = false; + + // SYNCHRONIZED -> + { + DocumentGuard aGuard( *this ); + + Controllers::iterator pos = ::std::find( m_aControllers.begin(), m_aControllers.end(), _xController ); + OSL_ENSURE( pos != m_aControllers.end(), "ODatabaseDocument::disconnectController: don't know this controller!" ); + if ( pos != m_aControllers.end() ) + { + m_aControllers.erase( pos ); + bNotifyViewClosed = true; + } - Controllers::iterator pos = ::std::find( m_aControllers.begin(), m_aControllers.end(), _xController ); - OSL_ENSURE( pos != m_aControllers.end(), "ODatabaseDocument::disconnectController: don't know this controller!" ); - if ( pos != m_aControllers.end() ) - m_aControllers.erase( pos ); + if ( m_xCurrentController == _xController ) + m_xCurrentController = NULL; - if ( m_xCurrentController == _xController ) - m_xCurrentController = NULL; + bLastControllerGone = m_aControllers.empty(); + bIsClosing = m_bClosing; + } + // <- SYNCHRONIZED - if ( m_aControllers.empty() ) - { - // reset the macro mode: in case the our impl struct stays alive (e.g. because our DataSource - // object still exists), and somebody subsequently re-opens the document, we want to have - // the security warning, again. - m_pImpl->resetMacroExecutionMode(); + if ( bNotifyViewClosed ) + m_aEventNotifier.notifyDocumentEvent( "OnViewClosed", Reference< XController2 >( _xController, UNO_QUERY ) ); + if ( bLastControllerGone && !bIsClosing ) + { // if this was the last view, close the document as a whole // #i51157# / 2006-03-16 / frank.schoenheit@sun.com try @@ -512,51 +556,52 @@ void SAL_CALL ODatabaseDocument::disconnectController( const Reference< XControl } } } + // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::lockControllers( ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); - OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); + DocumentGuard aGuard( *this ); ++m_pImpl->m_nControllerLockCount; } + // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::unlockControllers( ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); - OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); + DocumentGuard aGuard( *this ); --m_pImpl->m_nControllerLockCount; } + // ----------------------------------------------------------------------------- sal_Bool SAL_CALL ODatabaseDocument::hasControllersLocked( ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); - OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); + DocumentGuard aGuard( *this ); return m_pImpl->m_nControllerLockCount != 0; } + // ----------------------------------------------------------------------------- Reference< XController > SAL_CALL ODatabaseDocument::getCurrentController() throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); - OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); + DocumentGuard aGuard( *this ); return m_xCurrentController.is() ? m_xCurrentController : ( m_aControllers.empty() ? Reference< XController >() : *m_aControllers.begin() ); } + // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::setCurrentController( const Reference< XController >& _xController ) throw (NoSuchElementException, RuntimeException) { - ModelMethodGuard aGuard( *this ); - OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); + DocumentGuard aGuard( *this ); m_xCurrentController = _xController; + + m_aViewMonitor.onSetCurrentController( _xController ); } // ----------------------------------------------------------------------------- Reference< XInterface > SAL_CALL ODatabaseDocument::getCurrentSelection( ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); - OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); + DocumentGuard aGuard( *this ); Reference< XInterface > xRet; Reference< XSelectionSupplier > xDocView( getCurrentController(), UNO_QUERY ); @@ -570,91 +615,115 @@ Reference< XInterface > SAL_CALL ODatabaseDocument::getCurrentSelection( ) thro // XStorable sal_Bool SAL_CALL ODatabaseDocument::hasLocation( ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); - return m_pImpl->getLocation().getLength() > 0; + return getLocation().getLength() > 0; } // ----------------------------------------------------------------------------- ::rtl::OUString SAL_CALL ODatabaseDocument::getLocation( ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); - return m_pImpl->getLocation(); + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); + return m_pImpl->getURL(); } // ----------------------------------------------------------------------------- sal_Bool SAL_CALL ODatabaseDocument::isReadonly( ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); - OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); - + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); return m_pImpl->m_bDocumentReadOnly; } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::store( ) throw (IOException, RuntimeException) { - ModelMethodGuard aGuard( *this ); - //ModifyLock aLock( *this ); + DocumentGuard aGuard( *this ); - if ( m_pImpl->getLocation() == m_pImpl->getURL() ) + if ( m_pImpl->getDocFileLocation() == m_pImpl->getURL() ) if ( m_pImpl->m_bDocumentReadOnly ) throw IOException(); - impl_storeAs_throw( m_pImpl->getURL(), m_pImpl->m_aArgs, "OnSaveDone", aGuard ); + impl_storeAs_throw( m_pImpl->getURL(), m_pImpl->getResource(), SAVE, aGuard ); } // ----------------------------------------------------------------------------- void ODatabaseDocument::impl_storeAs_throw( const ::rtl::OUString& _rURL, const Sequence< PropertyValue>& _rArguments, - const sal_Char* _pAsciiDocumentEventName, ModelMethodGuard& _rGuard ) + const StoreType _eType, DocumentGuard& _rGuard ) { + OSL_PRECOND( ( _eType == SAVE ) || ( _eType == SAVE_AS ), + "ODatabaseDocument::impl_storeAs_throw: you introduced a new type which cannot be handled here!" ); + + // if we're in the process of initializing the document (which effectively means it is an implicit + // initialization triggered in storeAsURL), the we do not notify events, since to an observer, the SaveAs + // should not be noticable + bool bIsInitializationProcess = impl_isInitializing(); + + if ( !bIsInitializationProcess ) + { + _rGuard.clear(); + m_aEventNotifier.notifyDocumentEvent( _eType == SAVE ? "OnSave" : "OnSaveAs", NULL, makeAny( _rURL ) ); + _rGuard.reset(); + } + Reference< XStorage > xNewRootStorage; // will be non-NULL if our storage changed - sal_Bool bLocationChanged = ( _rURL != m_pImpl->getLocation() ); - if ( bLocationChanged ) + try { - // create storage for target URL - Reference< XStorage > xTargetStorage( impl_createStorageFor_throw( _rURL ) ); + ModifyLock aLock( *this ); + // ignore all changes of our "modified" state during storing - if ( m_pImpl->isEmbeddedDatabase() ) - m_pImpl->clearConnections(); - - // commit everything - m_pImpl->commitEmbeddedStorage(); - m_pImpl->commitStorages(); + sal_Bool bLocationChanged = ( _rURL != m_pImpl->getDocFileLocation() ); + if ( bLocationChanged ) + { + // create storage for target URL + Reference< XStorage > xTargetStorage( impl_createStorageFor_throw( _rURL ) ); - // copy own storage to target storage - Reference< XStorage > xCurrentStorage( m_pImpl->getRootStorage() ); - if ( xCurrentStorage.is() ) - xCurrentStorage->copyToStorage( xTargetStorage ); + if ( m_pImpl->isEmbeddedDatabase() ) + m_pImpl->clearConnections(); - m_pImpl->disposeStorages(); + // commit everything + m_pImpl->commitEmbeddedStorage(); + m_pImpl->commitStorages(); - xNewRootStorage = m_pImpl->switchToStorage( xTargetStorage ); + // copy own storage to target storage + Reference< XStorage > xCurrentStorage( m_pImpl->getRootStorage() ); + if ( xCurrentStorage.is() ) + xCurrentStorage->copyToStorage( xTargetStorage ); - m_pImpl->m_bDocumentReadOnly = sal_False; - } + m_pImpl->disposeStorages(); - // adjust arguments - ::comphelper::NamedValueCollection aResource( _rArguments ); - lcl_stripLoadArguments( aResource, m_pImpl->m_aArgs ); - Sequence< PropertyValue > aMediaDescriptor( lcl_appendFileNameToDescriptor( m_pImpl->m_aArgs, _rURL ) ); + xNewRootStorage = m_pImpl->switchToStorage( xTargetStorage ); - // store to current storage - Reference< XStorage > xCurrentStorage( m_pImpl->getOrCreateRootStorage(), UNO_QUERY_THROW ); - impl_storeToStorage_throw( xCurrentStorage, aMediaDescriptor ); + m_pImpl->m_bDocumentReadOnly = sal_False; + } - // success - tell our impl the new URL - m_pImpl->switchToURL( _rURL, _rURL ); + // store to current storage + Reference< XStorage > xCurrentStorage( m_pImpl->getOrCreateRootStorage(), UNO_QUERY_THROW ); + Sequence< PropertyValue > aMediaDescriptor( lcl_appendFileNameToDescriptor( _rArguments, _rURL ) ); + impl_storeToStorage_throw( xCurrentStorage, aMediaDescriptor ); - // create a document event (mutex still locked) - document::EventObject aEvent( *this, ::rtl::OUString::createFromAscii( _pAsciiDocumentEventName ) ); + // success - tell our impl + m_pImpl->attachResource( _rURL, aMediaDescriptor ); - // reset our "modified" flag, and clear the guard - impl_setModified_throw( sal_False, _rGuard ); + // if we are in an initialization process, then this is finished, now that we stored the document + if ( bIsInitializationProcess ) + impl_setInitialized(); + } + catch( const Exception& ) + { + // notify the failure + if ( !bIsInitializationProcess ) + m_aEventNotifier.notifyDocumentEventAsync( _eType == SAVE ? "OnSaveFailed" : "OnSaveAsFailed", NULL, makeAny( _rURL ) ); + throw; + } // notify the document event - impl_notifyEvent_nolck_nothrow( aEvent ); + if ( !bIsInitializationProcess ) + m_aEventNotifier.notifyDocumentEventAsync( _eType == SAVE ? "OnSaveDone" : "OnSaveAsDone", NULL, makeAny( _rURL ) ); + + // reset our "modified" flag, and clear the guard + impl_setModified_nothrow( sal_False, _rGuard ); + // <- SYNCHRONIZED // notify storage listeners - impl_notifyStorageChange_nolck_nothrow( xNewRootStorage ); + if ( xNewRootStorage.is() ) + impl_notifyStorageChange_nolck_nothrow( xNewRootStorage ); } // ----------------------------------------------------------------------------- @@ -671,10 +740,46 @@ Reference< XStorage > ODatabaseDocument::impl_createStorageFor_throw( const ::rt // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::storeAsURL( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (IOException, RuntimeException) { - ModelMethodGuard aGuard( *this ); - //ModifyLock aLock( *this ); + // SYNCHRONIZED -> + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); + + // Normally, a document initialization is done via XLoadable::load or XLoadable::initNew. For convenience + // reasons, and to not break existing API clients, it's allowed to call storeAsURL without having initialized + // the document, in which case the initialization will be done implicitly. + bool bImplicitInitialization = !impl_isInitialized(); + // implicit initialization while another initialization is just running is not possible + if ( bImplicitInitialization && impl_isInitializing() ) + throw DoubleInitializationException(); - impl_storeAs_throw( _rURL, _rArguments, "OnSaveAsDone", aGuard ); + if ( bImplicitInitialization ) + impl_setInitializing(); + + try + { + impl_storeAs_throw( _rURL, _rArguments, SAVE_AS, aGuard ); + // <- SYNCHRONIZED + + // impl_storeAs_throw cleared the lock on our mutex, but the below lines need this lock + // SYNCHRONIZED -> + aGuard.reset(); + + // our title might have changed, potentially at least + // Sadly, we cannot check this: Calling getTitle here and now would not deliver + // an up-to-date result, as the call is delegated to our TitleHelper instance, which itself + // updates its title only if it gets the OnSaveAsDone event (which was sent asynchronously + // by impl_storeAs_throw). So, we simply notify always, and also asynchronously + m_aEventNotifier.notifyDocumentEventAsync( "OnTitleChanged" ); + } + catch( const Exception& ) + { + impl_reset_nothrow(); + throw; + } + aGuard.clear(); + // <- SYNCHRONIZED + + if ( bImplicitInitialization ) + m_aEventNotifier.notifyDocumentEvent( "OnCreate" ); } // ----------------------------------------------------------------------------- @@ -693,9 +798,12 @@ void ODatabaseDocument::impl_storeToStorage_throw( const Reference< XStorage >& m_pImpl->commitStorages(); // copy own storage to target storage - Reference< XStorage > xCurrentStorage( m_pImpl->getOrCreateRootStorage(), UNO_QUERY_THROW ); - if ( xCurrentStorage != _rxTargetStorage ) - xCurrentStorage->copyToStorage( _rxTargetStorage ); + if ( impl_isInitialized() ) + { + Reference< XStorage > xCurrentStorage( m_pImpl->getOrCreateRootStorage(), UNO_QUERY_THROW ); + if ( xCurrentStorage != _rxTargetStorage ) + xCurrentStorage->copyToStorage( _rxTargetStorage ); + } // write into target storage ::comphelper::NamedValueCollection aWriteArgs( _rMediaDescriptor ); @@ -715,31 +823,47 @@ void ODatabaseDocument::impl_storeToStorage_throw( const Reference< XStorage >& // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::storeToURL( const ::rtl::OUString& _rURL, const Sequence< PropertyValue >& _rArguments ) throw (IOException, RuntimeException) { - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this ); ModifyLock aLock( *this ); - // create storage for target URL - Reference< XStorage > xTargetStorage( impl_createStorageFor_throw( _rURL ) ); + { + aGuard.clear(); + m_aEventNotifier.notifyDocumentEvent( "OnSaveTo", NULL, makeAny( _rURL ) ); + aGuard.reset(); + } + + try + { + // create storage for target URL + Reference< XStorage > xTargetStorage( impl_createStorageFor_throw( _rURL ) ); + + // extend media descriptor with URL + Sequence< PropertyValue > aMediaDescriptor( lcl_appendFileNameToDescriptor( _rArguments, _rURL ) ); - // extend media descriptor with URL - Sequence< PropertyValue > aMediaDescriptor( lcl_appendFileNameToDescriptor( _rArguments, _rURL ) ); + // store to this storage + impl_storeToStorage_throw( xTargetStorage, aMediaDescriptor ); + } + catch( const Exception& ) + { + m_aEventNotifier.notifyDocumentEventAsync( "OnSaveToFailed", NULL, makeAny( _rURL ) ); + throw; + } - // store to this storage - impl_storeToStorage_throw( xTargetStorage, aMediaDescriptor ); + m_aEventNotifier.notifyDocumentEventAsync( "OnSaveToDone", NULL, makeAny( _rURL ) ); } // ----------------------------------------------------------------------------- // XModifyBroadcaster void SAL_CALL ODatabaseDocument::addModifyListener( const Reference< XModifyListener >& _xListener ) throw (RuntimeException) { - ::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed); + DocumentGuard aGuard( *this ); m_aModifyListeners.addInterface(_xListener); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::removeModifyListener( const Reference< XModifyListener >& _xListener ) throw (RuntimeException) { - ::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed); + DocumentGuard aGuard( *this ); m_aModifyListeners.removeInterface(_xListener); } @@ -747,8 +871,7 @@ void SAL_CALL ODatabaseDocument::removeModifyListener( const Reference< XModifyL // XModifiable sal_Bool SAL_CALL ODatabaseDocument::isModified( ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); - OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); + DocumentGuard aGuard( *this ); return m_pImpl->m_bModified; } @@ -756,52 +879,82 @@ sal_Bool SAL_CALL ODatabaseDocument::isModified( ) throw (RuntimeException) // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::setModified( sal_Bool _bModified ) throw (PropertyVetoException, RuntimeException) { - ModelMethodGuard aGuard( *this ); - impl_setModified_throw( _bModified, aGuard ); + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); + if ( impl_isInitialized() ) + impl_setModified_nothrow( _bModified, aGuard ); + // it's allowed to call setModified without the document being initialized already. In this case, + // we simply ignore the call - when the initialization is finished, the respective code will set + // a proper "modified" flag } // ----------------------------------------------------------------------------- -void ODatabaseDocument::impl_setModified_throw( sal_Bool _bModified, ModelMethodGuard& _rGuard ) +void ODatabaseDocument::impl_setModified_nothrow( sal_Bool _bModified, DocumentGuard& _rGuard ) { - if ( m_pImpl->m_bModified == _bModified ) - return; - - if ( m_pImpl->isModifyLocked() ) - return; - - m_pImpl->m_bModified = _bModified; + // SYNCHRONIZED -> + bool bModifiedChanged = ( m_pImpl->m_bModified != _bModified ) && ( !m_pImpl->isModifyLocked() ); - document::EventObject aEvent( *this, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OnModifyChanged" ) ) ); + if ( bModifiedChanged ) + { + m_pImpl->m_bModified = _bModified; + m_aEventNotifier.notifyDocumentEventAsync( "OnModifyChanged" ); + } _rGuard.clear(); + // <- SYNCHRONIZED - m_aModifyListeners.notifyEach( &XModifyListener::modified, (const lang::EventObject&)aEvent ); - impl_notifyEvent_nolck_nothrow( aEvent ); + if ( bModifiedChanged ) + { + lang::EventObject aEvent( *this ); + m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvent ); + } } // ----------------------------------------------------------------------------- // ::com::sun::star::document::XEventBroadcaster -void SAL_CALL ODatabaseDocument::addEventListener(const uno::Reference< document::XEventListener >& _xListener ) throw (uno::RuntimeException) +void SAL_CALL ODatabaseDocument::addEventListener(const uno::Reference< document::XEventListener >& _Listener ) throw (uno::RuntimeException) +{ + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); + m_aEventNotifier.addLegacyEventListener( _Listener ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::removeEventListener( const uno::Reference< document::XEventListener >& _Listener ) throw (uno::RuntimeException) +{ + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); + m_aEventNotifier.removeLegacyEventListener( _Listener ); +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::addDocumentEventListener( const Reference< XDocumentEventListener >& _Listener ) throw (RuntimeException) { - ::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed); - m_aDocEventListeners.addInterface(_xListener); + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); + m_aEventNotifier.addDocumentEventListener( _Listener ); } // ----------------------------------------------------------------------------- -void SAL_CALL ODatabaseDocument::removeEventListener( const uno::Reference< document::XEventListener >& _xListener ) throw (uno::RuntimeException) +void SAL_CALL ODatabaseDocument::removeDocumentEventListener( const Reference< XDocumentEventListener >& _Listener ) throw (RuntimeException) { - ::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed); - m_aDocEventListeners.removeInterface(_xListener); + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); + m_aEventNotifier.removeDocumentEventListener( _Listener ); } // ----------------------------------------------------------------------------- -void SAL_CALL ODatabaseDocument::notifyEvent( const document::EventObject& _rEvent ) throw (RuntimeException) +void SAL_CALL ODatabaseDocument::notifyDocumentEvent( const ::rtl::OUString& _EventName, const Reference< XController2 >& _ViewController, const Any& _Supplement ) throw (IllegalArgumentException, NoSupportException, RuntimeException) { - ModelMethodGuard aGuard( *this ); - // used only to forward external events (e.g. for doc creation) from the frame loader - // to the global event broadcaster and all other interested doc event listener. - document::EventObject aEvent( *this, _rEvent.EventName ); + if ( !_EventName.getLength() ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); + + // SYNCHRONIZED -> + DocumentGuard aGuard( *this ); + + if ( !DocumentEvents::needsSynchronousNotification( _EventName ) ) + { + m_aEventNotifier.notifyDocumentEventAsync( _EventName, _ViewController, _Supplement ); + return; + } aGuard.clear(); - impl_notifyEvent_nolck_nothrow( aEvent ); + // <- SYNCHRONIZED + + m_aEventNotifier.notifyDocumentEvent( _EventName, _ViewController, _Supplement ); } // ----------------------------------------------------------------------------- @@ -844,9 +997,6 @@ void ODatabaseDocument::clearObjectContainer( WeakReference< XNameAccess >& _rxC // ----------------------------------------------------------------------------- Reference< XNameAccess > ODatabaseDocument::impl_getDocumentContainer_throw( ODatabaseModelImpl::ObjectType _eType ) { - ModelMethodGuard aGuard( *this ); - OSL_POSTCOND( m_pImpl.is(), "ODatabaseDocument::impl_getDocumentContainer_throw: Impl is NULL" ); - if ( ( _eType != ODatabaseModelImpl::E_FORM ) && ( _eType != ODatabaseModelImpl::E_REPORT ) ) throw IllegalArgumentException(); @@ -916,42 +1066,67 @@ void ODatabaseDocument::impl_disposeControllerFrames_nothrow() } // ----------------------------------------------------------------------------- -void SAL_CALL ODatabaseDocument::close( sal_Bool _bDeliverOwnership ) throw (::com::sun::star::util::CloseVetoException, RuntimeException) +void SAL_CALL ODatabaseDocument::close( sal_Bool _bDeliverOwnership ) throw (CloseVetoException, RuntimeException) { - document::EventObject aEvent( *this, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OnUnload" ) ) ); + // nearly everything below can/must be done without our mutex locked, the below is just for + // the checks for being disposed and the like + // SYNCHRONIZED -> + { + DocumentGuard aGuard( *this ); + m_bClosing = true; + } + // <- SYNCHRONIZED - m_aCloseListener.forEach< XCloseListener >( - boost::bind( &XCloseListener::queryClosing, _1, boost::cref( aEvent ), boost::cref( _bDeliverOwnership ) ) ); + try + { + // allow listeners to veto + lang::EventObject aEvent( *this ); + m_aCloseListener.forEach< XCloseListener >( + boost::bind( &XCloseListener::queryClosing, _1, boost::cref( aEvent ), boost::cref( _bDeliverOwnership ) ) ); - impl_closeControllerFrames_nolck_throw( _bDeliverOwnership ); + // notify that we're going to unload + m_aEventNotifier.notifyDocumentEvent( "OnPrepareUnload" ); - m_aCloseListener.notifyEach( &XCloseListener::notifyClosing, (const lang::EventObject&)aEvent ); + impl_closeControllerFrames_nolck_throw( _bDeliverOwnership ); - // notify the OnUnload at the earliest possibility - which is here and now - impl_notifyEvent_nolck_nothrow( aEvent ); + m_aCloseListener.notifyEach( &XCloseListener::notifyClosing, (const lang::EventObject&)aEvent ); + + dispose(); + } + catch ( const Exception& ) + { + ::osl::MutexGuard aGuard( m_xMutex->getMutex() ); + m_bClosing = false; + throw; + } - dispose(); + // SYNCHRONIZED -> + ::osl::MutexGuard aGuard( m_xMutex->getMutex() ); + m_bClosing = false; + // <- SYNCHRONIZED } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::addCloseListener( const Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (RuntimeException) { - ::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed); + DocumentGuard aGuard( *this ); m_aCloseListener.addInterface(Listener); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::removeCloseListener( const Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (RuntimeException) { - ::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed); + DocumentGuard aGuard( *this ); m_aCloseListener.removeInterface(Listener); } // ----------------------------------------------------------------------------- Reference< XNameAccess > SAL_CALL ODatabaseDocument::getFormDocuments( ) throw (RuntimeException) { + DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); return impl_getDocumentContainer_throw( ODatabaseModelImpl::E_FORM ); } // ----------------------------------------------------------------------------- Reference< XNameAccess > SAL_CALL ODatabaseDocument::getReportDocuments( ) throw (RuntimeException) { + DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); return impl_getDocumentContainer_throw( ODatabaseModelImpl::E_REPORT ); } @@ -1072,8 +1247,7 @@ void ODatabaseDocument::writeStorage( const Reference< XStorage >& _rxTargetStor // ----------------------------------------------------------------------------- Reference< XUIConfigurationManager > SAL_CALL ODatabaseDocument::getUIConfigurationManager( ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); - OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); + DocumentGuard aGuard( *this ); if ( !m_xUIConfigurationManager.is() ) { @@ -1111,7 +1285,7 @@ Reference< XUIConfigurationManager > SAL_CALL ODatabaseDocument::getUIConfigurat // ----------------------------------------------------------------------------- Reference< XStorage > SAL_CALL ODatabaseDocument::getDocumentSubStorage( const ::rtl::OUString& aStorageName, sal_Int32 nMode ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this ); Reference< XDocumentSubStorageSupplier > xStorageAccess( m_pImpl->getDocumentSubStorageSupplier() ); return xStorageAccess->getDocumentSubStorage( aStorageName, nMode ); @@ -1123,19 +1297,6 @@ Sequence< ::rtl::OUString > SAL_CALL ODatabaseDocument::getDocumentSubStoragesNa return xStorageAccess->getDocumentSubStoragesNames(); } -// ----------------------------------------------------------------------------- -void ODatabaseDocument::impl_notifyEvent_nolck_nothrow( const document::EventObject& _rEvent ) -{ - try - { - m_aDocEventListeners.notifyEach( &XEventListener::notifyEvent, _rEvent ); - } - catch(const Exception&) - { - DBG_UNHANDLED_EXCEPTION(); - } -} - //------------------------------------------------------------------------------ void ODatabaseDocument::impl_notifyStorageChange_nolck_nothrow( const Reference< XStorage >& _rxNewRootStorage ) { @@ -1155,39 +1316,51 @@ void ODatabaseDocument::disposing() return; } + if ( impl_isInitialized() ) + m_aEventNotifier.notifyDocumentEvent( "OnUnload" ); + + Reference< XModel > xHoldAlive( this ); + + m_aEventNotifier.disposing(); + + lang::EventObject aDisposeEvent(static_cast(this)); + m_aModifyListeners.disposeAndClear( aDisposeEvent ); + m_aCloseListener.disposeAndClear( aDisposeEvent ); + m_aStorageListeners.disposeAndClear( aDisposeEvent ); + + // SYNCHRONIZED -> + ::osl::MutexGuard aGuard( m_xMutex->getMutex() ); + DBG_ASSERT( m_aControllers.empty(), "ODatabaseDocument::disposing: there still are controllers!" ); // normally, nobody should explicitly dispose, but only XCloseable::close the document. And upon // closing, our controllers are closed, too - Reference< XModel > xHoldAlive( this ); - { - { - document::EventObject aEvent( *this, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OnLoad" ) ) ); - impl_notifyEvent_nolck_nothrow( aEvent ); - } + m_xUIConfigurationManager = NULL; - lang::EventObject aDisposeEvent(static_cast(this)); - m_aModifyListeners.disposeAndClear( aDisposeEvent ); - m_aCloseListener.disposeAndClear( aDisposeEvent ); - m_aDocEventListeners.disposeAndClear( aDisposeEvent ); - m_aStorageListeners.disposeAndClear( aDisposeEvent ); + clearObjectContainer( m_xForms ); + clearObjectContainer( m_xReports ); - m_xUIConfigurationManager = NULL; + // reset the macro mode: in case the our impl struct stays alive (e.g. because our DataSource + // object still exists), and somebody subsequently re-opens the document, we want to have + // the security warning, again. + m_pImpl->resetMacroExecutionMode(); - clearObjectContainer( m_xForms ); - clearObjectContainer( m_xReports ); + // similar argueing for our ViewMonitor + m_aViewMonitor.reset(); - m_pImpl->modelIsDisposing( ODatabaseModelImpl::ResetModelAccess() ); + // tell our Impl to forget us + m_pImpl->modelIsDisposing( impl_isInitialized(), ODatabaseModelImpl::ResetModelAccess() ); - // now, at the latest, the controller array should be empty. Controllers are - // expected to listen for our disposal, and disconnect then - DBG_ASSERT( m_aControllers.empty(), "ODatabaseDocument::disposing: there still are controllers!" ); - impl_disposeControllerFrames_nothrow(); - m_xModuleManager.clear(); - m_xTitleHelper.clear(); - } + // now, at the latest, the controller array should be empty. Controllers are + // expected to listen for our disposal, and disconnect then + DBG_ASSERT( m_aControllers.empty(), "ODatabaseDocument::disposing: there still are controllers!" ); + impl_disposeControllerFrames_nothrow(); + + m_xModuleManager.clear(); + m_xTitleHelper.clear(); m_pImpl.clear(); + // <- SYNCHRONIZED } // ----------------------------------------------------------------------------- // XComponent @@ -1232,7 +1405,7 @@ Reference< XInterface > ODatabaseDocument::Create( const Reference< XComponentCo ODatabaseContext* pContext = reinterpret_cast< ODatabaseContext* >( xDBContextTunnel->getSomething( ODatabaseContext::getUnoTunnelImplementationId() ) ); ::rtl::Reference pImpl( new ODatabaseModelImpl( aContext.getLegacyServiceFactory(), *pContext ) ); - Reference< XModel > xModel( pImpl->createNewModel_deliverOwnership() ); + Reference< XModel > xModel( pImpl->createNewModel_deliverOwnership( false ) ); return xModel.get(); } @@ -1253,15 +1426,14 @@ sal_Bool ODatabaseDocument::supportsService( const ::rtl::OUString& _rServiceNam // ----------------------------------------------------------------------------- Reference< XDataSource > SAL_CALL ODatabaseDocument::getDataSource() throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); - OSL_ENSURE(m_pImpl.is(),"Impl is NULL"); - return m_pImpl->getDataSource(); + DocumentGuard aGuard( *this, DocumentGuard::MethodWithoutInit ); + return m_pImpl->getOrCreateDataSource(); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::loadFromStorage( const Reference< XStorage >& /*xStorage*/, const Sequence< PropertyValue >& /*aMediaDescriptor*/ ) throw (IllegalArgumentException, DoubleInitializationException, IOException, Exception, RuntimeException) { - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this ); throw Exception( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Embedding of database documents is not supported." ) ), @@ -1273,8 +1445,7 @@ void SAL_CALL ODatabaseDocument::loadFromStorage( const Reference< XStorage >& / // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::storeToStorage( const Reference< XStorage >& _rxStorage, const Sequence< PropertyValue >& _rMediaDescriptor ) throw (IllegalArgumentException, IOException, Exception, RuntimeException) { - ModelMethodGuard aGuard( *this ); - //ModifyLock aLock( *this ); + DocumentGuard aGuard( *this ); impl_storeToStorage_throw( _rxStorage, _rMediaDescriptor ); } @@ -1282,7 +1453,7 @@ void SAL_CALL ODatabaseDocument::storeToStorage( const Reference< XStorage >& _r // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::switchToStorage( const Reference< XStorage >& _rxNewRootStorage ) throw (IllegalArgumentException, IOException, Exception, RuntimeException) { - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this ); Reference< XStorage > xNewRootStorage( m_pImpl->switchToStorage( _rxNewRootStorage ) ); @@ -1293,56 +1464,56 @@ void SAL_CALL ODatabaseDocument::switchToStorage( const Reference< XStorage >& _ // ----------------------------------------------------------------------------- Reference< XStorage > SAL_CALL ODatabaseDocument::getDocumentStorage( ) throw (IOException, Exception, RuntimeException) { - ModelMethodGuard aGuard( *this ); - return m_pImpl->getRootStorage(); + DocumentGuard aGuard( *this ); + return m_pImpl->getOrCreateRootStorage(); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::addStorageChangeListener( const Reference< XStorageChangeListener >& _Listener ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this ); m_aStorageListeners.addInterface( _Listener ); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::removeStorageChangeListener( const Reference< XStorageChangeListener >& _Listener ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this ); m_aStorageListeners.addInterface( _Listener ); } // ----------------------------------------------------------------------------- Reference< XStorageBasedLibraryContainer > SAL_CALL ODatabaseDocument::getBasicLibraries() throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); return m_pImpl->getLibraryContainer( true ); } // ----------------------------------------------------------------------------- Reference< XStorageBasedLibraryContainer > SAL_CALL ODatabaseDocument::getDialogLibraries() throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this ); return m_pImpl->getLibraryContainer( false ); } // ----------------------------------------------------------------------------- ::sal_Bool SAL_CALL ODatabaseDocument::getAllowMacroExecution() throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this ); return m_pImpl->adjustMacroMode_AutoReject(); } // ----------------------------------------------------------------------------- Reference< XEmbeddedScripts > SAL_CALL ODatabaseDocument::getScriptContainer() throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this ); return this; } // ----------------------------------------------------------------------------- Reference< provider::XScriptProvider > SAL_CALL ODatabaseDocument::getScriptProvider( ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this ); Reference< XScriptProvider > xScriptProvider( m_xScriptProvider ); if ( !xScriptProvider.is() ) @@ -1361,6 +1532,12 @@ Reference< provider::XScriptProvider > SAL_CALL ODatabaseDocument::getScriptProv return xScriptProvider; } +// ----------------------------------------------------------------------------- +Reference< XNameReplace > SAL_CALL ODatabaseDocument::getEvents( ) throw (RuntimeException) +{ + DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); + return m_pEventContainer; +} // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(RuntimeException) @@ -1386,7 +1563,7 @@ struct CreateAny : public ::std::unary_function< Reference, Any> // XModel2 Reference< XEnumeration > SAL_CALL ODatabaseDocument::getControllers( ) throw (RuntimeException) { - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this ); uno::Sequence< Any> aController( m_aControllers.size() ); ::std::transform( m_aControllers.begin(), m_aControllers.end(), aController.getArray(), CreateAny() ); return new ::comphelper::OAnyEnumeration(aController); @@ -1416,7 +1593,7 @@ Reference< XController2 > SAL_CALL ODatabaseDocument::createViewController( cons if ( !_Frame.is() ) throw IllegalArgumentException( ::rtl::OUString(), *this, 3 ); - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this ); ::comphelper::ComponentContext aContext( m_pImpl->m_aContext ); aGuard.clear(); @@ -1437,8 +1614,6 @@ Reference< XController2 > SAL_CALL ODatabaseDocument::createViewController( cons //============================================================================= Reference< XTitle > ODatabaseDocument::impl_getTitleHelper_throw() { - ModelMethodGuard aGuard( *this ); - if ( ! m_xTitleHelper.is ()) { Reference< XUntitledNumbers > xDesktop( @@ -1458,8 +1633,6 @@ Reference< XTitle > ODatabaseDocument::impl_getTitleHelper_throw() //============================================================================= uno::Reference< frame::XUntitledNumbers > ODatabaseDocument::impl_getUntitledHelper_throw(const uno::Reference< uno::XInterface >& _xComponent) { - ModelMethodGuard aGuard( *this ); - if ( !m_xModuleManager.is() ) m_xModuleManager.set( m_pImpl->m_aContext.createComponent( "com.sun.star.frame.ModuleManager" ), UNO_QUERY_THROW ); @@ -1498,9 +1671,8 @@ uno::Reference< frame::XUntitledNumbers > ODatabaseDocument::impl_getUntitledHel throw (uno::RuntimeException) { // SYNCHRONIZED -> - ModelMethodGuard aGuard( *this ); - - return impl_getTitleHelper_throw()->getTitle (); + DocumentGuard aGuard( *this, DocumentGuard::MethodUsedDuringInit ); + return impl_getTitleHelper_throw()->getTitle(); } //============================================================================= @@ -1509,9 +1681,10 @@ void SAL_CALL ODatabaseDocument::setTitle( const ::rtl::OUString& sTitle ) throw (uno::RuntimeException) { // SYNCHRONIZED -> - ModelMethodGuard aGuard( *this ); - - impl_getTitleHelper_throw()->setTitle (sTitle); + DocumentGuard aGuard( *this ); + impl_getTitleHelper_throw()->setTitle( sTitle ); + m_aEventNotifier.notifyDocumentEventAsync( "OnTitleChanged" ); + // <- SYNCHRONIZED } //============================================================================= @@ -1520,11 +1693,10 @@ void SAL_CALL ODatabaseDocument::addTitleChangeListener( const uno::Reference< f throw (uno::RuntimeException) { // SYNCHRONIZED -> - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this ); - uno::Reference< frame::XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper_throw(), uno::UNO_QUERY); - if (xBroadcaster.is ()) - xBroadcaster->addTitleChangeListener (xListener); + uno::Reference< frame::XTitleChangeBroadcaster > xBroadcaster( impl_getTitleHelper_throw(), uno::UNO_QUERY_THROW ); + xBroadcaster->addTitleChangeListener( xListener ); } //============================================================================= @@ -1533,11 +1705,10 @@ void SAL_CALL ODatabaseDocument::removeTitleChangeListener( const uno::Reference throw (uno::RuntimeException) { // SYNCHRONIZED -> - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this ); - uno::Reference< frame::XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper_throw(), uno::UNO_QUERY); - if (xBroadcaster.is ()) - xBroadcaster->removeTitleChangeListener (xListener); + uno::Reference< frame::XTitleChangeBroadcaster > xBroadcaster( impl_getTitleHelper_throw(), uno::UNO_QUERY_THROW ); + xBroadcaster->removeTitleChangeListener( xListener ); } //============================================================================= @@ -1546,9 +1717,7 @@ void SAL_CALL ODatabaseDocument::removeTitleChangeListener( const uno::Reference throw (lang::IllegalArgumentException, uno::RuntimeException ) { - // object already disposed? - ModelMethodGuard aGuard( *this ); - + DocumentGuard aGuard( *this ); return impl_getUntitledHelper_throw(xComponent)->leaseNumber (xComponent); } @@ -1558,9 +1727,7 @@ void SAL_CALL ODatabaseDocument::releaseNumber( ::sal_Int32 nNumber ) throw (lang::IllegalArgumentException, uno::RuntimeException ) { - // object already disposed? - ModelMethodGuard aGuard( *this ); - + DocumentGuard aGuard( *this ); impl_getUntitledHelper_throw()->releaseNumber (nNumber); } @@ -1570,8 +1737,7 @@ void SAL_CALL ODatabaseDocument::releaseNumberForComponent( const uno::Reference throw (lang::IllegalArgumentException, uno::RuntimeException ) { - // object already disposed? - ModelMethodGuard aGuard( *this ); + DocumentGuard aGuard( *this ); impl_getUntitledHelper_throw(xComponent)->releaseNumberForComponent (xComponent); } diff --git a/dbaccess/source/core/dataaccess/databasedocument.hxx b/dbaccess/source/core/dataaccess/databasedocument.hxx index 9b6a3f374a69..c50cdaa33ade 100644 --- a/dbaccess/source/core/dataaccess/databasedocument.hxx +++ b/dbaccess/source/core/dataaccess/databasedocument.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: databasedocument.hxx,v $ - * $Revision: 1.22 $ + * $Revision: 1.20.2.13 $ * * This file is part of OpenOffice.org. * @@ -31,6 +31,7 @@ #define _DBA_COREDATAACCESS_DATABASEDOCUMENT_HXX_ #include "ModelImpl.hxx" +#include "documenteventnotifier.hxx" /** === begin UNO includes === **/ #include @@ -46,28 +47,33 @@ #include #include #include -#include -#include - -#include #include #include #include #include #include #include +#include #include #include #include +#include +#include +#include /** === end UNO includes === **/ -#if ! defined(INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_14) -#define INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_14 -#define COMPHELPER_IMPLBASE_INTERFACE_NUMBER 14 +#if ! defined(INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_16) +#define INCLUDED_COMPHELPER_IMPLBASE_VAR_HXX_16 +#define COMPHELPER_IMPLBASE_INTERFACE_NUMBER 16 #include #endif +#include +#include +#include + #include +#include namespace comphelper { class NamedValueCollection; @@ -78,18 +84,70 @@ namespace dbaccess { //........................................................................ -class ODatabaseContext; +class DocumentEvents; +class DocumentEventExecutor; +class DocumentGuard; typedef ::std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController > > Controllers; +//============================================================ +//= ViewMonitor +//============================================================ +/** helper class monitoring the views of a document, and firing appropriate events + when views are attached / detached +*/ +class ViewMonitor : public boost::noncopyable +{ +public: + ViewMonitor( DocumentEventNotifier& _rEventNotifier ) + :m_rEventNotifier( _rEventNotifier ) + ,m_bIsNewDocument( true ) + ,m_bEverHadController( false ) + ,m_bLastIsFirstEverController( false ) + ,m_xLastConnectedController() + { + } + + void reset() + { + m_bEverHadController = false; + m_bLastIsFirstEverController = false; + m_xLastConnectedController.clear(); + } + + /** to be called when a view (aka controller) has been connected to the document + @return + if and only if this was the first-ever controller connected to the document + */ + bool onControllerConnected( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& _rxController + ); + + /** to be called when a controller is set as current controller + */ + void onSetCurrentController( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& _rxController + ); + + void onLoadedDocument() { m_bIsNewDocument = false; } + +private: + DocumentEventNotifier& m_rEventNotifier; + bool m_bIsNewDocument; + bool m_bEverHadController; + bool m_bLastIsFirstEverController; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController > + m_xLastConnectedController; +}; + //============================================================ //= ODatabaseDocument //============================================================ -typedef ::comphelper::WeakComponentImplHelper14 < ::com::sun::star::frame::XModel2 +typedef ::comphelper::WeakComponentImplHelper16 < ::com::sun::star::frame::XModel2 , ::com::sun::star::util::XModifiable , ::com::sun::star::frame::XStorable , ::com::sun::star::document::XEventBroadcaster - , ::com::sun::star::document::XEventListener + , ::com::sun::star::document::XDocumentEventBroadcaster , ::com::sun::star::view::XPrintable , ::com::sun::star::util::XCloseable , ::com::sun::star::lang::XServiceInfo @@ -99,6 +157,8 @@ typedef ::comphelper::WeakComponentImplHelper14 < ::com::sun::star::frame::XMo , ::com::sun::star::document::XEmbeddedScripts , ::com::sun::star::document::XScriptInvocationContext , ::com::sun::star::script::provider::XScriptProviderSupplier + , ::com::sun::star::document::XEventsSupplier + , ::com::sun::star::frame::XLoadable > ODatabaseDocument_OfficeDocument; typedef ::cppu::ImplHelper3< ::com::sun::star::frame::XTitle @@ -110,41 +170,64 @@ class ODatabaseDocument :public ModelDependentComponent // ModelDepe ,public ODatabaseDocument_OfficeDocument ,public ODatabaseDocument_Title { + enum InitState + { + NotInitialized, + Initializing, + Initialized + }; + DECLARE_STL_USTRINGACCESS_MAP(::com::sun::star::uno::Reference< ::com::sun::star::frame::XUntitledNumbers >,TNumberedController); ::com::sun::star::uno::Reference< ::com::sun::star::ui::XUIConfigurationManager> m_xUIConfigurationManager; ::cppu::OInterfaceContainerHelper m_aModifyListeners; ::cppu::OInterfaceContainerHelper m_aCloseListener; - ::cppu::OInterfaceContainerHelper m_aDocEventListeners; ::cppu::OInterfaceContainerHelper m_aStorageListeners; + DocumentEvents* m_pEventContainer; + ::rtl::Reference< DocumentEventExecutor > m_pEventExecutor; + DocumentEventNotifier m_aEventNotifier; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController > m_xCurrentController; Controllers m_aControllers; + ViewMonitor m_aViewMonitor; ::com::sun::star::uno::WeakReference< ::com::sun::star::container::XNameAccess > m_xForms; ::com::sun::star::uno::WeakReference< ::com::sun::star::container::XNameAccess > m_xReports; ::com::sun::star::uno::WeakReference< ::com::sun::star::script::provider::XScriptProvider > m_xScriptProvider; + /** @short such module manager is used to classify new opened documents. */ + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModuleManager > m_xModuleManager; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XTitle > m_xTitleHelper; + TNumberedController m_aNumberedControllers; + + /** true if and only if the DatabaseDocument's "initNew" or "load" have been called (or, well, + the document has be initialized implicitly - see storeAsURL + */ + InitState m_eInitState; + bool m_bClosing; + + enum StoreType { SAVE, SAVE_AS }; /** stores the document to the given URL, rebases it to the respective new storage, if necessary, resets the modified flag, and notifies any listeners as required + + @param _rURL + the URL to store the document to + @param _rArguments + arguments for storing the document (MediaDescriptor) + @param _eType + the type of the store process (Save or SaveAs). The method will automatically + notify the proper events for this type. + @param _rGuard + the instance lock to be released before doing synchronous notifications */ void impl_storeAs_throw( const ::rtl::OUString& _rURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue>& _rArguments, - const sal_Char* _pAsciiDocumentEventName, - ModelMethodGuard& _rGuard + const StoreType _eType, + DocumentGuard& _rGuard ); - /** @short such module manager is used to classify new opened documents. */ - ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModuleManager > m_xModuleManager; - ::com::sun::star::uno::Reference< ::com::sun::star::frame::XTitle > m_xTitleHelper; - TNumberedController m_aNumberedControllers; - - /** notifies the global event broadcaster - The method must be called without our mutex locked - */ - void impl_notifyEvent_nolck_nothrow( const ::com::sun::star::document::EventObject& _rEvent ); - /** notifies our storage change listeners that our underlying storage changed @param _rxNewRootStorage @@ -256,13 +339,13 @@ public: virtual void SAL_CALL setCurrentController( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& Controller ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException) ; virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getCurrentSelection( ) throw (::com::sun::star::uno::RuntimeException) ; -// ::com::sun::star::frame::XModel2 + // XModel2 virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL getControllers( ) throw (::com::sun::star::uno::RuntimeException) ; virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getAvailableViewControllerNames( ) throw (::com::sun::star::uno::RuntimeException) ; virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController2 > SAL_CALL createDefaultViewController( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& Frame ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) ; virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController2 > SAL_CALL createViewController( const ::rtl::OUString& ViewName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& Arguments, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& Frame ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) ; -// ::com::sun::star::frame::XStorable + // XStorable virtual sal_Bool SAL_CALL hasLocation( ) throw (::com::sun::star::uno::RuntimeException) ; virtual ::rtl::OUString SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException) ; virtual sal_Bool SAL_CALL isReadonly( ) throw (::com::sun::star::uno::RuntimeException) ; @@ -270,41 +353,43 @@ public: virtual void SAL_CALL storeAsURL( const ::rtl::OUString& sURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArguments ) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) ; virtual void SAL_CALL storeToURL( const ::rtl::OUString& sURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArguments ) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) ; -// ::com::sun::star::util::XModifyBroadcaster + // XModifyBroadcaster virtual void SAL_CALL addModifyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL removeModifyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); -// ::com::sun::star::util::XModifiable + // ::com::sun::star::util::XModifiable virtual sal_Bool SAL_CALL isModified( ) throw (::com::sun::star::uno::RuntimeException) ; virtual void SAL_CALL setModified( sal_Bool bModified ) throw (::com::sun::star::beans::PropertyVetoException, ::com::sun::star::uno::RuntimeException) ; -// ::com::sun::star::document::XEventBroadcaster + + // XEventBroadcaster virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XEventListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XEventListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); -// ::com::sun::star::document::XEventListener - virtual void SAL_CALL notifyEvent( const ::com::sun::star::document::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException); - + // XDocumentEventBroadcaster + virtual void SAL_CALL addDocumentEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XDocumentEventListener >& _Listener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeDocumentEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XDocumentEventListener >& _Listener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL notifyDocumentEvent( const ::rtl::OUString& _EventName, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController2 >& _ViewController, const ::com::sun::star::uno::Any& _Supplement ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); -// ::com::sun::star::view::XPrintable + // XPrintable virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getPrinter( ) throw (::com::sun::star::uno::RuntimeException) ; virtual void SAL_CALL setPrinter( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aPrinter ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) ; virtual void SAL_CALL print( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& xOptions ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) ; -// XFormDocumentsSupplier + // XFormDocumentsSupplier virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getFormDocuments( ) throw (::com::sun::star::uno::RuntimeException); -// XReportDocumentsSupplier + // XReportDocumentsSupplier virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > SAL_CALL getReportDocuments( ) throw (::com::sun::star::uno::RuntimeException); -// XCloseable + // XCloseable virtual void SAL_CALL close( sal_Bool DeliverOwnership ) throw (::com::sun::star::util::CloseVetoException, ::com::sun::star::uno::RuntimeException); virtual void SAL_CALL addCloseListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL removeCloseListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (::com::sun::star::uno::RuntimeException); -// XUIConfigurationManagerSupplier + // XUIConfigurationManagerSupplier virtual ::com::sun::star::uno::Reference< ::com::sun::star::ui::XUIConfigurationManager > SAL_CALL getUIConfigurationManager( ) throw (::com::sun::star::uno::RuntimeException); -// XDocumentSubStorageSupplier + // XDocumentSubStorageSupplier virtual ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > SAL_CALL getDocumentSubStorage( const ::rtl::OUString& aStorageName, sal_Int32 nMode ) throw (::com::sun::star::uno::RuntimeException); virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getDocumentSubStoragesNames( ) throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); @@ -330,6 +415,13 @@ public: // XScriptProviderSupplier virtual ::com::sun::star::uno::Reference< ::com::sun::star::script::provider::XScriptProvider > SAL_CALL getScriptProvider( ) throw (::com::sun::star::uno::RuntimeException); + // XEventsSupplier + virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameReplace > SAL_CALL getEvents( ) throw (::com::sun::star::uno::RuntimeException); + + // XLoadable + virtual void SAL_CALL initNew( ) throw (::com::sun::star::frame::DoubleInitializationException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL load( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArguments ) throw (::com::sun::star::frame::DoubleInitializationException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + // XTitle virtual ::rtl::OUString SAL_CALL getTitle( ) throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL setTitle( const ::rtl::OUString& sTitle ) throw (::com::sun::star::uno::RuntimeException); @@ -356,7 +448,50 @@ public: static void clearObjectContainer( ::com::sun::star::uno::WeakReference< ::com::sun::star::container::XNameAccess >& _rxContainer); + /** checks whether the component is already initialized, throws a NotInitializedException if not + */ + inline void checkInitialized() const + { + if ( !impl_isInitialized() ) + throw ::com::sun::star::lang::NotInitializedException( ::rtl::OUString(), getThis() ); + } + + /** checks the document is currently in the initialization phase, or already initialized. + Throws NotInitializedException if not so. + */ + inline void checkNotUninitilized() const + { + if ( impl_isInitialized() || impl_isInitializing() ) + // fine + return; + + throw ::com::sun::star::lang::NotInitializedException( ::rtl::OUString(), getThis() ); + } + + /** checks whether the document is currently being initialized, or already initialized, + throws a DoubleInitializationException if so + */ + inline void checkNotInitialized() const + { + if ( impl_isInitializing() || impl_isInitialized() ) + throw ::com::sun::star::frame::DoubleInitializationException( ::rtl::OUString(), getThis() ); + } + private: + /** returns whether the model is currently being initialized + */ + bool impl_isInitializing() const { return m_eInitState == Initializing; } + + /** returns whether the model is already initialized, i.e. the XModel's "initNew" or "load" methods have been called + */ + bool impl_isInitialized() const { return m_eInitState == Initialized; } + + /// tells the model it is being initialized now + void impl_setInitializing() { m_eInitState = Initializing; } + + /// tells the model its initialization is done + void impl_setInitialized(); + /** closes the frames of all connected controllers @param _bDeliverOwnership @@ -399,7 +534,7 @@ private: /** imports the document from the given resource. */ - bool impl_import_throw( const ::comphelper::NamedValueCollection& _rResource ); + void impl_import_throw( const ::comphelper::NamedValueCollection& _rResource ); /** creates a storage for the given URL, truncating it if a file with this name already exists @@ -414,9 +549,21 @@ private: const ::rtl::OUString& _rURL ) const; - /** clears the guard before notifying. + /** sets our "modified" flag + + will notify all our respective listeners, if the "modified" state actually changed + + @param _bModified + the (new) flag indicating whether the document is currently modified or not + @param _rGuard + the guard for our instance. At method entry, the guard must hold the lock. At the moment + of method leave, the lock will be released. + @precond + our mutex is locked + @postcond + our mutex is not locked */ - void impl_setModified_throw( sal_Bool _bModified, ModelMethodGuard& _rGuard ); + void impl_setModified_nothrow( sal_Bool _bModified, DocumentGuard& _rGuard ); /** stores the document to the given storage @@ -440,6 +587,61 @@ private: /// determines whether we should disable the scripting related interfaces bool impl_shouldDisallowScripting_nolck_nothrow() const; + + /** checks whether we need to implicitly initialize the document + + */ +}; + +/** an extended version of the ModelMethodGuard, which also cares for the initialization state + of the document +*/ +class DocumentGuard : public ModelMethodGuard +{ +public: + enum MethodType + { + // a method which is to initialize the document + InitMethod, + // a default method + DefaultMethod, + // a method which is used (externally) during the initialization phase + MethodUsedDuringInit, + // a method which does not need initialization - use with care! + MethodWithoutInit + }; + + /** constructs the guard + + @param _document + the ODatabaseDocument instance + + @throws ::com::sun::star::lang::DisposedException + If the given component is already disposed + + @throws ::com::sun::star::frame::DoubleInitializationException + if _eType is InitMethod, and the given component is already initialized, or currently being initialized. + + @throws ::com::sun::star::lang::NotInitializedException + if _eType is DefaultMethod, and the given component is not yet initialized; or if _eType + is MethodUsedDuringInit, and the component is still uninitialized, and not in the initialization + phase currently. + */ + DocumentGuard( const ODatabaseDocument& _document, MethodType _eType = DefaultMethod ) + :ModelMethodGuard( _document ) + { + switch ( _eType ) + { + case InitMethod: _document.checkNotInitialized(); break; + case DefaultMethod: _document.checkInitialized(); break; + case MethodUsedDuringInit: _document.checkNotUninitilized(); break; + case MethodWithoutInit: break; + } + } + + ~DocumentGuard() + { + } }; //........................................................................ diff --git a/dbaccess/source/core/dataaccess/datasource.cxx b/dbaccess/source/core/dataaccess/datasource.cxx index 3b22773aa404..18869c3f9b67 100644 --- a/dbaccess/source/core/dataaccess/datasource.cxx +++ b/dbaccess/source/core/dataaccess/datasource.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: datasource.cxx,v $ - * $Revision: 1.80 $ + * $Revision: 1.79.4.5 $ * * This file is part of OpenOffice.org. * @@ -1349,6 +1349,7 @@ void SAL_CALL ODatabaseSource::flush( ) throw (RuntimeException) { try { + // SYNCHRONIZED -> { ModelMethodGuard aGuard( *this ); @@ -1356,11 +1357,12 @@ void SAL_CALL ODatabaseSource::flush( ) throw (RuntimeException) SharedModel xModel( m_pImpl->getModel_noCreate(), SharedModel::NoTakeOwnership ); if ( !xModel.is() ) - xModel.reset( m_pImpl->createNewModel_deliverOwnership(), SharedModel::TakeOwnership ); + xModel.reset( m_pImpl->createNewModel_deliverOwnership( false ), SharedModel::TakeOwnership ); Reference< css::frame::XStorable> xStorable( xModel, UNO_QUERY_THROW ); xStorable->store(); } + // <- SYNCHRONIZED css::lang::EventObject aFlushedEvent(*this); m_aFlushListeners.notifyEach( &XFlushListener::flushed, aFlushedEvent ); @@ -1381,7 +1383,7 @@ void SAL_CALL ODatabaseSource::flushed( const EventObject& /*rEvent*/ ) throw (R // In general, we have the problem that embedded databases write into their underlying storage, which // logically is one of our sub storage, and practically is a temporary file maintained by the // package implementation. As long as we did not commit this storage and our main storage, - // the changes made by the embedded database engine is not really reflected in the database document + // the changes made by the embedded database engine are not really reflected in the database document // file. This is Bad (TM) for a "real" database application - imagine somebody entering some // data, and then crashing: For a database application, you would expect that the data still is present // when you connect to the database next time. @@ -1443,9 +1445,9 @@ Reference< XOfficeDatabaseDocument > SAL_CALL ODatabaseSource::getDatabaseDocume Reference< XModel > xModel( m_pImpl->getModel_noCreate() ); if ( !xModel.is() ) - xModel = m_pImpl->createNewModel_deliverOwnership(); + xModel = m_pImpl->createNewModel_deliverOwnership( false ); - return Reference< XOfficeDatabaseDocument >( xModel, UNO_QUERY ); + return Reference< XOfficeDatabaseDocument >( xModel, UNO_QUERY_THROW ); } // ----------------------------------------------------------------------------- Reference< XInterface > ODatabaseSource::getThis() const diff --git a/dbaccess/source/core/dataaccess/documentdefinition.cxx b/dbaccess/source/core/dataaccess/documentdefinition.cxx index c3cec1ca6eef..f8772375c3cf 100644 --- a/dbaccess/source/core/dataaccess/documentdefinition.cxx +++ b/dbaccess/source/core/dataaccess/documentdefinition.cxx @@ -867,7 +867,7 @@ void ODocumentDefinition::onCommandOpenSomething( const Any& _rOpenArgument, con // for the document, default to the interaction handler as used for loading the DB doc // This might be overwritten below, when examining _rOpenArgument. - ::comphelper::NamedValueCollection aDBDocArgs( m_pImpl->m_pDataSource->m_aArgs ); + ::comphelper::NamedValueCollection aDBDocArgs( m_pImpl->m_pDataSource->getResource() ); aDocumentArgs.put( "InteractionHandler", aDBDocArgs.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ) ); ::boost::optional< sal_Int16 > aDocumentMacroMode; @@ -1529,15 +1529,7 @@ namespace // ----------------------------------------------------------------------------- sal_Bool ODocumentDefinition::objectSupportsEmbeddedScripts() const { -// bool bAllowDocumentMacros = !m_pImpl->m_pDataSource || m_pImpl->m_pDataSource->hasAnyObjectWithMacros(); - // TODO: revert to the disabled code. The current version is just to be able - // to integrate an intermediate version of the CWS, which should behave as - // if no macros in DB docs are allowed - bool bAllowDocumentMacros = !m_pImpl->m_pDataSource->hasMacroStorages(); - // even if the current version is not able to create documents which contain macros, - // later versions will be. Such documents contain macro/script storages in the - // document root storage, in which case we need to disable the per-form/report - // scripting. + bool bAllowDocumentMacros = !m_pImpl->m_pDataSource || m_pImpl->m_pDataSource->hasAnyObjectWithMacros(); // if *any* of the objects of the database document already has macros, we continue to allow it // to have them, until the user did a migration. diff --git a/dbaccess/source/core/dataaccess/documentdefinition.hxx b/dbaccess/source/core/dataaccess/documentdefinition.hxx index 063e2316cfa5..97c3aa85659e 100644 --- a/dbaccess/source/core/dataaccess/documentdefinition.hxx +++ b/dbaccess/source/core/dataaccess/documentdefinition.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: documentdefinition.hxx,v $ - * $Revision: 1.32 $ + * $Revision: 1.28.6.4 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/core/dataaccess/documenteventexecutor.cxx b/dbaccess/source/core/dataaccess/documenteventexecutor.cxx new file mode 100644 index 000000000000..1e424ba2375f --- /dev/null +++ b/dbaccess/source/core/dataaccess/documenteventexecutor.cxx @@ -0,0 +1,234 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2008 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* $RCSfile: documenteventexecutor.cxx,v $ +* +* $Revision: 1.1.2.7 $ +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* +* for a copy of the LGPLv3 License. +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "documenteventexecutor.hxx" + +/** === begin UNO includes === **/ +#include +#include +#include +#include +/** === end UNO includes === **/ + +#include +#include +#include +#include +#include +#include + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::uno::WeakReference; + using ::com::sun::star::document::XDocumentEventBroadcaster; + using ::com::sun::star::document::XEventsSupplier; + using ::com::sun::star::container::XNameAccess; + using ::com::sun::star::frame::XModel; + using ::com::sun::star::util::XURLTransformer; + using ::com::sun::star::frame::XDispatchProvider; + using ::com::sun::star::frame::XDispatch; + using ::com::sun::star::util::URL; + using ::com::sun::star::beans::PropertyValue; + using ::com::sun::star::frame::XController; + using ::com::sun::star::document::DocumentEvent; + /** === end UNO using === **/ + using namespace ::com::sun::star; + + //==================================================================== + //= DocumentEventExecutor_Data + //==================================================================== + struct DocumentEventExecutor_Data + { + WeakReference< XEventsSupplier > xDocument; + Reference< XURLTransformer > xURLTransformer; + + DocumentEventExecutor_Data( const Reference< XEventsSupplier >& _rxDocument ) + :xDocument( _rxDocument ) + { + } + }; + + //-------------------------------------------------------------------- + namespace + { + static void lcl_dispatchScriptURL_throw( DocumentEventExecutor_Data& _rDocExecData, + const ::rtl::OUString& _rScriptURL, const DocumentEvent& _rTrigger ) + { + Reference< XModel > xDocument( _rDocExecData.xDocument.get(), UNO_QUERY_THROW ); + + Reference< XController > xController( xDocument->getCurrentController() ); + Reference< XDispatchProvider > xDispProv; + if ( xController.is() ) + xDispProv.set( xController->getFrame(), UNO_QUERY ); + if ( !xDispProv.is() ) + { + OSL_ENSURE( false, "lcl_dispatchScriptURL_throw: no controller/frame? How should I dispatch?" ); + return; + } + + URL aScriptURL; + aScriptURL.Complete = _rScriptURL; + if ( _rDocExecData.xURLTransformer.is() ) + _rDocExecData.xURLTransformer->parseStrict( aScriptURL ); + + // unfortunately, executing a script can trigger all kind of complex stuff, and unfortunately, not + // every component involved into this properly cares for thread safety. To be on the safe side, + // we lock the solar mutex here. + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + + Reference< XDispatch > xDispatch( xDispProv->queryDispatch( aScriptURL, ::rtl::OUString(), 0 ) ); + if ( !xDispatch.is() ) + { + OSL_ENSURE( false, "lcl_dispatchScriptURL_throw: no dispatcher for the script URL!" ); + return; + } + + PropertyValue aEventParam; + aEventParam.Value <<= _rTrigger; + Sequence< PropertyValue > aDispatchArgs( &aEventParam, 1 ); + xDispatch->dispatch( aScriptURL, aDispatchArgs ); + } + } + + //==================================================================== + //= DocumentEventExecutor + //==================================================================== + //-------------------------------------------------------------------- + DocumentEventExecutor::DocumentEventExecutor( const ::comphelper::ComponentContext& _rContext, + const Reference< XEventsSupplier >& _rxDocument ) + :m_pData( new DocumentEventExecutor_Data( _rxDocument ) ) + { + Reference< XDocumentEventBroadcaster > xBroadcaster( _rxDocument, UNO_QUERY_THROW ); + + osl_incrementInterlockedCount( &m_refCount ); + { + xBroadcaster->addDocumentEventListener( this ); + } + osl_decrementInterlockedCount( &m_refCount ); + + try + { + _rContext.createComponent( "com.sun.star.util.URLTransformer", m_pData->xURLTransformer ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //-------------------------------------------------------------------- + DocumentEventExecutor::~DocumentEventExecutor() + { + } + + //-------------------------------------------------------------------- + void SAL_CALL DocumentEventExecutor::documentEventOccured( const DocumentEvent& _Event ) throw (RuntimeException) + { + Reference< XEventsSupplier > xEventsSupplier( m_pData->xDocument.get(), UNO_QUERY ); + if ( !xEventsSupplier.is() ) + { + OSL_ENSURE( false, "DocumentEventExecutor::documentEventOccured: no document anymore, but still being notified?" ); + return; + } + + Reference< XModel > xDocument( xEventsSupplier, UNO_QUERY_THROW ); + + try + { + Reference< XNameAccess > xDocEvents( xEventsSupplier->getEvents().get(), UNO_SET_THROW ); + if ( !xDocEvents->hasByName( _Event.EventName ) ) + { + // this is worth an assertion: We are listener at the very same document which we just asked + // for its events. So when EventName is fired, why isn't it supported by xDocEvents? + OSL_ENSURE( false, "DocumentEventExecutor::documentEventOccured: an unsupported event is notified!" ); + return; + } + + const ::comphelper::NamedValueCollection aScriptDescriptor( xDocEvents->getByName( _Event.EventName ) ); + + + ::rtl::OUString sEventType; + bool bScriptAssigned = aScriptDescriptor.get_ensureType( "EventType", sEventType ); + + ::rtl::OUString sScript; + bScriptAssigned = bScriptAssigned && aScriptDescriptor.get_ensureType( "Script", sScript ); + + if ( !bScriptAssigned ) + // no script is assigned to this event + return; + + bool bDispatchScriptURL = + ( sEventType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Script" ) ) + || sEventType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Service" ) ) + ); + bool bNonEmptyScript = sScript.getLength() != 0; + + OSL_ENSURE( bDispatchScriptURL && bNonEmptyScript, + "DocumentEventExecutor::documentEventOccured: invalid/unsupported script descriptor" ); + + if ( bDispatchScriptURL && bNonEmptyScript ) + { + lcl_dispatchScriptURL_throw( *m_pData, sScript, _Event ); + } + } + catch( const RuntimeException& ) { throw; } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL DocumentEventExecutor::disposing( const lang::EventObject& /*_Source*/ ) throw (RuntimeException) + { + // not interested in + } + + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/dataaccess/documenteventexecutor.hxx b/dbaccess/source/core/dataaccess/documenteventexecutor.hxx new file mode 100644 index 000000000000..8d1eb4b2e3f7 --- /dev/null +++ b/dbaccess/source/core/dataaccess/documenteventexecutor.hxx @@ -0,0 +1,81 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2008 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* $RCSfile: documenteventexecutor.hxx,v $ +* +* $Revision: 1.1.2.2 $ +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* +* for a copy of the LGPLv3 License. +************************************************************************/ + +#ifndef DBACCESS_DOCUMENTEVENTEXECUTOR_HXX +#define DBACCESS_DOCUMENTEVENTEXECUTOR_HXX + +/** === begin UNO includes === **/ +#include +#include +/** === end UNO includes === **/ + +#include + +#include + +namespace comphelper +{ + class ComponentContext; +} + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + struct DocumentEventExecutor_Data; + //==================================================================== + //= DocumentEventExecutor + //==================================================================== + typedef ::cppu::WeakImplHelper1 < ::com::sun::star::document::XDocumentEventListener + > DocumentEventExecutor_Base; + class DocumentEventExecutor : public DocumentEventExecutor_Base + { + public: + DocumentEventExecutor( + const ::comphelper::ComponentContext& _rContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::document::XEventsSupplier >& _rxDocument ); + + protected: + virtual ~DocumentEventExecutor(); + + // css.document.XDocumentEventListener + virtual void SAL_CALL documentEventOccured( const ::com::sun::star::document::DocumentEvent& Event ) throw (::com::sun::star::uno::RuntimeException); + // css.lang.XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + + private: + ::std::auto_ptr< DocumentEventExecutor_Data > m_pData; + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // DBACCESS_DOCUMENTEVENTEXECUTOR_HXX diff --git a/dbaccess/source/core/dataaccess/documenteventnotifier.cxx b/dbaccess/source/core/dataaccess/documenteventnotifier.cxx new file mode 100644 index 000000000000..fb998a31716d --- /dev/null +++ b/dbaccess/source/core/dataaccess/documenteventnotifier.cxx @@ -0,0 +1,315 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2008 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* $RCSfile: documenteventnotifier.cxx,v $ +* +* $Revision: 1.1.2.4 $ +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* +* for a copy of the LGPLv3 License. +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "documenteventnotifier.hxx" + +/** === begin UNO includes === **/ +#include +/** === end UNO includes === **/ + +#include +#include +#include +#include + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::frame::DoubleInitializationException; + using ::com::sun::star::document::XDocumentEventListener; + using ::com::sun::star::document::DocumentEvent; + using ::com::sun::star::frame::XController2; + /** === end UNO using === **/ + using namespace ::com::sun::star; + + //================================================================== + //= DocumentEventHolder + //================================================================== + typedef ::comphelper::EventHolder< DocumentEvent > DocumentEventHolder; + + //==================================================================== + //= DocumentEventNotifier_Impl + //==================================================================== + class DocumentEventNotifier_Impl : public ::comphelper::IEventProcessor + { + oslInterlockedCount m_refCount; + ::cppu::OWeakObject& m_rDocument; + ::osl::Mutex& m_rMutex; + bool m_bInitialized; + bool m_bDisposed; + ::rtl::Reference< ::comphelper::AsyncEventNotifier > m_pEventBroadcaster; + ::cppu::OInterfaceContainerHelper m_aLegacyEventListeners; + ::cppu::OInterfaceContainerHelper m_aDocumentEventListeners; + + public: + DocumentEventNotifier_Impl( ::cppu::OWeakObject& _rBroadcasterDocument, ::osl::Mutex& _rMutex ) + :m_refCount( 0 ) + ,m_rDocument( _rBroadcasterDocument ) + ,m_rMutex( _rMutex ) + ,m_bInitialized( false ) + ,m_bDisposed( false ) + ,m_aLegacyEventListeners( _rMutex ) + ,m_aDocumentEventListeners( _rMutex ) + { + } + + // IReference + virtual void SAL_CALL acquire(); + virtual void SAL_CALL release(); + + void addLegacyEventListener( const Reference< document::XEventListener >& _Listener ) + { + m_aLegacyEventListeners.addInterface( _Listener ); + } + + void removeLegacyEventListener( const Reference< document::XEventListener >& _Listener ) + { + m_aLegacyEventListeners.removeInterface( _Listener ); + } + + void addDocumentEventListener( const Reference< XDocumentEventListener >& _Listener ) + { + m_aDocumentEventListeners.addInterface( _Listener ); + } + + void removeDocumentEventListener( const Reference< XDocumentEventListener >& _Listener ) + { + m_aDocumentEventListeners.removeInterface( _Listener ); + } + + void disposing(); + + void onDocumentInitialized(); + + void notifyDocumentEvent( const ::rtl::OUString& _EventName, const Reference< XController2 >& _ViewController, + const Any& _Supplement ) + { + impl_notifyEvent_nothrow( DocumentEvent( + m_rDocument, _EventName, _ViewController, _Supplement ) ); + } + + void notifyDocumentEventAsync( const ::rtl::OUString& _EventName, const Reference< XController2 >& _ViewController, + const Any& _Supplement ) + { + impl_notifyEventAsync_nothrow( DocumentEvent( + m_rDocument, _EventName, _ViewController, _Supplement ) ); + } + + protected: + virtual ~DocumentEventNotifier_Impl() + { + } + + // IEventProcessor + virtual void processEvent( const ::comphelper::AnyEvent& _rEvent ); + + private: + void impl_notifyEvent_nothrow( const DocumentEvent& _rEvent ); + void impl_notifyEventAsync_nothrow( const DocumentEvent& _rEvent ); + }; + + //-------------------------------------------------------------------- + void SAL_CALL DocumentEventNotifier_Impl::acquire() + { + osl_incrementInterlockedCount( &m_refCount ); + } + + //-------------------------------------------------------------------- + void SAL_CALL DocumentEventNotifier_Impl::release() + { + if ( 0 == osl_decrementInterlockedCount( &m_refCount ) ) + delete this; + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier_Impl::disposing() + { + // cancel any pending asynchronous events + ::osl::MutexGuard aGuard( m_rMutex ); + if ( m_pEventBroadcaster.is() ) + { + m_pEventBroadcaster->removeEventsForProcessor( this ); + m_pEventBroadcaster->terminate(); + m_pEventBroadcaster = NULL; + } + + lang::EventObject aEvent( m_rDocument ); + m_aLegacyEventListeners.disposeAndClear( aEvent ); + m_aDocumentEventListeners.disposeAndClear( aEvent ); + + m_bDisposed = true; + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier_Impl::onDocumentInitialized() + { + if ( m_bInitialized ) + throw DoubleInitializationException(); + + m_bInitialized = true; + if ( m_pEventBroadcaster.is() ) + // there are already pending asynchronous events + m_pEventBroadcaster->create(); + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier_Impl::impl_notifyEvent_nothrow( const DocumentEvent& _rEvent ) + { + OSL_PRECOND( m_bInitialized, + "DocumentEventNotifier_Impl::impl_notifyEvent_nothrow: only to be called when the document is already initialized!" ); + try + { + document::EventObject aLegacyEvent( _rEvent.Source, _rEvent.EventName ); + m_aLegacyEventListeners.notifyEach( &document::XEventListener::notifyEvent, aLegacyEvent ); + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + try + { + m_aDocumentEventListeners.notifyEach( &XDocumentEventListener::documentEventOccured, _rEvent ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier_Impl::impl_notifyEventAsync_nothrow( const DocumentEvent& _rEvent ) + { + if ( !m_pEventBroadcaster.is() ) + { + m_pEventBroadcaster.set( new ::comphelper::AsyncEventNotifier ); + if ( m_bInitialized ) + // start processing the events if and only if we (our document, respectively) are + // already initialized + m_pEventBroadcaster->create(); + } + m_pEventBroadcaster->addEvent( new DocumentEventHolder( _rEvent ), this ); + } + + // ----------------------------------------------------------------------------- + void DocumentEventNotifier_Impl::processEvent( const ::comphelper::AnyEvent& _rEvent ) + { + // beware, this is called from the notification thread + { + ::osl::MutexGuard aGuard( m_rMutex ); + if ( m_bDisposed ) + return; + } + const DocumentEventHolder& rEventHolder = dynamic_cast< const DocumentEventHolder& >( _rEvent ); + impl_notifyEvent_nothrow( rEventHolder.getEventObject() ); + } + + //==================================================================== + //= DocumentEventNotifier + //==================================================================== + //-------------------------------------------------------------------- + DocumentEventNotifier::DocumentEventNotifier( ::cppu::OWeakObject& _rBroadcasterDocument, ::osl::Mutex& _rMutex ) + :m_pImpl( new DocumentEventNotifier_Impl( _rBroadcasterDocument, _rMutex ) ) + { + } + + //-------------------------------------------------------------------- + DocumentEventNotifier::~DocumentEventNotifier() + { + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier::disposing() + { + m_pImpl->disposing(); + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier::onDocumentInitialized() + { + m_pImpl->onDocumentInitialized(); + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier::addLegacyEventListener( const Reference< document::XEventListener >& _Listener ) + { + m_pImpl->addLegacyEventListener( _Listener ); + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier::removeLegacyEventListener( const Reference< document::XEventListener >& _Listener ) + { + m_pImpl->removeLegacyEventListener( _Listener ); + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier::addDocumentEventListener( const Reference< XDocumentEventListener >& _Listener ) + { + m_pImpl->addDocumentEventListener( _Listener ); + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier::removeDocumentEventListener( const Reference< XDocumentEventListener >& _Listener ) + { + m_pImpl->removeDocumentEventListener( _Listener ); + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier::notifyDocumentEvent( const ::rtl::OUString& _EventName, + const Reference< XController2 >& _ViewController, const Any& _Supplement ) + { + m_pImpl->notifyDocumentEvent( _EventName, _ViewController, _Supplement ); + } + + //-------------------------------------------------------------------- + void DocumentEventNotifier::notifyDocumentEventAsync( const ::rtl::OUString& _EventName, + const Reference< XController2 >& _ViewController, const Any& _Supplement ) + { + m_pImpl->notifyDocumentEventAsync( _EventName, _ViewController, _Supplement ); + } + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/dataaccess/documenteventnotifier.hxx b/dbaccess/source/core/dataaccess/documenteventnotifier.hxx new file mode 100644 index 000000000000..cf0d5c2c389f --- /dev/null +++ b/dbaccess/source/core/dataaccess/documenteventnotifier.hxx @@ -0,0 +1,147 @@ + +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2008 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* $RCSfile: documenteventnotifier.hxx,v $ +* +* $Revision: 1.1.2.3 $ +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* +* for a copy of the LGPLv3 License. +************************************************************************/ + +#ifndef DBACCESS_DOCUMENTEVENTNOTIFIER_HXX +#define DBACCESS_DOCUMENTEVENTNOTIFIER_HXX + +/** === begin UNO includes === **/ +#include +#include +/** === end UNO includes === **/ + +#include + +namespace cppu +{ + class OWeakObject; +} + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + class DocumentEventNotifier_Impl; + //==================================================================== + //= DocumentEventNotifier + //==================================================================== + class DocumentEventNotifier + { + public: + DocumentEventNotifier( ::cppu::OWeakObject& _rBroadcasterDocument, ::osl::Mutex& _rMutex ); + ~DocumentEventNotifier(); + + void addLegacyEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XEventListener >& _Listener ); + void removeLegacyEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XEventListener >& _Listener ); + void addDocumentEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XDocumentEventListener >& _Listener ); + void removeDocumentEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XDocumentEventListener >& _Listener ); + + /** disposes the instance + @precond + the mutex is not locked + */ + void disposing(); + + /** tells the instance that its document is completely initialized now. + + Before you call this method, no notification will actually happen + + @precond + the mutex is locked + */ + void onDocumentInitialized(); + + /** notifies a document event described by the given parameters + + @precond + the mutex is not locked + @precond + ->onDocumentInitialized has been called + */ + void notifyDocumentEvent( + const ::rtl::OUString& _EventName, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController2 >& _rxViewController = NULL, + const ::com::sun::star::uno::Any& _Supplement = ::com::sun::star::uno::Any() + ); + + /** notifies a document event, described by the given parameters, asynchronously + + Note that no event is actually notified before you called ->onDocumentInitialized. + + @precond + the mutex is locked + */ + void notifyDocumentEventAsync( + const ::rtl::OUString& _EventName, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController2 >& _ViewController = NULL, + const ::com::sun::star::uno::Any& _Supplement = ::com::sun::star::uno::Any() + ); + + /** notifies a document event to all registered listeners + + @precond + the mutex is not locked + @precond + ->onDocumentInitialized has been called + */ + void notifyDocumentEvent( + const sal_Char* _pAsciiEventName, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController2 >& _rxViewController = NULL, + const ::com::sun::star::uno::Any& _rSupplement = ::com::sun::star::uno::Any() + ) + { + notifyDocumentEvent( ::rtl::OUString::createFromAscii( _pAsciiEventName ), _rxViewController, _rSupplement ); + } + + /** notifies a document event to all registered listeners, asynchronously + + Note that no event is actually notified before you called ->onDocumentInitialized. + + @precond + the mutex is locked + */ + void notifyDocumentEventAsync( + const sal_Char* _pAsciiEventName, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController2 >& _rxViewController = NULL, + const ::com::sun::star::uno::Any& _rSupplement = ::com::sun::star::uno::Any() + ) + { + notifyDocumentEventAsync( ::rtl::OUString::createFromAscii( _pAsciiEventName ), _rxViewController, _rSupplement ); + } + + private: + ::rtl::Reference< DocumentEventNotifier_Impl > m_pImpl; + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // DBACCESS_DOCUMENTEVENTNOTIFIER_HXX diff --git a/dbaccess/source/core/dataaccess/documentevents.cxx b/dbaccess/source/core/dataaccess/documentevents.cxx new file mode 100644 index 000000000000..cf93fa553eb4 --- /dev/null +++ b/dbaccess/source/core/dataaccess/documentevents.cxx @@ -0,0 +1,266 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2008 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* $RCSfile: documentevents.cxx,v $ +* +* $Revision: 1.1.2.9 $ +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* +* for a copy of the LGPLv3 License. +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "documentevents.hxx" + +/** === begin UNO includes === **/ +#include +/** === end UNO includes === **/ + +#include + +#include +#include +#include + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::beans::PropertyValue; + using ::com::sun::star::container::NoSuchElementException; + using ::com::sun::star::lang::WrappedTargetException; + using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + /** === end UNO using === **/ + + //==================================================================== + //= DocumentEvents_Data + //==================================================================== + typedef ::std::map< ::rtl::OUString, Sequence< PropertyValue > > NamedEventDescriptors; + + struct DocumentEvents_Data : public ::boost::noncopyable + { + ::cppu::OWeakObject& rParent; + ::osl::Mutex& rMutex; + NamedEventDescriptors aEventDescs; + + DocumentEvents_Data( ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex ) + :rParent( _rParent ) + ,rMutex( _rMutex ) + { + } + }; + + //==================================================================== + //= helper + //==================================================================== + struct DocumentEventData + { + const sal_Char* pAsciiEventName; + bool bNeedsSyncNotify; + }; + + //-------------------------------------------------------------------- + namespace + { + static const DocumentEventData* lcl_getDocumentEventData() + { + static const DocumentEventData s_aData[] = { + { "OnCreate", true }, + { "OnLoadFinished", true }, + { "OnNew", false }, // compatibility, see http://www.openoffice.org/issues/show_bug.cgi?id=46484 + { "OnLoad", false }, // compatibility, see http://www.openoffice.org/issues/show_bug.cgi?id=46484 + { "OnSaveAs", true }, + { "OnSaveAsDone", false }, + { "OnSaveAsFailed", false }, + { "OnSave", true }, + { "OnSaveDone", false }, + { "OnSaveFailed", false }, + { "OnSaveTo", true }, + { "OnSaveToDone", false }, + { "OnSaveToFailed", false }, + { "OnPrepareUnload", true }, + { "OnUnload", true }, + { "OnFocus", false }, + { "OnUnfocus", false }, + { "OnModifyChanged", false }, + { "OnViewCreated", false }, + { "OnPrepareViewClosing", true }, + { "OnViewClosed", false }, + { "OnTitleChanged", false }, + { NULL, false } + }; + return s_aData; + } + } + + //==================================================================== + //= DocumentEvents + //==================================================================== + //-------------------------------------------------------------------- + DocumentEvents::DocumentEvents( ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex ) + :m_pData( new DocumentEvents_Data( _rParent, _rMutex ) ) + { + const DocumentEventData* pEventData = lcl_getDocumentEventData(); + while ( pEventData->pAsciiEventName ) + { + m_pData->aEventDescs[ ::rtl::OUString::createFromAscii( pEventData->pAsciiEventName ) ] = + Sequence< PropertyValue >(); + ++pEventData; + } + } + + //-------------------------------------------------------------------- + DocumentEvents::~DocumentEvents() + { + } + + //-------------------------------------------------------------------- + void SAL_CALL DocumentEvents::acquire() throw() + { + m_pData->rParent.acquire(); + } + + //-------------------------------------------------------------------- + void SAL_CALL DocumentEvents::release() throw() + { + m_pData->rParent.release(); + } + + //-------------------------------------------------------------------- + bool DocumentEvents::needsSynchronousNotification( const ::rtl::OUString& _rEventName ) + { + const DocumentEventData* pEventData = lcl_getDocumentEventData(); + while ( pEventData->pAsciiEventName ) + { + if ( _rEventName.compareToAscii( pEventData->pAsciiEventName ) == 0 ) + return pEventData->bNeedsSyncNotify; + ++pEventData; + } + + // this is an unknown event ... assume async notification + return false; + } + + //-------------------------------------------------------------------- + void SAL_CALL DocumentEvents::replaceByName( const ::rtl::OUString& _Name, const Any& _Element ) throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_pData->rMutex ); + + NamedEventDescriptors::iterator elementPos = m_pData->aEventDescs.find( _Name ); + if ( elementPos == m_pData->aEventDescs.end() ) + throw NoSuchElementException( _Name, *this ); + + Sequence< PropertyValue > aEventDescriptor; + if ( _Element.hasValue() && !( _Element >>= aEventDescriptor ) ) + throw IllegalArgumentException( _Element.getValueTypeName(), *this, 2 ); + + // Weird enough, the event assignment UI has (well: had) the idea of using an empty "EventType"/"Script" + // to indicate the event descriptor should be reset, instead of just passing an empty event descriptor. + ::comphelper::NamedValueCollection aCheck( aEventDescriptor ); + if ( aCheck.has( "EventType" ) ) + { + ::rtl::OUString sEventType = aCheck.getOrDefault( "EventType", ::rtl::OUString() ); + OSL_ENSURE( sEventType.getLength(), "DocumentEvents::replaceByName: doing a reset via an empty EventType is weird!" ); + if ( !sEventType.getLength() ) + aEventDescriptor.realloc( 0 ); + } + if ( aCheck.has( "Script" ) ) + { + ::rtl::OUString sScript = aCheck.getOrDefault( "Script", ::rtl::OUString() ); + OSL_ENSURE( sScript.getLength(), "DocumentEvents::replaceByName: doing a reset via an empty Script is weird!" ); + if ( !sScript.getLength() ) + aEventDescriptor.realloc( 0 ); + } + + elementPos->second = aEventDescriptor; + } + + //-------------------------------------------------------------------- + Any SAL_CALL DocumentEvents::getByName( const ::rtl::OUString& _Name ) throw (NoSuchElementException, WrappedTargetException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_pData->rMutex ); + + NamedEventDescriptors::const_iterator elementPos = m_pData->aEventDescs.find( _Name ); + if ( elementPos == m_pData->aEventDescs.end() ) + throw NoSuchElementException( _Name, *this ); + + Any aReturn; + const Sequence< PropertyValue >& rEventDesc( elementPos->second ); + if ( rEventDesc.getLength() > 0 ) + aReturn <<= rEventDesc; + return aReturn; + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL DocumentEvents::getElementNames( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_pData->rMutex ); + + Sequence< ::rtl::OUString > aNames( m_pData->aEventDescs.size() ); + ::std::transform( + m_pData->aEventDescs.begin(), + m_pData->aEventDescs.end(), + aNames.getArray(), + ::std::select1st< NamedEventDescriptors::value_type >() + ); + return aNames; + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL DocumentEvents::hasByName( const ::rtl::OUString& _Name ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_pData->rMutex ); + + return m_pData->aEventDescs.find( _Name ) != m_pData->aEventDescs.end(); + } + + //-------------------------------------------------------------------- + Type SAL_CALL DocumentEvents::getElementType( ) throw (RuntimeException) + { + return ::cppu::UnoType< Sequence< PropertyValue > >::get(); + } + + //-------------------------------------------------------------------- + ::sal_Bool SAL_CALL DocumentEvents::hasElements( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_pData->rMutex ); + return !m_pData->aEventDescs.empty(); + } + + +//........................................................................ +} // namespace dbaccess +//........................................................................ diff --git a/dbaccess/source/core/dataaccess/documentevents.hxx b/dbaccess/source/core/dataaccess/documentevents.hxx new file mode 100644 index 000000000000..350a9f334e87 --- /dev/null +++ b/dbaccess/source/core/dataaccess/documentevents.hxx @@ -0,0 +1,91 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2008 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* $RCSfile: documentevents.hxx,v $ +* +* $Revision: 1.1.2.2 $ +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* +* for a copy of the LGPLv3 License. +************************************************************************/ + +#ifndef DBACCESS_DOCUMENTEVENTS_HXX +#define DBACCESS_DOCUMENTEVENTS_HXX + +#include "dbaccessdllapi.h" + +/** === begin UNO includes === **/ +#include +/** === end UNO includes === **/ + +#include + +#include +#include + +//........................................................................ +namespace dbaccess +{ +//........................................................................ + + //==================================================================== + //= DocumentEvents + //==================================================================== + struct DocumentEvents_Data; + + typedef ::cppu::WeakImplHelper1 < ::com::sun::star::container::XNameReplace + > DocumentEvents_Base; + + class DBACCESS_DLLPRIVATE DocumentEvents + :public DocumentEvents_Base + ,public ::boost::noncopyable + { + public: + DocumentEvents( ::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex ); + ~DocumentEvents(); + + static bool needsSynchronousNotification( const ::rtl::OUString& _rEventName ); + + // XInterface + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // XNameReplace + virtual void SAL_CALL replaceByName( const ::rtl::OUString& aName, const ::com::sun::star::uno::Any& aElement ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + + // XNameAccess + virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException); + + // XElementAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL hasElements( ) throw (::com::sun::star::uno::RuntimeException); + + private: + ::std::auto_ptr< DocumentEvents_Data > m_pData; + }; + +//........................................................................ +} // namespace dbaccess +//........................................................................ + +#endif // DBACCESS_DOCUMENTEVENTS_HXX diff --git a/dbaccess/source/core/dataaccess/makefile.mk b/dbaccess/source/core/dataaccess/makefile.mk index 77aa24c91bdc..f49e011bd861 100644 --- a/dbaccess/source/core/dataaccess/makefile.mk +++ b/dbaccess/source/core/dataaccess/makefile.mk @@ -8,7 +8,7 @@ # # $RCSfile: makefile.mk,v $ # -# $Revision: 1.10 $ +# $Revision: 1.10.2.3 $ # # This file is part of OpenOffice.org. # @@ -60,7 +60,10 @@ SLOFILES= \ $(SLO)$/myucp_resultset.obj \ $(SLO)$/databasedocument.obj \ $(SLO)$/dataaccessdescriptor.obj\ - $(SLO)$/ModelImpl.obj + $(SLO)$/ModelImpl.obj \ + $(SLO)$/documentevents.obj \ + $(SLO)$/documenteventexecutor.obj \ + $(SLO)$/documenteventnotifier.obj # --- Targets ---------------------------------- diff --git a/dbaccess/source/ext/macromigration/dbmm_global.hrc b/dbaccess/source/ext/macromigration/dbmm_global.hrc index d04e4de582c6..3ce7577426c7 100644 --- a/dbaccess/source/ext/macromigration/dbmm_global.hrc +++ b/dbaccess/source/ext/macromigration/dbmm_global.hrc @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: dbmm_global.hrc,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.5 $ * * This file is part of OpenOffice.org. * @@ -46,6 +46,12 @@ #define DLG_MACRO_MIGRATION RID_DBMM_DIALOG_START + 0 +//===================================================================== +//= error boxes +//===================================================================== + +#define ERR_INVALID_BACKUP_LOCATION RID_DBMM_DIALOG_START + 0 + //===================================================================== //= tab pages //===================================================================== @@ -59,17 +65,22 @@ //= strings //===================================================================== -#define STR_FORM ( RID_DBMM_STRING_START + 0 ) -#define STR_REPORT ( RID_DBMM_STRING_START + 1 ) -#define STR_OVERALL_PROGRESS ( RID_DBMM_STRING_START + 2 ) -#define STR_DATABASE_DOCUMENT ( RID_DBMM_STRING_START + 3 ) -#define STR_SAVED_COPY_TO ( RID_DBMM_STRING_START + 4 ) -#define STR_MOVED_LIBRARY ( RID_DBMM_STRING_START + 5 ) -#define STR_OOO_BASIC ( RID_DBMM_STRING_START + 6 ) -#define STR_JAVA_SCRIPT ( RID_DBMM_STRING_START + 7 ) -#define STR_BEAN_SHELL ( RID_DBMM_STRING_START + 8 ) -#define STR_JAVA ( RID_DBMM_STRING_START + 9 ) -#define STR_PYTHON ( RID_DBMM_STRING_START + 10 ) -#define STR_DIALOG ( RID_DBMM_STRING_START + 11 ) +#define STR_FORM ( RID_DBMM_STRING_START + 0 ) +#define STR_REPORT ( RID_DBMM_STRING_START + 1 ) +#define STR_OVERALL_PROGRESS ( RID_DBMM_STRING_START + 2 ) +#define STR_DATABASE_DOCUMENT ( RID_DBMM_STRING_START + 3 ) +#define STR_SAVED_COPY_TO ( RID_DBMM_STRING_START + 4 ) +#define STR_MOVED_LIBRARY ( RID_DBMM_STRING_START + 5 ) +#define STR_OOO_BASIC ( RID_DBMM_STRING_START + 6 ) +#define STR_JAVA_SCRIPT ( RID_DBMM_STRING_START + 7 ) +#define STR_BEAN_SHELL ( RID_DBMM_STRING_START + 8 ) +#define STR_JAVA ( RID_DBMM_STRING_START + 9 ) +#define STR_PYTHON ( RID_DBMM_STRING_START + 10 ) +#define STR_DIALOG ( RID_DBMM_STRING_START + 11 ) +#define STR_MIGRATING_LIBS ( RID_DBMM_STRING_START + 12 ) +#define STR_ERRORS ( RID_DBMM_STRING_START + 13 ) +#define STR_WARNINGS ( RID_DBMM_STRING_START + 14 ) +#define STR_EXCEPTION ( RID_DBMM_STRING_START + 15 ) +#define STR_LIBRARY_TYPE_AND_NAME ( RID_DBMM_STRING_START + 16 ) #endif // DBACCESS_DBMM_GLOBAL_HRC diff --git a/dbaccess/source/ext/macromigration/dbmm_types.cxx b/dbaccess/source/ext/macromigration/dbmm_types.cxx new file mode 100644 index 000000000000..c63823367b74 --- /dev/null +++ b/dbaccess/source/ext/macromigration/dbmm_types.cxx @@ -0,0 +1,66 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2008 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* $RCSfile: dbmm_types.cxx,v $ +* +* $Revision: 1.1.2.1 $ +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* +* for a copy of the LGPLv3 License. +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "dbmm_types.hxx" + +#include "dbmm_global.hrc" +#include "dbmm_module.hxx" + +//........................................................................ +namespace dbmm +{ +//........................................................................ + + //==================================================================== + //= helper + //==================================================================== + //-------------------------------------------------------------------- + String getScriptTypeDisplayName( const ScriptType _eType ) + { + USHORT nResId( 0 ); + + switch ( _eType ) + { + case eBasic: nResId = STR_OOO_BASIC; break; + case eBeanShell: nResId = STR_BEAN_SHELL; break; + case eJavaScript: nResId = STR_JAVA_SCRIPT; break; + case ePython: nResId = STR_PYTHON; break; + case eJava: nResId = STR_JAVA; break; + case eDialog: nResId = STR_DIALOG; break; + } + OSL_ENSURE( nResId != 0, "getScriptTypeDisplayName: illegal script type!" ); + return nResId ? String( MacroMigrationResId( nResId ) ) : String(); + } + +//........................................................................ +} // namespace dbmm +//........................................................................ diff --git a/dbaccess/source/ext/macromigration/dbmm_types.hxx b/dbaccess/source/ext/macromigration/dbmm_types.hxx index 7b14bd947032..df47e4d9aba2 100644 --- a/dbaccess/source/ext/macromigration/dbmm_types.hxx +++ b/dbaccess/source/ext/macromigration/dbmm_types.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: dbmm_types.hxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.1 $ * * This file is part of OpenOffice.org. * @@ -31,8 +31,7 @@ #ifndef DBACCESS_DBMM_TYPES_HXX #define DBACCESS_DBMM_TYPES_HXX -/** === begin UNO includes === **/ -/** === end UNO includes === **/ +#include //........................................................................ namespace dbmm @@ -61,6 +60,11 @@ namespace dbmm eReport }; + //==================================================================== + //= helper + //==================================================================== + String getScriptTypeDisplayName( const ScriptType _eType ); + //........................................................................ } // namespace dbmm //........................................................................ diff --git a/dbaccess/source/ext/macromigration/docerrorhandling.cxx b/dbaccess/source/ext/macromigration/docerrorhandling.cxx deleted file mode 100644 index 3c7a06d22636..000000000000 --- a/dbaccess/source/ext/macromigration/docerrorhandling.cxx +++ /dev/null @@ -1,91 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: docerrorhandling.cxx,v $ - * $Revision: 1.3 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_dbaccess.hxx" - -#include "docerrorhandling.hxx" - -/** === begin UNO includes === **/ -#include -#include -/** === end UNO includes === **/ - -#include -#include -#include -#include - -//........................................................................ -namespace dbmm -{ -//........................................................................ - - /** === begin UNO using === **/ - using ::com::sun::star::uno::Reference; - using ::com::sun::star::uno::XInterface; - using ::com::sun::star::uno::UNO_QUERY; - using ::com::sun::star::uno::UNO_QUERY_THROW; - using ::com::sun::star::uno::UNO_SET_THROW; - using ::com::sun::star::uno::Exception; - using ::com::sun::star::uno::RuntimeException; - using ::com::sun::star::uno::Any; - using ::com::sun::star::uno::makeAny; - using ::com::sun::star::sdb::XOfficeDatabaseDocument; - using ::com::sun::star::task::XInteractionHandler; - using ::com::sun::star::frame::XModel; - /** === end UNO using === **/ - - //==================================================================== - //= DocumentErrorHandling - //==================================================================== - //-------------------------------------------------------------------- - void DocumentErrorHandling::reportError( const ::comphelper::ComponentContext& _rContext, const Reference< XOfficeDatabaseDocument >& _rxDocument, const Any& _rError ) - { - try - { - Reference< XInteractionHandler > xHandler( _rContext.createComponent( "com.sun.star.task.InteractionHandler" ), UNO_QUERY_THROW ); - // check whether the DB doc has an own interaction handler set - Reference< XModel > xDocModel( _rxDocument, UNO_QUERY_THROW ); - ::comphelper::NamedValueCollection aDocArgs( xDocModel->getArgs() ); - xHandler = aDocArgs.getOrDefault( "InteractionHandler", xHandler ); - xHandler->handle( - new ::comphelper::OInteractionRequest( _rError ) - ); - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } - } - -//........................................................................ -} // namespace dbmm -//........................................................................ diff --git a/dbaccess/source/ext/macromigration/docerrorhandling.hxx b/dbaccess/source/ext/macromigration/docerrorhandling.hxx deleted file mode 100644 index 74f9df09558a..000000000000 --- a/dbaccess/source/ext/macromigration/docerrorhandling.hxx +++ /dev/null @@ -1,69 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: docerrorhandling.hxx,v $ - * $Revision: 1.3 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#ifndef DBACCESS_DOCERRORHANDLING_HXX -#define DBACCESS_DOCERRORHANDLING_HXX - -/** === begin UNO includes === **/ -#include -/** === end UNO includes === **/ - -namespace comphelper { - class ComponentContext; -} - -//........................................................................ -namespace dbmm -{ -//........................................................................ - - //==================================================================== - //= DocumentErrorHandling - //==================================================================== - class DocumentErrorHandling - { - public: - /** reports the given error (usually an exception caught on the caller's side) - to the user, using the document's interaction handler, if present. If the document - does not have an own interaction handler, the given component context is used - to create a new one. - */ - static void reportError( - const ::comphelper::ComponentContext& _rContext, - const ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XOfficeDatabaseDocument >& _rxDocument, - const ::com::sun::star::uno::Any& _rError - ); - }; - -//........................................................................ -} // namespace dbmm -//........................................................................ - -#endif // DBACCESS_DOCERRORHANDLING_HXX diff --git a/dbaccess/source/ext/macromigration/docinteraction.cxx b/dbaccess/source/ext/macromigration/docinteraction.cxx new file mode 100644 index 000000000000..9f7ded185553 --- /dev/null +++ b/dbaccess/source/ext/macromigration/docinteraction.cxx @@ -0,0 +1,157 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: docinteraction.cxx,v $ + * $Revision: 1.1.2.2 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "docinteraction.hxx" + +/** === begin UNO includes === **/ +#include +#include +/** === end UNO includes === **/ + +#include +#include +#include +#include +#include + +//........................................................................ +namespace dbmm +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::task::XInteractionHandler; + using ::com::sun::star::frame::XModel; + using ::com::sun::star::task::DocumentPasswordRequest; + using ::com::sun::star::task::InteractionClassification_QUERY; + using ::com::sun::star::task::PasswordRequestMode_PASSWORD_ENTER; + using ::com::sun::star::task::PasswordRequestMode_PASSWORD_REENTER; + /** === end UNO using === **/ + + //==================================================================== + //= InteractionHandler_Data + //==================================================================== + struct InteractionHandler_Data + { + Reference< XInteractionHandler > xHandler; + + InteractionHandler_Data( const Reference< XInteractionHandler >& _rxHandler ) + :xHandler( _rxHandler ) + { + } + + InteractionHandler_Data( const ::comphelper::ComponentContext& _rContext ) + :xHandler( _rContext.createComponent( "com.sun.star.task.InteractionHandler" ), UNO_QUERY_THROW ) + { + } + }; + + //==================================================================== + //= InteractionHandler + //==================================================================== + //-------------------------------------------------------------------- + InteractionHandler::InteractionHandler( const ::comphelper::ComponentContext& _rContext ) + :m_pData( new InteractionHandler_Data( _rContext ) ) + { + } + + //-------------------------------------------------------------------- + InteractionHandler::InteractionHandler( const Reference< XInteractionHandler >& _rxHandler ) + :m_pData( new InteractionHandler_Data( _rxHandler ) ) + { + } + + //-------------------------------------------------------------------- + InteractionHandler::InteractionHandler( const ::comphelper::ComponentContext& _rContext, const Reference< XModel >& _rxDocument ) + :m_pData( new InteractionHandler_Data( _rContext ) ) + { + // check whether the doumentc has an own interaction handler set + ::comphelper::NamedValueCollection aDocArgs( _rxDocument->getArgs() ); + m_pData->xHandler = aDocArgs.getOrDefault( "InteractionHandler", m_pData->xHandler ); + } + + //-------------------------------------------------------------------- + InteractionHandler::~InteractionHandler() + { + } + + //-------------------------------------------------------------------- + bool InteractionHandler::requestDocumentPassword( const ::rtl::OUString& _rDocumentName, ::rtl::OUString& _io_rPassword ) + { + // create request + DocumentPasswordRequest aRequest( + ::rtl::OUString(), NULL, + InteractionClassification_QUERY, + _io_rPassword.getLength() ? PasswordRequestMode_PASSWORD_REENTER : PasswordRequestMode_PASSWORD_ENTER, + _rDocumentName + ); + + ::rtl::Reference< ::comphelper::OInteractionRequest > pRequest( new ::comphelper::OInteractionRequest( makeAny( aRequest ) ) ); + ::rtl::Reference< ::comphelper::OInteractionPassword > pPassword( new ::comphelper::OInteractionPassword( _io_rPassword ) ); + ::rtl::Reference< ::comphelper::OInteractionAbort > pAbort( new ::comphelper::OInteractionAbort ); + pRequest->addContinuation( pPassword.get() ); + pRequest->addContinuation( pAbort.get() ); + + // handle + m_pData->xHandler->handle( pRequest.get() ); + + // finish up + if ( pAbort->wasSelected() ) + return false; + + _io_rPassword = pPassword->getPassword(); + return true; + } + + //-------------------------------------------------------------------- + void InteractionHandler::reportError( const Any& _rError ) + { + ::rtl::Reference< ::comphelper::OInteractionRequest > pRequest( new ::comphelper::OInteractionRequest( _rError ) ); + ::rtl::Reference< ::comphelper::OInteractionApprove > pApprove( new ::comphelper::OInteractionApprove ); + pRequest->addContinuation( pApprove.get() ); + + m_pData->xHandler->handle( pRequest.get() ); + } + +//........................................................................ +} // namespace dbmm +//........................................................................ diff --git a/dbaccess/source/ext/macromigration/docinteraction.hxx b/dbaccess/source/ext/macromigration/docinteraction.hxx new file mode 100644 index 000000000000..f24bfea7842f --- /dev/null +++ b/dbaccess/source/ext/macromigration/docinteraction.hxx @@ -0,0 +1,107 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: docinteraction.hxx,v $ + * $Revision: 1.1.2.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef DBACCESS_DOCERRORHANDLING_HXX +#define DBACCESS_DOCERRORHANDLING_HXX + +/** === begin UNO includes === **/ +#include +#include +/** === end UNO includes === **/ + +namespace comphelper { + class ComponentContext; +} + +#include + +//........................................................................ +namespace dbmm +{ +//........................................................................ + + //==================================================================== + //= DocumentErrorHandling + //==================================================================== + struct InteractionHandler_Data; + /** wraps common operations with an interaction handler. + */ + class InteractionHandler + { + public: + /** creates an interaction handler by instantiating a css.task.InteractionHandler + component at the given component context. + */ + InteractionHandler( const ::comphelper::ComponentContext& _rContext ); + + /** creates an InteractionHandler instance, using the given existing UNO handler. + */ + InteractionHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& _rxHandler ); + + /** creates an interaction handler by instantiating a css.task.InteractionHandler + component at the given component context, or using the given document's interaction handler, + if one is specified in the document's media descriptor. + */ + InteractionHandler( const ::comphelper::ComponentContext& _rContext, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& _rxDocument ); + + /** destructor + */ + ~InteractionHandler(); + + /** requests a document password + @param _rDocumentName + the document name + @param _io_rPassword + the initial password on method entry, the password as entered by the user on method leave + @return + if and only if the user entered a password, and confirmed with OK, + if the user aborted the request. + */ + bool requestDocumentPassword( + const ::rtl::OUString& _rDocumentName, + ::rtl::OUString& _io_rPassword + ); + + /** reports the given error (usually an exception caught on the caller's side) + to the user + */ + void reportError( + const ::com::sun::star::uno::Any& _rError + ); + + private: + ::std::auto_ptr< InteractionHandler_Data > m_pData; + }; + +//........................................................................ +} // namespace dbmm +//........................................................................ + +#endif // DBACCESS_DOCERRORHANDLING_HXX diff --git a/dbaccess/source/ext/macromigration/macromigration.hrc b/dbaccess/source/ext/macromigration/macromigration.hrc index 2a1165f74986..49668f254234 100644 --- a/dbaccess/source/ext/macromigration/macromigration.hrc +++ b/dbaccess/source/ext/macromigration/macromigration.hrc @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: macromigration.hrc,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.1 $ * * This file is part of OpenOffice.org. * @@ -93,5 +93,7 @@ #define STR_STATE_BACKUP_DBDOC 2 #define STR_STATE_MIGRATE 3 #define STR_STATE_SUMMARY 4 +#define STR_SUCCESSFUL 5 +#define STR_UNSUCCESSFUL 6 #endif // DBACCESS_MACROMIGRATION_HRC diff --git a/dbaccess/source/ext/macromigration/macromigration.src b/dbaccess/source/ext/macromigration/macromigration.src index 2dd7d3f8ad18..e92afa82f978 100644 --- a/dbaccess/source/ext/macromigration/macromigration.src +++ b/dbaccess/source/ext/macromigration/macromigration.src @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: macromigration.src,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.8 $ * * This file is part of OpenOffice.org. * @@ -88,16 +88,16 @@ TabPage TP_PREPARE TAB_PAGE_HEIGHT - CONTENT_POS_X - TAB_PAGE_CONTENT_MARGIN - ( 2 * FIXED_TEXT_HEIGHT - SPACING_UNRELATED ) ); WordBreak = TRUE; - Text [ en-US ] = "This wizard will guide you through the task of migrating your macros and scripts.\n\n" + Text [ en-US ] = "This wizard will guide you through the task of migrating your macros.\n\n" - "After you finished it, all macros and scripts which were formerly embedded into your " - "forms and reports will have been moved to the database document. In this course, libraries " - "will be renamed as needed.\n\n" + "After you finished it, all macros which were formerly embedded into the forms and reports of " + "the current database document will have been moved to the document itself. In this course, " + "libraries will be renamed as needed.\n\n" - "If your forms and reports contain references to those macros and scripts, they " - "will be adjusted, where possible.\n\n" + "If your forms and reports contain references to those macros, they will be adjusted, where " + "possible.\n\n" - "Before the migration can start, all forms, reports, queries and tables must be closed. " + "Before the migration can start, all forms, reports, queries and tables belonging to the document must be closed. " "Press 'Next' to do so."; }; @@ -231,8 +231,6 @@ TabPage TP_MIGRATE Pos = MAP_APPFONT( TAB_PAGE_CONTENT_MARGIN + 60, CONTENT_POS_X + 2 * FIXED_TEXT_HEIGHT + SPACING_UNRELATED ); Size = MAP_APPFONT( TAB_PAGE_WIDTH - ( TAB_PAGE_CONTENT_MARGIN + 60 ), FIXED_TEXT_HEIGHT ); - - Text [ en-US ] = "Form 1"; }; FixedText FT_CURRENT_PROGRESS_LABEL @@ -249,8 +247,6 @@ TabPage TP_MIGRATE Pos = MAP_APPFONT( TAB_PAGE_CONTENT_MARGIN + 60, CONTENT_POS_X + 2 * FIXED_TEXT_HEIGHT + SPACING_UNRELATED + FIXED_TEXT_HEIGHT + SPACING_UNRELATED ); Size = MAP_APPFONT( TAB_PAGE_WIDTH - ( TAB_PAGE_CONTENT_MARGIN + 60 ), FIXED_TEXT_HEIGHT ); - - Text [ en-US ] = "loading ..."; }; Window WND_CURRENT_PROGRESS @@ -299,8 +295,9 @@ TabPage TP_MIGRATE Size = MAP_APPFONT( TAB_PAGE_WIDTH - 2 * TAB_PAGE_CONTENT_MARGIN, 2 * FIXED_TEXT_HEIGHT ); WordBreak = TRUE; + Hide = TRUE; - Text [ en-US ] = "All documents have been successfully processed. Press 'Next' to show a detailed summary."; + Text [ en-US ] = "All forms and reports have been successfully processed. Press 'Next' to show a detailed summary."; }; }; @@ -328,7 +325,7 @@ TabPage TP_SUMMARY Pos = MAP_APPFONT( TAB_PAGE_CONTENT_MARGIN, CONTENT_POS_X ); Size = MAP_APPFONT( TAB_PAGE_WIDTH - 2 * TAB_PAGE_CONTENT_MARGIN, FIXED_TEXT_HEIGHT ); - Text [ en-US ] = "The following actions have been taken:"; + WordBreak = TRUE; }; MultiLineEdit ED_CHANGES @@ -342,6 +339,15 @@ TabPage TP_SUMMARY Border = TRUE; BorderStyle = WINDOW_BORDER_MONO; }; + + String STR_SUCCESSFUL + { + Text [ en-US ] = "The migration was successful. Below is a log of the actions which have been taken to your document."; + }; + String STR_UNSUCCESSFUL + { + Text [ en-US ] = "The migration was not successful. Examine the migration log below for details."; + }; }; String STR_FORM @@ -373,12 +379,22 @@ String STR_SAVED_COPY_TO String STR_MOVED_LIBRARY { - Text[ en-US ] = "moved $type$ library $old$ to $new$"; + Text[ en-US ] = "migrated $type$ library '$old$' to '$new$'"; +}; + +String STR_LIBRARY_TYPE_AND_NAME +{ + Text [ en-US ] = "$type$ library '$library$'"; +}; + +String STR_MIGRATING_LIBS +{ + Text [ en-US ] = "migrating libraries ..."; }; String STR_OOO_BASIC { - Text[ en-US ] = "%PRODUCTNAME% Basic"; + Text[ en-US ] = "%PRODUCTNAME Basic"; }; String STR_JAVA_SCRIPT @@ -406,3 +422,24 @@ String STR_DIALOG Text[ en-US ] = "dialog"; }; +String STR_ERRORS +{ + Text [ en-US ] = "Error(s)"; +}; + +String STR_WARNINGS +{ + Text [ en-US ] = "Warnings"; +}; + +String STR_EXCEPTION +{ + Text [ en-US ] = "caught exception: "; +}; + + +ErrorBox ERR_INVALID_BACKUP_LOCATION +{ + Buttons = WB_OK; + Message [ en-US ] = "You need to choose a backup location other than the document location itself."; +}; diff --git a/dbaccess/source/ext/macromigration/macromigrationdialog.cxx b/dbaccess/source/ext/macromigration/macromigrationdialog.cxx index 457b5982a90a..36ddf714f9bc 100644 --- a/dbaccess/source/ext/macromigration/macromigrationdialog.cxx +++ b/dbaccess/source/ext/macromigration/macromigrationdialog.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: macromigrationdialog.cxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.9 $ * * This file is part of OpenOffice.org. * @@ -33,23 +33,36 @@ #include "dbmm_global.hrc" #include "dbmm_module.hxx" -#include "docerrorhandling.hxx" +#include "docinteraction.hxx" #include "macromigration.hrc" #include "macromigrationdialog.hxx" #include "macromigrationpages.hxx" #include "migrationengine.hxx" +#include "migrationerror.hxx" #include "migrationlog.hxx" /** === begin UNO includes === **/ #include #include #include -#include +#include +#include +#include +#include +#include /** === end UNO includes === **/ +#include #include +#include +#include #include #include +#include +#include +#include + +#include //........................................................................ namespace dbmm @@ -61,7 +74,7 @@ namespace dbmm #define STATE_MIGRATE 2 #define STATE_SUMMARY 3 -#define PATH_DEFAULT 1 +#define PATH_DEFAULT 1 /** === begin UNO using === **/ using ::com::sun::star::uno::Reference; @@ -77,13 +90,38 @@ namespace dbmm using ::com::sun::star::sdb::XOfficeDatabaseDocument; using ::com::sun::star::frame::XModel2; using ::com::sun::star::frame::XController; + using ::com::sun::star::frame::XController2; using ::com::sun::star::container::XEnumeration; using ::com::sun::star::frame::XStorable; using ::com::sun::star::uno::Sequence; using ::com::sun::star::beans::PropertyValue; - using ::com::sun::star::frame::XModel; + using ::com::sun::star::frame::XFrame; + using ::com::sun::star::awt::XWindow; + using ::com::sun::star::util::XCloseable; + using ::com::sun::star::util::XCloseListener; + using ::com::sun::star::util::CloseVetoException; + using ::com::sun::star::lang::EventObject; + using ::com::sun::star::frame::XComponentLoader; + using ::com::sun::star::util::XModifiable; + using ::com::sun::star::ucb::XCommandEnvironment; + using ::com::sun::star::ucb::XContent; + using ::com::sun::star::ucb::XContentIdentifier; + using ::com::sun::star::ucb::XContentProvider; /** === end UNO using === **/ + //==================================================================== + //= helper + //==================================================================== + //-------------------------------------------------------------------- + static void lcl_getControllers_throw( const Reference< XModel2 >& _rxDocument, + ::std::list< Reference< XController2 > >& _out_rControllers ) + { + _out_rControllers.clear(); + Reference< XEnumeration > xControllerEnum( _rxDocument->getControllers(), UNO_SET_THROW ); + while ( xControllerEnum->hasMoreElements() ) + _out_rControllers.push_back( Reference< XController2 >( xControllerEnum->nextElement(), UNO_QUERY_THROW ) ); + } + //==================================================================== //= MacroMigrationDialog_Data //==================================================================== @@ -92,7 +130,11 @@ namespace dbmm ::comphelper::ComponentContext aContext; MigrationLog aLogger; Reference< XOfficeDatabaseDocument > xDocument; + Reference< XModel2 > xDocumentModel; + ::rtl::OUString sSuccessfulBackupLocation; bool bMigrationIsRunning; + bool bMigrationFailure; + bool bMigrationSuccess; MacroMigrationDialog_Data( const ::comphelper::ComponentContext& _rContext, @@ -100,12 +142,14 @@ namespace dbmm :aContext( _rContext ) ,aLogger() ,xDocument( _rxDocument ) + ,xDocumentModel( _rxDocument, UNO_QUERY ) ,bMigrationIsRunning( false ) + ,bMigrationFailure( false ) + ,bMigrationSuccess( false ) { } }; - //==================================================================== //= MacroMigrationDialog //==================================================================== @@ -136,7 +180,7 @@ namespace dbmm enableButtons( WZB_FINISH, true ); ActivatePage(); - OSL_PRECOND( m_pData->xDocument.is(), "MacroMigrationDialog::MacroMigrationDialog: illegal document!" ); + OSL_PRECOND( m_pData->xDocumentModel.is(), "MacroMigrationDialog::MacroMigrationDialog: illegal document!" ); } //-------------------------------------------------------------------- @@ -156,6 +200,21 @@ namespace dbmm return m_pData->xDocument; } + //-------------------------------------------------------------------- + short MacroMigrationDialog::Execute() + { + short nResult = MacroMigrationDialog_Base::Execute(); + if ( !m_pData->bMigrationFailure && !m_pData->bMigrationSuccess ) + // migration did not even start + return nResult; + + OSL_ENSURE( !m_pData->bMigrationFailure || !m_pData->bMigrationSuccess, + "MacroMigrationDialog::Execute: success *and* failure at the same time?!" ); + impl_reloadDocument_nothrow( m_pData->bMigrationSuccess ); + + return nResult; + } + //-------------------------------------------------------------------- BOOL MacroMigrationDialog::Close() { @@ -194,18 +253,23 @@ namespace dbmm enableButtons( WZB_FINISH | WZB_CANCEL | WZB_PREVIOUS | WZB_NEXT, false ); - // prevent closing - m_pData->bMigrationIsRunning = true; // start the migration asynchronously PostUserEvent( LINK( this, MacroMigrationDialog, OnStartMigration ) ); } break; case STATE_SUMMARY: - // enable the previous step - we can't return to the actual migration, it already happened (or failed) + // disable the previous step - we can't return to the actual migration, it already happened (or failed) enableState( STATE_MIGRATE, false ); updateTravelUI(); - dynamic_cast< ResultPage& >( *GetPage( STATE_SUMMARY ) ).displaySummary( m_pData->aLogger.getCompleteLog() ); + + // display the results + dynamic_cast< ResultPage& >( *GetPage( STATE_SUMMARY ) ).displayMigrationLog( + m_pData->bMigrationSuccess, m_pData->aLogger.getCompleteLog() ); + + enableButtons( WZB_FINISH, m_pData->bMigrationSuccess ); + enableButtons( WZB_CANCEL, m_pData->bMigrationFailure ); + defaultButton( m_pData->bMigrationSuccess ? WZB_FINISH : WZB_CANCEL ); break; default: @@ -261,21 +325,34 @@ namespace dbmm //-------------------------------------------------------------------- IMPL_LINK( MacroMigrationDialog, OnStartMigration, void*, /*_pNotInterestedIn*/ ) { + // prevent closing + m_pData->bMigrationIsRunning = true; + // initialize migration engine and progress ProgressPage& rProgressPage( dynamic_cast< ProgressPage& >( *GetPage( STATE_MIGRATE ) ) ); MigrationEngine aEngine( m_pData->aContext, m_pData->xDocument, rProgressPage, m_pData->aLogger ); rProgressPage.setDocumentCounts( aEngine.getFormCount(), aEngine.getReportCount() ); // do the migration - bool bSuccess = aEngine.migrateAll(); + m_pData->bMigrationSuccess = aEngine.migrateAll(); + m_pData->bMigrationFailure = !m_pData->bMigrationSuccess; // re-enable the UI - enableButtons( ( bSuccess ? WZB_FINISH | WZB_NEXT : 0 ), true ); - enableState( STATE_SUMMARY, bSuccess ); + enableButtons( WZB_FINISH | WZB_NEXT, true ); + enableState( STATE_SUMMARY, true ); updateTravelUI(); m_pData->bMigrationIsRunning = false; + if ( m_pData->bMigrationSuccess ) + { + rProgressPage.onFinishedSuccessfully(); + } + else + { // if there was an error, show the summary automatically + travelNext(); + } + // outta here return 0L; } @@ -301,16 +378,12 @@ namespace dbmm bool bSuccess = true; try { - ::std::vector< Reference< XController > > aControllers; - // collect all controllers of our document - Reference< XModel2 > xDocument( m_pData->xDocument, UNO_QUERY_THROW ); - Reference< XEnumeration > xControllerEnum( xDocument->getControllers(), UNO_SET_THROW ); - while ( xControllerEnum->hasMoreElements() ) - aControllers.push_back( Reference< XController >( xControllerEnum->nextElement(), UNO_QUERY_THROW ) ); + ::std::list< Reference< XController2 > > aControllers; + lcl_getControllers_throw( m_pData->xDocumentModel, aControllers ); // close all sub documents of all controllers - for ( ::std::vector< Reference< XController > >::const_iterator pos = aControllers.begin(); + for ( ::std::list< Reference< XController2 > >::const_iterator pos = aControllers.begin(); pos != aControllers.end() && bSuccess; ++pos ) @@ -335,17 +408,65 @@ namespace dbmm return bSuccess; } + //-------------------------------------------------------------------- + namespace + { + bool lcl_equalURLs_nothrow( const ::rtl::OUString& _lhs, const ::rtl::OUString _rhs ) + { + // the cheap situation: the URLs are equal + if ( _lhs == _rhs ) + return true; + + bool bEqual = true; + try + { + ::ucbhelper::Content aContentLHS = ::ucbhelper::Content( _lhs, Reference< XCommandEnvironment >() ); + ::ucbhelper::Content aContentRHS = ::ucbhelper::Content( _rhs, Reference< XCommandEnvironment >() ); + Reference< XContent > xContentLHS( aContentLHS.get(), UNO_SET_THROW ); + Reference< XContent > xContentRHS( aContentRHS.get(), UNO_SET_THROW ); + Reference< XContentIdentifier > xID1( xContentLHS->getIdentifier(), UNO_SET_THROW ); + Reference< XContentIdentifier > xID2( xContentRHS->getIdentifier(), UNO_SET_THROW ); + + ::ucbhelper::ContentBroker* pBroker = ::ucbhelper::ContentBroker::get(); + Reference< XContentProvider > xProvider( + pBroker ? pBroker->getContentProviderInterface() : Reference< XContentProvider >(), UNO_SET_THROW ); + + bEqual = ( 0 == xProvider->compareContentIds( xID1, xID2 ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return bEqual; + } + } + //-------------------------------------------------------------------- bool MacroMigrationDialog::impl_backupDocument_nothrow() const { - const SaveDBDocPage& rBackupPage = dynamic_cast< const SaveDBDocPage& >( *GetPage( STATE_BACKUP_DBDOC ) ); + if ( !m_pData->xDocumentModel.is() ) + // should never happen, but has been reported as assertion before + return false; + + SaveDBDocPage& rBackupPage = dynamic_cast< SaveDBDocPage& >( *GetPage( STATE_BACKUP_DBDOC ) ); ::rtl::OUString sBackupLocation( rBackupPage.getBackupLocation() ); Any aError; try { + // check that the backup location isn't the same as the document itself + if ( lcl_equalURLs_nothrow( sBackupLocation, m_pData->xDocumentModel->getURL() ) ) + { + ErrorBox aErrorBox( const_cast< MacroMigrationDialog* >( this ), MacroMigrationResId( ERR_INVALID_BACKUP_LOCATION ) ); + aErrorBox.Execute(); + rBackupPage.grabLocationFocus(); + return false; + } + + // store to the backup location const Reference< XStorable > xDocument( getDocument(), UNO_QUERY_THROW ); xDocument->storeToURL( sBackupLocation, Sequence< PropertyValue >() ); + m_pData->sSuccessfulBackupLocation = sBackupLocation; } catch( const Exception& ) { @@ -359,13 +480,152 @@ namespace dbmm } // display the error to the user - DocumentErrorHandling::reportError( m_pData->aContext, m_pData->xDocument, aError ); + InteractionHandler aHandler( m_pData->aContext, m_pData->xDocumentModel.get() ); + aHandler.reportError( aError ); - // TODO: log the error + m_pData->aLogger.logFailure( MigrationError( + ERR_DOCUMENT_BACKUP_FAILED, + sBackupLocation, + aError + ) ); return false; } + //-------------------------------------------------------------------- + void MacroMigrationDialog::impl_reloadDocument_nothrow( bool _bMigrationSuccess ) + { + typedef ::std::pair< Reference< XFrame >, ::rtl::OUString > ViewDescriptor; + ::std::list< ViewDescriptor > aViews; + + try + { + // the information which is necessary to reload the document + ::rtl::OUString sDocumentURL ( m_pData->xDocumentModel->getURL() ); + ::comphelper::NamedValueCollection aDocumentArgs( m_pData->xDocumentModel->getArgs() ); + if ( !_bMigrationSuccess ) + { + // if the migration was not successful, then reload from the backup + aDocumentArgs.put( "SalvagedFile", m_pData->sSuccessfulBackupLocation ); + // reset the modified flag of the document, so the controller can be suspended later + Reference< XModifiable > xModify( m_pData->xDocument, UNO_QUERY_THROW ); + xModify->setModified( sal_False ); + // after this reload, don't show the migration warning, again + aDocumentArgs.put( "SuppressMigrationWarning", sal_Bool(sal_True) ); + } + + // remove anything from the args which might refer to the old document + aDocumentArgs.remove( "Model" ); + aDocumentArgs.remove( "Stream" ); + aDocumentArgs.remove( "InputStream" ); + aDocumentArgs.remove( "FileName" ); + aDocumentArgs.remove( "URL" ); + + // collect all controllers of our document + ::std::list< Reference< XController2 > > aControllers; + lcl_getControllers_throw( m_pData->xDocumentModel, aControllers ); + + // close all those controllers + while ( !aControllers.empty() ) + { + Reference< XController2 > xController( aControllers.front(), UNO_SET_THROW ); + aControllers.pop_front(); + + Reference< XFrame > xFrame( xController->getFrame(), UNO_SET_THROW ); + ::rtl::OUString sViewName( xController->getViewControllerName() ); + + if ( !xController->suspend( sal_True ) ) + { // ouch. There shouldn't be any modal dialogs and such, so there + // really is no reason why suspending shouldn't work. + OSL_ENSURE( false, "MacroMigrationDialog::impl_reloadDocument_nothrow: could not suspend a controller!" ); + // ignoring this would be at the cost of a crash (potentially) + // so, we cannot continue here. + throw CloseVetoException(); + } + + aViews.push_back( ViewDescriptor( xFrame, sViewName ) ); + xFrame->setComponent( NULL, NULL ); + xController->dispose(); + } + + // Note the document is closed now - disconnecting the last controller + // closes it automatically. + + Reference< XOfficeDatabaseDocument > xNewDocument; + + // re-create the views + while ( !aViews.empty() ) + { + ViewDescriptor aView( aViews.front() ); + aViews.pop_front(); + + // load the document into this frame + Reference< XComponentLoader > xLoader( aView.first, UNO_QUERY_THROW ); + aDocumentArgs.put( "ViewName", aView.second ); + Reference< XInterface > xReloaded( xLoader->loadComponentFromURL( + sDocumentURL, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_self" ) ), + 0, + aDocumentArgs.getPropertyValues() + ) ); + + OSL_ENSURE( xReloaded != m_pData->xDocumentModel, + "MacroMigrationDialog::impl_reloadDocument_nothrow: this should have been a new instance!" ); + // this would be unexpected, but recoverable: The loader should at least have done + // this: really *load* the document, even if it loaded it into the old document instance + if ( !xNewDocument.is() ) + { + xNewDocument.set( xReloaded, UNO_QUERY_THROW ); + // for subsequent loads, into different frames, put the document into the load args + aDocumentArgs.put( "Model", xNewDocument ); + } + #if OSL_DEBUG_LEVEL > 0 + else + { + OSL_ENSURE( xNewDocument == xReloaded, + "MacroMigrationDialog::impl_reloadDocument_nothrow: unexpected: subsequent load attempt returned a wrong document!" ); + } + #endif + } + + m_pData->xDocument = xNewDocument; + m_pData->xDocumentModel.set( xNewDocument, UNO_QUERY ); + + // finally, now that the document has been reloaded - if the migration was not successful, + // then it was reloaded from the backup, but the real document still is broken. So, save + // the document once, which will write the content loaded from the backup to the real docfile. + if ( !_bMigrationSuccess ) + { + Reference< XModifiable > xModify( m_pData->xDocument, UNO_QUERY_THROW ); + xModify->setModified( sal_True ); + // this is just parnoia - in case saving the doc fails, perhaps the user is tempted to do so + Reference< XStorable > xStor( m_pData->xDocument, UNO_QUERY_THROW ); + xStor->store(); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + // close all frames from aViews - the respective controllers have been closed, but + // reloading didn't work, so the frames are zombies now. + while ( !aViews.empty() ) + { + ViewDescriptor aView( aViews.front() ); + aViews.pop_front(); + try + { + Reference< XCloseable > xFrameClose( aView.first, UNO_QUERY_THROW ); + xFrameClose->close( sal_True ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + } + //........................................................................ } // namespace dbmm //........................................................................ diff --git a/dbaccess/source/ext/macromigration/macromigrationdialog.hxx b/dbaccess/source/ext/macromigration/macromigrationdialog.hxx index 4a2a155de364..727dd333e1ea 100644 --- a/dbaccess/source/ext/macromigration/macromigrationdialog.hxx +++ b/dbaccess/source/ext/macromigration/macromigrationdialog.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: macromigrationdialog.hxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.1 $ * * This file is part of OpenOffice.org. * @@ -75,11 +75,13 @@ namespace dbmm // Dialog overridables virtual BOOL Close(); + virtual short Execute(); private: void impl_showCloseDocsError( bool _bShow ); bool impl_closeSubDocs_nothrow(); bool impl_backupDocument_nothrow() const; + void impl_reloadDocument_nothrow( bool _bMigrationSuccess ); private: DECL_LINK( OnStartMigration, void* ); diff --git a/dbaccess/source/ext/macromigration/macromigrationpages.cxx b/dbaccess/source/ext/macromigration/macromigrationpages.cxx index d91b68bd9d49..f46db80f7d73 100644 --- a/dbaccess/source/ext/macromigration/macromigrationpages.cxx +++ b/dbaccess/source/ext/macromigration/macromigrationpages.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: macromigrationpages.cxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.4 $ * * This file is part of OpenOffice.org. * @@ -43,6 +43,7 @@ #include #include +#include //........................................................................ namespace dbmm @@ -216,8 +217,8 @@ namespace dbmm ,m_aObjectCount ( this, MacroMigrationResId( FT_OBJECT_COUNT ) ) ,m_aCurrentObjectLabel ( this, MacroMigrationResId( FT_CURRENT_OBJECT_LABEL ) ) ,m_aCurrentObject ( this, MacroMigrationResId( FT_CURRENT_OBJECT ) ) - ,m_aCurrentActionLabel ( this, MacroMigrationResId( FT_CURRENT_PROGRESS_LABEL ) ) - ,m_aCurrentAction ( this, MacroMigrationResId( FT_CURRENT_PROGRESS ) ) + ,m_aCurrentActionLabel ( this, MacroMigrationResId( FT_CURRENT_PROGRESS_LABEL ) ) + ,m_aCurrentAction ( this, MacroMigrationResId( FT_CURRENT_PROGRESS ) ) ,m_aCurrentProgress ( this, MacroMigrationResId( WND_CURRENT_PROGRESS ) ) ,m_aAllProgressLabel ( this, MacroMigrationResId( FT_ALL_PROGRESS_LABEL ) ) ,m_aAllProgressText ( this, MacroMigrationResId( FT_OBJECT_COUNT_PROGRESS ) ) @@ -242,6 +243,12 @@ namespace dbmm m_aObjectCount.SetText( sText ); } + //-------------------------------------------------------------------- + void ProgressPage::onFinishedSuccessfully() + { + m_aMigrationDone.Show(); + } + //-------------------------------------------------------------------- void ProgressPage::startObject( const ::rtl::OUString& _rObjectName, const ::rtl::OUString& _rCurrentAction, const sal_uInt32 _nRange ) { @@ -252,6 +259,8 @@ namespace dbmm // since this is currently called from the main thread, which does not have the chance // to re-schedule, we need to explicitly update the display + m_aCurrentObject.Update(); + m_aCurrentAction.Update(); Update(); } @@ -259,6 +268,7 @@ namespace dbmm void ProgressPage::setObjectProgressText( const ::rtl::OUString& _rText ) { m_aCurrentAction.SetText( _rText ); + m_aCurrentAction.Update(); Update(); } @@ -272,9 +282,9 @@ namespace dbmm //-------------------------------------------------------------------- void ProgressPage::endObject() { - m_aCurrentObject.SetText( String() ); m_aCurrentAction.SetText( String() ); - m_aCurrentProgress.SetValue( (sal_uInt32)0 ); + m_aCurrentProgress.SetValue( m_aCurrentProgress.GetRange() ); + m_aCurrentAction.Update(); Update(); } @@ -307,6 +317,8 @@ namespace dbmm :MacroMigrationPage( _rParentDialog, MacroMigrationResId( TP_SUMMARY ) ) ,m_aChangesLabel( this, MacroMigrationResId( FT_CHANGES_LABEL ) ) ,m_aChanges ( this, MacroMigrationResId( ED_CHANGES ) ) + ,m_aSuccessful ( MacroMigrationResId( STR_SUCCESSFUL ) ) + ,m_aUnsuccessful( MacroMigrationResId( STR_UNSUCCESSFUL ) ) { FreeResource(); } @@ -318,9 +330,30 @@ namespace dbmm } //-------------------------------------------------------------------- - void ResultPage::displaySummary( const String& _rSummary ) + void ResultPage::displayMigrationLog( const bool _bSuccessful, const String& _rSummary ) { + m_aChangesLabel.SetText( _bSuccessful ? m_aSuccessful : m_aUnsuccessful ); m_aChanges.SetText( _rSummary ); + + // resize m_aChangesLabel and m_aChances as needed for the label text to fit + Rectangle aOriginalLabelSize( m_aChangesLabel.GetPosPixel(), m_aChangesLabel.GetSizePixel() ); + // assume 3 lines, at most + Rectangle aNewLabelSize( aOriginalLabelSize ); + aNewLabelSize.Bottom() = aNewLabelSize.Top() + m_aChangesLabel.LogicToPixel( Size( 0, 3*8 ), MAP_APPFONT ).Height(); + TextRectInfo aInfo; + aNewLabelSize = m_aChangesLabel.GetTextRect( aNewLabelSize, m_aChangesLabel.GetText(), TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK, &aInfo ); + aNewLabelSize.Bottom() = aNewLabelSize.Top() + m_aChangesLabel.LogicToPixel( Size( 0, aInfo.GetLineCount() * 8 ), MAP_APPFONT ).Height(); + + m_aChangesLabel.SetSizePixel( aNewLabelSize.GetSize() ); + + long nChangesDiff = aNewLabelSize.GetHeight() - aOriginalLabelSize.GetHeight(); + Size aChangesSize( m_aChanges.GetSizePixel() ); + aChangesSize.Height() -= nChangesDiff; + m_aChanges.SetSizePixel( aChangesSize ); + + Point aChangesPos( m_aChanges.GetPosPixel() ); + aChangesPos.Y() += nChangesDiff; + m_aChanges.SetPosPixel( aChangesPos ); } //........................................................................ diff --git a/dbaccess/source/ext/macromigration/macromigrationpages.hxx b/dbaccess/source/ext/macromigration/macromigrationpages.hxx index fdbb3091cf43..f4aefc4599c6 100644 --- a/dbaccess/source/ext/macromigration/macromigrationpages.hxx +++ b/dbaccess/source/ext/macromigration/macromigrationpages.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: macromigrationpages.hxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.3 $ * * This file is part of OpenOffice.org. * @@ -100,6 +100,7 @@ namespace dbmm public: ::rtl::OUString getBackupLocation() const { return m_aLocationController.getURL(); } + void grabLocationFocus() { m_aSaveAsLocation.GrabFocus(); } protected: FixedText m_aExplanation; @@ -133,6 +134,7 @@ namespace dbmm static TabPage* Create( ::svt::RoadmapWizard& _rParentDialog ); void setDocumentCounts( const sal_Int32 _nForms, const sal_Int32 _nReports ); + void onFinishedSuccessfully(); protected: // IMigrationProgress @@ -167,11 +169,13 @@ namespace dbmm static TabPage* Create( ::svt::RoadmapWizard& _rParentDialog ); - void displaySummary( const String& _rSummary ); + void displayMigrationLog( const bool _bSuccessful, const String& _rLog ); private: FixedText m_aChangesLabel; MultiLineEdit m_aChanges; + String m_aSuccessful; + String m_aUnsuccessful; }; //........................................................................ diff --git a/dbaccess/source/ext/macromigration/macromigrationwizard.cxx b/dbaccess/source/ext/macromigration/macromigrationwizard.cxx index 2516e91a561f..732fa9906119 100644 --- a/dbaccess/source/ext/macromigration/macromigrationwizard.cxx +++ b/dbaccess/source/ext/macromigration/macromigrationwizard.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: macromigrationwizard.cxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.2 $ * * This file is part of OpenOffice.org. * @@ -37,6 +37,7 @@ /** === begin UNO includes === **/ #include #include +#include /** === end UNO includes === **/ #include @@ -64,6 +65,7 @@ namespace dbmm using ::com::sun::star::ucb::AlreadyInitializedException; using ::com::sun::star::sdb::XOfficeDatabaseDocument; using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::frame::XStorable; /** === end UNO using === **/ //==================================================================== @@ -209,7 +211,7 @@ namespace dbmm if ( _rArguments.getLength() != 1 ) throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid number of initialization arguments. Expected 1." ) ), - // TODO: resoource + // TODO: resource *this, 1 ); @@ -223,6 +225,15 @@ namespace dbmm 1 ); + Reference< XStorable > xDocStor( m_xDocument, UNO_QUERY_THROW ); + if ( xDocStor->isReadonly() ) + throw IllegalArgumentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Not applicable to read-only documents." ) ), + // TODO: resource + *this, + 1 + ); + m_bInitialized = true; } diff --git a/dbaccess/source/ext/macromigration/makefile.mk b/dbaccess/source/ext/macromigration/makefile.mk index dba5395c35ac..3c833332fb8f 100644 --- a/dbaccess/source/ext/macromigration/makefile.mk +++ b/dbaccess/source/ext/macromigration/makefile.mk @@ -8,7 +8,7 @@ # # $RCSfile: makefile.mk,v $ # -# $Revision: 1.3 $ +# $Revision: 1.3.2.4 $ # # This file is part of OpenOffice.org. # @@ -56,9 +56,11 @@ SLOFILES= $(SLO)$/macromigrationwizard.obj \ $(SLO)$/dbmm_module.obj \ $(SLO)$/dbmm_services.obj \ $(SLO)$/migrationengine.obj \ - $(SLO)$/docerrorhandling.obj \ + $(SLO)$/docinteraction.obj \ $(SLO)$/progresscapture.obj \ + $(SLO)$/progressmixer.obj \ $(SLO)$/migrationlog.obj \ + $(SLO)$/dbmm_types.obj \ # --- library ----------------------------------- @@ -75,7 +77,8 @@ SHL1STDLIBS= \ $(SVTOOLLIB) \ $(SVLLIB) \ $(VCLLIB) \ - $(SVXLIB) + $(SVXLIB) \ + $(UCBHELPERLIB) SHL1LIBS= $(SLB)$/$(TARGET).lib SHL1IMPLIB= i$(TARGET) diff --git a/dbaccess/source/ext/macromigration/migrationengine.cxx b/dbaccess/source/ext/macromigration/migrationengine.cxx index efd8c86bfdd4..bf147de0b1e4 100644 --- a/dbaccess/source/ext/macromigration/migrationengine.cxx +++ b/dbaccess/source/ext/macromigration/migrationengine.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: migrationengine.cxx,v $ - * $Revision: 1.4 $ + * $Revision: 1.4.2.14 $ * * This file is part of OpenOffice.org. * @@ -34,11 +34,13 @@ #include "dbmm_global.hrc" #include "dbmm_module.hxx" #include "dbmm_types.hxx" -#include "docerrorhandling.hxx" +#include "docinteraction.hxx" #include "migrationengine.hxx" +#include "migrationerror.hxx" #include "migrationprogress.hxx" #include "migrationlog.hxx" #include "progresscapture.hxx" +#include "progressmixer.hxx" /** === begin UNO includes === **/ #include @@ -48,16 +50,38 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /** === end UNO includes === **/ -#include +#include +#include #include +#include +#include +#include #include #include #include #include +#include #include +#include #define DEFAULT_DOC_PROGRESS_RANGE 100000 @@ -90,19 +114,54 @@ namespace dbmm using ::com::sun::star::ucb::Command; using ::com::sun::star::embed::XComponentSupplier; using ::com::sun::star::task::XStatusIndicator; + using ::com::sun::star::embed::XStorage; + using ::com::sun::star::document::XStorageBasedDocument; + using ::com::sun::star::embed::XTransactedObject; + using ::com::sun::star::frame::XStorable; + using ::com::sun::star::embed::XEmbedPersist; + using ::com::sun::star::script::DocumentDialogLibraryContainer; + using ::com::sun::star::script::DocumentScriptLibraryContainer; + using ::com::sun::star::script::XStorageBasedLibraryContainer; + using ::com::sun::star::document::XEmbeddedScripts; + using ::com::sun::star::container::XNameContainer; + using ::com::sun::star::document::XEventsSupplier; + using ::com::sun::star::container::XNameReplace; + using com::sun::star::uri::UriReferenceFactory; + using com::sun::star::uri::XUriReferenceFactory; + using com::sun::star::uri::XVndSunStarScriptUrlReference; + using ::com::sun::star::form::XFormsSupplier; + using ::com::sun::star::drawing::XDrawPageSupplier; + using ::com::sun::star::drawing::XDrawPagesSupplier; + using ::com::sun::star::drawing::XDrawPage; + using ::com::sun::star::drawing::XDrawPages; + using ::com::sun::star::container::XIndexAccess; + using ::com::sun::star::script::XEventAttacherManager; + using ::com::sun::star::script::ScriptEventDescriptor; + using ::com::sun::star::script::XLibraryContainerPassword; /** === end UNO using === **/ + namespace ElementModes = ::com::sun::star::embed::ElementModes; + +// migration phases whose progresses are to be mixed into one progress +#define PHASE_JAVASCRIPT 1 +#define PHASE_BEANSHELL 2 +#define PHASE_PYTHON 3 +#define PHASE_JAVA 4 +#define PHASE_BASIC 5 +#define PHASE_DIALOGS 6 //==================================================================== //= SubDocument //==================================================================== struct SubDocument { - Reference< XCommandProcessor > xCommandProcessor; - ::rtl::OUString sHierarchicalName; - SubDocumentType eType; + Reference< XCommandProcessor > xCommandProcessor; + Reference< XModel > xDocument; // valid only temporarily + ::rtl::OUString sHierarchicalName; + SubDocumentType eType; SubDocument( const Reference< XCommandProcessor >& _rxCommandProcessor, const ::rtl::OUString& _rName, const SubDocumentType _eType ) :xCommandProcessor( _rxCommandProcessor ) + ,xDocument() ,sHierarchicalName( _rName ) ,eType( _eType ) { @@ -112,213 +171,104 @@ namespace dbmm typedef ::std::vector< SubDocument > SubDocuments; //==================================================================== - //= MigrationEngine_Impl - declaration - //==================================================================== - class MigrationEngine_Impl - { - public: - MigrationEngine_Impl( - const ::comphelper::ComponentContext& _rContext, - const Reference< XOfficeDatabaseDocument >& _rxDocument, - IMigrationProgress& _rProgress, - MigrationLog& _rLogger - ); - ~MigrationEngine_Impl(); - - inline sal_Int32 getFormCount() const { return m_nFormCount; } - inline sal_Int32 getReportCount()const { return m_nReportCount; } - bool migrateAll(); - - private: - ::comphelper::ComponentContext m_aContext; - const Reference< XOfficeDatabaseDocument > m_xDocument; - IMigrationProgress& m_rProgress; - MigrationLog& m_rLogger; - SubDocuments m_aSubDocs; - size_t m_nFormCount; - size_t m_nReportCount; - - private: - /** collects a description of all sub documents of our database document - - @return - if and only if collecting the documents was successful - */ - bool impl_collectSubDocuments_nothrow(); - - /** reports the given error (usually an exception caught on the caller's side) - to the user, using the document's interaction handler, if any. - */ - void impl_reportError_nothrow( const Any& _rError ) const; - - /** migrates the macros/scripts of the given sub document - */ - bool impl_handleDocument_nothrow( const SubDocument& _rDocument ) const; - }; - - //==================================================================== - //= MigrationEngine_Impl - implementation + //= helper //==================================================================== //-------------------------------------------------------------------- - MigrationEngine_Impl::MigrationEngine_Impl( const ::comphelper::ComponentContext& _rContext, - const Reference< XOfficeDatabaseDocument >& _rxDocument, IMigrationProgress& _rProgress, MigrationLog& _rLogger ) - :m_aContext( _rContext ) - ,m_xDocument( _rxDocument ) - ,m_rProgress( _rProgress ) - ,m_rLogger( _rLogger ) - ,m_aSubDocs() - ,m_nFormCount( 0 ) - ,m_nReportCount( 0 ) - { - OSL_VERIFY( impl_collectSubDocuments_nothrow() ); - } - - //-------------------------------------------------------------------- - MigrationEngine_Impl::~MigrationEngine_Impl() - { - } + typedef ::utl::SharedUNOComponent< XStorage > SharedStorage; - //-------------------------------------------------------------------- - bool MigrationEngine_Impl::migrateAll() + namespace { - if ( m_aSubDocs.empty() ) + //---------------------------------------------------------------- + static const ::rtl::OUString& lcl_getScriptsStorageName() { - OSL_ENSURE( false, "MigrationEngine_Impl::migrateAll: no forms/reports found!" ); - // The whole migration wizard is not expected to be called when there are no forms/reports - // with macros, not to mention when there are no forms/reports at all. - return false; + static const ::rtl::OUString s_sScriptsStorageName( RTL_CONSTASCII_USTRINGPARAM( "Scripts" ) ); + return s_sScriptsStorageName; } - // initialize global progress - sal_Int32 nOverallRange( m_aSubDocs.size() ); - String sProgressSkeleton = String( MacroMigrationResId( STR_OVERALL_PROGRESS ) ); - sProgressSkeleton.SearchAndReplaceAscii( "$overall$", String::CreateFromInt32( nOverallRange ) ); - - m_rProgress.start( nOverallRange ); - - for ( SubDocuments::const_iterator doc = m_aSubDocs.begin(); - doc != m_aSubDocs.end(); - ++doc - ) + //---------------------------------------------------------------- + static const ::rtl::OUString& lcl_getScriptsSubStorageName( const ScriptType _eType ) { - sal_Int32 nOverallProgressValue( doc - m_aSubDocs.begin() + 1 ); - // update overall progress text - ::rtl::OUString sOverallProgress( sProgressSkeleton ); - ::comphelper::string::searchAndReplaceAsciiI( sOverallProgress, "$current$", ::rtl::OUString::valueOf( nOverallProgressValue ) ); - m_rProgress.setOverallProgressText( sOverallProgress ); + static const ::rtl::OUString s_sBeanShell ( RTL_CONSTASCII_USTRINGPARAM( "beanshell" ) ); + static const ::rtl::OUString s_sJavaScript( RTL_CONSTASCII_USTRINGPARAM( "javascript" ) ); + static const ::rtl::OUString s_sPython ( RTL_CONSTASCII_USTRINGPARAM( "python" ) ); // TODO: is this correct? + static const ::rtl::OUString s_sJava ( RTL_CONSTASCII_USTRINGPARAM( "java" ) ); - // migrate document - if ( !impl_handleDocument_nothrow( *doc ) ) - return false; + switch ( _eType ) + { + case eBeanShell: return s_sBeanShell; + case eJavaScript: return s_sJavaScript; + case ePython: return s_sPython; + case eJava: return s_sJava; + default: + break; + } - // update overall progress vallue - m_rProgress.setOverallProgressValue( nOverallProgressValue ); + OSL_ENSURE( false, "lcl_getScriptsSubStorageName: illegal type!" ); + static ::rtl::OUString s_sEmpty; + return s_sEmpty; } - return true; - } - - //-------------------------------------------------------------------- - namespace - { - size_t lcl_collectHierarchicalElementNames_throw( - const Reference< XNameAccess >& _rxContainer, const ::rtl::OUString& _rContainerLoc, - SubDocuments& _out_rDocs, const SubDocumentType _eType ) + //---------------------------------------------------------------- + static bool lcl_getScriptTypeFromLanguage( const ::rtl::OUString& _rLanguage, ScriptType& _out_rScriptType ) { - size_t nAddedElements = 0; - - const ::rtl::OUString sHierarhicalBase( - _rContainerLoc.getLength() ? ::rtl::OUStringBuffer( _rContainerLoc ).appendAscii( "/" ).makeStringAndClear() - : ::rtl::OUString() ); - - Sequence< ::rtl::OUString > aElementNames( _rxContainer->getElementNames() ); - for ( const ::rtl::OUString* elementName = aElementNames.getConstArray(); - elementName != aElementNames.getConstArray() + aElementNames.getLength(); - ++elementName - ) + struct LanguageMapping { - Any aElement( _rxContainer->getByName( *elementName ) ); - ::rtl::OUString sElementName( ::rtl::OUStringBuffer( sHierarhicalBase ).append( *elementName ) ); + const sal_Char* pAsciiLanguage; + const ScriptType eScriptType; - Reference< XNameAccess > xSubContainer( aElement, UNO_QUERY ); - if ( xSubContainer.is() ) + LanguageMapping( const sal_Char* _pAsciiLanguage, const ScriptType _eScriptType ) + :pAsciiLanguage( _pAsciiLanguage ) + ,eScriptType( _eScriptType ) { - nAddedElements += lcl_collectHierarchicalElementNames_throw( xSubContainer, sElementName, _out_rDocs, _eType ); } - else + } + aLanguageMapping[] = + { + LanguageMapping( "JavaScript", eJavaScript ), + LanguageMapping( "BeanShell", eBeanShell ), + LanguageMapping( "Java", eJava ), + LanguageMapping( "Python", ePython ), // TODO: is this correct? + LanguageMapping( "Basic", eBasic ) + }; + for ( size_t i=0; i < sizeof( aLanguageMapping ) / sizeof( aLanguageMapping[0] ); ++i ) + { + if ( _rLanguage.equalsAscii( aLanguageMapping[i].pAsciiLanguage ) ) { - Reference< XCommandProcessor > xCommandProcessor( aElement, UNO_QUERY ); - OSL_ENSURE( xCommandProcessor.is(), "lcl_collectHierarchicalElementNames_throw: no container, and no comand processor? What *is* it, then?!" ); - if ( xCommandProcessor.is() ) - { - _out_rDocs.push_back( SubDocument( xCommandProcessor, sElementName, _eType ) ); - ++nAddedElements; - } + _out_rScriptType = aLanguageMapping[i].eScriptType; + return true; } } - return nAddedElements; + OSL_ENSURE( false, "lcl_getScriptTypeFromLanguage: unknown language!" ); + return false; } - } - - //-------------------------------------------------------------------- - bool MigrationEngine_Impl::impl_collectSubDocuments_nothrow() - { - try - { - ::rtl::OUString sRootLocation; - - Reference< XFormDocumentsSupplier > xSuppForms( m_xDocument, UNO_QUERY_THROW ); - Reference< XNameAccess > xDocContainer( xSuppForms->getFormDocuments(), UNO_SET_THROW ); - m_nFormCount = lcl_collectHierarchicalElementNames_throw( xDocContainer, sRootLocation, m_aSubDocs, eForm ); - Reference< XReportDocumentsSupplier > xSuppReports( m_xDocument, UNO_QUERY_THROW ); - xDocContainer.set( xSuppReports->getReportDocuments(), UNO_SET_THROW ); - m_nReportCount = lcl_collectHierarchicalElementNames_throw( xDocContainer, sRootLocation, m_aSubDocs, eReport ); - } - catch( const Exception& ) + //---------------------------------------------------------------- + ::rtl::OUString lcl_getSubDocumentDescription( const SubDocument& _rDocument ) { - // TODO: check whether we can handle this error - DBG_UNHANDLED_EXCEPTION(); - return false; + ::rtl::OUString sObjectName = String( MacroMigrationResId( _rDocument.eType == eForm ? STR_FORM : STR_REPORT ) ); + ::comphelper::string::searchAndReplaceAsciiI( sObjectName, "$name$", _rDocument.sHierarchicalName ); + return sObjectName; } - return true; - } - - //-------------------------------------------------------------------- - namespace - { - //................................................................ - static void lcl_disposeComponent_nothrow( const Reference< XCommandProcessor >& _rxCommandProc ) + //---------------------------------------------------------------- + static Any lcl_executeCommand_throw( const Reference< XCommandProcessor >& _rxCommandProc, + const sal_Char* _pAsciiCommand ) { - OSL_PRECOND( _rxCommandProc.is(), "lcl_disposeComponent_nothrow: illegal object!" ); + OSL_PRECOND( _rxCommandProc.is(), "lcl_executeCommand_throw: illegal object!" ); if ( !_rxCommandProc.is() ) - return; + return Any(); - bool bCouldClose = false; - try - { - Command aCommand; - aCommand.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "shutdown" ) ); - OSL_VERIFY( _rxCommandProc->execute( - aCommand, _rxCommandProc->createCommandIdentifier(), NULL ) >>= bCouldClose ); - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } - if ( !bCouldClose ) - { - ; - // TODO: can we handle this somehow? - } + Command aCommand; + aCommand.Name = ::rtl::OUString::createFromAscii( _pAsciiCommand ); + return _rxCommandProc->execute( + aCommand, _rxCommandProc->createCommandIdentifier(), NULL ); } - //................................................................ - static Reference< XModel > lcl_loadSubDocument_nothrow( const SubDocument& _rDocument, - const Reference< XStatusIndicator >& _rxProgress ) + //---------------------------------------------------------------- + static bool lcl_loadSubDocument_nothrow( SubDocument& _rDocument, + const Reference< XStatusIndicator >& _rxProgress, MigrationLog& _rLogger ) { - Reference< XModel > xDocument; + OSL_PRECOND( !_rDocument.xDocument.is(), "lcl_loadSubDocument_nothrow: already loaded!" ); try { @@ -338,66 +288,1493 @@ namespace dbmm ); OSL_ENSURE( xDocComponent.is(), "lcl_loadSubDocument_nothrow: no component loaded!" ); - xDocument.set( xDocComponent, UNO_QUERY_THROW ); + _rDocument.xDocument.set( xDocComponent, UNO_QUERY_THROW ); } catch( const Exception& ) { - // TODO: how to proceed? - DBG_UNHANDLED_EXCEPTION(); + _rLogger.logFailure( MigrationError( + ERR_OPENING_SUB_DOCUMENT_FAILED, + lcl_getSubDocumentDescription( _rDocument ), + ::cppu::getCaughtException() + ) ); } - - return xDocument; + return _rDocument.xDocument.is(); } - } - //-------------------------------------------------------------------- - bool MigrationEngine_Impl::impl_handleDocument_nothrow( const SubDocument& _rDocument ) const - { - DocumentID nDocID = m_rLogger.startedDocument( _rDocument.eType, _rDocument.sHierarchicalName ); + //---------------------------------------------------------------- + static bool lcl_unloadSubDocument_nothrow( SubDocument& _rDocument, MigrationLog& _rLogger ) + { + bool bSuccess = false; + Any aException; + try + { + OSL_VERIFY( lcl_executeCommand_throw( _rDocument.xCommandProcessor, "close" ) >>= bSuccess ); + } + catch( const Exception& ) + { + aException = ::cppu::getCaughtException(); + } - // start the progress - ::rtl::OUString aProgress; - aProgress = String( MacroMigrationResId( _rDocument.eType == eForm ? STR_FORM : STR_REPORT ) ); - ::comphelper::string::searchAndReplaceAsciiI( aProgress, "$name$", _rDocument.sHierarchicalName ); - m_rProgress.startObject( aProgress, ::rtl::OUString(), DEFAULT_DOC_PROGRESS_RANGE ); + // log the failure, if any + if ( !bSuccess ) + { + _rLogger.logFailure( MigrationError( + ERR_CLOSING_SUB_DOCUMENT_FAILED, + lcl_getSubDocumentDescription( _rDocument ), + aException + ) ); + } - // load the document - ::rtl::Reference< ProgressCapture > pStatusIndicator( new ProgressCapture( aProgress, m_rProgress ) ); - Reference< XModel > xDocument( lcl_loadSubDocument_nothrow( _rDocument, pStatusIndicator.get() ) ); - if ( !xDocument.is() ) + _rDocument.xDocument.clear(); + return bSuccess; + } + + //---------------------------------------------------------------- + bool lcl_commitStorage_nothrow( const Reference< XStorage >& _rxStorage ) { - pStatusIndicator->dispose(); - m_rProgress.endObject(); - m_rLogger.finishedDocument( nDocID, false ); - // TODO: log the *reason* for the failure - return false; + try + { + Reference< XTransactedObject > xTrans( _rxStorage, UNO_QUERY_THROW ); + xTrans->commit(); + } + catch( const Exception& ) + { + return false; + } + return true; } - // TODO + //---------------------------------------------------------------- + bool lcl_commitDocumentStorage_nothrow( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger ) + { + bool bSuccess = false; + Any aException; + try + { + Reference< XStorageBasedDocument > xStorageDoc( _rxDocument, UNO_QUERY_THROW ); + Reference< XStorage > xDocStorage( xStorageDoc->getDocumentStorage(), UNO_QUERY_THROW ); + bSuccess = lcl_commitStorage_nothrow( xDocStorage ); + } + catch( const Exception& ) + { + aException = ::cppu::getCaughtException(); + } + + // log the failure, if any + if ( !bSuccess ) + { + _rLogger.logFailure( MigrationError( + ERR_STORAGE_COMMIT_FAILED, + ::comphelper::DocumentInfo::getDocumentTitle( _rxDocument ), + aException + ) ); + } + return bSuccess; + } - // clean up - lcl_disposeComponent_nothrow( _rDocument.xCommandProcessor ); - pStatusIndicator->dispose(); + //---------------------------------------------------------------- + bool lcl_storeDocument_nothrow( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger ) + { + bool bSuccess = false; + Any aException; + try + { + Reference< XStorable > xStorable( _rxDocument, UNO_QUERY_THROW ); + xStorable->store(); + bSuccess = true; + } + catch( const Exception& ) + { + aException = ::cppu::getCaughtException(); + } - // end the progress, just in case the ProgressCapture didn't receive the XStatusIndicator::end event - m_rProgress.endObject(); + // log the failure, if any + if ( !bSuccess ) + { + _rLogger.logFailure( MigrationError( + ERR_STORING_DATABASEDOC_FAILED, + aException + ) ); + } + return bSuccess; + } - m_rLogger.finishedDocument( nDocID, true ); - return true; + //---------------------------------------------------------------- + bool lcl_storeEmbeddedDocument_nothrow( const SubDocument& _rDocument ) + { + try + { + lcl_executeCommand_throw( _rDocument.xCommandProcessor, "store" ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + return false; + } + return true; + } } - //-------------------------------------------------------------------- - void MigrationEngine_Impl::impl_reportError_nothrow( const Any& _rError ) const + //==================================================================== + //= DrawPageIterator + //==================================================================== + class DrawPageIterator + { + public: + DrawPageIterator( const Reference< XModel >& _rxDocument ) + :m_xDocument( _rxDocument ) + ,m_nPageCount( 0 ) + ,m_nCurrentPage( 0 ) + { + Reference< XDrawPageSupplier > xSingle( _rxDocument, UNO_QUERY ); + Reference< XDrawPagesSupplier > xMulti( _rxDocument, UNO_QUERY ); + if ( xSingle.is() ) + { + m_xSinglePage.set( xSingle->getDrawPage(), UNO_SET_THROW ); + m_nPageCount = 1; + } + else if ( xMulti.is() ) + { + m_xMultiPages.set( xMulti->getDrawPages(), UNO_SET_THROW ); + m_nPageCount = m_xMultiPages->getCount(); + } + } + + bool hasMore() const + { + return m_nCurrentPage < m_nPageCount; + } + + Reference< XDrawPage > next() + { + Reference< XDrawPage > xNextPage; + + if ( m_xSinglePage.is() ) + { + xNextPage = m_xSinglePage; + } + else if ( m_xMultiPages.is() ) + { + xNextPage.set( m_xMultiPages->getByIndex( m_nCurrentPage ), UNO_QUERY_THROW ); + } + ++m_nCurrentPage; + return xNextPage; + } + + private: + const Reference< XModel > m_xDocument; + Reference< XDrawPage > m_xSinglePage; + Reference< XDrawPages > m_xMultiPages; + sal_Int32 m_nPageCount; + sal_Int32 m_nCurrentPage; + }; + + //==================================================================== + //= FormComponentScripts + //==================================================================== + class FormComponentScripts { - DocumentErrorHandling::reportError( m_aContext, m_xDocument, _rError ); + public: + FormComponentScripts( + const Reference< XInterface >& _rxComponent, + const Reference< XEventAttacherManager >& _rxManager, + const sal_Int32 _nIndex + ) + :m_xComponent( _rxComponent, UNO_SET_THROW ) + ,m_xManager( _rxManager, UNO_SET_THROW ) + ,m_nIndex( _nIndex ) + { + } + + Sequence< ScriptEventDescriptor > getEvents() const + { + return m_xManager->getScriptEvents( m_nIndex ); + } + + void setEvents( const Sequence< ScriptEventDescriptor >& _rEvents ) const + { + m_xManager->registerScriptEvents( m_nIndex, _rEvents ); + } + + const Reference< XInterface >& getComponent() const + { + return m_xComponent; + } + + private: + const Reference< XInterface > m_xComponent; + const Reference< XEventAttacherManager > m_xManager; + const sal_Int32 m_nIndex; + }; + + //==================================================================== + //= FormComponentIterator + //==================================================================== + class FormComponentIterator + { + public: + FormComponentIterator( const Reference< XIndexAccess >& _rxContainer ) + :m_xContainer( _rxContainer, UNO_SET_THROW ) + ,m_xEventManager( _rxContainer, UNO_QUERY_THROW ) + ,m_nElementCount( _rxContainer->getCount() ) + ,m_nCurrentElement( 0 ) + { + } + + bool hasMore() const + { + return m_nCurrentElement < m_nElementCount; + } + + FormComponentScripts next() + { + FormComponentScripts aComponent( + Reference< XInterface >( m_xContainer->getByIndex( m_nCurrentElement ), UNO_QUERY_THROW ), + m_xEventManager, + m_nCurrentElement + ); + ++m_nCurrentElement; + return aComponent; + } + + private: + const Reference< XIndexAccess > m_xContainer; + const Reference< XEventAttacherManager > m_xEventManager; + const sal_Int32 m_nElementCount; + sal_Int32 m_nCurrentElement; + + }; + + //==================================================================== + //= ScriptsStorage - declaration + //==================================================================== + /** a helper class which encapsulates access to the storages for Java/Script, BeanShell, and Python scripts, + i.e. all script types which can be manipulated on storage level. + */ + class ScriptsStorage + { + public: + ScriptsStorage( MigrationLog& _rLogger ); + ScriptsStorage( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger ); + ~ScriptsStorage(); + + /** determines whether the instance is valid, i.e. refers to a valid root storage + for reading/storing scripts + */ + inline bool isValid() const { return m_xScriptsStorage.is(); } + + /** binds the instance to a new document. Only to be called when the instance is not yet + bound (i.e. isValid returns ). + */ + void bind( const Reference< XModel >& _rxDocument ); + + /// determines whether scripts of the given type are present + bool hasScripts( const ScriptType _eType ) const; + + /// returns the root storage for the scripts of the given type + SharedStorage + getScriptsRoot( const ScriptType _eType ) const; + + /** returns the names of the elements in the "Scripts" storage + */ + ::std::set< ::rtl::OUString > + getElementNames() const; + + /** removes the sub storage for a given script type + @precond + the respective storage is empty + @precond + the ScriptsStorage instance was opened for writing + */ + void removeScriptTypeStorage( const ScriptType _eType ) const; + + /** commits the changes at our XStorage object + */ + bool commit(); + + /** removes the "Scripts" sub storage from the given document's root storage + @precond + the "Scripts" storage is empty + */ + static bool + removeFromDocument( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger ); + + private: + MigrationLog& m_rLogger; + SharedStorage m_xScriptsStorage; + }; + + //==================================================================== + //= ScriptsStorage - implementation + //==================================================================== + //-------------------------------------------------------------------- + ScriptsStorage::ScriptsStorage( MigrationLog& _rLogger ) + :m_rLogger( _rLogger ) + ,m_xScriptsStorage() + { + } + + //-------------------------------------------------------------------- + ScriptsStorage::ScriptsStorage( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger ) + :m_rLogger( _rLogger ) + ,m_xScriptsStorage() + { + bind( _rxDocument ); + } + + //-------------------------------------------------------------------- + ScriptsStorage::~ScriptsStorage() + { + } + + //-------------------------------------------------------------------- + bool ScriptsStorage::commit() + { + return lcl_commitStorage_nothrow( m_xScriptsStorage ); + } + + //-------------------------------------------------------------------- + void ScriptsStorage::bind( const Reference< XModel >& _rxDocument ) + { + OSL_PRECOND( !isValid(), "ScriptsStorage:bind: did not bother, yet, to check whether this is allowed!" ); + try + { + Reference< XStorageBasedDocument > xStorageDoc( _rxDocument, UNO_QUERY_THROW ); + Reference< XStorage > xDocStorage( xStorageDoc->getDocumentStorage(), UNO_QUERY_THROW ); + + // the the "Scripts" storage exist, or if it does not (yet) exist and we are in write mode + // => open the storage + if ( ( xDocStorage->hasByName( lcl_getScriptsStorageName() ) + && xDocStorage->isStorageElement( lcl_getScriptsStorageName() ) + ) + || !xDocStorage->hasByName( lcl_getScriptsStorageName() ) + ) + { + m_xScriptsStorage.set( + xDocStorage->openStorageElement( + lcl_getScriptsStorageName(), ElementModes::READWRITE + ), + UNO_QUERY_THROW + ); + } + } + catch( const Exception& ) + { + m_rLogger.logFailure( MigrationError( + ERR_BIND_SCRIPT_STORAGE_FAILED, + ::comphelper::DocumentInfo::getDocumentTitle( _rxDocument ), + ::cppu::getCaughtException() + ) ); + } + } + + //-------------------------------------------------------------------- + bool ScriptsStorage::hasScripts( const ScriptType _eType ) const + { + OSL_PRECOND( isValid(), "ScriptsStorage::hasScripts: illegal call!" ); + if ( !isValid() ) + return false; + + const ::rtl::OUString& rSubStorageName( lcl_getScriptsSubStorageName( _eType ) ); + return m_xScriptsStorage->hasByName( rSubStorageName ) + && m_xScriptsStorage->isStorageElement( rSubStorageName ); + } + + //-------------------------------------------------------------------- + SharedStorage ScriptsStorage::getScriptsRoot( const ScriptType _eType ) const + { + SharedStorage xStorage; + if ( isValid() ) + { + xStorage.reset( m_xScriptsStorage->openStorageElement( + lcl_getScriptsSubStorageName( _eType ), ElementModes::READWRITE + ) ); + } + return xStorage; + } + + //-------------------------------------------------------------------- + ::std::set< ::rtl::OUString > ScriptsStorage::getElementNames() const + { + Sequence< ::rtl::OUString > aElementNames; + if ( isValid() ) + aElementNames = m_xScriptsStorage->getElementNames(); + + ::std::set< ::rtl::OUString > aNames; + ::std::copy( + aElementNames.getConstArray(), + aElementNames.getConstArray() + aElementNames.getLength(), + ::std::insert_iterator< ::std::set< ::rtl::OUString > >( aNames, aNames.end() ) + ); + return aNames; + } + + //-------------------------------------------------------------------- + void ScriptsStorage::removeScriptTypeStorage( const ScriptType _eType ) const + { + ::rtl::OUString sSubStorageName( lcl_getScriptsSubStorageName( _eType ) ); + if ( m_xScriptsStorage->hasByName( sSubStorageName ) ) + m_xScriptsStorage->removeElement( sSubStorageName ); + } + + //-------------------------------------------------------------------- + bool ScriptsStorage::removeFromDocument( const Reference< XModel >& _rxDocument, MigrationLog& _rLogger ) + { + try + { + Reference< XStorageBasedDocument > xStorageDoc( _rxDocument, UNO_QUERY_THROW ); + Reference< XStorage > xDocStorage( xStorageDoc->getDocumentStorage(), UNO_QUERY_THROW ); + xDocStorage->removeElement( lcl_getScriptsStorageName() ); + } + catch( const Exception& ) + { + _rLogger.logFailure( MigrationError( + ERR_REMOVE_SCRIPTS_STORAGE_FAILED, + ::comphelper::DocumentInfo::getDocumentTitle( _rxDocument ), + ::cppu::getCaughtException() + ) ) ; + return false; + } + return true; + } + + //==================================================================== + //= ProgressDelegator + //==================================================================== + class ProgressDelegator : public IProgressConsumer + { + public: + ProgressDelegator( IMigrationProgress& _rDelegator, + const ::rtl::OUString& _rObjectName, + const ::rtl::OUString& _rAction + ) + :m_rDelegator( _rDelegator ) + ,m_sObjectName( _rObjectName ) + ,m_sAction( _rAction ) + { + } + virtual ~ProgressDelegator() + { + } + + // IProgressConsumer + virtual void start( sal_uInt32 _nRange ) + { + m_rDelegator.startObject( m_sObjectName, m_sAction, _nRange ); + } + virtual void advance( sal_uInt32 _nValue ) + { + m_rDelegator.setObjectProgressValue( _nValue ); + } + virtual void end() + { + m_rDelegator.endObject(); + } + + private: + IMigrationProgress& m_rDelegator; + ::rtl::OUString m_sObjectName; + ::rtl::OUString m_sAction; + }; + + //==================================================================== + //= PhaseGuard + //==================================================================== + class PhaseGuard + { + public: + PhaseGuard( ProgressMixer& _rMixer ) + :m_rMixer( _rMixer ) + { + } + + PhaseGuard( ProgressMixer& _rMixer, const PhaseID _nID, const sal_uInt32 _nPhaseRange ) + :m_rMixer( _rMixer ) + { + start( _nID, _nPhaseRange ); + } + + ~PhaseGuard() + { + m_rMixer.endPhase(); + } + + void start( const PhaseID _nID, const sal_uInt32 _nPhaseRange ) + { + m_rMixer.startPhase( _nID, _nPhaseRange ); + } + + private: + ProgressMixer& m_rMixer; + }; + + //==================================================================== + //= MigrationEngine_Impl - declaration + //==================================================================== + class MigrationEngine_Impl + { + public: + MigrationEngine_Impl( + const ::comphelper::ComponentContext& _rContext, + const Reference< XOfficeDatabaseDocument >& _rxDocument, + IMigrationProgress& _rProgress, + MigrationLog& _rLogger + ); + ~MigrationEngine_Impl(); + + inline sal_Int32 getFormCount() const { return m_nFormCount; } + inline sal_Int32 getReportCount()const { return m_nReportCount; } + bool migrateAll(); + + private: + ::comphelper::ComponentContext m_aContext; + const Reference< XOfficeDatabaseDocument > m_xDocument; + const Reference< XModel > m_xDocumentModel; + IMigrationProgress& m_rProgress; + MigrationLog& m_rLogger; + mutable DocumentID m_nCurrentDocumentID; + SubDocuments m_aSubDocs; + size_t m_nFormCount; + size_t m_nReportCount; + + private: + /** collects a description of all sub documents of our database document + + @return + if and only if collecting the documents was successful + */ + bool impl_collectSubDocuments_nothrow(); + + /** migrates the macros/scripts of the given sub document + */ + bool impl_handleDocument_nothrow( const SubDocument& _rDocument ) const; + + /** checks the structure of the 'Scripts' folder of a sub document + for unknown elements + + @return + if and only if the 'Scripts' folder contains known elements only. + */ + bool impl_checkScriptStorageStructure_nothrow( const SubDocument& _rDocument ) const; + + /** migrates the scripts of the given "storage-based" script type + */ + bool impl_migrateScriptStorage_nothrow( + const SubDocument& _rDocument, + const ScriptType _eScriptType, + ProgressMixer& _rProgress, + const PhaseID _nPhaseID + ) const; + + /** migrates the content of the given "container based" libraries (Basic/Dialogs) + */ + bool impl_migrateContainerLibraries_nothrow( + const SubDocument& _rDocument, + const ScriptType _eScriptType, + ProgressMixer& _rProgress, + const PhaseID _nPhaseID + ) const; + + /** adjust the document-events which refer to macros/scripts in the document, taking into + account the new names of the moved libraries + */ + bool impl_adjustDocumentEvents_nothrow( + const SubDocument& _rDocument + ) const; + + /** adjusts the script references bound to form component events + */ + bool impl_adjustFormComponentEvents_nothrow( + const SubDocument& _rDocument + ) const; + + /** adjusts the script references for the elements of the given form component container + */ + void impl_adjustFormComponentEvents_throw( + const Reference< XIndexAccess >& _rxComponentContainer + ) const; + + /** adjusts the library name in the given script URL, so that it reflects + the new name of the library + + @return + if and only if adjustments to the script code have been made + */ + bool impl_adjustScriptLibrary_nothrow( + const ::rtl::OUString& _rScriptType, + ::rtl::OUString& _inout_rScriptCode + ) const; + + bool impl_adjustScriptLibrary_nothrow( Any& _inout_rScriptDescriptor ) const; + bool impl_adjustScriptLibrary_nothrow( ScriptEventDescriptor& _inout_rScriptEvent ) const; + + /** asks the user for a password for the given library, and unprotects the library + + @return + if and only if the library could be successfully unprotected + */ + bool impl_unprotectPasswordLibrary_throw( + const Reference< XLibraryContainerPassword >& _rxPasswordManager, + const ScriptType _eScriptType, + const ::rtl::OUString& _rLibraryName + ) const; + }; + + //==================================================================== + //= MigrationEngine_Impl - implementation + //==================================================================== + //-------------------------------------------------------------------- + MigrationEngine_Impl::MigrationEngine_Impl( const ::comphelper::ComponentContext& _rContext, + const Reference< XOfficeDatabaseDocument >& _rxDocument, IMigrationProgress& _rProgress, MigrationLog& _rLogger ) + :m_aContext( _rContext ) + ,m_xDocument( _rxDocument ) + ,m_xDocumentModel( _rxDocument, UNO_QUERY_THROW ) + ,m_rProgress( _rProgress ) + ,m_rLogger( _rLogger ) + ,m_nCurrentDocumentID( - 1 ) + ,m_aSubDocs() + ,m_nFormCount( 0 ) + ,m_nReportCount( 0 ) + { + OSL_VERIFY( impl_collectSubDocuments_nothrow() ); + } + + //-------------------------------------------------------------------- + MigrationEngine_Impl::~MigrationEngine_Impl() + { + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::migrateAll() + { + if ( m_aSubDocs.empty() ) + { + OSL_ENSURE( false, "MigrationEngine_Impl::migrateAll: no forms/reports found!" ); + // The whole migration wizard is not expected to be called when there are no forms/reports + // with macros, not to mention when there are no forms/reports at all. + return false; + } + + // initialize global progress + sal_Int32 nOverallRange( m_aSubDocs.size() ); + String sProgressSkeleton = String( MacroMigrationResId( STR_OVERALL_PROGRESS ) ); + sProgressSkeleton.SearchAndReplaceAscii( "$overall$", String::CreateFromInt32( nOverallRange ) ); + + m_rProgress.start( nOverallRange ); + + for ( SubDocuments::const_iterator doc = m_aSubDocs.begin(); + doc != m_aSubDocs.end(); + ++doc + ) + { + sal_Int32 nOverallProgressValue( doc - m_aSubDocs.begin() + 1 ); + // update overall progress text + ::rtl::OUString sOverallProgress( sProgressSkeleton ); + ::comphelper::string::searchAndReplaceAsciiI( sOverallProgress, "$current$", ::rtl::OUString::valueOf( nOverallProgressValue ) ); + m_rProgress.setOverallProgressText( sOverallProgress ); + + // migrate document + if ( !impl_handleDocument_nothrow( *doc ) ) + return false; + + // update overall progress vallue + m_rProgress.setOverallProgressValue( nOverallProgressValue ); + } + + // commit the root storage of the database document, for all changes made so far to take effect + if ( !lcl_commitDocumentStorage_nothrow( m_xDocumentModel, m_rLogger ) ) + return false; + + // save the document + if ( !lcl_storeDocument_nothrow( m_xDocumentModel, m_rLogger ) ) + return false; + + return true; + } + + //-------------------------------------------------------------------- + namespace + { + size_t lcl_collectHierarchicalElementNames_throw( + const Reference< XNameAccess >& _rxContainer, const ::rtl::OUString& _rContainerLoc, + SubDocuments& _out_rDocs, const SubDocumentType _eType ) + { + size_t nAddedElements = 0; + + const ::rtl::OUString sHierarhicalBase( + _rContainerLoc.getLength() ? ::rtl::OUStringBuffer( _rContainerLoc ).appendAscii( "/" ).makeStringAndClear() + : ::rtl::OUString() ); + + Sequence< ::rtl::OUString > aElementNames( _rxContainer->getElementNames() ); + for ( const ::rtl::OUString* elementName = aElementNames.getConstArray(); + elementName != aElementNames.getConstArray() + aElementNames.getLength(); + ++elementName + ) + { + Any aElement( _rxContainer->getByName( *elementName ) ); + ::rtl::OUString sElementName( ::rtl::OUStringBuffer( sHierarhicalBase ).append( *elementName ) ); + + Reference< XNameAccess > xSubContainer( aElement, UNO_QUERY ); + if ( xSubContainer.is() ) + { + nAddedElements += lcl_collectHierarchicalElementNames_throw( xSubContainer, sElementName, _out_rDocs, _eType ); + } + else + { + Reference< XCommandProcessor > xCommandProcessor( aElement, UNO_QUERY ); + OSL_ENSURE( xCommandProcessor.is(), "lcl_collectHierarchicalElementNames_throw: no container, and no comand processor? What *is* it, then?!" ); + if ( xCommandProcessor.is() ) + { + _out_rDocs.push_back( SubDocument( xCommandProcessor, sElementName, _eType ) ); + ++nAddedElements; + } + } + } + return nAddedElements; + } + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_collectSubDocuments_nothrow() + { + OSL_PRECOND( m_xDocument.is(), "MigrationEngine_Impl::impl_collectSubDocuments_nothrow: invalid document!" ); + if ( !m_xDocument.is() ) + return false; + + try + { + Reference< XNameAccess > xDocContainer( m_xDocument->getFormDocuments(), UNO_SET_THROW ); + m_nFormCount = lcl_collectHierarchicalElementNames_throw( xDocContainer, ::rtl::OUString(), m_aSubDocs, eForm ); + + xDocContainer.set( m_xDocument->getReportDocuments(), UNO_SET_THROW ); + m_nReportCount = lcl_collectHierarchicalElementNames_throw( xDocContainer, ::rtl::OUString(), m_aSubDocs, eReport ); + } + catch( const Exception& ) + { + m_rLogger.logFailure( MigrationError( + ERR_COLLECTING_DOCUMENTS_FAILED, + ::cppu::getCaughtException() + ) ); + return false; + } + return true; + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_handleDocument_nothrow( const SubDocument& _rDocument ) const + { + OSL_ENSURE( m_nCurrentDocumentID == -1, + "MigrationEngine_Impl::impl_handleDocument_nothrow: there already is a current document!"); + m_nCurrentDocumentID = m_rLogger.startedDocument( _rDocument.eType, _rDocument.sHierarchicalName ); + + // start the progress + ::rtl::OUString sObjectName( lcl_getSubDocumentDescription( _rDocument ) ); + m_rProgress.startObject( sObjectName, ::rtl::OUString(), DEFAULT_DOC_PROGRESS_RANGE ); + + // ----------------- + // load the document + ::rtl::Reference< ProgressCapture > pStatusIndicator( new ProgressCapture( sObjectName, m_rProgress ) ); + SubDocument aSubDocument( _rDocument ); + if ( !lcl_loadSubDocument_nothrow( aSubDocument, pStatusIndicator.get(), m_rLogger ) ) + { + pStatusIndicator->dispose(); + m_rProgress.endObject(); + m_rLogger.finishedDocument( m_nCurrentDocumentID ); + m_nCurrentDocumentID = -1; + return false; + } + + // ----------------- + // migrate the libraries + ProgressDelegator aDelegator( m_rProgress, sObjectName, String( MacroMigrationResId( STR_MIGRATING_LIBS ) ) ); + ProgressMixer aProgressMixer( aDelegator ); + aProgressMixer.registerPhase( PHASE_JAVASCRIPT, 1 ); + aProgressMixer.registerPhase( PHASE_BEANSHELL, 1 ); + aProgressMixer.registerPhase( PHASE_PYTHON, 1 ); + aProgressMixer.registerPhase( PHASE_JAVA, 1 ); + aProgressMixer.registerPhase( PHASE_BASIC, 5 ); + // more weight than then others, assuming that usually, there are much more Basic macros than any other scripts + aProgressMixer.registerPhase( PHASE_DIALOGS, 1 ); + + bool bSuccess = impl_checkScriptStorageStructure_nothrow( aSubDocument ); + + // migrate storage-based script libraries (which can be handled by mere storage operations) + bSuccess = bSuccess + && impl_migrateScriptStorage_nothrow( aSubDocument, eJavaScript, aProgressMixer, PHASE_JAVASCRIPT ) + && impl_migrateScriptStorage_nothrow( aSubDocument, eBeanShell, aProgressMixer, PHASE_BEANSHELL ) + && impl_migrateScriptStorage_nothrow( aSubDocument, ePython, aProgressMixer, PHASE_PYTHON ) + && impl_migrateScriptStorage_nothrow( aSubDocument, eJava, aProgressMixer, PHASE_JAVA ); + + // migrate Basic and dialog libraries + bSuccess = bSuccess + && impl_migrateContainerLibraries_nothrow( aSubDocument, eBasic, aProgressMixer, PHASE_BASIC ) + && impl_migrateContainerLibraries_nothrow( aSubDocument, eDialog, aProgressMixer, PHASE_DIALOGS ); + + // adjust the events in the document + // (note that errors are ignored here - failure to convert a script reference + // is not considered a critical error) + if ( bSuccess ) + { + impl_adjustDocumentEvents_nothrow( aSubDocument ); + impl_adjustFormComponentEvents_nothrow( aSubDocument ); + } + + // ----------------- + // clean up + // store the sub document, including removal of the (now obsolete) "Scripts" sub folder + bSuccess = bSuccess + && ScriptsStorage::removeFromDocument( aSubDocument.xDocument, m_rLogger ) + && lcl_commitDocumentStorage_nothrow( aSubDocument.xDocument, m_rLogger ) + && lcl_storeEmbeddedDocument_nothrow( aSubDocument ); + + // unload in any case, even if we were not successful + bSuccess = lcl_unloadSubDocument_nothrow( aSubDocument, m_rLogger ) + && bSuccess; + + pStatusIndicator->dispose(); + + // end the progress, just in case the ProgressCapture didn't receive the XStatusIndicator::end event + m_rProgress.endObject(); + + m_rLogger.finishedDocument( m_nCurrentDocumentID ); + m_nCurrentDocumentID = -1; + return bSuccess; + } + + //-------------------------------------------------------------------- + namespace + { + static ::rtl::OUString lcl_createTargetLibName( const SubDocument& _rDocument, + const ::rtl::OUString& _rSourceLibName, const Reference< XNameAccess >& _rxTargetStorage ) + { + // a prefix denoting the type + const ::rtl::OUString sPrefix( ::rtl::OUString::createFromAscii( _rDocument.eType == eForm ? "Form_" : "Report_" ) ); + + ::rtl::OUStringBuffer aBuffer; + aBuffer.append( sPrefix ); + + // first try with the base name of the sub document + aBuffer.append( _rDocument.sHierarchicalName.copy( + _rDocument.sHierarchicalName.lastIndexOf( '/' ) + 1 ) ); + aBuffer.appendAscii( "_" ); + aBuffer.append( _rSourceLibName ); + ::rtl::OUString sTargetName( aBuffer.makeStringAndClear() ); + if ( !_rxTargetStorage->hasByName( sTargetName ) ) + return sTargetName; + + // if this name is already used (which is valid, since documents with the same base + // name can exist in different logical folders), then use the complete name + aBuffer.append( sPrefix ); + aBuffer.append( ::comphelper::string::searchAndReplaceAllAsciiWithAscii( + _rDocument.sHierarchicalName, "/", "_" ) ); + aBuffer.appendAscii( "_" ); + aBuffer.append( _rSourceLibName ); + return aBuffer.makeStringAndClear(); + + } + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_checkScriptStorageStructure_nothrow( const SubDocument& _rDocument ) const + { + OSL_PRECOND( _rDocument.xDocument.is(), "MigrationEngine_Impl::impl_checkScriptStorageStructure_nothrow: invalid document!" ); + if ( !_rDocument.xDocument.is() ) + return false; + + try + { + // the root storage of the document whose scripts are to be migrated + ScriptsStorage aDocStorage( _rDocument.xDocument, m_rLogger ); + if ( !aDocStorage.isValid() ) + { // no scripts at all, or no scripts of the given type + return !m_rLogger.hadFailure(); + } + ::std::set< ::rtl::OUString > aElementNames( aDocStorage.getElementNames() ); + + ScriptType aKnownStorageBasedTypes[] = { + eBeanShell, eJavaScript, ePython, eJava + }; + for ( size_t i=0; i aStorageElements( xScriptsRoot->getElementNames() ); + aPhase.start( _nPhaseID, aStorageElements.getLength() ); + + for ( const ::rtl::OUString* element = aStorageElements.getConstArray(); + element != aStorageElements.getConstArray() + aStorageElements.getLength(); + ++element + ) + { + bool bIsScriptLibrary = xScriptsRoot->isStorageElement( *element ); + OSL_ENSURE( bIsScriptLibrary, + "MigrationEngine_Impl::impl_migrateScriptStorage_nothrow: warning: unknown scripts storage structure!" ); + // we cannot handle this. We would need to copy this stream to the respective scripts storage + // of the database document, but we cannot guarantee that the name is not used, yet, and we cannot + // simply rename the thing. + if ( !bIsScriptLibrary ) + { + m_rLogger.logFailure( MigrationError( + ERR_UNEXPECTED_LIBSTORAGE_ELEMENT, + lcl_getSubDocumentDescription( _rDocument ), + getScriptTypeDisplayName( _eScriptType ), + *element + ) ); + return false; + } + + // ensure we have access to the DBDoc's scripts storage + if ( !aDatabaseScripts.isValid() ) + { // not needed 'til now + aDatabaseScripts.bind( m_xDocumentModel ); + if ( aDatabaseScripts.isValid() ) + xTargetStorage = aDatabaseScripts.getScriptsRoot( _eScriptType ); + + if ( !xTargetStorage.is() ) + { + m_rLogger.logFailure( MigrationError( + ERR_CREATING_DBDOC_SCRIPT_STORAGE_FAILED, + getScriptTypeDisplayName( _eScriptType ) + ) ); + return false; + } + } + + // move the library to the DBDoc's scripts library, under the new name + ::rtl::OUString sNewLibName( lcl_createTargetLibName( _rDocument, *element, xTargetStorage.getTyped().get() ) ); + xScriptsRoot->moveElementTo( *element, xTargetStorage, sNewLibName ); + + // log the fact that we moved the library + m_rLogger.movedLibrary( m_nCurrentDocumentID, _eScriptType, *element, sNewLibName ); + + // progress + _rProgress.advancePhase( element - aStorageElements.getConstArray() ); + } + + // commit the storages, so the changes we made persist + if ( !lcl_commitStorage_nothrow( xScriptsRoot ) + || ( xTargetStorage.is() && !lcl_commitStorage_nothrow( xTargetStorage ) ) + ) + { + m_rLogger.logFailure( MigrationError( + ERR_COMMITTING_SCRIPT_STORAGES_FAILED, + lcl_getSubDocumentDescription( _rDocument ), + getScriptTypeDisplayName( _eScriptType ) + ) ); + return false; + } + + // now that the concrete scripts storage does not have any elements anymore, + // remove it + xScriptsRoot.reset( NULL ); // need to reset the storage to be allowed to remove it + aDocStorage.removeScriptTypeStorage( _eScriptType ); + + // done so far + bSuccess = aDocStorage.commit() + && aDatabaseScripts.commit(); + } + catch( const Exception& ) + { + aException = ::cppu::getCaughtException(); + bSuccess = false; + } + + // log the error, if any + if ( !bSuccess ) + { + m_rLogger.logFailure( MigrationError( + ERR_GENERAL_SCRIPT_MIGRATION_FAILURE, + lcl_getSubDocumentDescription( _rDocument ), + getScriptTypeDisplayName( _eScriptType ), + aException + ) ); + } + + return bSuccess; + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_migrateContainerLibraries_nothrow( const SubDocument& _rDocument, + const ScriptType _eScriptType, ProgressMixer& _rProgress, const PhaseID _nPhaseID ) const + { + OSL_PRECOND( ( _eScriptType == eBasic ) || ( _eScriptType == eDialog ), + "MigrationEngine_Impl::impl_migrateContainerLibraries_nothrow: illegal script type!" ); + + bool bSuccess = false; + PhaseGuard aPhase( _rProgress ); + Any aException; + do // artificial loop for flow control only + { + try + { + // access library container of the sub document + Reference< XEmbeddedScripts > xSubDocScripts( _rDocument.xDocument, UNO_QUERY ); + if ( !xSubDocScripts.is() ) + { // no script support in the sub document -> nothing to migrate + // (though ... this is suspicious, at least ...) + bSuccess = true; + break; + } + + Reference< XStorageBasedLibraryContainer > xSourceLibraries( + _eScriptType == eBasic ? xSubDocScripts->getBasicLibraries() : xSubDocScripts->getDialogLibraries(), + UNO_QUERY_THROW + ); + Reference< XLibraryContainerPassword > xSourcePasswords( xSourceLibraries, UNO_QUERY ); + OSL_ENSURE( xSourcePasswords.is(), + "MigrationEngine_Impl::impl_migrateContainerLibraries_nothrow: suspicious: no password management for the source libraries!" ); + + Sequence< ::rtl::OUString > aSourceLibNames( xSourceLibraries->getElementNames() ); + aPhase.start( _nPhaseID, aSourceLibNames.getLength() ); + + if ( !xSourceLibraries->hasElements() ) + { + bSuccess = true; + break; + } + + // create library containers for the document - those will be the target for the migration + Reference< XStorageBasedDocument > xStorageDoc( m_xDocument, UNO_QUERY_THROW ); + Reference< XStorageBasedLibraryContainer > xTargetLibraries; + if ( _eScriptType == eBasic ) + { + xTargetLibraries.set( DocumentScriptLibraryContainer::create( + m_aContext.getUNOContext(), xStorageDoc ), UNO_QUERY_THROW ); + } + else + { + xTargetLibraries.set( DocumentDialogLibraryContainer::create( + m_aContext.getUNOContext(), xStorageDoc ), UNO_QUERY_THROW ); + } + + // copy all libs to the target, with potentially renaming them + const ::rtl::OUString* pSourceLibBegin = aSourceLibNames.getConstArray(); + const ::rtl::OUString* pSourceLibEnd = pSourceLibBegin + aSourceLibNames.getLength(); + for ( const ::rtl::OUString* pSourceLibName = pSourceLibBegin; + pSourceLibName != pSourceLibEnd; + ++pSourceLibName + ) + { + // if the library is password-protected, ask the user to unprotect it + if ( xSourcePasswords.is() + && xSourcePasswords->isLibraryPasswordProtected( *pSourceLibName ) + && !xSourcePasswords->isLibraryPasswordVerified( *pSourceLibName ) + ) + { + if ( !impl_unprotectPasswordLibrary_throw( xSourcePasswords, _eScriptType, *pSourceLibName ) ) + { + m_rLogger.logFailure( MigrationError( + ERR_PASSWORD_VERIFICATION_FAILED, + _rDocument.sHierarchicalName, + getScriptTypeDisplayName( _eScriptType ), + *pSourceLibName + ) ); + return false; + } + } + + ::rtl::OUString sNewLibName( lcl_createTargetLibName( _rDocument, *pSourceLibName, xTargetLibraries.get() ) ); + + if ( xSourceLibraries->isLibraryLink( *pSourceLibName ) ) + { + // just re-create the link in the target library + xTargetLibraries->createLibraryLink( + sNewLibName, + xSourceLibraries->getLibraryLinkURL( *pSourceLibName ), + xSourceLibraries->isLibraryReadOnly( *pSourceLibName ) + ); + } + else + { + if ( !xSourceLibraries->isLibraryLoaded( *pSourceLibName ) ) + xSourceLibraries->loadLibrary( *pSourceLibName ); + + // copy the content of this particular libary + Reference< XNameAccess > xSourceLib( xSourceLibraries->getByName( *pSourceLibName ), UNO_QUERY_THROW ); + Reference< XNameContainer > xTargetLib( xTargetLibraries->createLibrary( sNewLibName ), UNO_QUERY_THROW ); + + Sequence< ::rtl::OUString > aLibElementNames( xSourceLib->getElementNames() ); + for ( const ::rtl::OUString* pSourceElementName = aLibElementNames.getConstArray(); + pSourceElementName != aLibElementNames.getConstArray() + aLibElementNames.getLength(); + ++pSourceElementName + ) + { + Any aElement = xSourceLib->getByName( *pSourceElementName ); + OSL_ENSURE( aElement.hasValue(), + "MigrationEngine_Impl::impl_migrateContainerLibraries_nothrow: invalid (empty) lib element!" ); + xTargetLib->insertByName( *pSourceElementName, aElement ); + } + + // transfer the read-only flag + xTargetLibraries->setLibraryReadOnly( + sNewLibName, xSourceLibraries->isLibraryReadOnly( *pSourceLibName ) ); + } + + // remove the source lib + xSourceLibraries->removeLibrary( *pSourceLibName ); + + // tell the logger + m_rLogger.movedLibrary( m_nCurrentDocumentID, _eScriptType, *pSourceLibName, sNewLibName ); + + // tell the progress + _rProgress.advancePhase( pSourceLibName - pSourceLibBegin ); + } + + // clean up + xSourceLibraries->storeLibraries(); + + xTargetLibraries->storeLibraries(); + Reference< XStorage > xTargetRoot( xTargetLibraries->getRootLocation(), UNO_QUERY_THROW ); + bSuccess = lcl_commitStorage_nothrow( xTargetRoot ); + } + catch( const Exception& ) + { + aException = ::cppu::getCaughtException(); + bSuccess = false; + } + } while ( false ); + + // log the error, if any + if ( !bSuccess ) + { + m_rLogger.logFailure( MigrationError( + ERR_GENERAL_MACRO_MIGRATION_FAILURE, + lcl_getSubDocumentDescription( _rDocument ), + aException + ) ); + } + + return bSuccess; + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow( const ::rtl::OUString& _rScriptType, + ::rtl::OUString& _inout_rScriptCode ) const + { + OSL_PRECOND( _inout_rScriptCode.getLength(), "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: invalid script!" ); + if ( !_inout_rScriptCode.getLength() ) + return false; + + bool bSuccess = false; + Any aException; + try + { + if ( !_rScriptType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Script" ) ) + || !_rScriptType.getLength() + ) + { + OSL_ENSURE( false, + "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: no or unknown script type!" ); + m_rLogger.logRecoverable( MigrationError( + ERR_UNKNOWN_SCRIPT_TYPE, + _rScriptType + ) ); + return false; + } + + // analyze the script URI + Reference< XUriReferenceFactory > xUriRefFac = UriReferenceFactory::create( m_aContext.getUNOContext() ); + Reference< XVndSunStarScriptUrlReference > xUri( xUriRefFac->parse( _inout_rScriptCode ), UNO_QUERY_THROW ); + + ::rtl::OUString sScriptLanguage = xUri->getParameter( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "language" ) ) ); + ScriptType eScriptType = eBasic; + if ( !lcl_getScriptTypeFromLanguage( sScriptLanguage, eScriptType ) ) + { + OSL_ENSURE( false, + "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: unknown script language!" ); + m_rLogger.logRecoverable( MigrationError( + ERR_UNKNOWN_SCRIPT_LANGUAGE, + sScriptLanguage + ) ); + return false; + } + + ::rtl::OUString sLocation = xUri->getParameter( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "location" ) ) ); + if ( !sLocation.equalsAscii( "document" ) ) + { + // only document libraries must be migrated, of course + return false; + } + + ::rtl::OUString sScriptName = xUri->getName(); + sal_Int32 nLibModuleSeparator = sScriptName.indexOf( '.' ); + if ( nLibModuleSeparator < 0 ) + { + OSL_ENSURE( false, + "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: invalid/unknown location format!" ); + m_rLogger.logRecoverable( MigrationError( + ERR_UNKNOWN_SCRIPT_NAME_FORMAT, + sScriptName + ) ); + return false; + } + + // replace the library name + ::rtl::OUString sLibrary = sScriptName.copy( 0, nLibModuleSeparator ); + ::rtl::OUString sNewLibName = m_rLogger.getNewLibraryName( + m_nCurrentDocumentID, eScriptType, sLibrary ); + OSL_ENSURE( sLibrary != sNewLibName, + "MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow: a library which has not been migrated?" ); + + ::rtl::OUStringBuffer aNewLocation; + aNewLocation.append( sNewLibName ); + aNewLocation.append( sScriptName.copy( nLibModuleSeparator ) ); + xUri->setName( aNewLocation.makeStringAndClear() ); + + // update the new script URL + _inout_rScriptCode = xUri->getUriReference(); + bSuccess = true; + } + catch( const Exception& ) + { + aException = ::cppu::getCaughtException(); + bSuccess = false; + } + + // log the failure, if any + if ( !bSuccess ) + { + m_rLogger.logRecoverable( MigrationError( + ERR_SCRIPT_TRANSLATION_FAILURE, + _rScriptType, + _inout_rScriptCode, + aException + ) ); + } + + return bSuccess; + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow( ScriptEventDescriptor& _inout_rScriptEvent ) const + { + if ( _inout_rScriptEvent.ScriptType.getLength() && _inout_rScriptEvent.ScriptCode.getLength() ) + return impl_adjustScriptLibrary_nothrow( _inout_rScriptEvent.ScriptType, _inout_rScriptEvent.ScriptCode ); + return false; + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_adjustScriptLibrary_nothrow( Any& _inout_rScriptDescriptor ) const + { + ::comphelper::NamedValueCollection aScriptDesc( _inout_rScriptDescriptor ); + + ::rtl::OUString sScriptType; + ::rtl::OUString sScript; + try + { + OSL_VERIFY( aScriptDesc.get_ensureType( "EventType", sScriptType ) ); + OSL_VERIFY( aScriptDesc.get_ensureType( "Script", sScript ) ); + } + catch( const Exception& ) + { + m_rLogger.logRecoverable( MigrationError( + ERR_INVALID_SCRIPT_DESCRIPTOR_FORMAT, + ::cppu::getCaughtException() + ) ); + } + + if ( sScriptType.getLength() && sScript.getLength() ) + if ( !impl_adjustScriptLibrary_nothrow( sScriptType, sScript ) ) + return false; + + aScriptDesc.put( "Script", sScript ); + _inout_rScriptDescriptor <<= aScriptDesc.getPropertyValues(); + return true; + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_adjustDocumentEvents_nothrow( const SubDocument& _rDocument ) const + { + try + { + Reference< XEventsSupplier > xSuppEvents( _rDocument.xDocument, UNO_QUERY ); + if ( !xSuppEvents.is() ) + // this is allowed. E.g. new-style reports currently do not support this + return true; + + Reference< XNameReplace > xEvents( xSuppEvents->getEvents(), UNO_SET_THROW ); + Sequence< ::rtl::OUString > aEventNames = xEvents->getElementNames(); + + Any aEvent; + for ( const ::rtl::OUString* eventName = aEventNames.getConstArray(); + eventName != aEventNames.getConstArray() + aEventNames.getLength(); + ++eventName + ) + { + aEvent = xEvents->getByName( *eventName ); + if ( !aEvent.hasValue() ) + continue; + + // translate + if ( !impl_adjustScriptLibrary_nothrow( aEvent ) ) + continue; + + // put back + xEvents->replaceByName( *eventName, aEvent ); + } + } + catch( const Exception& ) + { + m_rLogger.logRecoverable( MigrationError( + ERR_ADJUSTING_DOCUMENT_EVENTS_FAILED, + lcl_getSubDocumentDescription( _rDocument ), + ::cppu::getCaughtException() + ) ); + return false; + } + return true; + } + + //-------------------------------------------------------------------- + void MigrationEngine_Impl::impl_adjustFormComponentEvents_throw( const Reference< XIndexAccess >& _rxComponentContainer ) const + { + FormComponentIterator aCompIter( _rxComponentContainer ); + while ( aCompIter.hasMore() ) + { + // 1. adjust the component's scripts of the current component + FormComponentScripts aComponent( aCompIter.next() ); + Sequence< ScriptEventDescriptor > aEvents( aComponent.getEvents() ); + + bool bChangedComponentEvents = false; + for ( ScriptEventDescriptor* scriptEvent = aEvents.getArray(); + scriptEvent != aEvents.getArray() + aEvents.getLength(); + ++scriptEvent + ) + { + if ( !impl_adjustScriptLibrary_nothrow( *scriptEvent ) ) + continue; + + bChangedComponentEvents = true; + } + + if ( bChangedComponentEvents ) + aComponent.setEvents( aEvents ); + + // 2. step down if the component is a container itself + Reference< XIndexAccess > xContainer( aComponent.getComponent(), UNO_QUERY ); + if ( xContainer.is() ) + impl_adjustFormComponentEvents_throw( xContainer ); + } + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_adjustFormComponentEvents_nothrow( const SubDocument& _rDocument ) const + { + try + { + DrawPageIterator aPageIter( _rDocument.xDocument ); + while ( aPageIter.hasMore() ) + { + Reference< XFormsSupplier > xSuppForms( aPageIter.next(), UNO_QUERY_THROW ); + Reference< XIndexAccess > xForms( xSuppForms->getForms(), UNO_QUERY_THROW ); + impl_adjustFormComponentEvents_throw( xForms ); + } + } + catch( const Exception& ) + { + m_rLogger.logRecoverable( MigrationError( + ERR_ADJUSTING_FORMCOMP_EVENTS_FAILED, + lcl_getSubDocumentDescription( _rDocument ), + ::cppu::getCaughtException() + ) ); + return false; + } + return true; + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_unprotectPasswordLibrary_throw( const Reference< XLibraryContainerPassword >& _rxPasswordManager, + const ScriptType _eScriptType, const ::rtl::OUString& _rLibraryName ) const + { + // a human-readable description of the affected library + ::rtl::OUString sLibraryDescription( String( + MacroMigrationResId( STR_LIBRARY_TYPE_AND_NAME ) ) ); + ::comphelper::string::searchAndReplaceAsciiI( sLibraryDescription, "$type$", + getScriptTypeDisplayName( _eScriptType ) ); + ::comphelper::string::searchAndReplaceAsciiI( sLibraryDescription, "$library$", + _rLibraryName ); + + InteractionHandler aHandler( m_aContext, m_xDocumentModel ); + ::rtl::OUString sPassword; + while ( true ) + { + if ( !aHandler.requestDocumentPassword( sLibraryDescription, sPassword ) ) + // aborted by the user + return false; + + bool bSuccessVerification = _rxPasswordManager->verifyLibraryPassword( _rLibraryName, sPassword ); + if ( bSuccessVerification ) + return true; + } + + return false; } //==================================================================== //= MigrationEngine //==================================================================== //-------------------------------------------------------------------- - MigrationEngine::MigrationEngine( const ::comphelper::ComponentContext& _rContext, const Reference< XOfficeDatabaseDocument >& _rxDocument, - IMigrationProgress& _rProgress, MigrationLog& _rLogger ) + MigrationEngine::MigrationEngine( const ::comphelper::ComponentContext& _rContext, + const Reference< XOfficeDatabaseDocument >& _rxDocument, IMigrationProgress& _rProgress, + MigrationLog& _rLogger ) :m_pImpl( new MigrationEngine_Impl( _rContext, _rxDocument, _rProgress, _rLogger ) ) { } diff --git a/dbaccess/source/ext/macromigration/migrationerror.hxx b/dbaccess/source/ext/macromigration/migrationerror.hxx new file mode 100644 index 000000000000..ce5bcabb23f2 --- /dev/null +++ b/dbaccess/source/ext/macromigration/migrationerror.hxx @@ -0,0 +1,162 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2008 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* $RCSfile: migrationerror.hxx,v $ +* +* $Revision: 1.1.2.3 $ +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* +* for a copy of the LGPLv3 License. +************************************************************************/ + +#ifndef DBACCESS_MIGRATIONERROR_HXX +#define DBACCESS_MIGRATIONERROR_HXX + +/** === begin UNO includes === **/ +#include +/** === end UNO includes === **/ + +#include + +//........................................................................ +namespace dbmm +{ +//........................................................................ + + enum MigrationErrorType + { + ERR_OPENING_SUB_DOCUMENT_FAILED = 1, + ERR_CLOSING_SUB_DOCUMENT_FAILED, + ERR_STORAGE_COMMIT_FAILED, + ERR_STORING_DATABASEDOC_FAILED, + ERR_COLLECTING_DOCUMENTS_FAILED, + ERR_UNEXPECTED_LIBSTORAGE_ELEMENT, + ERR_CREATING_DBDOC_SCRIPT_STORAGE_FAILED, + ERR_COMMITTING_SCRIPT_STORAGES_FAILED, + ERR_GENERAL_SCRIPT_MIGRATION_FAILURE, + ERR_GENERAL_MACRO_MIGRATION_FAILURE, + ERR_UNKNOWN_SCRIPT_TYPE, + ERR_UNKNOWN_SCRIPT_LANGUAGE, + ERR_UNKNOWN_SCRIPT_NAME_FORMAT, + ERR_SCRIPT_TRANSLATION_FAILURE, + ERR_INVALID_SCRIPT_DESCRIPTOR_FORMAT, + ERR_ADJUSTING_DOCUMENT_EVENTS_FAILED, + ERR_ADJUSTING_FORMCOMP_EVENTS_FAILED, + ERR_BIND_SCRIPT_STORAGE_FAILED, + ERR_REMOVE_SCRIPTS_STORAGE_FAILED, + ERR_DOCUMENT_BACKUP_FAILED, + ERR_UNKNOWN_SCRIPT_FOLDER, + ERR_EXAMINING_SCRIPTS_FOLDER_FAILED, + ERR_PASSWORD_VERIFICATION_FAILED + }; + + //==================================================================== + //= MigrationError + //==================================================================== + /** encapsulates information about an error which happened during the migration + */ + struct MigrationError + { + const MigrationErrorType eType; + ::std::vector< ::rtl::OUString > aErrorDetails; + const ::com::sun::star::uno::Any aCaughtException; + + MigrationError( + const MigrationErrorType _eType ) + :eType( _eType ) + { + } + + MigrationError( + const MigrationErrorType _eType, + const ::com::sun::star::uno::Any& _rCaughtException ) + :eType( _eType ) + ,aCaughtException( _rCaughtException ) + { + } + + MigrationError( + const MigrationErrorType _eType, + const ::rtl::OUString& _rDetail ) + :eType( _eType ) + { + impl_constructDetails( _rDetail ); + } + + MigrationError( + const MigrationErrorType _eType, + const ::rtl::OUString& _rDetail, + const ::com::sun::star::uno::Any& _rCaughtException ) + :eType( _eType ) + ,aCaughtException( _rCaughtException ) + { + impl_constructDetails( _rDetail ); + } + + MigrationError( + const MigrationErrorType _eType, + const ::rtl::OUString& _rDetail1, + const ::rtl::OUString& _rDetail2 ) + :eType( _eType ) + { + impl_constructDetails( _rDetail1, _rDetail2 ); + } + + MigrationError( + const MigrationErrorType _eType, + const ::rtl::OUString& _rDetail1, + const ::rtl::OUString& _rDetail2, + const ::com::sun::star::uno::Any& _rCaughtException ) + :eType( _eType ) + ,aCaughtException( _rCaughtException ) + { + impl_constructDetails( _rDetail1, _rDetail2 ); + } + + MigrationError( + const MigrationErrorType _eType, + const ::rtl::OUString& _rDetail1, + const ::rtl::OUString& _rDetail2, + const ::rtl::OUString& _rDetail3 ) + :eType( _eType ) + { + impl_constructDetails( _rDetail1, _rDetail2, _rDetail3 ); + } + + private: + void impl_constructDetails( + const ::rtl::OUString& _rDetail1, + const ::rtl::OUString& _rDetail2 = ::rtl::OUString(), + const ::rtl::OUString& _rDetail3 = ::rtl::OUString() + ) + { + if ( _rDetail1.getLength() ) aErrorDetails.push_back( _rDetail1 ); + if ( _rDetail2.getLength() ) aErrorDetails.push_back( _rDetail2 ); + if ( _rDetail3.getLength() ) aErrorDetails.push_back( _rDetail3 ); + } + }; + +//........................................................................ +} // namespace dbmm +//........................................................................ + +#endif // DBACCESS_MIGRATIONERROR_HXX + diff --git a/dbaccess/source/ext/macromigration/migrationlog.cxx b/dbaccess/source/ext/macromigration/migrationlog.cxx index ff6bcd1e0bbe..4c94bc0a45de 100644 --- a/dbaccess/source/ext/macromigration/migrationlog.cxx +++ b/dbaccess/source/ext/macromigration/migrationlog.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: migrationlog.cxx,v $ - * $Revision: 1.4 $ + * $Revision: 1.4.2.8 $ * * This file is part of OpenOffice.org. * @@ -33,16 +33,20 @@ #include "dbmm_module.hxx" #include "dbmm_global.hrc" +#include "migrationerror.hxx" #include "migrationlog.hxx" /** === begin UNO includes === **/ /** === end UNO includes === **/ +#include +#include #include #include #include #include +#include //........................................................................ namespace dbmm @@ -84,20 +88,17 @@ namespace dbmm SubDocumentType eType; ::rtl::OUString sName; ::std::vector< LibraryEntry > aMovedLibraries; - bool bSuccess; DocumentEntry() :eType( eForm ) ,sName() ,aMovedLibraries() - ,bSuccess( false ) { } DocumentEntry( const SubDocumentType _eType, const ::rtl::OUString& _rName ) :eType( _eType ) ,sName( _rName ) - ,bSuccess( false ) { } }; @@ -107,6 +108,11 @@ namespace dbmm //==================================================================== typedef ::std::map< DocumentID, DocumentEntry > DocumentLogs; + //==================================================================== + //= ErrorLog + //==================================================================== + typedef ::std::list< MigrationError > ErrorLog; + //==================================================================== //= MigrationLog_Data //==================================================================== @@ -114,6 +120,8 @@ namespace dbmm { ::rtl::OUString sBackupLocation; DocumentLogs aDocumentLogs; + ErrorLog aFailures; + ErrorLog aWarnings; }; //==================================================================== @@ -130,6 +138,24 @@ namespace dbmm { } + //-------------------------------------------------------------------- + void MigrationLog::logFailure( const MigrationError& _rError ) + { + m_pData->aFailures.push_back( _rError ); + } + + //-------------------------------------------------------------------- + void MigrationLog::logRecoverable( const MigrationError& _rError ) + { + m_pData->aWarnings.push_back( _rError ); + } + + //-------------------------------------------------------------------- + bool MigrationLog::hadFailure() const + { + return !m_pData->aFailures.empty(); + } + //-------------------------------------------------------------------- void MigrationLog::backedUpDocument( const ::rtl::OUString& _rNewDocumentLocation ) { @@ -172,13 +198,14 @@ namespace dbmm } //-------------------------------------------------------------------- - void MigrationLog::finishedDocument( const DocumentID _nDocID, const bool _bSuccessful ) + void MigrationLog::finishedDocument( const DocumentID _nDocID ) { OSL_ENSURE( m_pData->aDocumentLogs.find( _nDocID ) != m_pData->aDocumentLogs.end(), "MigrationLog::finishedDocument: document is not known!" ); DocumentEntry& rDocEntry = m_pData->aDocumentLogs[ _nDocID ]; - rDocEntry.bSuccess = _bSuccessful; + (void)rDocEntry; + // nothing to do here } //-------------------------------------------------------------------- @@ -213,21 +240,180 @@ namespace dbmm //-------------------------------------------------------------------- namespace { - String lcl_getScriptTypeDisplayName( const ScriptType _eType ) + //---------------------------------------------------------------- + static void lcl_appendErrorDescription( ::rtl::OUStringBuffer& _inout_rBuffer, const MigrationError& _rError ) + { + const sal_Char* pAsciiErrorDescription( NULL ); + ::std::vector< const sal_Char* > aAsciiParameterNames; + switch ( _rError.eType ) + { + case ERR_OPENING_SUB_DOCUMENT_FAILED: + pAsciiErrorDescription = "opening '#name#' failed"; + aAsciiParameterNames.push_back( "#name#" ); + break; + + case ERR_CLOSING_SUB_DOCUMENT_FAILED: + pAsciiErrorDescription = "closing '#name#' failed"; + aAsciiParameterNames.push_back( "#name#" ); + break; + + case ERR_STORAGE_COMMIT_FAILED: + pAsciiErrorDescription = "committing the changes for document '#name#' failed"; + aAsciiParameterNames.push_back( "#name#" ); + break; + + case ERR_STORING_DATABASEDOC_FAILED: + pAsciiErrorDescription = "storing the database document failed"; + break; + + case ERR_COLLECTING_DOCUMENTS_FAILED: + pAsciiErrorDescription = "collecting the forms/reports of the database document failed"; + break; + + case ERR_UNEXPECTED_LIBSTORAGE_ELEMENT: + pAsciiErrorDescription = "unexpected #lib# storage element in document '#doc#', named '#element#'"; + aAsciiParameterNames.push_back( "#doc#" ); + aAsciiParameterNames.push_back( "#libstore#" ); + aAsciiParameterNames.push_back( "#element#" ); + break; + + case ERR_CREATING_DBDOC_SCRIPT_STORAGE_FAILED: + pAsciiErrorDescription = "creating the database document's storage for #scripttype# scripts failed"; + aAsciiParameterNames.push_back( "#scripttype#" ); + break; + + case ERR_COMMITTING_SCRIPT_STORAGES_FAILED: + pAsciiErrorDescription = "saving the #scripttype# scripts for document '#doc#' failed"; + aAsciiParameterNames.push_back( "#scripttype#" ); + aAsciiParameterNames.push_back( "#doc#" ); + break; + + case ERR_GENERAL_SCRIPT_MIGRATION_FAILURE: + pAsciiErrorDescription = "general error during migrationg #scripttype# scripts of document '#doc#'"; + aAsciiParameterNames.push_back( "#scripttype#" ); + aAsciiParameterNames.push_back( "#doc#" ); + break; + + case ERR_GENERAL_MACRO_MIGRATION_FAILURE: + pAsciiErrorDescription = "general error during macro migration of document '#doc#'"; + aAsciiParameterNames.push_back( "#doc#" ); + break; + + case ERR_UNKNOWN_SCRIPT_TYPE: + pAsciiErrorDescription = "unknown script type: #type#"; + aAsciiParameterNames.push_back( "#type#" ); + break; + + case ERR_UNKNOWN_SCRIPT_LANGUAGE: + pAsciiErrorDescription = "unknown script language: #lang#"; + aAsciiParameterNames.push_back( "#lang#" ); + break; + + case ERR_UNKNOWN_SCRIPT_NAME_FORMAT: + pAsciiErrorDescription = "unknown script name format: #script#"; + aAsciiParameterNames.push_back( "#script#" ); + break; + + case ERR_SCRIPT_TRANSLATION_FAILURE: + pAsciiErrorDescription = "analyzing/translating the script URL failed; script type: #type#; script: #code#"; + aAsciiParameterNames.push_back( "#type#" ); + aAsciiParameterNames.push_back( "#code#" ); + break; + + case ERR_INVALID_SCRIPT_DESCRIPTOR_FORMAT: + pAsciiErrorDescription = "invalid script descriptor format"; + break; + + case ERR_ADJUSTING_DOCUMENT_EVENTS_FAILED: + pAsciiErrorDescription = "adjusting events for document #doc# failed"; + aAsciiParameterNames.push_back( "#doc#" ); + break; + + case ERR_ADJUSTING_FORMCOMP_EVENTS_FAILED: + pAsciiErrorDescription = "adjusting form component events for '#doc#' failed"; + aAsciiParameterNames.push_back( "#doc#" ); + break; + + case ERR_BIND_SCRIPT_STORAGE_FAILED: + pAsciiErrorDescription = "binding to the script storage failed for document '#doc#'"; + aAsciiParameterNames.push_back( "#doc#" ); + break; + + case ERR_REMOVE_SCRIPTS_STORAGE_FAILED: + pAsciiErrorDescription = "removing a scripts storage failed for document '#doc#'"; + aAsciiParameterNames.push_back( "#doc#" ); + break; + + case ERR_DOCUMENT_BACKUP_FAILED: + pAsciiErrorDescription = "backing up the document to #location# failed"; + aAsciiParameterNames.push_back( "#location#" ); + break; + + case ERR_UNKNOWN_SCRIPT_FOLDER: + pAsciiErrorDescription = "unknown script folder '#name#' in document '#doc#'"; + aAsciiParameterNames.push_back( "#doc#" ); + aAsciiParameterNames.push_back( "#name#" ); + break; + + case ERR_EXAMINING_SCRIPTS_FOLDER_FAILED: + pAsciiErrorDescription = "examining the 'Scripts' folder failed for document '#doc#'"; + aAsciiParameterNames.push_back( "#doc#" ); + break; + + case ERR_PASSWORD_VERIFICATION_FAILED: + pAsciiErrorDescription = "password verification failed for document '#doc#', #libtype# library '#name#'"; + aAsciiParameterNames.push_back( "#doc#" ); + aAsciiParameterNames.push_back( "#libtype#" ); + aAsciiParameterNames.push_back( "#name#" ); + break; + + // do *not* add a default case here: Without a default, some compilers will warn you when + // you miss a newly-introduced enum value here + } + OSL_ENSURE( pAsciiErrorDescription, "lcl_appendErrorDescription: no error message!" ); + if ( pAsciiErrorDescription ) + { + ::rtl::OUString sSubstituted( ::rtl::OUString::createFromAscii( pAsciiErrorDescription ) ); + OSL_ENSURE( aAsciiParameterNames.size() == _rError.aErrorDetails.size(), + "lcl_appendErrorDescription: unexpected number of error message parameters!" ); + + for ( size_t i=0; i < ::std::min( aAsciiParameterNames.size(), _rError.aErrorDetails.size() ); ++i ) + { + ::comphelper::string::searchAndReplaceAsciiI( sSubstituted, aAsciiParameterNames[i], + _rError.aErrorDetails[i] ); + } + + _inout_rBuffer.append( sSubstituted ); + } + } + + //---------------------------------------------------------------- + void lcl_describeErrors( ::rtl::OUStringBuffer& _rBuffer, const ErrorLog& _rErrors, const USHORT _nHeadingResId ) { - USHORT nResId( 0 ); + _rBuffer.appendAscii( "=== " ); + _rBuffer.append ( String( MacroMigrationResId( _nHeadingResId ) ) ); + _rBuffer.appendAscii( " ===\n" ); - switch ( _eType ) + String sException( MacroMigrationResId( STR_EXCEPTION ) ); + + for ( ErrorLog::const_iterator error = _rErrors.begin(); + error != _rErrors.end(); + ++error + ) { - case eBasic: nResId = STR_OOO_BASIC; break; - case eBeanShell: nResId = STR_BEAN_SHELL; break; - case eJavaScript: nResId = STR_JAVA_SCRIPT; break; - case ePython: nResId = STR_PYTHON; break; - case eJava: nResId = STR_JAVA; break; - case eDialog: nResId = STR_DIALOG; break; + _rBuffer.append( sal_Unicode( '-' ) ); + _rBuffer.append( sal_Unicode( ' ' ) ); + lcl_appendErrorDescription( _rBuffer, *error ); + _rBuffer.append( sal_Unicode( '\n' ) ); + + if ( !error->aCaughtException.hasValue() ) + continue; + + _rBuffer.append( sException ); + _rBuffer.append( ::comphelper::anyToString( error->aCaughtException ) ); + _rBuffer.append( sal_Unicode( '\n' ) ); + _rBuffer.append( sal_Unicode( '\n' ) ); } - OSL_ENSURE( nResId != 0, "lcl_getScriptTypeDisplayName: illegal script type!" ); - return nResId ? String( MacroMigrationResId( nResId ) ) : String(); } } @@ -236,54 +422,65 @@ namespace dbmm { ::rtl::OUStringBuffer aBuffer; - String sBackedUp( MacroMigrationResId( STR_SAVED_COPY_TO ) ); - sBackedUp.SearchAndReplaceAllAscii( "$location$", m_pData->sBackupLocation ); - - aBuffer.appendAscii( "=== " ); - aBuffer.append ( String( MacroMigrationResId( STR_DATABASE_DOCUMENT ) ) ); - aBuffer.appendAscii( " ===\n" ); - aBuffer.append ( sBackedUp ); - aBuffer.appendAscii( "\n\n" ); - - String sMovedLibTemplate( MacroMigrationResId( STR_MOVED_LIBRARY ) ); - - for ( DocumentLogs::const_iterator doc = m_pData->aDocumentLogs.begin(); - doc != m_pData->aDocumentLogs.end(); - ++doc - ) + if ( m_pData->sBackupLocation.getLength() ) { - const DocumentEntry& rDoc( doc->second ); - - if ( rDoc.aMovedLibraries.empty() ) - continue; - - String sDocTitle( MacroMigrationResId( rDoc.eType == eForm ? STR_FORM : STR_REPORT ) ); - sDocTitle.SearchAndReplaceAllAscii( "$name$", rDoc.sName ); + String sBackedUp( MacroMigrationResId( STR_SAVED_COPY_TO ) ); + sBackedUp.SearchAndReplaceAllAscii( "$location$", m_pData->sBackupLocation ); aBuffer.appendAscii( "=== " ); - aBuffer.append ( sDocTitle ); + aBuffer.append ( String( MacroMigrationResId( STR_DATABASE_DOCUMENT ) ) ); aBuffer.appendAscii( " ===\n" ); + aBuffer.append ( sBackedUp ); + aBuffer.appendAscii( "\n\n" ); + } - for ( ::std::vector< LibraryEntry >::const_iterator lib = rDoc.aMovedLibraries.begin(); - lib != rDoc.aMovedLibraries.end(); - ++lib + if ( !m_pData->aFailures.empty() ) + { + lcl_describeErrors( aBuffer, m_pData->aFailures + , STR_ERRORS ); + } + else + { + String sMovedLibTemplate( MacroMigrationResId( STR_MOVED_LIBRARY ) ); + + for ( DocumentLogs::const_iterator doc = m_pData->aDocumentLogs.begin(); + doc != m_pData->aDocumentLogs.end(); + ++doc ) { - String sMovedLib( sMovedLibTemplate ); - sMovedLib.SearchAndReplaceAllAscii( "$type$", lcl_getScriptTypeDisplayName( lib->eType ) ); - sMovedLib.SearchAndReplaceAllAscii( "$old$", lib->sOldName ); - sMovedLib.SearchAndReplaceAllAscii( "$new$", lib->sNewName ); + const DocumentEntry& rDoc( doc->second ); - aBuffer.append ( sMovedLib ); - aBuffer.appendAscii( "\n" ); - } + if ( rDoc.aMovedLibraries.empty() ) + continue; - if ( !rDoc.bSuccess ) - { - // TODO + String sDocTitle( MacroMigrationResId( rDoc.eType == eForm ? STR_FORM : STR_REPORT ) ); + sDocTitle.SearchAndReplaceAllAscii( "$name$", rDoc.sName ); + + aBuffer.appendAscii( "=== " ); + aBuffer.append ( sDocTitle ); + aBuffer.appendAscii( " ===\n" ); + + for ( ::std::vector< LibraryEntry >::const_iterator lib = rDoc.aMovedLibraries.begin(); + lib != rDoc.aMovedLibraries.end(); + ++lib + ) + { + String sMovedLib( sMovedLibTemplate ); + sMovedLib.SearchAndReplaceAllAscii( "$type$", getScriptTypeDisplayName( lib->eType ) ); + sMovedLib.SearchAndReplaceAllAscii( "$old$", lib->sOldName ); + sMovedLib.SearchAndReplaceAllAscii( "$new$", lib->sNewName ); + + aBuffer.append( sMovedLib ); + aBuffer.append( sal_Unicode( '\n' ) ); + } + + aBuffer.append( sal_Unicode( '\n' ) ); } + } - aBuffer.appendAscii( "\n" ); + if ( !m_pData->aWarnings.empty() ) + { + lcl_describeErrors( aBuffer, m_pData->aWarnings, STR_WARNINGS ); } return aBuffer.makeStringAndClear(); diff --git a/dbaccess/source/ext/macromigration/migrationlog.hxx b/dbaccess/source/ext/macromigration/migrationlog.hxx index 38adbba98965..87e60bd68b53 100644 --- a/dbaccess/source/ext/macromigration/migrationlog.hxx +++ b/dbaccess/source/ext/macromigration/migrationlog.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: migrationlog.hxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.2 $ * * This file is part of OpenOffice.org. * @@ -46,6 +46,7 @@ namespace dbmm //........................................................................ typedef sal_Int16 DocumentID; + struct MigrationError; //==================================================================== //= MigrationLog @@ -60,6 +61,17 @@ namespace dbmm //---------------------------------------------------------------- //- event logging + /** logs an unrecoverable error during the migration process + */ + void logFailure( const MigrationError& _rError ); + + /** logs a recoverable (or at least ignorable) error during the migration process + */ + void logRecoverable( const MigrationError& _rError ); + + /// checks whether logFailure has been called + bool hadFailure() const; + /// logs the fact that the database document has been backed up void backedUpDocument( const ::rtl::OUString& _rNewDocumentLocation ); @@ -80,7 +92,7 @@ namespace dbmm /** logs that the migration for a certain document has been finished */ - void finishedDocument( const DocumentID _nDocID, const bool _bSuccessful ); + void finishedDocument( const DocumentID _nDocID ); //---------------------------------------------------------------- //- information retrieval diff --git a/dbaccess/source/ext/macromigration/migrationprogress.hxx b/dbaccess/source/ext/macromigration/migrationprogress.hxx index 33ac7c3238c2..8818010d8ea2 100644 --- a/dbaccess/source/ext/macromigration/migrationprogress.hxx +++ b/dbaccess/source/ext/macromigration/migrationprogress.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: migrationprogress.hxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.1 $ * * This file is part of OpenOffice.org. * @@ -40,7 +40,7 @@ namespace dbmm //........................................................................ //==================================================================== - //= MigrationProgress + //= IMigrationProgress //==================================================================== class SAL_NO_VTABLE IMigrationProgress { diff --git a/dbaccess/source/ext/macromigration/progressmixer.cxx b/dbaccess/source/ext/macromigration/progressmixer.cxx new file mode 100644 index 000000000000..a59e1a59b7fe --- /dev/null +++ b/dbaccess/source/ext/macromigration/progressmixer.cxx @@ -0,0 +1,218 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2008 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* $RCSfile: progressmixer.cxx,v $ +* +* $Revision: 1.1.2.1 $ +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* +* for a copy of the LGPLv3 License. +************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_dbaccess.hxx" + +#include "progressmixer.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +#include + +#include + +//........................................................................ +namespace dbmm +{ +//........................................................................ + + /** === begin UNO using === **/ + /** === end UNO using === **/ + +#define OVERALL_RANGE 100000 + + //==================================================================== + //= misc types + //==================================================================== + struct PhaseData + { + // the weight of the phase, relative to all other phases + PhaseWeight nWeight; + // the "local" range of the phase + sal_uInt32 nRange; + // this is the point in the "overall range" at which this phase starts + sal_uInt32 nGlobalStart; + /** the "global" range of the phase, i.e. its range after weighting with all other + phases + */ + sal_uInt32 nGlobalRange; + + PhaseData() + :nWeight(1) + ,nRange(100) + ,nGlobalStart(0) + ,nGlobalRange(100) + { + } + + PhaseData( const PhaseWeight _nWeight ) + :nWeight( _nWeight ) + ,nRange(100) + ,nGlobalStart(0) + ,nGlobalRange(100) + { + } + }; + + typedef ::std::map< PhaseID, PhaseData > Phases; + + //==================================================================== + //= ProgressMixer_Data + //==================================================================== + struct ProgressMixer_Data + { + Phases aPhases; + Phases::iterator pCurrentPhase; + sal_uInt32 nWeightSum; /// the cached sum of the weights + double nOverallStretch; + IProgressConsumer& rConsumer; + + ProgressMixer_Data( IProgressConsumer& _rConsumer ) + :aPhases() + ,pCurrentPhase( aPhases.end() ) + ,nWeightSum( 0 ) + ,nOverallStretch( 0 ) + ,rConsumer( _rConsumer ) + { + } + }; + + //-------------------------------------------------------------------- + namespace + { + //---------------------------------------------------------------- + bool lcl_isRunning( const ProgressMixer_Data& _rData ) + { + return _rData.pCurrentPhase != _rData.aPhases.end(); + } + + //---------------------------------------------------------------- + void lcl_ensureInitialized( ProgressMixer_Data& _rData ) + { + OSL_PRECOND( _rData.nWeightSum, "lcl_ensureInitialized: we have no phases, this will crash!" ); + + if ( _rData.nOverallStretch ) + return; + + _rData.nOverallStretch = 1.0 * OVERALL_RANGE / _rData.nWeightSum; + + // tell the single phases their "overall starting point" + PhaseWeight nRunningWeight( 0 ); + for ( Phases::iterator phase = _rData.aPhases.begin(); + phase != _rData.aPhases.end(); + ++phase + ) + { + phase->second.nGlobalStart = (sal_uInt32)( nRunningWeight * _rData.nOverallStretch ); + nRunningWeight += phase->second.nWeight; + + sal_uInt32 nNextPhaseStart = (sal_uInt32)( nRunningWeight * _rData.nOverallStretch ); + phase->second.nGlobalRange = nNextPhaseStart - phase->second.nGlobalStart; + } + + _rData.rConsumer.start( OVERALL_RANGE ); + } + } + + //==================================================================== + //= ProgressMixer + //==================================================================== + //-------------------------------------------------------------------- + ProgressMixer::ProgressMixer( IProgressConsumer& _rConsumer ) + :m_pData( new ProgressMixer_Data( _rConsumer ) ) + { + } + + //-------------------------------------------------------------------- + ProgressMixer::~ProgressMixer() + { + } + + //-------------------------------------------------------------------- + void ProgressMixer::registerPhase( const PhaseID _nID, const PhaseWeight _nWeight ) + { + OSL_PRECOND( !lcl_isRunning( *m_pData ), "ProgressMixer::registerPhase: already running!" ); + OSL_ENSURE( m_pData->aPhases.find( _nID ) == m_pData->aPhases.end(), + "ProgressMixer::registerPhase: ID already used!" ); + m_pData->aPhases[ _nID ] = PhaseData( _nWeight ); + m_pData->nWeightSum += _nWeight; + } + + //-------------------------------------------------------------------- + void ProgressMixer::startPhase( const PhaseID _nID, const sal_uInt32 _nPhaseRange ) + { + OSL_ENSURE( m_pData->aPhases.find( _nID ) != m_pData->aPhases.end(), + "ProgresMixer::startPhase: unknown phase!" ); + + m_pData->aPhases[ _nID ].nRange = _nPhaseRange; + m_pData->pCurrentPhase = m_pData->aPhases.find( _nID ); + } + + //-------------------------------------------------------------------- + void ProgressMixer::advancePhase( const sal_uInt32 _nPhaseProgress ) + { + OSL_PRECOND( lcl_isRunning( *m_pData ), "ProgresMixer::advancePhase: not running!" ); + + // in case this is the first call, ensure all the ranges/weights are calculated + // correctly + lcl_ensureInitialized( *m_pData ); + + const PhaseData& rPhase( m_pData->pCurrentPhase->second ); + + double nLocalProgress = 1.0 * _nPhaseProgress / rPhase.nRange; + sal_uInt32 nOverallProgress = (sal_uInt32) + ( rPhase.nGlobalStart + nLocalProgress * rPhase.nGlobalRange ); + + m_pData->rConsumer.advance( nOverallProgress ); + } + + //-------------------------------------------------------------------- + void ProgressMixer::endPhase() + { + OSL_PRECOND( lcl_isRunning( *m_pData ), "ProgresMixer::endPhase: not running!" ); + + // in case this is the first call, ensure all the ranges/weights are calculated + // correctly + lcl_ensureInitialized( *m_pData ); + + // simply assume the phase's complete range is over + advancePhase( m_pData->pCurrentPhase->second.nRange ); + + // if that's the last phase, this is the "global end", too + Phases::const_iterator pNextPhase( m_pData->pCurrentPhase ); + ++pNextPhase; + if ( pNextPhase == m_pData->aPhases.end() ) + m_pData->rConsumer.end(); + } + +//........................................................................ +} // namespace dbmm +//........................................................................ diff --git a/dbaccess/source/ext/macromigration/progressmixer.hxx b/dbaccess/source/ext/macromigration/progressmixer.hxx new file mode 100644 index 000000000000..291fdc331661 --- /dev/null +++ b/dbaccess/source/ext/macromigration/progressmixer.hxx @@ -0,0 +1,103 @@ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2008 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* $RCSfile: progressmixer.hxx,v $ +* +* $Revision: 1.1.2.1 $ +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* +* for a copy of the LGPLv3 License. +************************************************************************/ + +#ifndef DBACCESS_PROGRESSMIXER_HXX +#define DBACCESS_PROGRESSMIXER_HXX + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +#include + +#include + +//........................................................................ +namespace dbmm +{ +//........................................................................ + + typedef sal_uInt32 PhaseID; + typedef sal_uInt32 PhaseWeight; + + //==================================================================== + //= IProgressConsumer + //==================================================================== + class SAL_NO_VTABLE IProgressConsumer + { + public: + virtual void start( sal_uInt32 _nRange ) = 0; + virtual void advance( sal_uInt32 _nValue ) = 0; + virtual void end() = 0; + }; + + //==================================================================== + //= ProgressMixer + //==================================================================== + struct ProgressMixer_Data; + /** a class which mixes (i.e. concatenates) progress values from different + sources/phases, with different weight + */ + class ProgressMixer + { + public: + ProgressMixer( IProgressConsumer& _rConsumer ); + ~ProgressMixer(); + + /** registers a phase of the process, which has the given weight + in the overall process + @precond + the progress is not runnig, yet + */ + void registerPhase( const PhaseID _nID, const PhaseWeight _nWeight ); + + /** enters the phase with the given ID, with the phase having + the given overall range + */ + void startPhase( const PhaseID _nID, const sal_uInt32 _nPhaseRange ); + + /** announces a new progress in the current phase. + + The given phase progress must be between 0 and the overall phase range + as specified in ->startPhase. + */ + void advancePhase( const sal_uInt32 _nPhaseProgress ); + + /** leaves the current phase, which has been started with ->startPhase previously + */ + void endPhase(); + + private: + ::std::auto_ptr< ProgressMixer_Data > m_pData; + }; + +//........................................................................ +} // namespace dbmm +//........................................................................ + +#endif // DBACCESS_PROGRESSMIXER_HXX diff --git a/dbaccess/source/filter/migration/cfgimport.cxx b/dbaccess/source/filter/migration/cfgimport.cxx index 23b4f3bb68ba..182bd9acbed9 100644 --- a/dbaccess/source/filter/migration/cfgimport.cxx +++ b/dbaccess/source/filter/migration/cfgimport.cxx @@ -620,7 +620,14 @@ void OCfgImport::createDataSource(const ::rtl::OUString& _sName) aURL.setExtension(sExtension); sFileName = aURL.GetMainURL(INetURLObject::NO_DECODE); } - m_xModel->attachResource(sFileName,Sequence()); + + Sequence< PropertyValue > aArgs(1); + aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FileName" ) ); + aArgs[0].Value <<= sFileName; + + Reference< XLoadable > xLoad( m_xModel, UNO_QUERY_THROW ); + xLoad->load( aArgs ); + m_xModel->attachResource( sFileName, Sequence< PropertyValue >() ); } catch(Exception&) { diff --git a/dbaccess/source/filter/xml/dbloader2.cxx b/dbaccess/source/filter/xml/dbloader2.cxx index 75529ac34551..eb461bad11e1 100644 --- a/dbaccess/source/filter/xml/dbloader2.cxx +++ b/dbaccess/source/filter/xml/dbloader2.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: dbloader2.cxx,v $ - * $Revision: 1.39 $ + * $Revision: 1.32.28.13 $ * * This file is part of OpenOffice.org. * @@ -37,7 +37,6 @@ /** === begin UNO includes === **/ #include #include -#include #include #include #include @@ -62,6 +61,7 @@ #include #include #include +#include /** === end UNO includes === **/ #include @@ -473,16 +473,32 @@ void SAL_CALL DBContentLoader::load(const Reference< XFrame > & rFrame, const :: } else { - Sequence< Any > aCreationArgs( 1 ); - aCreationArgs[0] <<= NamedValue( INFO_POOLURL, makeAny( sSalvagedURL ) ); - xDocumentDataSource.set( xDatabaseContext->createInstanceWithArguments( aCreationArgs ), UNO_QUERY_THROW ); + ::comphelper::NamedValueCollection aCreationArgs; + aCreationArgs.put( (::rtl::OUString)INFO_POOLURL, sSalvagedURL ); + xDocumentDataSource.set( xDatabaseContext->createInstanceWithArguments( aCreationArgs.getWrappedNamedValues() ), UNO_QUERY_THROW ); } xModel.set( xDocumentDataSource->getDatabaseDocument(), UNO_QUERY ); - if ( xModel.is() && bNewAndInteractive ) + + if ( bCreateNew && xModel.is() ) { - const ::rtl::OUString sURL = xModel->getURL(); - bSuccess = impl_executeNewDatabaseWizard( xModel, bStartTableWizard ); + if ( bNewAndInteractive ) + { + bSuccess = impl_executeNewDatabaseWizard( xModel, bStartTableWizard ); + } + else + { + try + { + Reference< XLoadable > xLoad( xModel, UNO_QUERY_THROW ); + xLoad->initNew(); + bSuccess = true; + } + catch( const Exception& ) + { + bSuccess = false; + } + } // initially select the "Tables" category (will be done below) nInitialSelection = ::com::sun::star::sdb::application::DatabaseObjectContainer::TABLES; @@ -501,7 +517,11 @@ void SAL_CALL DBContentLoader::load(const Reference< XFrame > & rFrame, const :: try { aMediaDesc.put( "FileName", _rURL ); - xModel->attachResource( _rURL, aMediaDesc.getPropertyValues() ); + Reference< XLoadable > xLoad( xModel, UNO_QUERY_THROW ); + + Sequence< PropertyValue > aResource( aMediaDesc.getPropertyValues() ); + xLoad->load( aResource ); + xModel->attachResource( _rURL, aResource ); } catch(const Exception&) { @@ -523,8 +543,8 @@ void SAL_CALL DBContentLoader::load(const Reference< XFrame > & rFrame, const :: { xController->attachModel( xModel ); rFrame->setComponent( xController->getComponentWindow(), xController.get() ); - xModel->setCurrentController( xController.get() ); xController->attachFrame( rFrame ); + xModel->setCurrentController( xController.get() ); } } catch( const Exception& ) @@ -536,43 +556,6 @@ void SAL_CALL DBContentLoader::load(const Reference< XFrame > & rFrame, const :: if (bSuccess) { - try - { - Reference< css::container::XSet > xModelCollection; - if ( m_aContext.createComponent( "com.sun.star.frame.GlobalEventBroadcaster", xModelCollection ) ) - xModelCollection->insert(css::uno::makeAny(xModel)); - - Reference< css::document::XEventListener > xDocEventBroadcaster(xModel,UNO_QUERY_THROW); - css::document::EventObject aEvent; - aEvent.Source = xModel; - ::std::vector< ::rtl::OUString > aEvents; - if ( bCreateNew ) - { - aEvents.push_back(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OnCreate"))); - aEvents.push_back(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OnNew"))); // UI event - } - else - { - aEvents.push_back(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OnLoadFinished"))); - aEvents.push_back(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OnLoad"))); // UI event - } - - std::vector< rtl::OUString >::iterator aIter = aEvents.begin(); - const std::vector< rtl::OUString >::iterator aEnd = aEvents.end(); - for (; aIter != aEnd; ++aIter) - { - aEvent.EventName = *aIter; - xDocEventBroadcaster->notifyEvent(aEvent); - } - - aEvent.EventName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OnViewCreated")); - Reference< css::document::XEventListener > xGlobalDocEventBroadcaster(xModelCollection,UNO_QUERY_THROW); - xGlobalDocEventBroadcaster->notifyEvent(aEvent); - } - catch(Exception) - { - OSL_ENSURE(0,"Could not add database model to global model collection and broadcast the events OnNew/OnLoad!"); - } if ( rListener.is() ) rListener->loadFinished(this); diff --git a/dbaccess/source/filter/xml/xmlEnums.hxx b/dbaccess/source/filter/xml/xmlEnums.hxx index 123b2c628fa5..7e4321e9f7cf 100644 --- a/dbaccess/source/filter/xml/xmlEnums.hxx +++ b/dbaccess/source/filter/xml/xmlEnums.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: xmlEnums.hxx,v $ - * $Revision: 1.7 $ + * $Revision: 1.7.2.1 $ * * This file is part of OpenOffice.org. * @@ -39,7 +39,8 @@ namespace dbaxml XML_TOK_DOC_AUTOSTYLES, XML_TOK_DOC_SETTINGS, XML_TOK_DOC_DATABASE, - XML_TOK_DOC_STYLES + XML_TOK_DOC_STYLES, + XML_TOK_DOC_SCRIPT }; enum XMLDatabaseToken { diff --git a/dbaccess/source/filter/xml/xmlExport.cxx b/dbaccess/source/filter/xml/xmlExport.cxx index 4441d77a2acd..cc661fab1914 100644 --- a/dbaccess/source/filter/xml/xmlExport.cxx +++ b/dbaccess/source/filter/xml/xmlExport.cxx @@ -244,10 +244,9 @@ namespace dbaxml }; // ----------------------------------------------------------------------------- ODBExport::ODBExport(const Reference< XMultiServiceFactory >& _rxMSF,sal_uInt16 nExportFlag) -: SvXMLExport( _rxMSF,MAP_10TH_MM,XML_DATABASE, EXPORT_OASIS) +: SvXMLExport( _rxMSF,MAP_10TH_MM,XML_DATABASE, EXPORT_OASIS | nExportFlag) ,m_bAllreadyFilled(sal_False) { - setExportFlags( EXPORT_OASIS | nExportFlag); GetMM100UnitConverter().setCoreMeasureUnit(MAP_10TH_MM); GetMM100UnitConverter().setXMLMeasureUnit(MAP_CM); diff --git a/dbaccess/source/filter/xml/xmlExport.hxx b/dbaccess/source/filter/xml/xmlExport.hxx index 26419b6f4e59..e11f9b244cfd 100644 --- a/dbaccess/source/filter/xml/xmlExport.hxx +++ b/dbaccess/source/filter/xml/xmlExport.hxx @@ -212,7 +212,7 @@ protected: virtual ~ODBExport(){}; public: - ODBExport(const Reference< XMultiServiceFactory >& _rxMSF, sal_uInt16 nExportFlag = EXPORT_CONTENT | EXPORT_AUTOSTYLES | EXPORT_PRETTY|EXPORT_FONTDECLS); + ODBExport(const Reference< XMultiServiceFactory >& _rxMSF, sal_uInt16 nExportFlag = EXPORT_CONTENT | EXPORT_AUTOSTYLES | EXPORT_PRETTY | EXPORT_FONTDECLS | EXPORT_SCRIPTS ); // XServiceInfo DECLARE_SERVICE_INFO_STATIC( ); diff --git a/dbaccess/source/filter/xml/xmlfilter.cxx b/dbaccess/source/filter/xml/xmlfilter.cxx index f27262d3614a..8ab5d173acf0 100644 --- a/dbaccess/source/filter/xml/xmlfilter.cxx +++ b/dbaccess/source/filter/xml/xmlfilter.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: xmlfilter.cxx,v $ - * $Revision: 1.20 $ + * $Revision: 1.20.2.2 $ * * This file is part of OpenOffice.org. * @@ -55,6 +55,9 @@ #ifndef _XMLOFF_XMLNMSPE_HXX #include #endif +#ifndef _XMLOFF_XMLSCRIPTI_HXX +#include +#endif #ifndef _XMLOFF_XMLTOKEN_HXX #include #endif @@ -216,13 +219,9 @@ sal_Int32 ReadThroughComponent( { return ERRCODE_IO_BROKENPACKAGE; } - catch( IOException& ) - { - return 1; - } catch( Exception& ) { - return 1; + DBG_UNHANDLED_EXCEPTION(); } // success! @@ -474,6 +473,9 @@ SvXMLImportContext* ODBFilter::CreateContext( sal_uInt16 nPrefix, GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP ); pContext = CreateStylesContext(nPrefix, rLocalName, xAttrList, sal_True); break; + case XML_TOK_DOC_SCRIPT: + pContext = CreateScriptContext( rLocalName ); + break; } if ( !pContext ) @@ -538,13 +540,14 @@ const SvXMLTokenMap& ODBFilter::GetDocElemTokenMap() const static __FAR_DATA SvXMLTokenMapEntry aElemTokenMap[]= { { XML_NAMESPACE_OFFICE, XML_SETTINGS, XML_TOK_DOC_SETTINGS }, - { XML_NAMESPACE_OOO, XML_SETTINGS, XML_TOK_DOC_SETTINGS }, + { XML_NAMESPACE_OOO, XML_SETTINGS, XML_TOK_DOC_SETTINGS }, { XML_NAMESPACE_OFFICE, XML_STYLES, XML_TOK_DOC_STYLES }, - { XML_NAMESPACE_OOO, XML_STYLES, XML_TOK_DOC_STYLES }, + { XML_NAMESPACE_OOO, XML_STYLES, XML_TOK_DOC_STYLES }, { XML_NAMESPACE_OFFICE, XML_AUTOMATIC_STYLES, XML_TOK_DOC_AUTOSTYLES }, - { XML_NAMESPACE_OOO, XML_AUTOMATIC_STYLES, XML_TOK_DOC_AUTOSTYLES }, + { XML_NAMESPACE_OOO, XML_AUTOMATIC_STYLES, XML_TOK_DOC_AUTOSTYLES }, { XML_NAMESPACE_OFFICE, XML_DATABASE, XML_TOK_DOC_DATABASE }, - { XML_NAMESPACE_OOO, XML_DATABASE, XML_TOK_DOC_DATABASE }, + { XML_NAMESPACE_OOO, XML_DATABASE, XML_TOK_DOC_DATABASE }, + { XML_NAMESPACE_OFFICE, XML_SCRIPTS, XML_TOK_DOC_SCRIPT }, XML_TOKEN_MAP_END }; m_pDocElemTokenMap.reset(new SvXMLTokenMap( aElemTokenMap )); @@ -781,6 +784,11 @@ SvXMLImportContext* ODBFilter::CreateStylesContext(sal_uInt16 _nPrefix,const ::r return pContext; } // ----------------------------------------------------------------------------- +SvXMLImportContext* ODBFilter::CreateScriptContext( const ::rtl::OUString& _rLocalName ) +{ + return new XMLScriptContext( *this, XML_NAMESPACE_OFFICE, _rLocalName, GetModel() ); +} +// ----------------------------------------------------------------------------- UniReference < XMLPropertySetMapper > ODBFilter::GetTableStylesPropertySetMapper() const { if ( !m_xTableStylesPropertySetMapper.is() ) diff --git a/dbaccess/source/filter/xml/xmlfilter.hxx b/dbaccess/source/filter/xml/xmlfilter.hxx index 6d3052cd8d36..4805e242055d 100644 --- a/dbaccess/source/filter/xml/xmlfilter.hxx +++ b/dbaccess/source/filter/xml/xmlfilter.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: xmlfilter.hxx,v $ - * $Revision: 1.8 $ + * $Revision: 1.8.2.1 $ * * This file is part of OpenOffice.org. * @@ -146,6 +146,8 @@ private: SvXMLImportContext* CreateStylesContext(sal_uInt16 nPrefix,const ::rtl::OUString& rLocalName, const Reference< XAttributeList>& xAttrList, sal_Bool bIsAutoStyle ); + SvXMLImportContext* CreateScriptContext( const ::rtl::OUString& rLocalName ); + protected: // SvXMLImport virtual SvXMLImportContext *CreateContext( sal_uInt16 nPrefix, diff --git a/dbaccess/source/ui/app/AppController.cxx b/dbaccess/source/ui/app/AppController.cxx index 398ead3525ca..4c7c97054368 100644 --- a/dbaccess/source/ui/app/AppController.cxx +++ b/dbaccess/source/ui/app/AppController.cxx @@ -76,6 +76,7 @@ #include #include #include +#include /** === end UNO includes === **/ #ifndef _TOOLS_DEBUG_HXX @@ -263,6 +264,8 @@ using namespace ::com::sun::star::datatransfer; using namespace ::com::sun::star::ui::dialogs; using namespace ::com::sun::star::task; using ::com::sun::star::document::XEmbeddedScripts; +using ::com::sun::star::document::XDocumentEventBroadcaster; +using ::com::sun::star::document::DocumentEvent; using ::com::sun::star::sdb::application::NamedDatabaseObject; namespace DatabaseObject = ::com::sun::star::sdb::application::DatabaseObject; @@ -513,18 +516,22 @@ void SAL_CALL OApplicationController::disposing() ::rtl::OUString sUrl = m_xModel->getURL(); if ( sUrl.getLength() ) { - ::rtl::OUString aFilter; - INetURLObject aURL( m_xModel->getURL() ); - const SfxFilter* pFilter = getStandardDatabaseFilter(); - if ( pFilter ) - aFilter = pFilter->GetFilterName(); - - // add to svtool history options - SvtHistoryOptions().AppendItem( ePICKLIST, - aURL.GetURLNoPass( INetURLObject::NO_DECODE ), - aFilter, - getStrippedDatabaseName(), - ::rtl::OUString() ); + ::comphelper::NamedValueCollection aArgs( m_xModel->getArgs() ); + if ( true == aArgs.getOrDefault( "PickListEntry", true ) ) + { + ::rtl::OUString aFilter; + INetURLObject aURL( m_xModel->getURL() ); + const SfxFilter* pFilter = getStandardDatabaseFilter(); + if ( pFilter ) + aFilter = pFilter->GetFilterName(); + + // add to svtool history options + SvtHistoryOptions().AppendItem( ePICKLIST, + aURL.GetURLNoPass( INetURLObject::NO_DECODE ), + aFilter, + getStrippedDatabaseName(), + ::rtl::OUString() ); + } } m_aModelConnector.clear(); @@ -533,6 +540,7 @@ void SAL_CALL OApplicationController::disposing() } catch(Exception) { + DBG_UNHANDLED_EXCEPTION(); } m_pView = NULL; @@ -642,6 +650,17 @@ void SAL_CALL OApplicationController::disposing(const EventObject& _rSource) thr //-------------------------------------------------------------------- sal_Bool SAL_CALL OApplicationController::suspend(sal_Bool bSuspend) throw( RuntimeException ) { + // notify the OnPrepareViewClosing event (before locking any mutex) + Reference< XDocumentEventBroadcaster > xBroadcaster( m_xModel, UNO_QUERY ); + if ( xBroadcaster.is() ) + { + xBroadcaster->notifyDocumentEvent( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OnPrepareViewClosing" ) ), + this, + Any() + ); + } + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); ::osl::MutexGuard aGuard(m_aMutex); @@ -819,11 +838,9 @@ FeatureState OApplicationController::GetState(sal_uInt16 _nId) const // Our document supports embedding scripts into it, if and only if there are no // forms/reports with macros/scripts into them. So, we need to enable migration // if and only if the database document does *not* support embedding scripts. -// bool bAvailable = !Reference< XEmbeddedScripts >( m_xModel, UNO_QUERY ).is(); - // TODO: revert to the disabled code. The current version is just to be able - // to integrate an intermediate version of the CWS, which should behave as - // if no macros in DB docs are allowed - bool bAvailable = false; + bool bAvailable = + !Reference< XEmbeddedScripts >( m_xModel, UNO_QUERY ).is() + && !Reference< XStorable >( m_xModel, UNO_QUERY_THROW )->isReadonly(); aReturn.bEnabled = bAvailable; if ( !bAvailable ) aReturn.bInvisible = true; @@ -2732,11 +2749,6 @@ IMPL_LINK( OApplicationController, OnFirstControllerConnected, void*, /**/ ) // if we have forms or reports which contain macros/scripts, then show a warning // which suggests the user to migrate them to the database document - // TODO: remove the following line. The current version is just to be able - // to integrate an intermediate version of the CWS, which should behave as - // if no macros in DB docs are allowed - return 0L; -/* Reference< XEmbeddedScripts > xDocumentScripts( m_xModel, UNO_QUERY ); if ( xDocumentScripts.is() ) { @@ -2779,7 +2791,6 @@ IMPL_LINK( OApplicationController, OnFirstControllerConnected, void*, /**/ ) } return 1L; -*/ } // ----------------------------------------------------------------------------- @@ -2801,7 +2812,7 @@ sal_Bool SAL_CALL OApplicationController::attachModel(const Reference< XModel > if ( _rxModel.is() ) { m_xDocumentModify.set( m_xModel, UNO_QUERY_THROW ); - m_aModelConnector = ModelControllerConnector( _rxModel, this ); + m_aModelConnector.connect( _rxModel, this ); onConnectedModel(); } else diff --git a/dbaccess/source/ui/app/AppControllerDnD.cxx b/dbaccess/source/ui/app/AppControllerDnD.cxx index cea54ff26a9b..e063e45c824a 100644 --- a/dbaccess/source/ui/app/AppControllerDnD.cxx +++ b/dbaccess/source/ui/app/AppControllerDnD.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: AppControllerDnD.cxx,v $ - * $Revision: 1.29 $ + * $Revision: 1.26.6.4 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/app/AppControllerGen.cxx b/dbaccess/source/ui/app/AppControllerGen.cxx index 43d5773fc610..59c5bcf8334b 100644 --- a/dbaccess/source/ui/app/AppControllerGen.cxx +++ b/dbaccess/source/ui/app/AppControllerGen.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: AppControllerGen.cxx,v $ - * $Revision: 1.37 $ + * $Revision: 1.32.6.5 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/app/AppView.cxx b/dbaccess/source/ui/app/AppView.cxx index a03e589c7679..1f9288bf489a 100644 --- a/dbaccess/source/ui/app/AppView.cxx +++ b/dbaccess/source/ui/app/AppView.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: AppView.cxx,v $ - * $Revision: 1.25 $ + * $Revision: 1.22.6.3 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/app/app.src b/dbaccess/source/ui/app/app.src index 4a2387f67585..c913d16ebd2d 100644 --- a/dbaccess/source/ui/app/app.src +++ b/dbaccess/source/ui/app/app.src @@ -451,18 +451,17 @@ String STR_FOLDER_LABEL String STR_SUB_DOCS_WITH_SCRIPTS { - Text [ en-US ] = "The document contains forms and/or reports with macros and/or scripts embedded."; + Text [ en-US ] = "The document contains forms or reports with embedded macros."; }; String STR_SUB_DOCS_WITH_SCRIPTS_DETAIL { - Text [ en-US ] = "Scripts and macros should nowadays be embedded into the database document itself.\n\n" + Text [ en-US ] = "Macros should be embedded into the database document itself.\n\n" "You can continue to use your document as before, however, you are encouraged to migrate " - "your scripts and macros. The menu item 'Tools / Migrate Scripts and Macros ...' will " - "assist you with this.\n\n" + "your macros. The menu item 'Tools / Migrate Macros ...' will assist you with this.\n\n" - "Note that you won't be able to embed macros or scripts into the database document until " + "Note that you won't be able to embed macros into the database document itself until " "this migration is done. "; }; diff --git a/dbaccess/source/ui/browser/brwctrlr.cxx b/dbaccess/source/ui/browser/brwctrlr.cxx index 9600465c610f..6352df1c8e4d 100644 --- a/dbaccess/source/ui/browser/brwctrlr.cxx +++ b/dbaccess/source/ui/browser/brwctrlr.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: brwctrlr.cxx,v $ - * $Revision: 1.108 $ + * $Revision: 1.105.6.3 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/browser/dbloader.cxx b/dbaccess/source/ui/browser/dbloader.cxx index 386b16232291..fddf41331548 100644 --- a/dbaccess/source/ui/browser/dbloader.cxx +++ b/dbaccess/source/ui/browser/dbloader.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: dbloader.cxx,v $ - * $Revision: 1.37 $ + * $Revision: 1.36.2.3 $ * * This file is part of OpenOffice.org. * @@ -335,15 +335,6 @@ void SAL_CALL DBContentLoader::load(const Reference< XFrame > & rFrame, const :: xController->attachFrame(rFrame); } - if ( xDatabaseDocument.is() ) - { - Reference< document::XEventListener > xGlobalDocEventBroadcaster(m_xServiceFactory->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.GlobalEventBroadcaster"))),UNO_QUERY_THROW); - document::EventObject aEvent( xDatabaseDocument, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OnViewCreated")) ); - xGlobalDocEventBroadcaster->notifyEvent(aEvent); - // TODO: is this correct? The newly created view is not a view for the database document, at least not in - // the sense that its XController::getModel would return the database document - } - if ( rListener.is() ) rListener->loadFinished( this ); } diff --git a/dbaccess/source/ui/browser/dsbrowserDnD.cxx b/dbaccess/source/ui/browser/dsbrowserDnD.cxx index ca96901e9506..9dc6e028bfd2 100644 --- a/dbaccess/source/ui/browser/dsbrowserDnD.cxx +++ b/dbaccess/source/ui/browser/dsbrowserDnD.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: dsbrowserDnD.cxx,v $ - * $Revision: 1.81 $ + * $Revision: 1.78.140.3 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/browser/exsrcbrw.cxx b/dbaccess/source/ui/browser/exsrcbrw.cxx index a60f56938a80..179ca9e63795 100644 --- a/dbaccess/source/ui/browser/exsrcbrw.cxx +++ b/dbaccess/source/ui/browser/exsrcbrw.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: exsrcbrw.cxx,v $ - * $Revision: 1.34 $ + * $Revision: 1.32.6.2 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/browser/sbagrid.cxx b/dbaccess/source/ui/browser/sbagrid.cxx index ec468871db64..dfda4b4f119b 100644 --- a/dbaccess/source/ui/browser/sbagrid.cxx +++ b/dbaccess/source/ui/browser/sbagrid.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: sbagrid.cxx,v $ - * $Revision: 1.86 $ + * $Revision: 1.83.6.3 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/browser/unodatbr.cxx b/dbaccess/source/ui/browser/unodatbr.cxx index e2e02c6ab9df..8e2f1cbce337 100644 --- a/dbaccess/source/ui/browser/unodatbr.cxx +++ b/dbaccess/source/ui/browser/unodatbr.cxx @@ -3094,11 +3094,6 @@ void SbaTableQueryBrowser::impl_initialize() m_aDocScriptSupport = ::boost::optional< bool >( Reference< XEmbeddedScripts >( xDocument, UNO_QUERY ).is() ); } - // TODO: remove the following line. The current version is just to be able - // to integrate an intermediate version of the CWS, which should behave as - // if no macros in DB docs are allowed - m_aDocScriptSupport = ::boost::optional< bool> ( false ); - if ( implSelect( sInitialDataSourceName, sInitialCommand, nInitialDisplayCommandType, bEsacpeProcessing, xConnection, sal_True ) ) { try diff --git a/dbaccess/source/ui/control/RelationControl.cxx b/dbaccess/source/ui/control/RelationControl.cxx index 7558f7de7671..b782d309d9db 100644 --- a/dbaccess/source/ui/control/RelationControl.cxx +++ b/dbaccess/source/ui/control/RelationControl.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: RelationControl.cxx,v $ - * $Revision: 1.25 $ + * $Revision: 1.23.6.2 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/control/tabletree.cxx b/dbaccess/source/ui/control/tabletree.cxx index c14bcba6fc3d..2f469a948b64 100644 --- a/dbaccess/source/ui/control/tabletree.cxx +++ b/dbaccess/source/ui/control/tabletree.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: tabletree.cxx,v $ - * $Revision: 1.38 $ + * $Revision: 1.35.78.3 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/control/toolboxcontroller.cxx b/dbaccess/source/ui/control/toolboxcontroller.cxx index 838934875452..a3608f49828a 100644 --- a/dbaccess/source/ui/control/toolboxcontroller.cxx +++ b/dbaccess/source/ui/control/toolboxcontroller.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: toolboxcontroller.cxx,v $ - * $Revision: 1.15 $ + * $Revision: 1.13.98.2 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/dlg/AdabasStat.cxx b/dbaccess/source/ui/dlg/AdabasStat.cxx index b04ece8a24cf..3c684a7994ce 100644 --- a/dbaccess/source/ui/dlg/AdabasStat.cxx +++ b/dbaccess/source/ui/dlg/AdabasStat.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: AdabasStat.cxx,v $ - * $Revision: 1.19 $ + * $Revision: 1.17.158.2 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/dlg/ConnectionPage.src b/dbaccess/source/ui/dlg/ConnectionPage.src index d90b4a2cca37..245e843319d1 100644 --- a/dbaccess/source/ui/dlg/ConnectionPage.src +++ b/dbaccess/source/ui/dlg/ConnectionPage.src @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: ConnectionPage.src,v $ - * $Revision: 1.8 $ + * $Revision: 1.8.2.1 $ * * This file is part of OpenOffice.org. * @@ -165,7 +165,7 @@ String STR_CONNECTION_SUCCESS String STR_CONNECTION_NO_SUCCESS { - Text [ en-US ] = "The connection could not be established successfully."; + Text [ en-US ] = "The connection could not be established."; }; String STR_JDBCDRIVER_SUCCESS diff --git a/dbaccess/source/ui/dlg/ExtensionNotPresent.cxx b/dbaccess/source/ui/dlg/ExtensionNotPresent.cxx index 3cff5951c5f6..f9bd1e007341 100644 --- a/dbaccess/source/ui/dlg/ExtensionNotPresent.cxx +++ b/dbaccess/source/ui/dlg/ExtensionNotPresent.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: ExtensionNotPresent.cxx,v $ - * $Revision: 1.4 $ + * $Revision: 1.2.158.2 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/dlg/adminpages.cxx b/dbaccess/source/ui/dlg/adminpages.cxx index a6fbd46ba6b0..ff43481b847d 100644 --- a/dbaccess/source/ui/dlg/adminpages.cxx +++ b/dbaccess/source/ui/dlg/adminpages.cxx @@ -320,7 +320,7 @@ namespace dbaui eImage = OSQLMessageBox::Error; aMessage = String(ModuleRes(STR_CONNECTION_NO_SUCCESS)); } - OSQLMessageBox aMsg(this,sTitle,aMessage,eImage); + OSQLMessageBox aMsg( this, sTitle, aMessage, WB_OK, eImage ); aMsg.Execute(); } if ( !bSuccess ) diff --git a/dbaccess/source/ui/dlg/dbwizsetup.cxx b/dbaccess/source/ui/dlg/dbwizsetup.cxx index e151f2214d4b..80b8b389c45a 100644 --- a/dbaccess/source/ui/dlg/dbwizsetup.cxx +++ b/dbaccess/source/ui/dlg/dbwizsetup.cxx @@ -915,74 +915,30 @@ void ODbTypeWizDialogSetup::enableConfirmSettings( bool _bEnable ) //------------------------------------------------------------------------- sal_Bool ODbTypeWizDialogSetup::SaveDatabaseDocument() { - Reference< XInteractionHandler > xHandler(getORB()->createInstance(SERVICE_TASK_INTERACTION_HANDLER), UNO_QUERY); + Reference< XInteractionHandler > xHandler( getORB()->createInstance( SERVICE_TASK_INTERACTION_HANDLER ), UNO_QUERY ); try { if (callSaveAsDialog() == sal_True) { m_pImpl->saveChanges(*m_pOutSet); Reference< XPropertySet > xDatasource = m_pImpl->getCurrentDataSource(); -#if OSL_DEBUG_LEVEL > 0 - SFX_ITEMSET_GET(*m_pOutSet, pDocUrl, SfxStringItem, DSID_DOCUMENT_URL, sal_True); - (void)pDocUrl; -#endif - Reference xStore(getDataSourceOrModel(xDatasource),UNO_QUERY); - Reference xComponent(xStore,UNO_QUERY); - ::rtl::OUString sPath = m_pImpl->getDocumentUrl(*m_pOutSet); - if ( xStore.is() ) - { - if ( m_pGeneralPage->GetDatabaseCreationMode() == OGeneralPage::eCreateNew ) - CreateDatabase(); - Reference< XModel > xModel(xStore, UNO_QUERY); - - Sequence aArgs = xModel->getArgs(); - - sal_Bool bOverwrite = sal_True; - sal_Bool bAddOverwrite = sal_True; - sal_Bool bAddInteractionHandler = sal_True; - PropertyValue* pIter = aArgs.getArray(); - PropertyValue* pEnd = pIter + aArgs.getLength(); - for(;pIter != pEnd;++pIter) - { - if ( pIter->Name.equalsAscii("Overwrite") ) - { - pIter->Value <<= bOverwrite; - bAddOverwrite = sal_False; - } - if ( pIter->Name.equalsAscii("InteractionHandler") ) - { - pIter->Value <<= xHandler; - bAddInteractionHandler = sal_False; - } + Reference< XModel > xModel( getDataSourceOrModel( xDatasource ), UNO_QUERY_THROW ); + Reference< XStorable > xStore( xModel, UNO_QUERY_THROW ); - } - if ( bAddOverwrite ) - { - sal_Int32 nLen = aArgs.getLength(); - aArgs.realloc(nLen+1); - aArgs[nLen].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Overwrite")); - aArgs[nLen].Value <<= bOverwrite; - } - if ( bAddInteractionHandler ) - { - sal_Int32 nLen = aArgs.getLength(); - aArgs.realloc(nLen+1); - aArgs[nLen].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("InteractionHandler")); - aArgs[nLen].Value <<= xHandler; - } - xStore->storeAsURL(sPath,aArgs); + if ( m_pGeneralPage->GetDatabaseCreationMode() == OGeneralPage::eCreateNew ) + CreateDatabase(); - if (pFinalPage != NULL) - { - if (pFinalPage->IsDatabaseDocumentToBeRegistered()) - RegisterDataSourceByLocation(sPath); - } - else - { - RegisterDataSourceByLocation(sPath); - } - return sal_True; - } + ::comphelper::NamedValueCollection aArgs( xModel->getArgs() ); + aArgs.put( "Overwrite", sal_Bool( sal_True ) ); + aArgs.put( "InteractionHandler", xHandler ); + + ::rtl::OUString sPath = m_pImpl->getDocumentUrl( *m_pOutSet ); + xStore->storeAsURL( sPath, aArgs.getPropertyValues() ); + + if ( !pFinalPage || pFinalPage->IsDatabaseDocumentToBeRegistered() ) + RegisterDataSourceByLocation( sPath ); + + return sal_True; } } catch (Exception& e) @@ -1318,10 +1274,10 @@ sal_Bool ODbTypeWizDialogSetup::SaveDatabaseDocument() skipUntil(PAGE_DBSETUPWIZARD_FINAL); } if (getCurrentState() == PAGE_DBSETUPWIZARD_FINAL) - return SaveDatabaseDocument() ? OWizardMachine::onFinish(_nResult) : sal_False; + return SaveDatabaseDocument() ? OWizardMachine::onFinish( _nResult ) : sal_False; else { - enableButtons( WZB_FINISH, sal_False); + enableButtons( WZB_FINISH, sal_False ); return sal_False; } } diff --git a/dbaccess/source/ui/dlg/directsql.cxx b/dbaccess/source/ui/dlg/directsql.cxx index 10a7b04a0ae2..4f713e27f277 100644 --- a/dbaccess/source/ui/dlg/directsql.cxx +++ b/dbaccess/source/ui/dlg/directsql.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: directsql.cxx,v $ - * $Revision: 1.12 $ + * $Revision: 1.10.158.2 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/dlg/queryorder.cxx b/dbaccess/source/ui/dlg/queryorder.cxx index 0760d4bc8b36..e0f4359a9e0c 100644 --- a/dbaccess/source/ui/dlg/queryorder.cxx +++ b/dbaccess/source/ui/dlg/queryorder.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: queryorder.cxx,v $ - * $Revision: 1.22 $ + * $Revision: 1.20.172.2 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/dlg/tablespage.cxx b/dbaccess/source/ui/dlg/tablespage.cxx index d284d9db3e3c..0f3bb3f73c0a 100644 --- a/dbaccess/source/ui/dlg/tablespage.cxx +++ b/dbaccess/source/ui/dlg/tablespage.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: tablespage.cxx,v $ - * $Revision: 1.35 $ + * $Revision: 1.33.6.2 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/inc/brwctrlr.hxx b/dbaccess/source/ui/inc/brwctrlr.hxx index 025286aa3010..04d73cf778ec 100644 --- a/dbaccess/source/ui/inc/brwctrlr.hxx +++ b/dbaccess/source/ui/inc/brwctrlr.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: brwctrlr.hxx,v $ - * $Revision: 1.43 $ + * $Revision: 1.40.6.3 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/misc/DExport.cxx b/dbaccess/source/ui/misc/DExport.cxx index 76cfa846dd17..fe31c60abc3b 100644 --- a/dbaccess/source/ui/misc/DExport.cxx +++ b/dbaccess/source/ui/misc/DExport.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: DExport.cxx,v $ - * $Revision: 1.42 $ + * $Revision: 1.40.32.2 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/misc/TableCopyHelper.cxx b/dbaccess/source/ui/misc/TableCopyHelper.cxx index 8f612326a0e3..299926f222b8 100644 --- a/dbaccess/source/ui/misc/TableCopyHelper.cxx +++ b/dbaccess/source/ui/misc/TableCopyHelper.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: TableCopyHelper.cxx,v $ - * $Revision: 1.13 $ + * $Revision: 1.11.32.2 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/misc/TokenWriter.cxx b/dbaccess/source/ui/misc/TokenWriter.cxx index 6725ba1da53d..db8bd6e5e21f 100644 --- a/dbaccess/source/ui/misc/TokenWriter.cxx +++ b/dbaccess/source/ui/misc/TokenWriter.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: TokenWriter.cxx,v $ - * $Revision: 1.39 $ + * $Revision: 1.36.14.3 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/misc/controllerframe.cxx b/dbaccess/source/ui/misc/controllerframe.cxx index 8badaf9d55a5..f0c93586f26c 100644 --- a/dbaccess/source/ui/misc/controllerframe.cxx +++ b/dbaccess/source/ui/misc/controllerframe.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: controllerframe.cxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.2.2 $ * * This file is part of OpenOffice.org. * @@ -36,6 +36,8 @@ #include #include #include +#include +#include /** === end UNO includes === **/ #include @@ -66,6 +68,7 @@ namespace dbaui using ::com::sun::star::frame::FrameAction_FRAME_UI_DEACTIVATING; using ::com::sun::star::frame::XModel; using ::com::sun::star::frame::XController; + using ::com::sun::star::frame::XController2; using ::com::sun::star::frame::XFramesSupplier; using ::com::sun::star::sdb::XOfficeDatabaseDocument; using ::com::sun::star::awt::XTopWindow; @@ -73,6 +76,7 @@ namespace dbaui using ::com::sun::star::awt::XWindow2; using ::com::sun::star::lang::DisposedException; using ::com::sun::star::lang::EventObject; + using ::com::sun::star::document::XDocumentEventBroadcaster; /** === end UNO using === **/ //==================================================================== @@ -118,6 +122,7 @@ namespace dbaui ControllerFrame_Data( IController& _rController ) :m_rController( _rController ) ,m_xFrame() + ,m_xDocEventBroadcaster() ,m_pListener() ,m_bActive( false ) { @@ -125,6 +130,7 @@ namespace dbaui IController& m_rController; Reference< XFrame > m_xFrame; + Reference< XDocumentEventBroadcaster > m_xDocEventBroadcaster; ::rtl::Reference< FrameWindowActivationListener > m_pListener; bool m_bActive; }; @@ -141,11 +147,26 @@ namespace dbaui _rData.m_pListener->dispose(); _rData.m_pListener = NULL; } + // remember new frame _rData.m_xFrame = _rxFrame; + // create new listener if ( _rData.m_xFrame.is() ) _rData.m_pListener = new FrameWindowActivationListener( _rData ); + + // at this point in time, we can assume the controller also has a model set, if it supports models + try + { + Reference< XController > xController( _rData.m_rController.getXController(), UNO_SET_THROW ); + Reference< XModel > xModel( xController->getModel() ); + if ( xModel.is() ) + _rData.m_xDocEventBroadcaster.set( xModel, UNO_QUERY ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } } //-------------------------------------------------------------------- @@ -203,6 +224,26 @@ namespace dbaui } } + //-------------------------------------------------------------------- + /** broadcasts the OnFocus resp. OnUnfocus event + */ + static void lcl_notifyFocusChange_nothrow( ControllerFrame_Data& _rData, bool _bActive ) + { + try + { + if ( _rData.m_xDocEventBroadcaster.is() ) + { + ::rtl::OUString sEventName( ::rtl::OUString::createFromAscii( _bActive ? "OnFocus" : "OnUnfocus" ) ); + Reference< XController2 > xController( _rData.m_rController.getXController(), UNO_QUERY_THROW ); + _rData.m_xDocEventBroadcaster->notifyDocumentEvent( sEventName, xController, Any() ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + //-------------------------------------------------------------------- static void lcl_updateActive_nothrow( ControllerFrame_Data& _rData, bool _bActive ) { @@ -211,6 +252,7 @@ namespace dbaui _rData.m_bActive = _bActive; lcl_updateActiveComponents_nothrow( _rData ); + lcl_notifyFocusChange_nothrow( _rData, _bActive ); } //-------------------------------------------------------------------- @@ -335,7 +377,10 @@ namespace dbaui // update active component if ( m_pData->m_bActive ) + { lcl_updateActiveComponents_nothrow( *m_pData ); + lcl_notifyFocusChange_nothrow( *m_pData, true ); + } return m_pData->m_xFrame; } diff --git a/dbaccess/source/ui/misc/databaseobjectview.cxx b/dbaccess/source/ui/misc/databaseobjectview.cxx index 3d9206d0803a..724e9f0f4285 100644 --- a/dbaccess/source/ui/misc/databaseobjectview.cxx +++ b/dbaccess/source/ui/misc/databaseobjectview.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: databaseobjectview.cxx,v $ - * $Revision: 1.11 $ + * $Revision: 1.8.6.3 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/misc/documentcontroller.cxx b/dbaccess/source/ui/misc/documentcontroller.cxx index 37bfdd2b9753..523307d55013 100644 --- a/dbaccess/source/ui/misc/documentcontroller.cxx +++ b/dbaccess/source/ui/misc/documentcontroller.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: documentcontroller.cxx,v $ - * $Revision: 1.7 $ + * $Revision: 1.5.178.4 $ * * This file is part of OpenOffice.org. * @@ -83,11 +83,14 @@ namespace dbaui } //-------------------------------------------------------------------- - void ModelControllerConnector::swap( ModelControllerConnector& _rSource ) + void ModelControllerConnector::connect( const Reference< XModel >& _rxModel, const Reference< XController >& _rxController ) { - ModelControllerConnector aTemp( _rSource ); - _rSource.impl_copyFrom( *this ); - impl_copyFrom( aTemp ); + impl_disconnect(); + + m_xModel = _rxModel; + m_xController = _rxController; + + impl_connect(); } //-------------------------------------------------------------------- diff --git a/dbaccess/source/ui/misc/dsmeta.cxx b/dbaccess/source/ui/misc/dsmeta.cxx index 10f955e4a7d2..4fe29a04e2a6 100644 --- a/dbaccess/source/ui/misc/dsmeta.cxx +++ b/dbaccess/source/ui/misc/dsmeta.cxx @@ -68,26 +68,26 @@ namespace dbaui bAutoIncrementIsPrimaryKey = ( _AutoPKey != 0 ); } - enum Special { All, None }; + enum Special { All, AllButIgnoreCurrency, None }; InitAdvanced( Special _eType ) :AdvancedSettingsSupport() { - bGeneratedValues = ( _eType == All ); - bUseSQL92NamingConstraints = ( _eType == All ); - bAppendTableAliasInSelect = ( _eType == All ); - bUseKeywordAsBeforeAlias = ( _eType == All ); - bUseBracketedOuterJoinSyntax = ( _eType == All ); - bIgnoreDriverPrivileges = ( _eType == All ); - bParameterNameSubstitution = ( _eType == All ); - bDisplayVersionColumns = ( _eType == All ); - bUseCatalogInSelect = ( _eType == All ); - bUseSchemaInSelect = ( _eType == All ); - bUseIndexDirectionKeyword = ( _eType == All ); - bUseDOSLineEnds = ( _eType == All ); - bBooleanComparisonMode = ( _eType == All ); - bFormsCheckRequiredFields = ( _eType == All ); - bIgnoreCurrency = false; // Oracle special + bGeneratedValues = ( _eType == All ) || ( _eType == AllButIgnoreCurrency ); + bUseSQL92NamingConstraints = ( _eType == All ) || ( _eType == AllButIgnoreCurrency ); + bAppendTableAliasInSelect = ( _eType == All ) || ( _eType == AllButIgnoreCurrency ); + bUseKeywordAsBeforeAlias = ( _eType == All ) || ( _eType == AllButIgnoreCurrency ); + bUseBracketedOuterJoinSyntax = ( _eType == All ) || ( _eType == AllButIgnoreCurrency ); + bIgnoreDriverPrivileges = ( _eType == All ) || ( _eType == AllButIgnoreCurrency ); + bParameterNameSubstitution = ( _eType == All ) || ( _eType == AllButIgnoreCurrency ); + bDisplayVersionColumns = ( _eType == All ) || ( _eType == AllButIgnoreCurrency ); + bUseCatalogInSelect = ( _eType == All ) || ( _eType == AllButIgnoreCurrency ); + bUseSchemaInSelect = ( _eType == All ) || ( _eType == AllButIgnoreCurrency ); + bUseIndexDirectionKeyword = ( _eType == All ) || ( _eType == AllButIgnoreCurrency ); + bUseDOSLineEnds = ( _eType == All ) || ( _eType == AllButIgnoreCurrency ); + bBooleanComparisonMode = ( _eType == All ) || ( _eType == AllButIgnoreCurrency ); + bFormsCheckRequiredFields = ( _eType == All ) || ( _eType == AllButIgnoreCurrency ); + bIgnoreCurrency = ( _eType == All ); bAutoIncrementIsPrimaryKey = false; // hsqldb special } }; @@ -128,8 +128,8 @@ namespace dbaui s_aSupport[ ::dbaccess::DST_CALC ] = InitAdvanced( InitAdvanced::None ); s_aSupport[ ::dbaccess::DST_DBASE ] = InitAdvanced( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ); s_aSupport[ ::dbaccess::DST_FLAT ] = InitAdvanced( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - s_aSupport[ ::dbaccess::DST_JDBC ] = InitAdvanced( InitAdvanced::All ); - s_aSupport[ ::dbaccess::DST_ODBC ] = InitAdvanced( InitAdvanced::All ); + s_aSupport[ ::dbaccess::DST_JDBC ] = InitAdvanced( InitAdvanced::AllButIgnoreCurrency ); + s_aSupport[ ::dbaccess::DST_ODBC ] = InitAdvanced( InitAdvanced::AllButIgnoreCurrency ); s_aSupport[ ::dbaccess::DST_ADO ] = InitAdvanced( 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 ); s_aSupport[ ::dbaccess::DST_MOZILLA ] = InitAdvanced( InitAdvanced::None ); s_aSupport[ ::dbaccess::DST_THUNDERBIRD ] = InitAdvanced( InitAdvanced::None ); @@ -143,18 +143,16 @@ namespace dbaui s_aSupport[ ::dbaccess::DST_MACAB ] = InitAdvanced( InitAdvanced::None ); s_aSupport[ ::dbaccess::DST_MSACCESS_2007 ] = InitAdvanced( 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0 ); s_aSupport[ ::dbaccess::DST_EMBEDDED_HSQLDB ] = InitAdvanced( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1 ); - s_aSupport[ ::dbaccess::DST_USERDEFINE1 ] = InitAdvanced( InitAdvanced::All ); - s_aSupport[ ::dbaccess::DST_USERDEFINE2 ] = InitAdvanced( InitAdvanced::All ); - s_aSupport[ ::dbaccess::DST_USERDEFINE3 ] = InitAdvanced( InitAdvanced::All ); - s_aSupport[ ::dbaccess::DST_USERDEFINE4 ] = InitAdvanced( InitAdvanced::All ); - s_aSupport[ ::dbaccess::DST_USERDEFINE5 ] = InitAdvanced( InitAdvanced::All ); - s_aSupport[ ::dbaccess::DST_USERDEFINE6 ] = InitAdvanced( InitAdvanced::All ); - s_aSupport[ ::dbaccess::DST_USERDEFINE7 ] = InitAdvanced( InitAdvanced::All ); - s_aSupport[ ::dbaccess::DST_USERDEFINE8 ] = InitAdvanced( InitAdvanced::All ); - s_aSupport[ ::dbaccess::DST_USERDEFINE9 ] = InitAdvanced( InitAdvanced::All ); - s_aSupport[ ::dbaccess::DST_USERDEFINE10 ] = InitAdvanced( InitAdvanced::All ); - - s_aSupport[ ::dbaccess::DST_ORACLE_JDBC ].bIgnoreCurrency = true; + s_aSupport[ ::dbaccess::DST_USERDEFINE1 ] = InitAdvanced( InitAdvanced::AllButIgnoreCurrency ); + s_aSupport[ ::dbaccess::DST_USERDEFINE2 ] = InitAdvanced( InitAdvanced::AllButIgnoreCurrency ); + s_aSupport[ ::dbaccess::DST_USERDEFINE3 ] = InitAdvanced( InitAdvanced::AllButIgnoreCurrency ); + s_aSupport[ ::dbaccess::DST_USERDEFINE4 ] = InitAdvanced( InitAdvanced::AllButIgnoreCurrency ); + s_aSupport[ ::dbaccess::DST_USERDEFINE5 ] = InitAdvanced( InitAdvanced::AllButIgnoreCurrency ); + s_aSupport[ ::dbaccess::DST_USERDEFINE6 ] = InitAdvanced( InitAdvanced::AllButIgnoreCurrency ); + s_aSupport[ ::dbaccess::DST_USERDEFINE7 ] = InitAdvanced( InitAdvanced::AllButIgnoreCurrency ); + s_aSupport[ ::dbaccess::DST_USERDEFINE8 ] = InitAdvanced( InitAdvanced::AllButIgnoreCurrency ); + s_aSupport[ ::dbaccess::DST_USERDEFINE9 ] = InitAdvanced( InitAdvanced::AllButIgnoreCurrency ); + s_aSupport[ ::dbaccess::DST_USERDEFINE10 ] = InitAdvanced( InitAdvanced::AllButIgnoreCurrency ); } return s_aSupport[ _eType ]; } diff --git a/dbaccess/source/ui/misc/dsntypes.cxx b/dbaccess/source/ui/misc/dsntypes.cxx deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/dbaccess/source/ui/misc/indexcollection.cxx b/dbaccess/source/ui/misc/indexcollection.cxx index 3ec084fb4001..9f485067d4a4 100644 --- a/dbaccess/source/ui/misc/indexcollection.cxx +++ b/dbaccess/source/ui/misc/indexcollection.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: indexcollection.cxx,v $ - * $Revision: 1.10 $ + * $Revision: 1.8.254.2 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/misc/singledoccontroller.cxx b/dbaccess/source/ui/misc/singledoccontroller.cxx index 2ef890cd8713..965185288203 100644 --- a/dbaccess/source/ui/misc/singledoccontroller.cxx +++ b/dbaccess/source/ui/misc/singledoccontroller.cxx @@ -169,13 +169,9 @@ namespace dbaui bool documentHasScriptSupport() const { - // TODO: revert to the disabled code. The current version is just to be able - // to integrate an intermediate version of the CWS, which should behave as - // if no macros in DB docs are allowed - return false; -// OSL_PRECOND( !!m_aDocScriptSupport, -// "OSingleDocumentControllerImpl::documentHasScriptSupport: not completely initialized, yet - don't know!?" ); -// return !!m_aDocScriptSupport && *m_aDocScriptSupport; + OSL_PRECOND( !!m_aDocScriptSupport, + "OSingleDocumentControllerImpl::documentHasScriptSupport: not completely initialized, yet - don't know!?" ); + return !!m_aDocScriptSupport && *m_aDocScriptSupport; } void setDocumentScriptSupport( const bool _bSupport ) diff --git a/dbaccess/source/ui/uno/composerdialogs.cxx b/dbaccess/source/ui/uno/composerdialogs.cxx index 0f1670c90866..204b1b0aae26 100644 --- a/dbaccess/source/ui/uno/composerdialogs.cxx +++ b/dbaccess/source/ui/uno/composerdialogs.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: composerdialogs.cxx,v $ - * $Revision: 1.12 $ + * $Revision: 1.9.32.3 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/uno/dbinteraction.cxx b/dbaccess/source/ui/uno/dbinteraction.cxx index a4d4ee2965b9..b1290f9ee0be 100644 --- a/dbaccess/source/ui/uno/dbinteraction.cxx +++ b/dbaccess/source/ui/uno/dbinteraction.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: dbinteraction.cxx,v $ - * $Revision: 1.19 $ + * $Revision: 1.17.6.2 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/source/ui/uno/unoDirectSql.cxx b/dbaccess/source/ui/uno/unoDirectSql.cxx index c2bdd22e3167..823ba3dd2714 100644 --- a/dbaccess/source/ui/uno/unoDirectSql.cxx +++ b/dbaccess/source/ui/uno/unoDirectSql.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: unoDirectSql.cxx,v $ - * $Revision: 1.10 $ + * $Revision: 1.7.142.3 $ * * This file is part of OpenOffice.org. * diff --git a/dbaccess/uiconfig/dbapp/menubar/menubar.xml b/dbaccess/uiconfig/dbapp/menubar/menubar.xml index d8470c03f15c..629aa199f353 100644 --- a/dbaccess/uiconfig/dbapp/menubar/menubar.xml +++ b/dbaccess/uiconfig/dbapp/menubar/menubar.xml @@ -105,6 +105,7 @@ + diff --git a/dbaccess/util/makefile.mk b/dbaccess/util/makefile.mk index d9ccc3a5ffda..1f7f14601c1d 100644 --- a/dbaccess/util/makefile.mk +++ b/dbaccess/util/makefile.mk @@ -137,13 +137,13 @@ SHL2STDLIBS= \ .IF "$(GUI)"!="WNT" || "$(COM)"=="GCC" SHL2STDLIBS+= \ -l$(TARGET)$(DLLPOSTFIX) +SHL2DEPN=$(SHL1TARGETN) .ELSE SHL2STDLIBS+= \ - i$(TARGET).lib + $(LB)$/i$(TARGET).lib +SHL2DEPN=$(LB)$/i$(TARGET).lib .ENDIF - -SHL2DEPN= SHL2IMPLIB=i$(TARGET2) SHL2LIBS=$(LIB2TARGET) SHL2DEF=$(MISC)$/$(SHL2TARGET).def -- cgit