summaryrefslogtreecommitdiff
path: root/dbaccess/qa/complex/dbaccess
diff options
context:
space:
mode:
Diffstat (limited to 'dbaccess/qa/complex/dbaccess')
-rw-r--r--dbaccess/qa/complex/dbaccess/ApplicationController.java176
-rw-r--r--dbaccess/qa/complex/dbaccess/Beamer.java191
-rw-r--r--dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java83
-rwxr-xr-xdbaccess/qa/complex/dbaccess/CopyTableInterActionHandler.java50
-rwxr-xr-xdbaccess/qa/complex/dbaccess/CopyTableWizard.java236
-rw-r--r--dbaccess/qa/complex/dbaccess/DataSource.java110
-rwxr-xr-xdbaccess/qa/complex/dbaccess/DatabaseApplication.java101
-rw-r--r--dbaccess/qa/complex/dbaccess/DatabaseDocument.java1034
-rw-r--r--dbaccess/qa/complex/dbaccess/FileHelper.java44
-rw-r--r--dbaccess/qa/complex/dbaccess/Parser.java208
-rw-r--r--dbaccess/qa/complex/dbaccess/PropertyBag.java294
-rw-r--r--dbaccess/qa/complex/dbaccess/Query.java126
-rw-r--r--dbaccess/qa/complex/dbaccess/QueryInQuery.java192
-rw-r--r--dbaccess/qa/complex/dbaccess/RowSet.java1026
-rw-r--r--dbaccess/qa/complex/dbaccess/RowSetEventListener.java111
-rwxr-xr-xdbaccess/qa/complex/dbaccess/SingleSelectQueryComposer.java395
-rw-r--r--dbaccess/qa/complex/dbaccess/TestCase.java126
-rw-r--r--dbaccess/qa/complex/dbaccess/UISettings.java152
-rw-r--r--dbaccess/qa/complex/dbaccess/dbaccess.sce12
-rwxr-xr-xdbaccess/qa/complex/dbaccess/makefile.mk78
20 files changed, 4745 insertions, 0 deletions
diff --git a/dbaccess/qa/complex/dbaccess/ApplicationController.java b/dbaccess/qa/complex/dbaccess/ApplicationController.java
new file mode 100644
index 000000000000..4c964e82dc06
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/ApplicationController.java
@@ -0,0 +1,176 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.frame.FrameSearchFlag;
+import com.sun.star.frame.XComponentLoader;
+import com.sun.star.frame.XModel;
+import com.sun.star.frame.XStorable;
+import com.sun.star.lang.XComponent;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.sdb.XOfficeDatabaseDocument;
+import com.sun.star.sdb.application.XDatabaseDocumentUI;
+import com.sun.star.sdbcx.XTablesSupplier;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+import connectivity.tools.HsqlColumnDescriptor;
+import connectivity.tools.HsqlDatabase;
+import connectivity.tools.HsqlTableDescriptor;
+import helper.URLHelper;
+import java.io.File;
+import java.io.IOException;
+
+/** complex test case for Base's application UI
+ */
+public class ApplicationController extends TestCase
+{
+
+ private HsqlDatabase m_database;
+ private XOfficeDatabaseDocument m_databaseDocument;
+ private XDatabaseDocumentUI m_documentUI;
+
+ public ApplicationController()
+ {
+ super();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+
+ public String[] getTestMethodNames()
+ {
+ return new String[]
+ {
+ "checkSaveAs"
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public String getTestObjectName()
+ {
+ return getClass().getName();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_closeDocument()
+ {
+ if (m_database != null)
+ {
+ m_database.close();
+ m_database = null;
+ m_databaseDocument = null;
+ m_documentUI = null;
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_switchToDocument(String _documentURL) throws java.lang.Exception
+ {
+ // close previous database document
+ impl_closeDocument();
+
+ // create/load the new database document
+ m_database = (_documentURL == null)
+ ? new HsqlDatabase(getORB())
+ : new HsqlDatabase(getORB(), _documentURL);
+ m_databaseDocument = m_database.getDatabaseDocument();
+
+ // load it into a frame
+ final Object object = getORB().createInstance("com.sun.star.frame.Desktop");
+ final XComponentLoader xComponentLoader = UnoRuntime.queryInterface(XComponentLoader.class, object);
+ final XComponent loadedComponent = xComponentLoader.loadComponentFromURL(m_database.getDocumentURL(), "_blank", FrameSearchFlag.ALL, new PropertyValue[0]);
+
+ assure("too many document instances!",
+ UnoRuntime.areSame(loadedComponent, m_databaseDocument));
+
+ // get the controller, which provides access to various UI operations
+ final XModel docModel = UnoRuntime.queryInterface(XModel.class,
+ loadedComponent);
+ m_documentUI = UnoRuntime.queryInterface(XDatabaseDocumentUI.class,
+ docModel.getCurrentController());
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void before() throws java.lang.Exception
+ {
+ super.before();
+ impl_switchToDocument(null);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void after() throws java.lang.Exception
+ {
+ impl_closeDocument();
+ super.after();
+ }
+ // --------------------------------------------------------------------------------------------------------
+
+ public void checkSaveAs() throws Exception, IOException, java.lang.Exception
+ {
+ // issue 93737 describes the problem that when you save-as a database document, and do changes to it,
+ // then those changes are saved in the old document, actually
+ final String oldDocumentURL = m_database.getDocumentURL();
+
+ final String newDocumentURL = createTempFileURL();
+
+ // store the doc in a new location
+ final XStorable storeDoc = UnoRuntime.queryInterface( XStorable.class, m_databaseDocument );
+ storeDoc.storeAsURL( newDocumentURL, new PropertyValue[] { } );
+
+ // connect
+ m_documentUI.connect();
+ assure("could not connect to " + m_database.getDocumentURL(), m_documentUI.isConnected());
+
+ // create a table in the database
+ m_database.createTable(new HsqlTableDescriptor("abc", new HsqlColumnDescriptor[]
+ {
+ new HsqlColumnDescriptor("a", "VARCHAR(50)"),
+ new HsqlColumnDescriptor("b", "VARCHAR(50)"),
+ new HsqlColumnDescriptor("c", "VARCHAR(50)")
+ }));
+
+ // load the old document, and verify there is *no* table therein
+ impl_switchToDocument(oldDocumentURL);
+ m_documentUI.connect();
+ assure("could not connect to " + m_database.getDocumentURL(), m_documentUI.isConnected());
+ XTablesSupplier suppTables = UnoRuntime.queryInterface( XTablesSupplier.class, m_documentUI.getActiveConnection() );
+ XNameAccess tables = suppTables.getTables();
+ assure("the table was created in the wrong database", !tables.hasByName("abc"));
+
+ // load the new document, and verify there *is* a table therein
+ impl_switchToDocument(newDocumentURL);
+ m_documentUI.connect();
+ assure("could not connect to " + m_database.getDocumentURL(), m_documentUI.isConnected());
+
+ suppTables = UnoRuntime.queryInterface( XTablesSupplier.class, m_documentUI.getActiveConnection() );
+ tables = suppTables.getTables();
+ assure("the newly created table has not been written", tables.hasByName("abc"));
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/Beamer.java b/dbaccess/qa/complex/dbaccess/Beamer.java
new file mode 100644
index 000000000000..909bf39d1707
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/Beamer.java
@@ -0,0 +1,191 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.beans.PropertyState;
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XEnumeration;
+import com.sun.star.container.XEnumerationAccess;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.frame.FrameSearchFlag;
+import com.sun.star.frame.XComponentLoader;
+import com.sun.star.frame.XController;
+import com.sun.star.frame.XDispatch;
+import com.sun.star.frame.XDispatchProvider;
+import com.sun.star.frame.XFrame;
+import com.sun.star.frame.XModel;
+import com.sun.star.frame.XStorable;
+import com.sun.star.lang.XComponent;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.sdb.CommandType;
+import com.sun.star.sdb.XDocumentDataSource;
+import com.sun.star.sdb.XOfficeDatabaseDocument;
+import com.sun.star.sdb.application.XDatabaseDocumentUI;
+import com.sun.star.sdbcx.XTablesSupplier;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+import com.sun.star.uno.XNamingService;
+import com.sun.star.util.URL;
+import com.sun.star.util.XCloseable;
+import com.sun.star.util.XURLTransformer;
+import com.sun.star.view.XSelectionSupplier;
+import connectivity.tools.DataSource;
+import connectivity.tools.HsqlColumnDescriptor;
+import connectivity.tools.HsqlDatabase;
+import connectivity.tools.HsqlTableDescriptor;
+import helper.URLHelper;
+import java.io.File;
+import java.io.IOException;
+import util.UITools;
+
+/** complex test case for Base's application UI
+ */
+public class Beamer extends complexlib.ComplexTestCase
+{
+
+ private XModel docModel;
+
+ public Beamer()
+ {
+ super();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ protected final XComponentContext getComponentContext()
+ {
+ XComponentContext context = null;
+ try
+ {
+ final 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 String[] getTestMethodNames()
+ {
+ return new String[]
+ {
+ "testBeamer"
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public String getTestObjectName()
+ {
+ return getClass().getName();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ protected final XMultiServiceFactory getORB()
+ {
+ return (XMultiServiceFactory) param.getMSF();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_closeDocument()
+ {
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void before() throws Exception, java.lang.Exception
+ {
+ // load it into a frame
+ final Object object = getORB().createInstance("com.sun.star.frame.Desktop");
+ final XComponentLoader xComponentLoader = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class, object);
+ final XComponent loadedComponent = xComponentLoader.loadComponentFromURL("private:factory/swriter", "_blank", 0, new PropertyValue[0]);
+ // get the controller, which provides access to various UI operations
+ docModel = (XModel) UnoRuntime.queryInterface(XModel.class, loadedComponent);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void after()
+ {
+ }
+ // --------------------------------------------------------------------------------------------------------
+
+ public void testBeamer() throws Exception, IOException, java.lang.Exception
+ {
+ final XController controller = docModel.getCurrentController();
+ final XFrame frame = controller.getFrame();
+ final XDispatchProvider dispatchP = (XDispatchProvider) UnoRuntime.queryInterface(XDispatchProvider.class, frame);
+ URL command = new URL();
+ // command.Complete = ".component:DB/DataSourceBrowser";
+ command.Complete = ".uno:ViewDataSourceBrowser";
+
+ Object instance = getORB().createInstance("com.sun.star.util.URLTransformer");
+ XURLTransformer atrans = (XURLTransformer) UnoRuntime.queryInterface(XURLTransformer.class, instance);
+ com.sun.star.util.URL[] aURLA = new com.sun.star.util.URL[1];
+ aURLA[0] = command;
+ atrans.parseStrict(aURLA);
+ command = aURLA[0];
+
+ final XDispatch dispatch = dispatchP.queryDispatch(command, "_self", FrameSearchFlag.AUTO);
+ assure(dispatch != null);
+ dispatch.dispatch(command, new PropertyValue[0]);
+
+ final PropertyValue[] props = new PropertyValue[]
+ {
+ new PropertyValue("DataSourceName", 0, "Bibliography", PropertyState.DIRECT_VALUE),
+ new PropertyValue("CommandType", 0, Integer.valueOf(CommandType.TABLE), PropertyState.DIRECT_VALUE),
+ new PropertyValue("Command", 0, "biblio", PropertyState.DIRECT_VALUE)
+ };
+
+ final XFrame beamer = frame.findFrame("_beamer", 0);
+ assure(beamer != null);
+ final XEnumerationAccess evtBc = (XEnumerationAccess) UnoRuntime.queryInterface(XEnumerationAccess.class, getORB().createInstance("com.sun.star.frame.GlobalEventBroadcaster"));
+ XEnumeration enumeration = evtBc.createEnumeration();
+ int count = -1;
+ while (enumeration.hasMoreElements())
+ {
+ enumeration.nextElement();
+ ++count;
+ }
+ final XSelectionSupplier selSup = (XSelectionSupplier)UnoRuntime.queryInterface(XSelectionSupplier.class, beamer.getController());
+ selSup.select(props);
+ final com.sun.star.util.XCloseable close = (com.sun.star.util.XCloseable)UnoRuntime.queryInterface(com.sun.star.util.XCloseable.class, frame);
+ close.close(false);
+
+ enumeration = evtBc.createEnumeration();
+ int count2 = 0;
+ while (enumeration.hasMoreElements())
+ {
+ enumeration.nextElement();
+ ++count2;
+ }
+
+ assure("count1 = " + count + " count2 = " + count2, count == count2);
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java b/dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java
new file mode 100644
index 000000000000..3bba8fa45001
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java
@@ -0,0 +1,83 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.sdb.XSingleSelectQueryComposer;
+import com.sun.star.uno.UnoRuntime;
+import connectivity.tools.CRMDatabase;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public abstract class CRMBasedTestCase extends TestCase
+{
+ protected CRMDatabase m_database;
+
+ // --------------------------------------------------------------------------------------------------------
+ protected void createTestCase()
+ {
+ try
+ {
+ m_database = new CRMDatabase( getORB(), false );
+ }
+ catch ( Exception e )
+ {
+ e.printStackTrace( System.err );
+ assure( "caught an exception (" + e.getMessage() + ") while creating the test case", false );
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @Override
+ public void before()
+ {
+ createTestCase();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @Override
+ public void after()
+ {
+ try
+ {
+ if ( m_database != null )
+ m_database.saveAndClose();
+ }
+ catch ( Exception ex )
+ {
+ Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, null, ex );
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** creates a SingleSelectQueryComposer for our connection
+ */
+ protected final XSingleSelectQueryComposer createQueryComposer() throws com.sun.star.uno.Exception
+ {
+ return m_database.getConnection().createSingleSelectQueryComposer();
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/CopyTableInterActionHandler.java b/dbaccess/qa/complex/dbaccess/CopyTableInterActionHandler.java
new file mode 100755
index 000000000000..53527e356f78
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/CopyTableInterActionHandler.java
@@ -0,0 +1,50 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.lib.uno.helper.WeakBase;
+import com.sun.star.task.XInteractionHandler;
+import com.sun.star.task.XInteractionRequest;
+
+/**
+ *
+ * @author oj93728
+ */
+class CopyTableInterActionHandler extends WeakBase
+ implements XInteractionHandler
+{
+ private final CopyTableWizard test;
+ public CopyTableInterActionHandler(CopyTableWizard testCase)
+ {
+ test = testCase;
+ }
+
+ public void handle(XInteractionRequest xRequest)
+ {
+ test.assure(xRequest.toString());
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/CopyTableWizard.java b/dbaccess/qa/complex/dbaccess/CopyTableWizard.java
new file mode 100755
index 000000000000..7c3db7f6020d
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/CopyTableWizard.java
@@ -0,0 +1,236 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.awt.XExtendedToolkit;
+import com.sun.star.awt.XWindow;
+import com.sun.star.beans.Optional;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.sdb.CommandType;
+import com.sun.star.sdb.application.XCopyTableWizard;
+import com.sun.star.sdb.DataAccessDescriptorFactory;
+import com.sun.star.sdbc.XConnection;
+import com.sun.star.sdbcx.XTablesSupplier;
+import com.sun.star.task.XInteractionHandler;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+import connectivity.tools.DbaseDatabase;
+import java.io.IOException;
+import util.UITools;
+
+/** complex test case for Base's application UI
+ */
+public class CopyTableWizard extends CRMBasedTestCase
+{
+
+ private DatabaseApplication source;
+ private DatabaseApplication dest;
+
+ public CopyTableWizard()
+ {
+ super();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public String[] getTestMethodNames()
+ {
+ return new String[]
+ {
+ "copyTable", "copyTableDbase"
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @Override
+ public String getTestObjectName()
+ {
+ return getClass().getName();
+ }
+// --------------------------------------------------------------------------------------------------------
+ // --------------------------------------------------------------------------------------------------------
+
+ @Override
+ public void after()
+ {
+ dest.store();
+ super.after();
+ }
+
+ @Override
+ public void before()
+ {
+ try
+ {
+ createTestCase();
+ source = new DatabaseApplication(this.m_database.getDatabase());
+ dest = new DatabaseApplication(new DbaseDatabase(getORB()));
+ }
+ catch (java.lang.Exception ex)
+ {
+ assure(false);
+ }
+ }
+ // --------------------------------------------------------------------------------------------------------
+
+
+
+ class CopyThread implements Runnable
+ {
+
+ final XCopyTableWizard copyWizard;
+
+ public CopyThread(final XCopyTableWizard copyWizard)
+ {
+ this.copyWizard = copyWizard;
+ }
+
+ public void run()
+ {
+ copyWizard.execute();
+ }
+ }
+
+ private XWindow getActiveWindow()
+ {
+ Object toolKit = null;
+ try
+ {
+ toolKit = getORB().createInstance("com.sun.star.awt.Toolkit");
+ }
+ catch (com.sun.star.uno.Exception e)
+ {
+ return null;
+ }
+
+ XExtendedToolkit tk = (XExtendedToolkit) UnoRuntime.queryInterface(XExtendedToolkit.class, toolKit);
+ Object atw = tk.getActiveTopWindow();
+ return (XWindow) UnoRuntime.queryInterface(XWindow.class, atw);
+ }
+
+ public void copyTable() throws Exception, IOException, java.lang.Exception
+ {
+ copyTable(source,source);
+ }
+
+ public void copyTableDbase() throws Exception, IOException, java.lang.Exception
+ {
+ copyTable(source,dest);
+ }
+ public void copyTable(final DatabaseApplication sourceDb,final DatabaseApplication destDb) throws Exception, IOException, java.lang.Exception
+ {
+ final XConnection destConnection = destDb.getDocumentUI().getActiveConnection();
+
+ final XConnection sourceConnection = sourceDb.getDocumentUI().getActiveConnection();
+ final XTablesSupplier suppTables = (XTablesSupplier) UnoRuntime.queryInterface(XTablesSupplier.class, sourceConnection);
+ final XNameAccess tables = suppTables.getTables();
+
+ final String[] names = tables.getElementNames();
+ for (int i = 0; i < names.length; i++)
+ {
+ copyTable(names[i], sourceConnection, destConnection);
+ }
+ }
+
+ public void assure(final String message)
+ {
+ assure(message, false);
+ }
+
+ private void copyTable(final String tableName, final XConnection sourceConnection, final XConnection destConnection) throws Exception, IOException, java.lang.Exception
+ {
+
+ final XInteractionHandler interAction = new CopyTableInterActionHandler(this);
+ final XComponentContext context = getComponentContext();
+ final XPropertySet sourceDescriptor = DataAccessDescriptorFactory.get(context).createDataAccessDescriptor();
+ sourceDescriptor.setPropertyValue("CommandType", CommandType.TABLE);
+ sourceDescriptor.setPropertyValue("Command", tableName);
+ sourceDescriptor.setPropertyValue("ActiveConnection", sourceConnection);
+
+ final XPropertySet destDescriptor = DataAccessDescriptorFactory.get(context).createDataAccessDescriptor();
+ destDescriptor.setPropertyValue("ActiveConnection", destConnection);
+
+ final XCopyTableWizard copyWizard = com.sun.star.sdb.application.CopyTableWizard.createWithInteractionHandler(context, sourceDescriptor, destDescriptor, interAction);
+ copyWizard.setOperation((short) 0); // com.sun.star.sdb.application.CopyDefinitionAndData
+ Optional<String> auto = new Optional<String>();
+
+ auto.IsPresent = destConnection.getMetaData().supportsCoreSQLGrammar();
+ if (auto.IsPresent)
+ {
+ auto.Value = "ID_test";
+ }
+ copyWizard.setCreatePrimaryKey(auto);
+ Thread thread = new Thread(new CopyThread(copyWizard));
+ thread.start();
+ sleep();
+
+ try
+ {
+ final XWindow dialog = getActiveWindow();
+ final UITools uiTools = new UITools(getORB(), dialog);
+ final XAccessible root = uiTools.getRoot();
+ final XAccessibleContext accContext = root.getAccessibleContext();
+ final int count = accContext.getAccessibleChildCount();
+ String buttonName = "Create";
+ final XAccessibleContext childContext = accContext.getAccessibleChild(count - 3).getAccessibleContext();
+ final String name = childContext.getAccessibleName();
+ if (name != null && !"".equals(name))
+ {
+ buttonName = name;
+ }
+ try
+ {
+ uiTools.clickButton(buttonName);
+ }
+ catch (java.lang.Exception exception)
+ {
+ exception.printStackTrace();
+ }
+ }
+ catch (com.sun.star.lang.IndexOutOfBoundsException indexOutOfBoundsException)
+ {
+ }
+ sleep();
+
+ thread.join();
+ }
+
+ private void sleep()
+ {
+ try
+ {
+ Thread.sleep(500);
+ }
+ catch (java.lang.InterruptedException e)
+ {
+ }
+ }
+ // --------------------------------------------------------------------------------------------------------
+}
diff --git a/dbaccess/qa/complex/dbaccess/DataSource.java b/dbaccess/qa/complex/dbaccess/DataSource.java
new file mode 100644
index 000000000000..f74d5af8d8f0
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/DataSource.java
@@ -0,0 +1,110 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XNamingService;
+import complexlib.ComplexTestCase;
+import connectivity.tools.CRMDatabase;
+import connectivity.tools.HsqlDatabase;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class DataSource extends ComplexTestCase
+{
+
+ HsqlDatabase m_database;
+ connectivity.tools.DataSource m_dataSource;
+
+ // --------------------------------------------------------------------------------------------------------
+ public String[] getTestMethodNames()
+ {
+ return new String[]
+ {
+ "testRegistrationName"
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public String getTestObjectName()
+ {
+ return "DataSource";
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void createTestCase()
+ {
+ try
+ {
+ if (m_database == null)
+ {
+ final CRMDatabase database = new CRMDatabase( getFactory(), false );
+ m_database = database.getDatabase();
+ m_dataSource = m_database.getDataSource();
+ }
+ }
+ catch (Exception e)
+ {
+ failed("could not create the test case, error message:\n" + e.getMessage());
+ }
+ catch (java.lang.Exception e)
+ {
+ failed("could not create the test case, error message:\n" + e.getMessage());
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private XMultiServiceFactory getFactory()
+ {
+ return (XMultiServiceFactory) param.getMSF();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void testRegistrationName()
+ {
+ try
+ {
+ createTestCase();
+ // 1. check the existing "Bibliography" data source whether it has the proper name
+ String dataSourceName = "Bibliography";
+ final connectivity.tools.DataSource bibliography = new connectivity.tools.DataSource(getFactory(), dataSourceName);
+ assureEquals("pre-registered database has a wrong name!", dataSourceName, bibliography.getName());
+ // 2. register a newly created data source, and verify it has the proper name
+ dataSourceName = "someDataSource";
+ final XNamingService dataSourceRegistrations = (XNamingService) UnoRuntime.queryInterface(
+ XNamingService.class, getFactory().createInstance("com.sun.star.sdb.DatabaseContext"));
+ dataSourceRegistrations.registerObject("someDataSource", m_dataSource.getXDataSource());
+ assureEquals("registration name of a newly registered data source is wrong", dataSourceName, m_dataSource.getName());
+ }
+ catch (Exception ex)
+ {
+ Logger.getLogger(DataSource.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/DatabaseApplication.java b/dbaccess/qa/complex/dbaccess/DatabaseApplication.java
new file mode 100755
index 000000000000..d6bfa804eafa
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/DatabaseApplication.java
@@ -0,0 +1,101 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.frame.FrameSearchFlag;
+import com.sun.star.frame.XComponentLoader;
+import com.sun.star.frame.XModel;
+import com.sun.star.frame.XStorable;
+import com.sun.star.lang.XComponent;
+import com.sun.star.sdb.XOfficeDatabaseDocument;
+import com.sun.star.sdb.application.XDatabaseDocumentUI;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import connectivity.tools.DatabaseAccess;
+
+/**
+ *
+ * @author oj93728
+ */
+public class DatabaseApplication
+{
+
+ private final XOfficeDatabaseDocument databaseDocument;
+ private final XDatabaseDocumentUI documentUI;
+ private final DatabaseAccess db;
+
+ public DatabaseApplication(final DatabaseAccess _db) throws Exception
+ {
+ db = _db;
+ databaseDocument = db.getDatabaseDocument();
+
+ // load it into a frame
+ final Object object = db.getORB().createInstance("com.sun.star.frame.Desktop");
+ final XComponentLoader xComponentLoader = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class, object);
+ final XComponent loadedComponent = xComponentLoader.loadComponentFromURL(db.getDocumentURL(), "_blank", FrameSearchFlag.ALL, new PropertyValue[0]);
+
+ // get the controller, which provides access to various UI operations
+ final XModel docModel = (XModel) UnoRuntime.queryInterface(XModel.class,
+ loadedComponent);
+ documentUI = (XDatabaseDocumentUI) UnoRuntime.queryInterface(XDatabaseDocumentUI.class,
+ docModel.getCurrentController());
+ documentUI.connect();
+ }
+
+ public XOfficeDatabaseDocument getDatabaseDocument()
+ {
+ return databaseDocument;
+ }
+
+ public XDatabaseDocumentUI getDocumentUI()
+ {
+ return documentUI;
+ }
+
+ public DatabaseAccess getDb()
+ {
+ return db;
+ }
+
+ public void store()
+ {
+ // store the doc in a new location
+ try
+ {
+ final XStorable storeDoc = (XStorable) UnoRuntime.queryInterface(XStorable.class,
+ databaseDocument);
+ if (storeDoc != null)
+ {
+ storeDoc.store();
+ }
+ }
+ catch (com.sun.star.io.IOException iOException)
+ {
+ }
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/DatabaseDocument.java b/dbaccess/qa/complex/dbaccess/DatabaseDocument.java
new file mode 100644
index 000000000000..02fb820f3fd4
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/DatabaseDocument.java
@@ -0,0 +1,1034 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+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.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.XDocumentDataSource;
+import com.sun.star.sdbc.XDataSource;
+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 java.io.IOException;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class DatabaseDocument extends TestCase implements com.sun.star.document.XDocumentEventListener
+{
+
+ private static final String _BLANK = "_blank";
+ private XComponent m_callbackFactory = null;
+ private final ArrayList m_documentEvents = new ArrayList();
+ private final ArrayList m_globalEvents = new ArrayList();
+ // 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()
+ {
+ final 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 final ArrayList m_eventListeners = new ArrayList();
+
+ 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()
+ {
+ final EventObject event = new EventObject(this);
+
+ final ArrayList eventListenersCopy = (ArrayList) m_eventListeners.clone();
+ final 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.task.InteractionHandler"));
+ }
+ catch (Exception ex)
+ {
+ Logger.getLogger(DatabaseDocument.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ public void handle(XInteractionRequest _request)
+ {
+ final 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
+ final XInteractionContinuation continuations[] = _request.getContinuations();
+ for (int i = 0; i < continuations.length; ++i)
+ {
+ final XInteractionApprove approve = (XInteractionApprove) UnoRuntime.queryInterface(XInteractionApprove.class,
+ continuations[i]);
+ if (approve != null)
+ {
+ approve.select();
+ m_loadDocState = STATE_MACRO_EXEC_APPROVED;
+ break;
+ }
+ }
+ }
+ };
+
+ // ========================================================================================================
+ // --------------------------------------------------------------------------------------------------------
+ public String[] getTestMethodNames()
+ {
+ return new String[]
+ {
+ "testLoadable",
+ "testDocumentRevenants",
+ "testDocumentEvents",
+ "testGlobalEvents"
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public String getTestObjectName()
+ {
+ return "DatabaseDocument";
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void before() throws java.lang.Exception
+ {
+ super.before();
+
+ try
+ {
+ // at our service factory, insert a new factory for our CallbackComponent
+ // this will allow the Basic code in our test documents to call back into this test case
+ // here, by just instantiating this service
+ final XSet globalFactory = (XSet) UnoRuntime.queryInterface(
+ XSet.class, getORB());
+ m_callbackFactory = new CallbackComponentFactory();
+ globalFactory.insert(m_callbackFactory);
+
+ // register ourself as listener at the global event broadcaster
+ final XDocumentEventBroadcaster broadcaster = (XDocumentEventBroadcaster) UnoRuntime.queryInterface(
+ XDocumentEventBroadcaster.class, getORB().createInstance("com.sun.star.frame.GlobalEventBroadcaster"));
+ broadcaster.addDocumentEventListener(this);
+ }
+ catch (Exception e)
+ {
+ log.println("could not create the test case, error message:\n" + e.getMessage());
+ e.printStackTrace(System.err);
+ failed("failed to create the test case");
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void after() throws java.lang.Exception
+ {
+ try
+ {
+ // dispose our callback factory. This will automatically remove it from our service
+ // factory
+ m_callbackFactory.dispose();
+
+ // revoke ourself as listener at the global event broadcaster
+ final XDocumentEventBroadcaster broadcaster = (XDocumentEventBroadcaster) UnoRuntime.queryInterface(
+ XDocumentEventBroadcaster.class, getORB().createInstance("com.sun.star.frame.GlobalEventBroadcaster"));
+ broadcaster.removeDocumentEventListener(this);
+ }
+ catch (Exception e)
+ {
+ log.println("could not create the test case, error message:\n" + e.getMessage());
+ e.printStackTrace(System.err);
+ failed("failed to close the test case");
+ }
+
+ super.after();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private static class UnoMethodDescriptor
+ {
+
+ public Class unoInterfaceClass = null;
+ public String methodName = null;
+
+ public UnoMethodDescriptor(Class _class, String _method)
+ {
+ unoInterfaceClass = _class;
+ methodName = _method;
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_checkDocumentInitState(Object _document, boolean _isInitialized)
+ {
+ // things you cannot do with an uninitialized document:
+ final UnoMethodDescriptor[] unsupportedMethods = new UnoMethodDescriptor[]
+ {
+ new UnoMethodDescriptor(XStorable.class, "store"),
+ new UnoMethodDescriptor(XFormDocumentsSupplier.class, "getFormDocuments"),
+ new UnoMethodDescriptor(XReportDocumentsSupplier.class, "getReportDocuments"),
+ new UnoMethodDescriptor(XScriptProviderSupplier.class, "getScriptProvider"),
+ new UnoMethodDescriptor(XEventsSupplier.class, "getEvents"),
+ new UnoMethodDescriptor(XTitle.class, "getTitle"),
+ new UnoMethodDescriptor(XModel2.class, "getControllers")
+ // (there's much more than this, but we cannot list all methods here, can we ...)
+ };
+
+ for (int i = 0; i < unsupportedMethods.length; ++i)
+ {
+ assureException( _document, unsupportedMethods[i].unoInterfaceClass,
+ unsupportedMethods[i].methodName, new Object[]{}, _isInitialized ? null : NotInitializedException.class );
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private XModel impl_createDocument() throws Exception
+ {
+ final XModel databaseDoc = (XModel) UnoRuntime.queryInterface(XModel.class,
+ getORB().createInstance("com.sun.star.sdb.OfficeDatabaseDocument"));
+
+ // should not be initialized here - we did neither initNew nor load nor storeAsURL it
+ impl_checkDocumentInitState(databaseDoc, false);
+
+ return databaseDoc;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_closeDocument(XModel _databaseDoc) throws CloseVetoException, IOException, Exception
+ {
+ final XCloseable closeDoc = (XCloseable) UnoRuntime.queryInterface(XCloseable.class,
+ _databaseDoc);
+ closeDoc.close(true);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private XModel impl_createEmptyEmbeddedHSQLDocument() throws Exception, IOException
+ {
+ final XModel databaseDoc = (XModel) UnoRuntime.queryInterface(XModel.class,
+ getORB().createInstance("com.sun.star.sdb.OfficeDatabaseDocument"));
+ final XStorable storeDoc = (XStorable) UnoRuntime.queryInterface(XStorable.class, databaseDoc);
+
+ // verify the document rejects API calls which require it to be initialized
+ impl_checkDocumentInitState(databaseDoc, false);
+
+ // though the document is not initialized, you can ask for the location, the URL, and the args
+ final String location = storeDoc.getLocation();
+ final String url = databaseDoc.getURL();
+ final PropertyValue[] args = databaseDoc.getArgs();
+ // they should be all empty at this time
+ assureEquals("location is expected to be empty here", "", location);
+ assureEquals("URL is expected to be empty here", "", url);
+ assureEquals("Args are expected to be empty here", 0, args.length);
+
+ // and, you should be able to set properties at the data source
+ final XOfficeDatabaseDocument dataSourceAccess = (XOfficeDatabaseDocument) UnoRuntime.queryInterface(
+ XOfficeDatabaseDocument.class, databaseDoc);
+ final XPropertySet dsProperties = (XPropertySet) UnoRuntime.queryInterface(
+ XPropertySet.class, dataSourceAccess.getDataSource());
+ dsProperties.setPropertyValue("URL", "sdbc:embedded:hsqldb");
+
+ final String documentURL = createTempFileURL();
+ storeDoc.storeAsURL(documentURL, new PropertyValue[0]);
+
+ // now that the document is stored, ...
+ // ... its URL should be correct
+ assureEquals("wrong URL after storing the document", documentURL, databaseDoc.getURL());
+ // ... it should be initialized
+ impl_checkDocumentInitState(databaseDoc, true);
+
+ return databaseDoc;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void testLoadable() throws Exception, IOException
+ {
+ XModel databaseDoc = impl_createEmptyEmbeddedHSQLDocument();
+ String documentURL = databaseDoc.getURL();
+
+ // there's three methods how you can initialize a database document:
+
+ // ....................................................................
+ // 1. XStorable::storeAsURL
+ // (this is for compatibility reasons, to not break existing code)
+ // this test is already made in impl_createEmptyEmbeddedHSQLDocument
+
+ // ....................................................................
+ // 2. XLoadable::load
+ databaseDoc = (XModel) UnoRuntime.queryInterface(XModel.class,
+ getORB().createInstance("com.sun.star.sdb.OfficeDatabaseDocument"));
+ documentURL = copyToTempFile(documentURL);
+ // load the doc, and verify it's initialized then, and has the proper URL
+ XLoadable loadDoc = (XLoadable) UnoRuntime.queryInterface(XLoadable.class, databaseDoc);
+ loadDoc.load(new PropertyValue[]
+ {
+ new PropertyValue("URL", 0, documentURL, PropertyState.DIRECT_VALUE)
+ });
+ databaseDoc.attachResource(documentURL, new PropertyValue[0]);
+
+ assureEquals("wrong URL after loading the document", documentURL, databaseDoc.getURL());
+ impl_checkDocumentInitState(databaseDoc, true);
+
+ // and while we are here ... initilizing the same document again should not be possible
+ assureException( databaseDoc, XLoadable.class, "initNew", new Object[0],
+ DoubleInitializationException.class );
+ assureException( databaseDoc, XLoadable.class, "load", new Object[] { new PropertyValue[0] },
+ DoubleInitializationException.class );
+
+ // ....................................................................
+ // 3. XLoadable::initNew
+ impl_closeDocument(databaseDoc);
+ databaseDoc = impl_createDocument();
+ loadDoc = (XLoadable) UnoRuntime.queryInterface(XLoadable.class, databaseDoc);
+ loadDoc.initNew();
+ assureEquals("wrong URL after initializing the document", "", databaseDoc.getURL());
+ impl_checkDocumentInitState(databaseDoc, true);
+
+ // same as above - initializing the document a second time must fail
+ assureException( databaseDoc, XLoadable.class, "initNew", new Object[0],
+ DoubleInitializationException.class );
+ assureException( databaseDoc, XLoadable.class, "load", new Object[] { new PropertyValue[0] },
+ DoubleInitializationException.class );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private PropertyValue[] impl_getMarkerLoadArgs()
+ {
+ return new PropertyValue[]
+ {
+ new PropertyValue( "PickListEntry", 0, false, PropertyState.DIRECT_VALUE ),
+ new PropertyValue( "TestCase_Marker", 0, "Yes", PropertyState.DIRECT_VALUE )
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private boolean impl_hasMarker( final PropertyValue[] _args )
+ {
+ for ( int i=0; i<_args.length; ++i )
+ {
+ if ( _args[i].Name.equals( "TestCase_Marker" ) && _args[i].Value.equals( "Yes" ) )
+ return true;
+ }
+ return false;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private PropertyValue[] impl_getDefaultLoadArgs()
+ {
+ return new PropertyValue[]
+ {
+ new PropertyValue("PickListEntry", 0, false, PropertyState.DIRECT_VALUE)
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private PropertyValue[] impl_getMacroExecLoadArgs()
+ {
+ return new PropertyValue[]
+ {
+ new PropertyValue("PickListEntry", 0, false, PropertyState.DIRECT_VALUE),
+ new PropertyValue("MacroExecutionMode", 0, com.sun.star.document.MacroExecMode.USE_CONFIG, PropertyState.DIRECT_VALUE),
+ new PropertyValue("InteractionHandler", 0, new MacroExecutionApprove(getORB()), PropertyState.DIRECT_VALUE)
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private int impl_setMacroSecurityLevel(int _level) throws Exception
+ {
+ final XMultiServiceFactory configProvider = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class,
+ getORB().createInstance("com.sun.star.configuration.ConfigurationProvider"));
+
+ final PropertyValue[] args = new PropertyValue[]
+ {
+ new PropertyValue("nodepath", 0, "/org.openoffice.Office.Common/Security/Scripting", PropertyState.DIRECT_VALUE)
+ };
+
+ final XPropertySet securitySettings = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class,
+ configProvider.createInstanceWithArguments("com.sun.star.configuration.ConfigurationUpdateAccess", args));
+ final int oldValue = ((Integer) securitySettings.getPropertyValue("MacroSecurityLevel")).intValue();
+ securitySettings.setPropertyValue("MacroSecurityLevel", Integer.valueOf(_level));
+
+ final XChangesBatch committer = (XChangesBatch) UnoRuntime.queryInterface(XChangesBatch.class,
+ securitySettings);
+ committer.commitChanges();
+
+ return oldValue;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private XModel impl_loadDocument( final String _documentURL, final PropertyValue[] _loadArgs ) throws Exception
+ {
+ final XComponentLoader loader = (XComponentLoader) UnoRuntime.queryInterface( XComponentLoader.class,
+ getORB().createInstance("com.sun.star.frame.Desktop") );
+ return (XModel) UnoRuntime.queryInterface( XModel.class,
+ loader.loadComponentFromURL( _documentURL, _BLANK, 0, _loadArgs ) );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_storeDocument( final XModel _document ) throws Exception, IOException
+ {
+ // store the document
+ final String documentURL = FileHelper.getOOoCompatibleFileURL( _document.getURL() );
+ final XStorable storeDoc = (XStorable) UnoRuntime.queryInterface( XStorable.class,
+ _document );
+ storeDoc.store();
+
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private XModel impl_createDocWithMacro( final String _libName, final String _moduleName, final String _code ) throws Exception, IOException
+ {
+ // create an empty document
+ XModel databaseDoc = impl_createEmptyEmbeddedHSQLDocument();
+
+ // create Basic library/module therein
+ final XEmbeddedScripts embeddedScripts = (XEmbeddedScripts) UnoRuntime.queryInterface(XEmbeddedScripts.class,
+ databaseDoc);
+ final XStorageBasedLibraryContainer basicLibs = embeddedScripts.getBasicLibraries();
+ final XNameContainer newLib = basicLibs.createLibrary( _libName );
+ newLib.insertByName( _moduleName, _code );
+
+ return databaseDoc;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** tests various aspects of database document "revenants"
+ *
+ * Well, I do not really have a good term for this ... The point is, database documents are in real
+ * only *one* aspect of a more complex thing. The second aspect is a data source. Both, in some sense,
+ * just represent different views on the same thing. For a given database, there's at each time at most
+ * one data source, and at most one database document. Both have a independent life time, and are
+ * created when needed.
+ * In particular, a document can be closed (this is what happens when the last UI window displaying
+ * this document is closed), and then dies. Now when the other "view", the data source, still exists,
+ * the the underlying document data is not discarded, but kept alive (else the data source would die
+ * just because the document dies, which is not desired). If the document is loaded, again, then
+ * it is re-created, using the data of its previous "incarnation".
+ *
+ * This method here tests some of those aspects of a document which should survive the death of one
+ * instance and re-creation as a revenant.
+ */
+ public void testDocumentRevenants() throws Exception, IOException
+ {
+ // create an empty document
+ XModel databaseDoc = impl_createDocWithMacro( "Lib", "Module",
+ "Sub Hello\n" +
+ " MsgBox \"Hello\"\n" +
+ "End Sub\n"
+ );
+ impl_storeDocument( databaseDoc );
+ final String documentURL = databaseDoc.getURL();
+
+ // at this stage, the marker should not yet be present in the doc's args, else some of the below
+ // tests become meaningless
+ assure( "A newly created doc should not have the test case marker", !impl_hasMarker( databaseDoc.getArgs() ) );
+
+ // obtain the DataSource associated with the document. Keeping this alive
+ // ensures that the "impl data" of the document is kept alive, too, so when closing
+ // and re-opening it, this "impl data" must be re-used.
+ XDocumentDataSource dataSource = (XDocumentDataSource)UnoRuntime.queryInterface( XDocumentDataSource.class,
+ ((XOfficeDatabaseDocument)UnoRuntime.queryInterface(
+ XOfficeDatabaseDocument.class, databaseDoc )).getDataSource() );
+
+ // close and reload the doc
+ impl_closeDocument(databaseDoc);
+ databaseDoc = impl_loadDocument( documentURL, impl_getMarkerLoadArgs() );
+ // since we just put the marker into the load-call, it should be present at the doc
+ assure( "The test case marker got lost.", impl_hasMarker( databaseDoc.getArgs() ) );
+
+ // The basic library should have survived
+ final XEmbeddedScripts embeddedScripts = (XEmbeddedScripts) UnoRuntime.queryInterface(XEmbeddedScripts.class,
+ databaseDoc);
+ final XStorageBasedLibraryContainer basicLibs = embeddedScripts.getBasicLibraries();
+ assure( "Baisc lib did not survive reloading a closed document", basicLibs.hasByName( "Lib" ) );
+ final XNameContainer lib = (XNameContainer)UnoRuntime.queryInterface(
+ XNameContainer.class, basicLibs.getByName( "Lib" ) );
+ assure( "Basic module did not survive reloading a closed document", lib.hasByName( "Module" ) );
+
+ // now closing the doc, and obtaining it from the data source, should preserve the marker we put into the load
+ // args
+ impl_closeDocument( databaseDoc );
+ databaseDoc = (XModel)UnoRuntime.queryInterface( XModel.class, dataSource.getDatabaseDocument() );
+ assure( "The test case marker did not survive re-retrieval of the doc from the data source.",
+ impl_hasMarker( databaseDoc.getArgs() ) );
+
+ // on the other hand, closing and regurlarly re-loading the doc *without* the marker should indeed
+ // lose it
+ impl_closeDocument( databaseDoc );
+ databaseDoc = impl_loadDocument( documentURL, impl_getDefaultLoadArgs() );
+ assure( "Reloading the document kept the old args, instead of the newly supplied ones.",
+ !impl_hasMarker( databaseDoc.getArgs() ) );
+
+ // clean up
+ impl_closeDocument( databaseDoc );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void testDocumentEvents() throws Exception, IOException
+ {
+ // create an empty document
+ final String libName = "EventHandlers";
+ final String moduleName = "all";
+ final String eventHandlerCode =
+ "Option Explicit\n" +
+ "\n" +
+ "Sub OnLoad\n" +
+ " Dim oCallback as Object\n" +
+ " oCallback = createUnoService( \"" + getCallbackComponentServiceName() + "\" )\n" +
+ "\n" +
+ " ' as long as the Document is not passed to the Basic callbacks, we need to create\n" +
+ " ' one ourself\n" +
+ " Dim oEvent as new com.sun.star.document.DocumentEvent\n" +
+ " oEvent.EventName = \"OnLoad\"\n" +
+ " oEvent.Source = ThisComponent\n" +
+ "\n" +
+ " oCallback.documentEventOccured( oEvent )\n" +
+ "End Sub\n";
+ XModel databaseDoc = impl_createDocWithMacro( libName, moduleName, eventHandlerCode );
+ final String documentURL = databaseDoc.getURL();
+
+ // bind the macro to the OnLoad event
+ final String macroURI = "vnd.sun.star.script:" + libName + "." + moduleName + ".OnLoad?language=Basic&location=document";
+ final XEventsSupplier eventsSupplier = (XEventsSupplier) UnoRuntime.queryInterface(XEventsSupplier.class,
+ databaseDoc);
+ eventsSupplier.getEvents().replaceByName("OnLoad", new PropertyValue[]
+ {
+ new PropertyValue("EventType", 0, "Script", PropertyState.DIRECT_VALUE),
+ new PropertyValue("Script", 0, macroURI, PropertyState.DIRECT_VALUE)
+ });
+
+ // store the document, and close it
+ impl_storeDocument( databaseDoc );
+ impl_closeDocument( databaseDoc );
+
+ // ensure the macro security configuration is "ask the user for document macro execution"
+ final int oldSecurityLevel = impl_setMacroSecurityLevel(1);
+
+ // load it, again
+ m_loadDocState = STATE_LOADING_DOC;
+ // expected order of states is:
+ // STATE_LOADING_DOC - initialized here
+ // STATE_MACRO_EXEC_APPROVED - done in our interaction handler, which auto-approves the execution of macros
+ // STATE_ON_LOAD_RECEIVED - done in our callback for the document events
+ //
+ // In particular, it is important that the interaction handler (which plays the role of the user confirmation
+ // here) is called before the OnLoad notification is received - since the latter happens from within
+ // a Basic macro which is bound to the OnLoad event of the document.
+
+ final String context = "OnLoad";
+ impl_startObservingEvents(context);
+ databaseDoc = impl_loadDocument( documentURL, impl_getMacroExecLoadArgs() );
+ impl_stopObservingEvents(m_documentEvents, new String[]
+ {
+ "OnLoad"
+ }, context);
+
+ assureEquals("our provided interaction handler was not called", STATE_ON_LOAD_RECEIVED, m_loadDocState);
+
+ // restore macro security level
+ impl_setMacroSecurityLevel(oldSecurityLevel);
+
+ // close the document
+ impl_closeDocument(databaseDoc);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void testGlobalEvents() throws Exception, IOException
+ {
+ XModel databaseDoc = impl_createEmptyEmbeddedHSQLDocument();
+ final XStorable storeDoc = (XStorable) UnoRuntime.queryInterface(XStorable.class,
+ databaseDoc);
+
+ String context, newURL;
+
+ // XStorable.store
+ final String oldURL = databaseDoc.getURL();
+ context = "store";
+ impl_startObservingEvents(context);
+ storeDoc.store();
+ assureEquals("store is not expected to change the document URL", databaseDoc.getURL(), oldURL);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnSave", "OnSaveDone"
+ }, context);
+
+ // XStorable.storeToURL
+ context = "storeToURL";
+ impl_startObservingEvents(context);
+ storeDoc.storeToURL(createTempFileURL(), new PropertyValue[0]);
+ assureEquals("storetoURL is not expected to change the document URL", databaseDoc.getURL(), oldURL);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnSaveTo", "OnSaveToDone"
+ }, context);
+
+ // XStorable.storeAsURL
+ newURL = createTempFileURL();
+ context = "storeAsURL";
+ impl_startObservingEvents(context);
+ storeDoc.storeAsURL(newURL, new PropertyValue[0]);
+ assureEquals("storeAsURL is expected to change the document URL", databaseDoc.getURL(), newURL);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnSaveAs", "OnSaveAsDone"
+ }, context);
+
+ // XModifiable.setModified
+ final XModifiable modifyDoc = (XModifiable) UnoRuntime.queryInterface(XModifiable.class,
+ databaseDoc);
+ context = "setModified";
+ impl_startObservingEvents(context);
+ modifyDoc.setModified(true);
+ assureEquals("setModified didn't work", modifyDoc.isModified(), true);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnModifyChanged"
+ }, context);
+
+ // XStorable.store, with implicit reset of the "Modified" flag
+ context = "store (2)";
+ impl_startObservingEvents(context);
+ storeDoc.store();
+ assureEquals("'store' should implicitly reset the modified flag", modifyDoc.isModified(), false);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnSave", "OnSaveDone", "OnModifyChanged"
+ }, context);
+
+ // XComponentLoader.loadComponentFromURL
+ newURL = copyToTempFile(databaseDoc.getURL());
+ final XComponentLoader loader = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class,
+ getORB().createInstance("com.sun.star.frame.Desktop"));
+ context = "loadComponentFromURL";
+ impl_startObservingEvents(context);
+ databaseDoc = (XModel) UnoRuntime.queryInterface(XModel.class,
+ loader.loadComponentFromURL(newURL, _BLANK, 0, impl_getDefaultLoadArgs()));
+ impl_stopObservingEvents(m_globalEvents,
+ new String[]
+ {
+ "OnLoadFinished", "OnViewCreated", "OnFocus", "OnLoad"
+ }, context);
+
+ // closing a document by API
+ final XCloseable closeDoc = (XCloseable) UnoRuntime.queryInterface(XCloseable.class,
+ databaseDoc);
+ context = "close (API)";
+ impl_startObservingEvents(context);
+ closeDoc.close(true);
+ impl_stopObservingEvents(m_globalEvents,
+ new String[]
+ {
+ "OnPrepareUnload", "OnViewClosed", "OnUnload"
+ }, context);
+
+ // closing a document via UI
+ context = "close (UI)";
+ impl_startObservingEvents("prepare for '" + context + "'");
+ databaseDoc = (XModel) UnoRuntime.queryInterface(XModel.class,
+ loader.loadComponentFromURL(newURL, _BLANK, 0, impl_getDefaultLoadArgs()));
+ impl_waitForEvent(m_globalEvents, "OnLoad", 5000);
+ // wait for all events to arrive - OnLoad should be the last one
+
+ final XDispatchProvider dispatchProvider = (XDispatchProvider) UnoRuntime.queryInterface(XDispatchProvider.class,
+ databaseDoc.getCurrentController().getFrame());
+ final URL url = impl_getURL(".uno:CloseDoc");
+ final XDispatch dispatcher = dispatchProvider.queryDispatch(url, "", 0);
+ impl_startObservingEvents(context);
+ dispatcher.dispatch(url, new PropertyValue[0]);
+ impl_stopObservingEvents(m_globalEvents,
+ new String[]
+ {
+ "OnPrepareViewClosing", "OnViewClosed", "OnPrepareUnload", "OnUnload"
+ }, context);
+
+ // creating a new document
+ databaseDoc = impl_createDocument();
+ final XLoadable loadDoc = (XLoadable) UnoRuntime.queryInterface(XLoadable.class,
+ databaseDoc);
+ context = "initNew";
+ impl_startObservingEvents(context);
+ loadDoc.initNew();
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnCreate"
+ }, context);
+
+ impl_startObservingEvents(context + " (cleanup)");
+ impl_closeDocument(databaseDoc);
+ impl_waitForEvent(m_globalEvents, "OnUnload", 5000);
+
+ // focus changes
+ context = "activation";
+ // for this, load a database document ...
+ impl_startObservingEvents("prepare for '" + context + "'");
+ databaseDoc = (XModel) UnoRuntime.queryInterface(XModel.class,
+ loader.loadComponentFromURL(newURL, _BLANK, 0, impl_getDefaultLoadArgs()));
+ final int previousOnLoadEventPos = impl_waitForEvent(m_globalEvents, "OnLoad", 5000);
+ // ... and another document ...
+ final String otherURL = copyToTempFile(databaseDoc.getURL());
+ final XModel otherDoc = (XModel) UnoRuntime.queryInterface(XModel.class,
+ loader.loadComponentFromURL(otherURL, _BLANK, 0, impl_getDefaultLoadArgs()));
+ impl_raise(otherDoc);
+ impl_waitForEvent(m_globalEvents, "OnLoad", 5000, previousOnLoadEventPos + 1);
+
+ // ... and switch between the two
+ impl_startObservingEvents(context);
+ impl_raise(databaseDoc);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnUnfocus", "OnFocus"
+ }, context);
+
+ // cleanup
+ impl_startObservingEvents("cleanup after '" + context + "'");
+ impl_closeDocument(databaseDoc);
+ impl_closeDocument(otherDoc);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private URL impl_getURL(String _completeURL) throws Exception
+ {
+ final URL[] url =
+ {
+ new URL()
+ };
+ url[0].Complete = _completeURL;
+ final XURLTransformer urlTransformer = (XURLTransformer) UnoRuntime.queryInterface(XURLTransformer.class,
+ getORB().createInstance("com.sun.star.util.URLTransformer"));
+ urlTransformer.parseStrict(url);
+ return url[0];
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_raise(XModel _document)
+ {
+ final XFrame frame = _document.getCurrentController().getFrame();
+ final XTopWindow topWindow = (XTopWindow) UnoRuntime.queryInterface(XTopWindow.class,
+ frame.getContainerWindow());
+ topWindow.toFront();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_startObservingEvents(String _context)
+ {
+ log.println(" " + _context + " {");
+ synchronized (m_documentEvents)
+ {
+ m_documentEvents.clear();
+ }
+ synchronized (m_globalEvents)
+ {
+ m_globalEvents.clear();
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_stopObservingEvents(ArrayList _actualEvents, String[] _expectedEvents, String _context)
+ {
+ try
+ {
+ synchronized (_actualEvents)
+ {
+ int actualEventCount = _actualEvents.size();
+ while (actualEventCount < _expectedEvents.length)
+ {
+ // well, it's possible not all events already arrived, yet - finally, some of them
+ // are notified asynchronously
+ // So, wait a few seconds.
+ try
+ {
+ _actualEvents.wait(20000);
+ }
+ catch (InterruptedException ex)
+ {
+ }
+
+ if (actualEventCount == _actualEvents.size())
+ // the above wait was left because of the timeout, *not* because an event
+ // arrived. Okay, we won't wait any longer, this is a failure.
+ {
+ break;
+ }
+ actualEventCount = _actualEvents.size();
+ }
+
+ assureEquals("wrong event count for '" + _context + "'",
+ _expectedEvents.length, _actualEvents.size());
+
+ for (int i = 0; i < _expectedEvents.length; ++i)
+ {
+ assureEquals("wrong event at positon " + (i + 1) + " for '" + _context + "'",
+ _expectedEvents[i], _actualEvents.get(i));
+ }
+ }
+ }
+ finally
+ {
+ log.println(" }");
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ int impl_waitForEvent(ArrayList _eventQueue, String _expectedEvent, int _maxMilliseconds)
+ {
+ return impl_waitForEvent(_eventQueue, _expectedEvent, _maxMilliseconds, 0);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ int impl_waitForEvent(ArrayList _eventQueue, String _expectedEvent, int _maxMilliseconds, int _firstQueueElementToCheck)
+ {
+ synchronized (_eventQueue)
+ {
+ int waitedMilliseconds = 0;
+
+ while (waitedMilliseconds < _maxMilliseconds)
+ {
+ for (int i = _firstQueueElementToCheck; i < _eventQueue.size(); ++i)
+ {
+ if (_expectedEvent.equals(_eventQueue.get(i)))
+ // found the event in the queue
+ {
+ return i;
+ }
+ }
+
+ // wait a little, perhaps the event will still arrive
+ try
+ {
+ _eventQueue.wait(500);
+ waitedMilliseconds += 500;
+ }
+ catch (InterruptedException e)
+ {
+ }
+ }
+ }
+
+ failed("expected event '" + _expectedEvent + "' did not arrive after " + _maxMilliseconds + " milliseconds");
+ return -1;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ void onDocumentEvent(DocumentEvent _Event)
+ {
+ if ("OnTitleChanged".equals(_Event.EventName))
+ // OnTitleChanged events are notified too often. This is known, and accepted.
+ // (the deeper reason is that it's diffult to determine, in the DatabaseDocument implementatin,
+ // when the title actually changed. In particular, when we do a saveAsURL, and then ask for a
+ // title *before* the TitleHelper got the document's OnSaveAsDone event, then the wrong (old)
+ // title is obtained.
+ {
+ return;
+ }
+
+ if ((_Event.EventName.equals("OnLoad")) && (m_loadDocState != STATE_NOT_STARTED))
+ {
+ assureEquals("OnLoad event must come *after* invocation of the interaction handler / user!",
+ m_loadDocState, STATE_MACRO_EXEC_APPROVED);
+ m_loadDocState = STATE_ON_LOAD_RECEIVED;
+ }
+
+ synchronized (m_documentEvents)
+ {
+ m_documentEvents.add(_Event.EventName);
+ m_documentEvents.notifyAll();
+ }
+
+ log.println(" document event: " + _Event.EventName);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void documentEventOccured(DocumentEvent _Event)
+ {
+ if ("OnTitleChanged".equals(_Event.EventName))
+ // ignore. See onDocumentEvent for a justification
+ {
+ return;
+ }
+
+ synchronized (m_globalEvents)
+ {
+ m_globalEvents.add(_Event.EventName);
+ m_globalEvents.notifyAll();
+ }
+
+ log.println(" global event: " + _Event.EventName);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void disposing(EventObject _Event)
+ {
+ // not interested in
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/FileHelper.java b/dbaccess/qa/complex/dbaccess/FileHelper.java
new file mode 100644
index 000000000000..f72dc0ff7ca3
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/FileHelper.java
@@ -0,0 +1,44 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package complex.dbaccess;
+
+public class FileHelper
+{
+ private FileHelper(){}
+ static public String getOOoCompatibleFileURL( String _javaFileURL )
+ {
+ String returnURL = _javaFileURL;
+ if ( ( returnURL.indexOf( "file:/" ) == 0 ) && ( returnURL.indexOf( "file:///" ) == -1 ) )
+ {
+ // for some reason, the URLs here in Java start with "file:/" only, instead of "file:///"
+ // Some of the office code doesn't like this ...
+ returnURL = "file:///" + returnURL.substring( 6 );
+ }
+ return returnURL;
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/Parser.java b/dbaccess/qa/complex/dbaccess/Parser.java
new file mode 100644
index 000000000000..2b1b9342edcb
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/Parser.java
@@ -0,0 +1,208 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XIndexAccess;
+import com.sun.star.sdb.XParametersSupplier;
+import com.sun.star.sdb.XSingleSelectQueryComposer;
+import com.sun.star.sdbc.DataType;
+import com.sun.star.sdbc.SQLException;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+
+public class Parser extends CRMBasedTestCase
+{
+ // --------------------------------------------------------------------------------------------------------
+ public String[] getTestMethodNames()
+ {
+ return new String[] {
+ "checkJoinSyntax",
+ "checkParameterTypes",
+ "checkWhere",
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public String getTestObjectName()
+ {
+ return "Parser";
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ protected void createTestCase()
+ {
+ try
+ {
+ super.createTestCase();
+ m_database.getDatabase().getDataSource().createQuery( "query products", "SELECT * FROM \"products\"" );
+ }
+ catch ( Exception e )
+ {
+ e.printStackTrace( System.err );
+ assure( "caught an exception (" + e.getMessage() + ") while creating the test case", false );
+ }
+ }
+
+ public void checkWhere() throws Exception
+ {
+ final XSingleSelectQueryComposer composer = createQueryComposer();
+ final String SELECT = "SELECT \"products\".\"Name\" FROM \"products\" WHERE ";
+ final String[] queries = new String[]
+ {
+ "\"ID\" in ( 1,2,3,4)"
+ ,"not ( \"ID\" in ( 1,2,3,4))"
+ ,"(1 = 1) is true"
+ ,"(1 = 1) is not false"
+ ,"(1 = 1) is not null"
+ ,"not ( (1 = 1) is not null)"
+ ,"'a' like 'a%'"
+ ,"not ( 'a' like 'a%')"
+ ,"'a' not like 'a%'"
+ ,"1 between 0 and 2"
+ ,"not ( 1 between 0 and 2 )"
+ ,"1 not between 3 and 4"
+ ,"1 not between ( select \"ID\" from \"categories\") and ( select \"ID\" from \"categories\")"
+ ,"1 = 1"
+ ,"0 < 1"
+ ,"not(0 < 1)"
+ ,"1 > 0"
+ ,"not(1 > 0)"
+ ,"1 <> 0"
+ ,"(1 <> 0 and 'a' = 'a' and 'c' = 'd') or (1 = 1 and 2 = 2 and 3 = 4)"
+ ,"not ( 1 <> 0 )"
+ ,"\"CategoryID\" in ( select \"ID\" from \"categories\")"
+ ,"not (\"CategoryID\" in ( select \"ID\" from \"categories\"))"
+ ,"\"CategoryID\" not in ( select \"ID\" from \"categories\")"
+ };
+ for (int i = 0; i < queries.length; i++)
+ {
+ composer.setQuery( SELECT + queries[i]);
+ }
+ }
+ // --------------------------------------------------------------------------------------------------------
+ /** verifies that aliases for inner queries work as expected
+ */
+ public void checkJoinSyntax() throws Exception
+ {
+ final XSingleSelectQueryComposer composer = createQueryComposer();
+
+ // feed the composer with some statements. If any of those cannot be parsed, the composer
+ // will throw an exception - which is a regression then
+ composer.setQuery(
+ "SELECT \"categories\".\"Name\", " +
+ "\"products\".\"Name\" " +
+ "FROM \"products\" RIGHT OUTER JOIN \"categories\" AS \"categories\" ON \"products\".\"CategoryID\" = \"categories\".\"ID\"" );
+
+ composer.setQuery(
+ "SELECT \"categories\".\"Name\", " +
+ "\"products\".\"Name\" " +
+ "FROM \"products\" LEFT OUTER JOIN \"categories\" AS \"categories\" ON \"products\".\"CategoryID\" = \"categories\".\"ID\"" );
+
+ composer.setQuery(
+ "SELECT \"categories\".\"Name\", " +
+ "\"products\".\"Name\" " +
+ "FROM \"products\" CROSS JOIN \"categories\" AS \"categories\"" );
+
+ composer.setQuery(
+ "SELECT \"categories\".\"Name\", " +
+ "\"products\".\"Name\" " +
+ "FROM \"products\" INNER JOIN \"categories\" AS \"categories\" ON \"products\".\"CategoryID\" = \"categories\".\"ID\"" );
+
+ // just to be sure the composer *really* parses upon setting the query: feed it with
+ // an unparseable statement
+ boolean caughtExpected = false;
+ try
+ {
+ composer.setQuery( "NONSENSE" );
+ }
+ catch( SQLException e )
+ {
+ caughtExpected = true;
+ }
+ assure( "pre-condition not met: parser should except on unparseable statements, else the complete" +
+ "test is bogus!", caughtExpected );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_checkParameters( final String _statement, final String[] _expectedParameterNames, final int[] _expectedParameterTypes,final String _context ) throws Exception
+ {
+ final XSingleSelectQueryComposer composer = createQueryComposer();
+ composer.setQuery( _statement );
+
+ assureEquals( "checkParameterTypes: internal error", _expectedParameterNames.length, _expectedParameterTypes.length );
+
+ final XParametersSupplier paramSupp = (XParametersSupplier)UnoRuntime.queryInterface(
+ XParametersSupplier.class, composer );
+ final XIndexAccess parameters = paramSupp.getParameters();
+
+ assureEquals( "(ctx: " + _context + ") unexpected parameter count", _expectedParameterNames.length, parameters.getCount() );
+ for ( int i=0; i<parameters.getCount(); ++i )
+ {
+ final XPropertySet parameter = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class,
+ parameters.getByIndex(i) );
+
+ final String name = (String)parameter.getPropertyValue( "Name" );
+ assureEquals( "(ctx: " + _context + ") unexpected parameter name for parameter number " + ( i + 1 ), _expectedParameterNames[i], name );
+
+ final int type = ((Integer)parameter.getPropertyValue( "Type" )).intValue();
+ assureEquals( "(ctx: " + _context + ") unexpected data type for parameter number " + ( i + 1 ), _expectedParameterTypes[i], type );
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** verifies that the parser properly recognizes the types of parameters
+ */
+ public void checkParameterTypes() throws Exception
+ {
+ impl_checkParameters(
+ "SELECT * FROM \"all orders\" " +
+ "WHERE ( \"Order Date\" >= :order_date ) " +
+ " AND ( ( \"Customer Name\" LIKE :customer ) " +
+ " OR ( \"Product Name\" LIKE ? ) " +
+ " )",
+ new String[] { "order_date", "customer", "Product Name" },
+ new int[] { DataType.DATE, DataType.VARCHAR, DataType.VARCHAR },
+ ">= && LIKE"
+ );
+
+ impl_checkParameters(
+ "SELECT * FROM \"categories\" " +
+ "WHERE \"ID\" BETWEEN :id_lo AND :id_hi",
+ new String[] { "id_lo", "id_hi" },
+ new int[] { DataType.INTEGER, DataType.INTEGER },
+ "BETWEEN"
+ );
+
+ impl_checkParameters(
+ "SELECT CONCAT( :prefix, CONCAT( \"Name\", :suffix ) ) FROM \"customers\"",
+ new String[] { "prefix", "suffix" },
+ new int[] { DataType.VARCHAR, DataType.VARCHAR },
+ "CONCAT"
+ );
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/PropertyBag.java b/dbaccess/qa/complex/dbaccess/PropertyBag.java
new file mode 100644
index 000000000000..c686be886bba
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/PropertyBag.java
@@ -0,0 +1,294 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package complex.dbaccess;
+
+import complexlib.ComplexTestCase;
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XInterface;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.beans.*;
+
+public class PropertyBag extends ComplexTestCase
+{
+ private static final String VALUE = "Value";
+ private XPropertyContainer m_bag;
+ private XPropertySet m_set;
+ private XPropertyAccess m_access;
+ private XMultiServiceFactory m_orb = null;
+
+ public String[] getTestMethodNames()
+ {
+ return new String[]
+ {
+ "checkBasics",
+ "checkSequenceAccess",
+ "checkDynamicSet"
+ };
+ }
+
+ public String getTestObjectName()
+ {
+ return "PropertyBag";
+ }
+
+ public void before()
+ {
+ m_orb = (XMultiServiceFactory)param.getMSF();
+ }
+
+ public void checkBasics()
+ {
+ createEmptyBag();
+ log.println("testing the basics");
+
+ // check whether empty property names are rejected
+ boolean caughtExpected = false;
+ try
+ {
+ m_bag.addProperty( "", PropertyAttribute.BOUND, Integer.valueOf( 3 ) );
+ }
+ catch(com.sun.star.lang.IllegalArgumentException e) { caughtExpected = true; }
+ catch(com.sun.star.uno.Exception e) { }
+ if ( !caughtExpected )
+ failed( "empty property names are not rejected by XPropertyContainer::addProperty" );
+
+ // check whether duplicate insertions are rejected
+ caughtExpected = false;
+ try
+ {
+ m_bag.addProperty( VALUE, PropertyAttribute.BOUND, "" );
+ m_bag.addProperty( VALUE, PropertyAttribute.BOUND, "" );
+ }
+ catch(com.sun.star.beans.PropertyExistException e) { caughtExpected = true; }
+ catch(com.sun.star.uno.Exception e) { }
+ if ( !caughtExpected )
+ failed( "insertion of duplicate property names is not rejected" );
+
+ // try removing the property we just added - this should fail, as it does not have
+ // the REMOVEABLE attribute
+ caughtExpected = false;
+ try
+ {
+ m_bag.removeProperty( VALUE);
+ }
+ catch(com.sun.star.beans.NotRemoveableException e) { caughtExpected = true; }
+ catch(com.sun.star.uno.Exception e) { }
+ if ( !caughtExpected )
+ failed( "removing non-removeable properties is expected to fail - but it didn't" );
+
+ // try removing a non-existent property
+ caughtExpected = false;
+ try
+ {
+ m_bag.removeProperty( "NonExistent" );
+ }
+ catch(com.sun.star.beans.UnknownPropertyException e) { caughtExpected = true; }
+ catch(com.sun.star.uno.Exception e) { }
+ if ( !caughtExpected )
+ failed( "removing non-existent properties is expected to fail - but it didn't" );
+
+ // try writing and reading a value for the one property we have so far
+ try
+ {
+ final String testValue = "someArbitraryValue";
+ m_set.setPropertyValue( VALUE , testValue);
+ final String currentValue = (String)m_set.getPropertyValue( VALUE);
+ if ( !currentValue.equals( testValue ) )
+ failed( "set property is not remembered" );
+ }
+ catch(com.sun.star.uno.Exception e)
+ {
+ failed( "setting or getting a property value failed" );
+ }
+
+ // try setting an illegal value for the property
+ caughtExpected = false;
+ try
+ {
+ m_set.setPropertyValue( VALUE, Integer.valueOf( 3 ) );
+ }
+ catch(com.sun.star.lang.IllegalArgumentException e) { caughtExpected = true; }
+ catch(com.sun.star.uno.Exception e) { }
+ if ( !caughtExpected )
+ failed( "the bag does not respect the property type we declared for the property" );
+ }
+
+ public void checkSequenceAccess() throws com.sun.star.uno.Exception
+ {
+ log.println( "checking PropertySetAccess via sequences" );
+ createStandardBag( false );
+
+ // ---------------------------------
+ // XPropertyAccess.setPropertyValues
+ final PropertyValue expectedValues[] =
+ {
+ new PropertyValue( "BoolValue", -1, Boolean.FALSE, PropertyState.DIRECT_VALUE ),
+ new PropertyValue( "StringValue", -1, "some text", PropertyState.DIRECT_VALUE ),
+ new PropertyValue( "IntegerValue", -1, Integer.valueOf( 3 ), PropertyState.DIRECT_VALUE ),
+ new PropertyValue( "InterfaceValue", -1, m_bag, PropertyState.DIRECT_VALUE )
+ };
+ m_access.setPropertyValues( expectedValues );
+
+ for ( int i=0; i<expectedValues.length; ++i )
+ {
+ final Object value = m_set.getPropertyValue( expectedValues[i].Name );
+ if ( !value.equals( expectedValues[i].Value ) )
+ {
+ log.println( "property name : " + expectedValues[i].Name );
+ log.println( "expected value: " + expectedValues[i].Value.toString() );
+ log.println( "current value : " + value.toString() );
+ failed( "retrieving a previously set property (" + expectedValues[i].Value.getClass().toString() + ") failed" );
+ }
+ }
+
+ // ---------------------------------
+ // XPropertyAccess.getPropertyValues
+ final PropertyValue currentValues[] = m_access.getPropertyValues();
+ for ( int i=0; i<currentValues.length; ++i )
+ {
+ final String name = currentValues[i].Name;
+ final Object value = currentValues[i].Value;
+ for ( int j=0; j<expectedValues.length; ++j )
+ {
+ if ( expectedValues[j].Name.equals( name ) )
+ {
+ if ( !expectedValues[j].Value.equals( value ) )
+ {
+ log.println( "property name : " + expectedValues[j].Name );
+ log.println( "expected value: " + expectedValues[j].Value.toString() );
+ log.println( "current value : " + value.toString() );
+ failed( "getPropertyValues failed for property '" + name + "' failed" );
+ }
+ break;
+ }
+ }
+
+ if ( !m_set.getPropertyValue( name ).equals( value ) )
+ failed( "XPropertyAccess::getPropertyValues() and XPropertyset::getPropertyValue results are inconsistent" );
+ }
+ }
+
+ public void checkDynamicSet() throws com.sun.star.uno.Exception
+ {
+ log.println( "checking proper dynamic of the set" );
+ createStandardBag( false );
+
+ final PropertyValue props[] =
+ {
+ new PropertyValue( "BoolValue", -1, Boolean.FALSE, PropertyState.DIRECT_VALUE),
+ new PropertyValue( "StringValue", -1, "test", PropertyState.DIRECT_VALUE ),
+ new PropertyValue( "SomeOtherStringValue", -1, "string value", PropertyState.DIRECT_VALUE )
+ };
+
+ // try setting some property values which are not existent
+ boolean caughtExpected = false;
+ try
+ {
+ m_access.setPropertyValues( props );
+ }
+ catch( com.sun.star.beans.UnknownPropertyException e ) { caughtExpected = true; }
+ catch( com.sun.star.uno.Exception e ) { }
+ if ( !caughtExpected )
+ failed( "the set shouldn't accept unknown property values, if not explicitly told to do so" );
+
+ // re-create the bag, this time allow it to implicitly add properties
+ createStandardBag( true );
+ boolean success = false;
+ try { m_access.setPropertyValues( props ); success = true; }
+ catch( com.sun.star.uno.Exception e ) { }
+ if ( !success )
+ failed( "property bag failed to implicitly add unknown properties" );
+
+ // see whether this property was really added, and not just ignored
+ final PropertyValue newlyAdded = props[ props.length - 1 ];
+ try
+ {
+ if ( !m_set.getPropertyValue( newlyAdded.Name ).equals( newlyAdded.Value ) )
+ failed( "the new property was not really added, or not added with the proper value" );
+ }
+ catch( com.sun.star.uno.Exception e ) { }
+ }
+
+ private void createEmptyBag()
+ {
+ try
+ {
+ m_bag = null;
+ final String serviceName = "com.sun.star.beans.PropertyBag";
+ m_bag = (XPropertyContainer)UnoRuntime.queryInterface( XPropertyContainer.class,
+ m_orb.createInstance( serviceName )
+ );
+ if ( m_bag == null )
+ failed( "could not create a " + serviceName + " instance" );
+ m_set = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, m_bag );
+ m_access = (XPropertyAccess)UnoRuntime.queryInterface( XPropertyAccess.class, m_bag );
+ }
+ catch( com.sun.star.uno.Exception e )
+ {
+ }
+ }
+
+ private void createStandardBag( boolean allowLazyAdding )
+ {
+ try
+ {
+ m_bag = null;
+
+ final Object initArgs[] = { new NamedValue( "AutomaticAddition", Boolean.valueOf( allowLazyAdding ) ) };
+
+ final String serviceName = "com.sun.star.beans.PropertyBag";
+ m_bag = (XPropertyContainer)UnoRuntime.queryInterface( XPropertyContainer.class,
+ m_orb.createInstanceWithArguments( serviceName, initArgs )
+ );
+ if ( m_bag == null )
+ failed( "could not create a " + serviceName + " instance" );
+ m_set = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, m_bag );
+ m_access = (XPropertyAccess)UnoRuntime.queryInterface( XPropertyAccess.class, m_bag );
+
+ final Object properties[][] =
+ {
+ { "BoolValue", Boolean.TRUE },
+ { "StringValue", "" },
+ { "IntegerValue", Integer.valueOf( 3 ) },
+ { "InterfaceValue", (XInterface)m_bag }
+ };
+ for ( int i=0; i<properties.length; ++i )
+ {
+ m_bag.addProperty(
+ (String)properties[i][0],
+ PropertyAttribute.MAYBEVOID,
+ properties[i][1]
+ );
+ }
+ }
+ catch( com.sun.star.uno.Exception e )
+ {
+ }
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/Query.java b/dbaccess/qa/complex/dbaccess/Query.java
new file mode 100644
index 000000000000..81a651fd5696
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/Query.java
@@ -0,0 +1,126 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XIndexAccess;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.container.XNamed;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.sdb.XQueriesSupplier;
+import com.sun.star.sdbcx.XColumnsSupplier;
+import com.sun.star.uno.UnoRuntime;
+import connectivity.tools.CRMDatabase;
+
+public class Query extends complexlib.ComplexTestCase {
+
+ connectivity.tools.HsqlDatabase m_database;
+
+ // --------------------------------------------------------------------------------------------------------
+ public String[] getTestMethodNames() {
+ return new String[]
+ {
+ "testQueryColumns"
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public String getTestObjectName() {
+ return "Query";
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void createTestCase()
+ {
+ try
+ {
+ if ( m_database == null )
+ {
+ final CRMDatabase database = new CRMDatabase( getFactory(), false );
+ m_database = database.getDatabase();
+ }
+ }
+ catch( Exception e )
+ {
+ log.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 testQueryColumns()
+ {
+ createTestCase();
+
+ try
+ {
+ final XQueriesSupplier suppQueries = UnoRuntime.queryInterface(
+ XQueriesSupplier.class, m_database.defaultConnection().getXConnection() );
+ final XNameAccess queries = suppQueries.getQueries();
+
+ final String[] queryNames = new String[] { "parseable", "parseable native", "unparseable" };
+ final String[][] expectedColumnNames = new String[][] {
+ new String[] { "ID", "Name", "Address", "City", "Postal","Comment" },
+ new String[] { "TABLE_CATALOG", "TABLE_SCHEMA", "TABLE_NAME", "VIEW_DEFINITION", "CHECK_OPTION", "IS_UPDATABLE", "VALID" },
+ new String[] { "ID_VARCHAR" }
+ };
+
+ for ( int i = 0; i < queryNames.length; ++i )
+ {
+ final XPropertySet query = UnoRuntime.queryInterface(
+ XPropertySet.class, queries.getByName( queryNames[i] ) );
+
+ final XColumnsSupplier suppCols = UnoRuntime.queryInterface(
+ XColumnsSupplier.class, query);
+ final XIndexAccess columns = UnoRuntime.queryInterface(
+ XIndexAccess.class, suppCols.getColumns());
+
+ // check whether the columns supplied by the query match what we expected
+ assure( "invalid column count (found " + columns.getCount() + ", expected: " + expectedColumnNames[i].length + ") for query \"" + queryNames[i] + "\"",
+ columns.getCount() == expectedColumnNames[i].length );
+ for ( int col = 0; col < columns.getCount(); ++col )
+ {
+ final XNamed columnName = UnoRuntime.queryInterface(
+ XNamed.class, columns.getByIndex(col) );
+ assure( "column no. " + col + " of query \"" + queryNames[i] + "\" not matching",
+ columnName.getName().equals( expectedColumnNames[i][col] ) );
+ }
+ }
+ }
+ catch ( Exception e )
+ {
+ assure( "caught an unexpected exception: " + e.getMessage(), false );
+ }
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/QueryInQuery.java b/dbaccess/qa/complex/dbaccess/QueryInQuery.java
new file mode 100644
index 000000000000..002d0395b791
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/QueryInQuery.java
@@ -0,0 +1,192 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.container.ElementExistException;
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.sdb.CommandType;
+import com.sun.star.sdbc.SQLException;
+import connectivity.tools.HsqlColumnDescriptor;
+import connectivity.tools.HsqlTableDescriptor;
+import connectivity.tools.RowSet;
+import com.sun.star.sdbc.XStatement;
+import com.sun.star.sdbc.XResultSet;
+
+public class QueryInQuery extends CRMBasedTestCase
+{
+ private static final String QUERY_PRODUCTS = "query products";
+ // --------------------------------------------------------------------------------------------------------
+ public String[] getTestMethodNames()
+ {
+ return new String[] {
+ "executeSimpleSelect",
+ "executeAliasedSelect",
+ "checkNameCollisions",
+ "checkCyclicReferences",
+ "checkStatementQiQSupport"
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public String getTestObjectName()
+ {
+ return "QueryInQuery";
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ protected void createTestCase()
+ {
+ try
+ {
+ super.createTestCase();
+ m_database.getDatabase().getDataSource().createQuery( QUERY_PRODUCTS,"SELECT * FROM \"products\"");
+ }
+ catch ( Exception e )
+ {
+ e.printStackTrace( System.err );
+ assure( "caught an exception (" + e.getMessage() + ") while creating the test case", false );
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void verifyEqualRowSetContent( int _outerCommandType, String _outerCommand, int _innerCommandType, String _innerCommand ) throws SQLException
+ {
+ final RowSet outerRowSet = m_database.getDatabase().createRowSet( _outerCommandType, _outerCommand );
+ outerRowSet.execute();
+
+ final RowSet innerRowSet = m_database.getDatabase().createRowSet( _innerCommandType, _innerCommand );
+ innerRowSet.execute();
+
+ outerRowSet.last();
+ innerRowSet.last();
+ assure( "wrong record counts", outerRowSet.getRow() == innerRowSet.getRow() );
+
+ outerRowSet.beforeFirst();
+ innerRowSet.beforeFirst();
+ assure( "wrong column counts", outerRowSet.getColumnCount() == innerRowSet.getColumnCount() );
+
+ while ( outerRowSet.next() && innerRowSet.next() )
+ {
+ for ( int i=1; i <= outerRowSet.getColumnCount(); ++i )
+ {
+ assure( "content of column " + i + " of row " + outerRowSet.getRow() + " not identical",
+ innerRowSet.getString(i).equals( outerRowSet.getString(i) ) );
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** executes a SQL statement simply selecting all columns from a query
+ */
+ public void executeSimpleSelect() throws SQLException
+ {
+ verifyEqualRowSetContent(
+ CommandType.COMMAND, "SELECT * FROM \"query products\"",
+ CommandType.QUERY,QUERY_PRODUCTS);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** verifies that aliases for inner queries work as expected
+ */
+ public void executeAliasedSelect() throws SQLException
+ {
+ verifyEqualRowSetContent(
+ CommandType.COMMAND, "SELECT \"PROD\".\"ID\" FROM \"query products\" AS \"PROD\"",
+ CommandType.COMMAND, "SELECT \"ID\" FROM \"products\"" );
+ verifyEqualRowSetContent(
+ CommandType.COMMAND, "SELECT \"PROD\".* FROM \"query products\" AS \"PROD\"",
+ CommandType.QUERY,QUERY_PRODUCTS);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** verifies that aliases for inner queries work as expected
+ */
+ public void checkNameCollisions()
+ {
+ // create a query with a name which is used by a table
+ boolean caughtExpected = false;
+ try
+ {
+ m_database.getDatabase().getDataSource().createQuery( "products", "SELECT * FROM \"products\"" );
+ }
+ catch ( WrappedTargetException e ) { caughtExpected = true; }
+ catch ( IllegalArgumentException e ) {}
+ catch ( ElementExistException e ) { caughtExpected = true; }
+ assure( "creating queries with the name of an existing table should not be possible",
+ caughtExpected );
+
+ // create a table with a name which is used by a query
+ final HsqlTableDescriptor table = new HsqlTableDescriptor( QUERY_PRODUCTS,
+ new HsqlColumnDescriptor[] {
+ new HsqlColumnDescriptor( "ID", "INTEGER" ),
+ new HsqlColumnDescriptor( "Name", "VARCHAR(50)" ) } );
+
+ caughtExpected = false;
+ try
+ {
+ m_database.getDatabase().createTableInSDBCX( table );
+ }
+ catch ( SQLException e ) { caughtExpected = true; }
+ catch ( ElementExistException ex ) { }
+ assure( "creating tables with the name of an existing query should not be possible",
+ caughtExpected );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void checkCyclicReferences() throws ElementExistException, WrappedTargetException, IllegalArgumentException
+ {
+ // some queries which create a cycle in the sub query tree
+ m_database.getDatabase().getDataSource().createQuery( "orders level 1", "SELECT * FROM \"orders level 0\"" );
+ m_database.getDatabase().getDataSource().createQuery( "orders level 2", "SELECT * FROM \"orders level 1\"" );
+ m_database.getDatabase().getDataSource().createQuery( "orders level 3", "SELECT * FROM \"orders level 2\"" );
+ m_database.getDatabase().getDataSource().createQuery( "orders level 0", "SELECT * FROM \"orders level 3\"" );
+
+ final RowSet rowSet = m_database.getDatabase().createRowSet( CommandType.QUERY, "orders level 0" );
+
+ boolean caughtExpected = false;
+ try { rowSet.execute(); }
+ catch ( SQLException e ) { caughtExpected = ( e.ErrorCode == -com.sun.star.sdb.ErrorCondition.PARSER_CYCLIC_SUB_QUERIES ); }
+
+ assure( "executing a query with cyclic nested sub queries should fail!", caughtExpected );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void checkStatementQiQSupport()
+ {
+ try
+ {
+ final XStatement statement = m_database.getConnection().createStatement();
+ final XResultSet resultSet = statement.executeQuery( "SELECT * FROM \"query products\"" );
+ assure( "Result Set is null", resultSet != null );
+ }
+ catch( SQLException e )
+ {
+ assure( "SDB level statements do not allow for queries in queries", false );
+ }
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/RowSet.java b/dbaccess/qa/complex/dbaccess/RowSet.java
new file mode 100644
index 000000000000..5a13f6724d1f
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/RowSet.java
@@ -0,0 +1,1026 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.beans.PropertyVetoException;
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XIndexAccess;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.lang.XComponent;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.sdb.CommandType;
+import com.sun.star.sdb.XParametersSupplier;
+import com.sun.star.sdb.XResultSetAccess;
+import com.sun.star.sdb.XRowSetApproveBroadcaster;
+import com.sun.star.sdbc.SQLException;
+import com.sun.star.sdbc.XParameters;
+import com.sun.star.sdbc.XPreparedStatement;
+import com.sun.star.sdbc.XResultSet;
+import com.sun.star.sdbc.XResultSetUpdate;
+import com.sun.star.sdbc.XRow;
+import com.sun.star.sdbc.XRowSet;
+import com.sun.star.sdbc.XRowUpdate;
+import com.sun.star.sdbcx.XColumnsSupplier;
+import com.sun.star.sdbcx.XDeleteRows;
+import com.sun.star.sdbcx.XRowLocate;
+import com.sun.star.uno.UnoRuntime;
+import complexlib.ComplexTestCase;
+import connectivity.tools.CRMDatabase;
+import connectivity.tools.DataSource;
+import connectivity.tools.HsqlDatabase;
+import connectivity.tools.sdb.Connection;
+import java.lang.reflect.Method;
+import java.util.Random;
+
+public class RowSet extends ComplexTestCase
+{
+
+ static final int MAX_TABLE_ROWS = 100;
+ static final int MAX_FETCH_ROWS = 10;
+ private static final String NEXT = "next";
+ private static final String TEST21 = "Test21";
+ HsqlDatabase m_database;
+ DataSource m_dataSource;
+ XRowSet m_rowSet;
+ XResultSet m_resultSet;
+ XResultSetUpdate m_resultSetUpdate;
+ XRow m_row;
+ XRowLocate m_rowLocate;
+ XPropertySet m_rowSetProperties;
+ XParametersSupplier m_paramsSupplier;
+
+ // --------------------------------------------------------------------------------------------------------
+ class ResultSetMovementStress implements Runnable
+ {
+
+ XResultSet m_resultSet;
+ XRow m_row;
+ int m_id;
+
+ public ResultSetMovementStress(XResultSet _resultSet, int _id) throws java.lang.Exception
+ {
+ m_resultSet = _resultSet;
+ m_row = UnoRuntime.queryInterface( XRow.class, m_resultSet );
+ m_id = _id;
+ }
+
+ public void run()
+ {
+ try
+ {
+ m_resultSet.beforeFirst();
+ for (int i = 0; m_resultSet.next(); ++i)
+ {
+ int pos = m_resultSet.getRow();
+ // final int val = m_row.getInt(1);
+// log.println("Clone Move(" + m_id +") before i: " + (i+1) + " Pos: " + pos + " Val: " + val);
+ testPosition(m_resultSet, m_row, i + 1, "clone move(" + m_id + ")");
+// val = m_row.getInt(1);
+// log.println("Clone Move(" + m_id +") after i: " + (i+1) + " Pos: " + pos + " Val: " + val);
+ int pos2 = m_resultSet.getRow();
+ assure("ResultSetMovementStress wrong position: " + i + " Pos1: " + pos + " Pos2: " + pos2, pos == pos2);
+ }
+ }
+ catch (Exception e)
+ {
+ assure("ResultSetMovementStress(" + m_id + ") failed: " + e, false);
+ }
+ }
+ }
+ // --------------------------------------------------------------------------------------------------------
+
+ public String[] getTestMethodNames()
+ {
+ return new String[]
+ {
+ "testRowSet",
+ "testRowSetEvents",
+ "testDeleteBehavior",
+ "testCloneMovesPlusDeletions",
+ "testCloneMovesPlusInsertions",
+ "testParameters"
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public String getTestObjectName()
+ {
+ return "RowSet";
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void createTestCase(boolean _defaultRowSet)
+ {
+ if (m_database == null)
+ {
+ try
+ {
+ final CRMDatabase database = new CRMDatabase( getFactory(), false );
+ m_database = database.getDatabase();
+ m_dataSource = m_database.getDataSource();
+ }
+ catch (Exception e)
+ {
+ assure("could not create the embedded HSQL database: " + e.getMessage(), false);
+ }
+ }
+
+ try
+ {
+ createStruture();
+ }
+ catch (SQLException e)
+ {
+ assure("could not connect to the database/table structure, error message:\n" + e.getMessage(), false);
+ }
+
+ if (_defaultRowSet)
+ {
+ createRowSet("TEST1", CommandType.TABLE, true, true);
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private XMultiServiceFactory getFactory()
+ {
+ return (XMultiServiceFactory) param.getMSF();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** creates a com.sun.star.sdb.RowSet to use during the test
+ * @param command
+ * the command to use for the RowSet
+ * @param commandType
+ * the command type to use for the RowSet
+ * @param execute
+ * determines whether the RowSet should be executed
+ */
+ private void createRowSet(String command, int commandType, boolean execute)
+ {
+ createRowSet(command, commandType, execute, false);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** creates a com.sun.star.sdb.RowSet to use during the test
+ * @param command
+ * the command to use for the RowSet
+ * @param commandType
+ * the command type to use for the RowSet
+ * @param limitFetchSize
+ * determines whether the fetch size of the RowSet should be limited to MAX_FETCH_ROWS
+ * @param execute
+ * determines whether the RowSet should be executed
+ */
+ private void createRowSet(String command, int commandType, boolean execute, boolean limitFetchSize)
+ {
+ try
+ {
+ m_rowSet = UnoRuntime.queryInterface( XRowSet.class, getFactory().createInstance( "com.sun.star.sdb.RowSet" ) );
+ final XPropertySet rowSetProperties = UnoRuntime.queryInterface( XPropertySet.class, m_rowSet );
+ rowSetProperties.setPropertyValue("Command", command);
+ rowSetProperties.setPropertyValue("CommandType", Integer.valueOf(commandType));
+ rowSetProperties.setPropertyValue("ActiveConnection", m_database.defaultConnection().getXConnection());
+ if (limitFetchSize)
+ {
+ rowSetProperties.setPropertyValue("FetchSize", Integer.valueOf(MAX_FETCH_ROWS));
+ }
+
+ m_resultSet = UnoRuntime.queryInterface( XResultSet.class, m_rowSet );
+ m_resultSetUpdate = UnoRuntime.queryInterface( XResultSetUpdate.class, m_rowSet );
+ m_row = UnoRuntime.queryInterface( XRow.class, m_rowSet );
+ m_rowLocate = UnoRuntime.queryInterface( XRowLocate.class, m_resultSet );
+ m_rowSetProperties = UnoRuntime.queryInterface( XPropertySet.class, m_rowSet );
+ m_paramsSupplier = UnoRuntime.queryInterface( XParametersSupplier.class, m_rowSet );
+
+ if (execute)
+ {
+ m_rowSet.execute();
+ }
+ }
+ catch (Exception e)
+ {
+ assure("caught an exception while creating the RowSet. Type:\n" + e.getClass().toString() + "\nMessage:\n" + e.getMessage(), false);
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void testRowSet() throws java.lang.Exception
+ {
+
+ log.println("testing testRowSet");
+ createTestCase(true);
+
+ // sequential postioning
+ m_resultSet.beforeFirst();
+ testSequentialPositining(m_resultSet, m_row);
+
+ // absolute positioning
+ testAbsolutePositioning(m_resultSet, m_row);
+
+ // 3rd test
+ test3(createClone(), m_resultSet);
+ // 4th test
+ test4(m_resultSet);
+
+ // concurrent (multi threaded) access to the row set and its clones
+ testConcurrentAccess(m_resultSet);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ XResultSet createClone() throws SQLException
+ {
+ final XResultSetAccess rowAcc = UnoRuntime.queryInterface( XResultSetAccess.class, m_rowSet );
+ return rowAcc.createResultSet();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ void createStruture() throws SQLException
+ {
+ m_database.executeSQL("DROP TABLE \"TEST1\" IF EXISTS");
+ m_database.executeSQL("CREATE TABLE \"TEST1\" (\"ID\" integer not null primary key, \"col2\" varchar(50) )");
+
+ final Connection connection = m_database.defaultConnection();
+ final XPreparedStatement prep = connection.prepareStatement("INSERT INTO \"TEST1\" values (?,?)");
+ final XParameters para = UnoRuntime.queryInterface( XParameters.class, prep );
+ for (int i = 1; i <= MAX_TABLE_ROWS; ++i)
+ {
+ para.setInt(1, i);
+ para.setString(2, "Test" + i);
+ prep.executeUpdate();
+ }
+
+ connection.refreshTables();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ void testPosition(XResultSet m_resultSet, XRow m_row, int expectedValue, String location) throws SQLException
+ {
+ final int val = m_row.getInt(1);
+ final int pos = m_resultSet.getRow();
+ assure(location + ": value/position do not match: " + pos + " (pos) != " + val + " (val)", val == pos);
+ assure(location + ": value/position are not as expected: " + val + " (val) != " + expectedValue + " (expected)", val == expectedValue);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ void testSequentialPositining(XResultSet _resultSet, XRow _row)
+ {
+ try
+ {
+ // 1st test
+ int i = 1;
+ while (_resultSet.next())
+ {
+ testPosition(_resultSet, _row, i, "testSequentialPositining");
+ ++i;
+ }
+ }
+ catch (Exception e)
+ {
+ assure("testSequentialPositining failed: " + e, false);
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ void testAbsolutePositioning(XResultSet _resultSet, XRow _row)
+ {
+ try
+ {
+ for (int i = 1; i <= MAX_FETCH_ROWS; ++i)
+ {
+ final int calcPos = (MAX_TABLE_ROWS % i) + 1;
+ assure("testAbsolutePositioning failed", _resultSet.absolute(calcPos));
+ testPosition(_resultSet, _row, calcPos, "testAbsolutePositioning");
+ }
+ }
+ catch (Exception e)
+ {
+ assure("testAbsolutePositioning failed: " + e, false);
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ void test3(XResultSet clone, XResultSet _resultSet)
+ {
+ try
+ {
+ final XRow _row = UnoRuntime.queryInterface( XRow.class, _resultSet );
+ final XRow cloneRow = UnoRuntime.queryInterface( XRow.class, clone );
+ for (int i = 1; i <= MAX_FETCH_ROWS; ++i)
+ {
+ final int calcPos = (MAX_TABLE_ROWS % i) + 1;
+ if (clone.absolute(calcPos))
+ {
+ testPosition(clone, cloneRow, calcPos, "test3");
+ testAbsolutePositioning(_resultSet, _row);
+ testAbsolutePositioning(clone, cloneRow);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ assure("test3 failed: " + e, false);
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ void test4(XResultSet _resultSet)
+ {
+ try
+ {
+ final XRow _row = UnoRuntime.queryInterface( XRow.class, _resultSet );
+ _resultSet.beforeFirst();
+
+ for (int i = 1; i <= MAX_TABLE_ROWS; ++i)
+ {
+ _resultSet.next();
+ final XResultSet clone = createClone();
+ final XRow cloneRow = UnoRuntime.queryInterface( XRow.class, clone );
+ final int calcPos = MAX_TABLE_ROWS - 1;
+ if (calcPos != 0 && clone.absolute(calcPos))
+ {
+ testPosition(clone, cloneRow, calcPos, "test4: clone");
+ testPosition(_resultSet, _row, i, "test4: rowset");
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ assure("test4 failed: " + e, false);
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ void testConcurrentAccess(XResultSet _resultSet)
+ {
+ log.println("testing Thread");
+ try
+ {
+ // final XRow _row = (XRow)UnoRuntime.queryInterface(XRow.class,_resultSet);
+ _resultSet.beforeFirst();
+
+ final int numberOfThreads = 10;
+
+ final Thread threads[] = new Thread[numberOfThreads];
+ for (int i = 0; i < numberOfThreads; ++i)
+ {
+ threads[i] = new Thread(new ResultSetMovementStress(createClone(), i));
+ log.println("starting thread " + (i + 1) + " of " + (numberOfThreads));
+ threads[i].start();
+ }
+
+ for (int i = 0; i < numberOfThreads; ++i)
+ {
+ threads[i].join();
+ }
+ }
+ catch (Exception e)
+ {
+ assure("testConcurrentAccess failed: " + e, false);
+ }
+ }
+ // --------------------------------------------------------------------------------------------------------
+
+ public void testRowSetEvents() throws java.lang.Exception
+ {
+ log.println("testing RowSet Events");
+ createTestCase(true);
+
+ // first we create our RowSet object
+ final RowSetEventListener pRow = new RowSetEventListener();
+
+ final XColumnsSupplier colSup = UnoRuntime.queryInterface( XColumnsSupplier.class, m_rowSet );
+ final XPropertySet col = UnoRuntime.queryInterface( XPropertySet.class, colSup.getColumns().getByName( "ID" ) );
+ col.addPropertyChangeListener("Value", pRow);
+ m_rowSetProperties.addPropertyChangeListener("IsModified", pRow);
+ m_rowSetProperties.addPropertyChangeListener("IsNew", pRow);
+ m_rowSetProperties.addPropertyChangeListener("IsRowCountFinal", pRow);
+ m_rowSetProperties.addPropertyChangeListener("RowCount", pRow);
+
+ final XRowSetApproveBroadcaster xApBroad = UnoRuntime.queryInterface( XRowSetApproveBroadcaster.class, m_resultSet );
+ xApBroad.addRowSetApproveListener(pRow);
+ m_rowSet.addRowSetListener(pRow);
+
+ // do some movements to check if we got all notifications
+ final Class cResSet = Class.forName("com.sun.star.sdbc.XResultSet");
+ final boolean moves[] = new boolean[9];
+ for (int i = 0; i < moves.length; ++i)
+ {
+ moves[i] = false;
+ }
+ moves[RowSetEventListener.APPROVE_CURSOR_MOVE] = true;
+ moves[RowSetEventListener.COLUMN_VALUE] = true;
+ moves[RowSetEventListener.CURSOR_MOVED] = true;
+ moves[RowSetEventListener.IS_ROW_COUNT_FINAL] = true;
+ moves[RowSetEventListener.ROW_COUNT] = true;
+
+ testCursorMove(m_resultSet, cResSet.getMethod("afterLast", (Class[]) null), pRow, moves, null);
+
+ moves[RowSetEventListener.IS_ROW_COUNT_FINAL] = false;
+ moves[RowSetEventListener.ROW_COUNT] = false;
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod("last", (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod("first", (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod("previous", (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+ moves[RowSetEventListener.IS_MODIFIED] = true;
+ final XRowUpdate updRow = UnoRuntime.queryInterface( XRowUpdate.class, m_resultSet );
+ updRow.updateString(2, TEST21);
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+
+ moves[RowSetEventListener.IS_MODIFIED] = false;
+ final Class cupd = Class.forName("com.sun.star.sdbc.XResultSetUpdate");
+ final XResultSetUpdate upd = UnoRuntime.queryInterface( XResultSetUpdate.class, m_resultSet );
+ testCursorMove(upd, cupd.getMethod("moveToInsertRow", (Class[]) null), pRow, moves, null);
+
+ updRow.updateInt(1, MAX_TABLE_ROWS + 2);
+ updRow.updateString(2, "HHHH");
+ moves[RowSetEventListener.APPROVE_CURSOR_MOVE] = false;
+ moves[RowSetEventListener.CURSOR_MOVED] = false;
+ moves[RowSetEventListener.IS_MODIFIED] = true;
+ moves[RowSetEventListener.IS_NEW] = true;
+ moves[RowSetEventListener.ROW_COUNT] = true;
+ moves[RowSetEventListener.APPROVE_ROW_CHANGE] = true;
+ moves[RowSetEventListener.ROW_CHANGED] = true;
+ testCursorMove(upd, cupd.getMethod("insertRow", (Class[]) null), pRow, moves, null);
+
+ moves[RowSetEventListener.IS_NEW] = false;
+ moves[RowSetEventListener.ROW_COUNT] = false;
+ m_resultSet.first();
+ updRow.updateInt(1, MAX_TABLE_ROWS + 3);
+ updRow.updateString(2, "__");
+ testCursorMove(upd, cupd.getMethod("updateRow", (Class[]) null), pRow, moves, null);
+
+ moves[RowSetEventListener.IS_NEW] = true;
+ moves[RowSetEventListener.ROW_COUNT] = true;
+ m_resultSet.first();
+ testCursorMove(upd, cupd.getMethod("deleteRow", (Class[]) null), pRow, moves, null);
+
+ moves[RowSetEventListener.IS_NEW] = false;
+ moves[RowSetEventListener.COLUMN_VALUE] = true;
+ moves[RowSetEventListener.ROW_COUNT] = false;
+ m_resultSet.first();
+ updRow.updateString(2, TEST21);
+ testCursorMove(m_resultSet, cResSet.getMethod("refreshRow", (Class[]) null), pRow, moves, null);
+
+ m_resultSet.first();
+ updRow.updateString(2, TEST21);
+ testCursorMove(upd, cupd.getMethod("cancelRowUpdates", (Class[]) null), pRow, moves, null);
+
+ for (int i = 0; i < moves.length; ++i)
+ {
+ moves[i] = false;
+ }
+ moves[RowSetEventListener.APPROVE_CURSOR_MOVE] = true;
+ moves[RowSetEventListener.COLUMN_VALUE] = true;
+ moves[RowSetEventListener.CURSOR_MOVED] = true;
+
+ final Class cloc = Class.forName("com.sun.star.sdbcx.XRowLocate");
+ m_resultSet.first();
+ final Object bookmark = m_rowLocate.getBookmark();
+ m_resultSet.next();
+ final Object temp[] = new Object[1];
+ temp[0] = bookmark;
+ Class ctemp[] = new Class[1];
+ ctemp[0] = Object.class;
+ testCursorMove(m_rowLocate, cloc.getMethod("moveToBookmark", ctemp), pRow, moves, temp);
+
+ final Object temp2[] = new Object[2];
+ temp2[0] = bookmark;
+ temp2[1] = Integer.valueOf(1);
+ final Class ctemp2[] = new Class[2];
+ ctemp2[0] = Object.class;
+ ctemp2[1] = int.class;
+ testCursorMove(m_rowLocate, cloc.getMethod("moveRelativeToBookmark", ctemp2), pRow, moves, temp2);
+
+ for (int i = 0; i < moves.length; ++i)
+ {
+ moves[i] = false;
+ }
+ moves[RowSetEventListener.APPROVE_ROW_CHANGE] = true;
+ moves[RowSetEventListener.ROW_CHANGED] = true;
+ moves[RowSetEventListener.ROW_COUNT] = true;
+ final Class cdelRows = Class.forName("com.sun.star.sdbcx.XDeleteRows");
+ ctemp[0] = Object[].class;
+ final XDeleteRows delRows = UnoRuntime.queryInterface( XDeleteRows.class, m_resultSet );
+ final Object bookmarks[] = new Object[5];
+ m_resultSet.first();
+ for (int i = 0; i < bookmarks.length; ++i)
+ {
+ m_resultSet.next();
+ bookmarks[i] = m_rowLocate.getBookmark();
+ }
+
+ temp[0] = bookmarks;
+ testCursorMove(delRows, cdelRows.getMethod("deleteRows", ctemp), pRow, moves, temp);
+
+ // now destroy the RowSet
+ final XComponent xComp = UnoRuntime.queryInterface( XComponent.class, m_resultSet );
+ xComp.dispose();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void testCursorMove(Object res, Method _method, RowSetEventListener _evt, boolean _must[], Object args[]) throws java.lang.Exception
+ {
+ _evt.clearCalling();
+ _method.invoke(res, args);
+
+ log.println("testing events for " + _method.getName());
+ final int calling[] = _evt.getCalling();
+ int pos = 1;
+ assure("Callings are not in the correct order for APPROVE_CURSOR_MOVE ",
+ (!_must[RowSetEventListener.APPROVE_CURSOR_MOVE] || calling[RowSetEventListener.APPROVE_CURSOR_MOVE] == -1) || calling[RowSetEventListener.APPROVE_CURSOR_MOVE] == pos++);
+ assure("Callings are not in the correct order for APPROVE_ROW_CHANGE",
+ (!_must[RowSetEventListener.APPROVE_ROW_CHANGE] || calling[RowSetEventListener.APPROVE_ROW_CHANGE] == -1) || calling[RowSetEventListener.APPROVE_ROW_CHANGE] == pos++);
+ assure("Callings are not in the correct order for COLUMN_VALUE",
+ (!_must[RowSetEventListener.COLUMN_VALUE] || calling[RowSetEventListener.COLUMN_VALUE] == -1) || calling[RowSetEventListener.COLUMN_VALUE] == pos++);
+ assure("Callings are not in the correct order for CURSOR_MOVED",
+ (!_must[RowSetEventListener.CURSOR_MOVED] || calling[RowSetEventListener.CURSOR_MOVED] == -1) || calling[RowSetEventListener.CURSOR_MOVED] == pos++);
+ assure("Callings are not in the correct order for ROW_CHANGED",
+ (!_must[RowSetEventListener.ROW_CHANGED] || calling[RowSetEventListener.ROW_CHANGED] == -1) || calling[RowSetEventListener.ROW_CHANGED] == pos++);
+ assure("Callings are not in the correct order for IS_MODIFIED",
+ (!_must[RowSetEventListener.IS_MODIFIED] || calling[RowSetEventListener.IS_MODIFIED] == -1) || calling[RowSetEventListener.IS_MODIFIED] == pos++);
+ assure("Callings are not in the correct order for IS_NEW",
+ (!_must[RowSetEventListener.IS_NEW] || calling[RowSetEventListener.IS_NEW] == -1) || calling[RowSetEventListener.IS_NEW] == pos++);
+ assure("Callings are not in the correct order for ROW_COUNT",
+ (!_must[RowSetEventListener.ROW_COUNT] || calling[RowSetEventListener.ROW_COUNT] == -1) || calling[RowSetEventListener.ROW_COUNT] == pos++);
+ assure("Callings are not in the correct order for IS_ROW_COUNT_FINAL",
+ (!_must[RowSetEventListener.IS_ROW_COUNT_FINAL] || calling[RowSetEventListener.IS_ROW_COUNT_FINAL] == -1) || calling[RowSetEventListener.IS_ROW_COUNT_FINAL] == pos);
+
+ _evt.clearCalling();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** returns the current row count of the RowSet
+ */
+ private int currentRowCount() throws UnknownPropertyException, WrappedTargetException
+ {
+ final Integer rowCount = (Integer) m_rowSetProperties.getPropertyValue("RowCount");
+ return rowCount.intValue();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** positions the row set at an arbitrary position between 2 and (current row count - 1)
+ */
+ private int positionRandom() throws SQLException, UnknownPropertyException, WrappedTargetException
+ {
+ final int position = (new Random()).nextInt(currentRowCount() - 2) + 2;
+ assure("sub task failed: could not position to row no. " + (Integer.valueOf(position)).toString(),
+ m_resultSet.absolute(position));
+ return m_resultSet.getRow();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** moves the result set to a random record between 2 and (current row count - 1), and deletes this record
+ *
+ * After returning from this method, the row set is still positioned at the deleted record
+ * @return
+ * the number/position of the record which has been deleted
+ */
+ private int deleteRandom() throws SQLException, UnknownPropertyException, WrappedTargetException
+ {
+ // check if the current position and the row count in the result set is changed by a deletion (it should not)
+ final int positionBefore = positionRandom();
+ final int rowCountBefore = currentRowCount();
+
+ m_resultSetUpdate.deleteRow();
+
+ final int positionAfter = m_resultSet.getRow();
+ final int rowCountAfter = currentRowCount();
+ assure("position changed during |deleteRow| (it should not)", positionAfter == positionBefore);
+ assure("row count changed with a |deleteRow| (it should not)", rowCountBefore == rowCountAfter);
+ assure("RowSet does not report the current row as deleted after |deleteRow|", m_resultSet.rowDeleted());
+
+ return positionBefore;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void testDeleteBehavior() throws Exception
+ {
+ createTestCase(true);
+
+ // ensure that all records are known
+ m_resultSet.last();
+ final int initialRowCount = currentRowCount();
+
+ // delete a random row
+ int deletedRow = deleteRandom();
+
+ // .....................................................................................................
+ // asking for the bookmark of a deleted row should fail
+ boolean caughtException = false;
+ try
+ {
+ m_rowLocate.getBookmark();
+ }
+ catch (SQLException e)
+ {
+ caughtException = true;
+ }
+ assure("asking for the bookmark of a deleted row should throw an exception", caughtException);
+
+ // .....................................................................................................
+ // isXXX methods should return |false| on a deleted row
+ assure("one of the isFoo failed after |deleteRow|", !m_resultSet.isBeforeFirst() && !m_resultSet.isAfterLast() && !m_resultSet.isFirst() && !m_resultSet.isLast());
+ // note that we can assume that isFirst / isLast also return |false|, since deleteRandom did
+ // not position on the first or last record, but inbetween
+
+ // .....................................................................................................
+ // check if moving away from this row in either direction yields the expected results
+ assure("|previous| after |deleteRow| failed", m_resultSet.previous());
+ final int positionPrevious = m_resultSet.getRow();
+ assure("position after |previous| after |deleteRow| is not as expected", positionPrevious == deletedRow - 1);
+
+ deletedRow = deleteRandom();
+ assure("|next| after |deleteRow| failed", m_resultSet.next());
+ final int positionAfter = m_resultSet.getRow();
+ assure("position after |next| after |deleteRow| is not as expected", positionAfter == deletedRow);
+ // since the deleted record "vanishs" as soon as the cursor is moved away from it, the absolute position does
+ // not change with a |next| call here
+
+ // .....................................................................................................
+ // check if the deleted rows really vanished after moving away from them
+ assure("row count did not change as expected after two deletions", initialRowCount - 2 == currentRowCount());
+
+ // .....................................................................................................
+ // check if the deleted row vanishes after moving to the insertion row
+ final int rowCountBefore = currentRowCount();
+ final int deletedPos = deleteRandom();
+ m_resultSetUpdate.moveToInsertRow();
+ assure("moving to the insertion row immediately after |deleteRow| does not adjust the row count", rowCountBefore == currentRowCount() + 1);
+
+ m_resultSetUpdate.moveToCurrentRow();
+ assure("|moveToCurrentRow| after |deleteRow| + |moveToInsertRow| results in unexpected position",
+ (m_resultSet.getRow() == deletedPos) && !m_resultSet.rowDeleted());
+
+ // the same, but this time with deleting the first row (which is not covered by deleteRandom)
+ m_resultSet.last();
+ m_resultSetUpdate.deleteRow();
+ m_resultSetUpdate.moveToInsertRow();
+ m_resultSetUpdate.moveToCurrentRow();
+ assure("|last| + |deleteRow| + |moveToInsertRow| + |moveToCurrentRow| results in wrong state", m_resultSet.isAfterLast());
+
+ // .....................................................................................................
+ // check if deleting a deleted row fails as expected
+ deleteRandom();
+ caughtException = false;
+ try
+ {
+ m_resultSetUpdate.deleteRow();
+ }
+ catch (SQLException e)
+ {
+ caughtException = true;
+ }
+ assure("deleting a deleted row succeeded - it shouldn't", caughtException);
+
+ // .....................................................................................................
+ // check if deleteRows fails if it contains the bookmark of a previously-deleted row
+ m_resultSet.first();
+ final Object firstBookmark = m_rowLocate.getBookmark();
+ positionRandom();
+ final Object deleteBookmark = m_rowLocate.getBookmark();
+ m_resultSetUpdate.deleteRow();
+ final XDeleteRows multiDelete = UnoRuntime.queryInterface( XDeleteRows.class, m_resultSet );
+ final int[] deleteSuccess = multiDelete.deleteRows(new Object[]
+ {
+ firstBookmark, deleteBookmark
+ });
+ assure("XDeleteRows::deleteRows with the bookmark of an already-deleted row failed",
+ (deleteSuccess.length == 2) && (deleteSuccess[0] != 0) && (deleteSuccess[1] == 0));
+
+ // .....................................................................................................
+ // check if refreshing a deleted row fails as expected
+ deleteRandom();
+ caughtException = false;
+ try
+ {
+ m_resultSet.refreshRow();
+ }
+ catch (SQLException e)
+ {
+ caughtException = true;
+ }
+ assure("refreshing a deleted row succeeded - it shouldn't", caughtException);
+
+ // .....................................................................................................
+ // rowUpdated/rowDeleted
+ deleteRandom();
+ assure("rowDeleted and/or rowUpdated are wrong on a deleted row", !m_resultSet.rowUpdated() && !m_resultSet.rowInserted());
+
+ // .....................................................................................................
+ // updating values in a deleted row should fail
+ deleteRandom();
+ final XRowUpdate rowUpdated = UnoRuntime.queryInterface( XRowUpdate.class, m_resultSet );
+ caughtException = false;
+ try
+ {
+ rowUpdated.updateString(2, TEST21);
+ }
+ catch (SQLException e)
+ {
+ caughtException = true;
+ }
+ assure("updating values in a deleted row should not succeed", caughtException);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** checks whether deletions on the main RowSet properly interfere (or don't interfere) with the movement
+ * on a clone of the RowSet
+ */
+ @SuppressWarnings("empty-statement")
+ public void testCloneMovesPlusDeletions() throws SQLException, UnknownPropertyException, WrappedTargetException
+ {
+ createTestCase(true);
+ // ensure that all records are known
+ m_resultSet.last();
+
+ final XResultSet clone = createClone();
+ final XRowLocate cloneRowLocate = UnoRuntime.queryInterface( XRowLocate.class, clone );
+
+ positionRandom();
+
+ // .....................................................................................................
+ // move the clone to the same record as the RowSet, and delete this record
+ cloneRowLocate.moveToBookmark(m_rowLocate.getBookmark());
+ final int clonePosition = clone.getRow();
+ m_resultSetUpdate.deleteRow();
+
+ assure("clone doesn't know that its current row has been deleted via the RowSet", clone.rowDeleted());
+ assure("clone's position changed somehow during deletion", clonePosition == clone.getRow());
+
+ // .....................................................................................................
+ // move the row set away from the deleted record. This should still not touch the state of the clone
+ m_resultSet.previous();
+
+ assure("clone doesn't know (anymore) that its current row has been deleted via the RowSet", clone.rowDeleted());
+ assure("clone's position changed somehow during deletion and RowSet-movement", clonePosition == clone.getRow());
+
+ // .....................................................................................................
+ // move the clone away from the deleted record
+ clone.next();
+ assure("clone still assumes that its row is deleted - but we already moved it", !clone.rowDeleted());
+
+ // .....................................................................................................
+ // check whether deleting the extremes (first / last) work
+ m_resultSet.first();
+ cloneRowLocate.moveToBookmark(m_rowLocate.getBookmark());
+ m_resultSetUpdate.deleteRow();
+ clone.previous();
+ assure("deleting the first record left the clone in a strange state (after |previous|)", clone.isBeforeFirst());
+ clone.next();
+ assure("deleting the first record left the clone in a strange state (after |previous| + |next|)", clone.isFirst());
+
+ m_resultSet.last();
+ cloneRowLocate.moveToBookmark(m_rowLocate.getBookmark());
+ m_resultSetUpdate.deleteRow();
+ clone.next();
+ assure("deleting the last record left the clone in a strange state (after |next|)", clone.isAfterLast());
+ clone.previous();
+ assure("deleting the first record left the clone in a strange state (after |next| + |previous|)", clone.isLast());
+
+ // .....................................................................................................
+ // check whether movements of the clone interfere with movements of the RowSet, if the latter is on a deleted row
+ final int positionBefore = positionRandom();
+ m_resultSetUpdate.deleteRow();
+ assure("|deleteRow|, but no |rowDeleted| (this should have been found much earlier!)", m_resultSet.rowDeleted());
+ clone.beforeFirst();
+ while (clone.next());
+ assure("row set forgot that the current row is deleted", m_resultSet.rowDeleted());
+
+ assure("moving to the next record after |deleteRow| and clone moves failed", m_resultSet.next());
+ assure("wrong position after |deleteRow| and clone movement", !m_resultSet.isAfterLast() && !m_resultSet.isBeforeFirst());
+ assure("wrong absolute position after |deleteRow| and clone movement", m_resultSet.getRow() == positionBefore);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** checks whether insertions on the main RowSet properly interfere (or don't interfere) with the movement
+ * on a clone of the RowSet
+ */
+ public void testCloneMovesPlusInsertions() throws SQLException, UnknownPropertyException, WrappedTargetException, PropertyVetoException, com.sun.star.lang.IllegalArgumentException
+ {
+ createTestCase(true);
+ // ensure that all records are known
+ m_rowSetProperties.setPropertyValue("FetchSize", Integer.valueOf(10));
+
+ final XResultSet clone = createClone();
+ final XRow cloneRow = UnoRuntime.queryInterface( XRow.class, clone );
+
+ // .....................................................................................................
+ // first check the basic scenario without the |moveToInsertRow| |moveToCurrentRow|, to ensure that
+ // really those are broken, if at all
+ m_resultSet.last();
+ clone.first();
+ clone.absolute(11);
+ clone.first();
+
+ final int rowValue1 = m_row.getInt(1);
+ final int rowPos = m_resultSet.getRow();
+ final int rowValue2 = m_row.getInt(1);
+ assure("repeated query for the same column value delivers different values (" + rowValue1 + " and " + rowValue2 + ") on row: " + rowPos,
+ rowValue1 == rowValue2);
+
+ testPosition(clone, cloneRow, 1, "mixed clone/rowset move: clone check");
+ testPosition(m_resultSet, m_row, MAX_TABLE_ROWS, "mixed clone/rowset move: rowset check");
+
+ // .....................................................................................................
+ // now the complete scenario
+ m_resultSet.last();
+ m_resultSetUpdate.moveToInsertRow();
+ clone.first();
+ clone.absolute(11);
+ clone.first();
+ m_resultSetUpdate.moveToCurrentRow();
+
+ testPosition(clone, cloneRow, 1, "mixed clone/rowset move/insertion: clone check");
+ testPosition(m_resultSet, m_row, 100, "mixed clone/rowset move/insertion: rowset check");
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void testTableParameters()
+ {
+ // for a row set simply based on a table, there should be not parameters at all
+ createRowSet("products", CommandType.TABLE, false);
+ try
+ {
+ verifyParameters(new String[]
+ {
+ }, "testTableParameters");
+ }
+ catch (Exception e)
+ {
+ assure("testing the parameters of a table failed" + e.getMessage(), false);
+ }
+ }
+ // --------------------------------------------------------------------------------------------------------
+
+ private void testParametersAfterNormalExecute()
+ {
+ try
+ {
+ createRowSet("SELECT * FROM \"customers\"", CommandType.COMMAND, true);
+ m_rowSetProperties.setPropertyValue("Command", "SELECT * FROM \"customers\" WHERE \"City\" = :city");
+ final XParameters rowsetParams = UnoRuntime.queryInterface( XParameters.class, m_rowSet );
+ rowsetParams.setString(1, "London");
+ m_rowSet.execute();
+ }
+ catch (Exception e)
+ {
+ assure("testing the parameters of a table failed" + e.getMessage(), false);
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void verifyParameters(String[] _paramNames, String _context) throws com.sun.star.uno.Exception
+ {
+ final XIndexAccess params = m_paramsSupplier.getParameters();
+ final int expected = _paramNames.length;
+ final int found = params != null ? params.getCount() : 0;
+
+ assure("wrong number of parameters (expected: " + expected + ", found: " + found + ") in " + _context,
+ found == expected);
+
+ if (found == 0)
+ {
+ return;
+ }
+
+ for (int i = 0; i < expected; ++i)
+ {
+ final XPropertySet parameter = UnoRuntime.queryInterface( XPropertySet.class, params.getByIndex( i ) );
+
+ final String expectedName = _paramNames[i];
+ final String foundName = (String) parameter.getPropertyValue("Name");
+ assure("wrong parameter name (expected: " + expectedName + ", found: " + foundName + ") in" + _context,
+ expectedName.equals(foundName));
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void testParametrizedQuery()
+ {
+ try
+ {
+ // for a row set based on a parametrized query, those parameters should be properly
+ // recognized
+ m_dataSource.createQuery("products like", "SELECT * FROM \"products\" WHERE \"Name\" LIKE :product_name");
+ createRowSet("products like", CommandType.QUERY, false);
+ verifyParameters(new String[]
+ {
+ "product_name"
+ }, "testParametrizedQuery");
+ }
+ catch (Exception e)
+ {
+ assure("testing the parameters of a parametrized query failed" + e.getMessage(), false);
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void testParametersInteraction()
+ {
+ try
+ {
+ createRowSet("products like", CommandType.QUERY, false);
+
+ // let's fill in a parameter value via XParameters, and see whether it is respected by the parameters container
+ final XParameters rowsetParams = UnoRuntime.queryInterface(XParameters.class, m_rowSet);
+ rowsetParams.setString(1, "Apples");
+
+ XIndexAccess params = m_paramsSupplier.getParameters();
+ XPropertySet firstParam = UnoRuntime.queryInterface( XPropertySet.class, params.getByIndex( 0 ) );
+ Object firstParamValue = firstParam.getPropertyValue("Value");
+
+ assure("XParameters and the parameters container do not properly interact",
+ "Apples".equals(firstParamValue));
+
+ // let's see whether this also survices an execute of the row set
+ rowsetParams.setString(1, "Oranges");
+ m_rowSet.execute();
+ {
+ // TODO: the following would not be necessary if the parameters container would *survive*
+ // the execution of the row set. It currently doesn't (though the values it represents do).
+ // It would be nice, but not strictly necessary, if it would.
+ params = m_paramsSupplier.getParameters();
+ firstParam = UnoRuntime.queryInterface( XPropertySet.class, params.getByIndex( 0 ) );
+ }
+ firstParamValue = firstParam.getPropertyValue("Value");
+ assure("XParameters and the parameters container do not properly interact, after the row set has been executed",
+ "Oranges".equals(firstParamValue));
+ }
+ catch (Exception e)
+ {
+ assure("could not test the relationship between XParameters and XParametersSupplier" + e.getMessage(), false);
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void testParametersInFilter()
+ {
+ try
+ {
+ createRowSet("SELECT * FROM \"customers\"", CommandType.COMMAND, false);
+ m_rowSetProperties.setPropertyValue("Filter", "\"City\" = :city");
+
+ m_rowSetProperties.setPropertyValue("ApplyFilter", Boolean.TRUE);
+ verifyParameters(new String[]
+ {
+ "city"
+ }, "testParametersInFilter");
+
+ m_rowSetProperties.setPropertyValue("ApplyFilter", Boolean.FALSE);
+ verifyParameters(new String[]
+ {
+ }, "testParametersInFilter");
+ }
+ catch (Exception e)
+ {
+ assure("testing the parameters within a WHERE clause failed" + e.getMessage(), false);
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** checks the XParametersSupplier functionality of a RowSet
+ */
+ public void testParameters()
+ {
+ createTestCase(false);
+ // use an own RowSet instance, not the one which is also used for the other cases
+
+ testTableParameters();
+ testParametrizedQuery();
+ testParametersInFilter();
+
+ testParametersAfterNormalExecute();
+
+ testParametersInteraction();
+ }
+}
+
diff --git a/dbaccess/qa/complex/dbaccess/RowSetEventListener.java b/dbaccess/qa/complex/dbaccess/RowSetEventListener.java
new file mode 100644
index 000000000000..c4569986a5d7
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/RowSetEventListener.java
@@ -0,0 +1,111 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package complex.dbaccess;
+
+import com.sun.star.sdb.XRowSetApproveListener;
+import com.sun.star.sdbc.XRowSetListener;
+import com.sun.star.sdb.RowChangeEvent;
+import com.sun.star.lang.EventObject;
+import com.sun.star.beans.XPropertyChangeListener;
+
+public class RowSetEventListener implements XRowSetApproveListener,XRowSetListener,XPropertyChangeListener
+{
+ public static final int APPROVE_CURSOR_MOVE = 0;
+ public static final int APPROVE_ROW_CHANGE = 1;
+ public static final int COLUMN_VALUE = 2;
+ public static final int CURSOR_MOVED = 3;
+ public static final int ROW_CHANGED = 4;
+ public static final int IS_MODIFIED = 5;
+ public static final int IS_NEW = 6;
+ public static final int ROW_COUNT = 7;
+ public static final int IS_ROW_COUNT_FINAL = 8;
+
+ int callPos = 1;
+ int calling [];
+
+ RowSetEventListener(){
+ calling = new int [9];
+ clearCalling();
+ }
+ public int[] getCalling(){
+ return calling;
+ }
+ public void clearCalling(){
+ for(int i = 0 ; i < calling.length; ++i){
+ calling[i] = -1;
+ }
+ callPos = 1;
+ }
+ // XEventListener
+ public void disposing(com.sun.star.lang.EventObject event)
+ {
+ }
+ // XRowSetApproveBroadcaster
+ public boolean approveCursorMove(EventObject event)
+ {
+ calling[APPROVE_CURSOR_MOVE] = callPos++;
+ return true;
+ }
+ public boolean approveRowChange(RowChangeEvent event)
+ {
+ calling[APPROVE_ROW_CHANGE] = callPos++;
+ return true;
+ }
+ public boolean approveRowSetChange(EventObject event)
+ {
+ return true;
+ }
+
+ // XRowSetListener
+ public void cursorMoved(com.sun.star.lang.EventObject event)
+ {
+ calling[CURSOR_MOVED] = callPos++;
+ }
+ public void rowChanged(com.sun.star.lang.EventObject event)
+ {
+ calling[ROW_CHANGED] = callPos++;
+ }
+ public void rowSetChanged(com.sun.star.lang.EventObject event)
+ {
+ }
+
+ public void propertyChange(com.sun.star.beans.PropertyChangeEvent propertyChangeEvent) {
+ if ( "Value".equals(propertyChangeEvent.PropertyName) ){
+ calling[COLUMN_VALUE] = callPos++;
+ } else if ( "IsModified".equals(propertyChangeEvent.PropertyName) ){
+ calling[IS_MODIFIED] = callPos++;
+ } else if ( "IsNew".equals(propertyChangeEvent.PropertyName) ){
+ calling[IS_NEW] = callPos++;
+ } else if ( "RowCount".equals(propertyChangeEvent.PropertyName) ){
+ calling[ROW_COUNT] = callPos++;
+ } else if ( "IsRowCountFinal".equals(propertyChangeEvent.PropertyName) ){
+ calling[IS_ROW_COUNT_FINAL] = callPos++;
+ }
+ }
+
+}
diff --git a/dbaccess/qa/complex/dbaccess/SingleSelectQueryComposer.java b/dbaccess/qa/complex/dbaccess/SingleSelectQueryComposer.java
new file mode 100755
index 000000000000..bb3636100849
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/SingleSelectQueryComposer.java
@@ -0,0 +1,395 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.beans.*;
+import com.sun.star.sdbcx.*;
+import com.sun.star.sdb.*;
+import com.sun.star.container.*;
+
+import com.sun.star.sdbc.DataType;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class SingleSelectQueryComposer extends CRMBasedTestCase
+{
+
+ private XSingleSelectQueryComposer m_composer = null;
+ private final static String COMPLEXFILTER = "( \"ID\" = 1 AND \"Postal\" = '4' )" +
+ " OR ( \"ID\" = 2 AND \"Postal\" = '5' )" +
+ " OR ( \"ID\" = '3' AND \"Postal\" = '6' AND \"Address\" = '7' )" +
+ " OR ( \"Address\" = '8' )" +
+ " OR ( \"Postal\" = '9' )";
+ private final static String INNERPRODUCTSQUERY = "products (inner)";
+
+ // --------------------------------------------------------------------------------------------------------
+ public String[] getTestMethodNames()
+ {
+ return new String[]
+ {
+ "testSetCommand",
+ "testAttributes",
+ "testSubQueries",
+ "testParameters",
+ "testDisjunctiveNormalForm",
+ "testConditionByColumn"
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public String getTestObjectName()
+ {
+ return "SingleSelectQueryComposer";
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void createQueries() throws Exception
+ {
+ m_database.getDatabase().getDataSource().createQuery(INNERPRODUCTSQUERY, "SELECT * FROM \"products\"");
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ protected void createTestCase()
+ {
+ try
+ {
+ super.createTestCase();
+
+ createQueries();
+
+ m_composer = createQueryComposer();
+
+ }
+ catch (Exception e)
+ {
+ assure("caught an exception (" + e.getMessage() + ") while creating the test case", false);
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void checkAttributeAccess(String _attributeName, String _attributeValue)
+ {
+ log.println("setting " + _attributeName + " to " + _attributeValue);
+ String realValue = null;
+ try
+ {
+ final Class composerClass = m_composer.getClass();
+ final Method attributeGetter = composerClass.getMethod("get" + _attributeName, new Class[]
+ {
+ });
+ final Method attributeSetter = composerClass.getMethod("set" + _attributeName, new Class[]
+ {
+ String.class
+ });
+
+ attributeSetter.invoke(m_composer, new Object[]
+ {
+ _attributeValue
+ });
+ realValue = (String) attributeGetter.invoke(m_composer, new Object[]
+ {
+ });
+ }
+ catch (NoSuchMethodException e)
+ {
+ }
+ catch (IllegalAccessException e)
+ {
+ }
+ catch (InvocationTargetException e)
+ {
+ }
+ assure("set/get" + _attributeName + " not working as expected (set: " + _attributeValue + ", get: " + (realValue != null ? realValue : "null") + ")",
+ realValue.equals(_attributeValue));
+ log.println(" (results in " + (String) m_composer.getQuery() + ")");
+ }
+
+ /** tests setCommand of the composer
+ */
+ public void testSetCommand()
+ {
+ log.println("testing SingleSelectQueryComposer's setCommand");
+
+ try
+ {
+ final String table = "SELECT * FROM \"customers\"";
+ m_composer.setCommand("customers",CommandType.TABLE);
+ assure("setCommand/getQuery TABLE inconsistent", m_composer.getQuery().equals(table));
+
+ m_database.getDatabase().getDataSource().createQuery("set command test", "SELECT * FROM \"orders for customer\" \"a\", \"customers\" \"b\" WHERE \"a\".\"Product Name\" = \"b\".\"Name\"");
+ m_composer.setCommand("set command test",CommandType.QUERY);
+ assure("setCommand/getQuery QUERY inconsistent", m_composer.getQuery().equals(m_database.getDatabase().getDataSource().getQueryDefinition("set command test").getCommand()));
+
+ final String sql = "SELECT * FROM \"orders for customer\" WHERE \"Product Name\" = 'test'";
+ m_composer.setCommand(sql,CommandType.COMMAND);
+ assure("setCommand/getQuery COMMAND inconsistent", m_composer.getQuery().equals(sql));
+ }
+ catch (Exception e)
+ {
+ assure("Exception caught: " + e, false);
+ }
+ }
+ /** tests accessing attributes of the composer (order, filter, group by, having)
+ */
+ public void testAttributes()
+ {
+ log.println("testing SingleSelectQueryComposer's attributes (order, filter, group by, having)");
+
+ try
+ {
+ log.println("check setElementaryQuery");
+ final String simpleQuery2 = "SELECT * FROM \"customers\" WHERE \"Name\" = 'oranges'";
+ m_composer.setElementaryQuery(simpleQuery2);
+ assure("setElementaryQuery/getQuery inconsistent", m_composer.getQuery().equals(simpleQuery2));
+
+ log.println("check setQuery");
+ final String simpleQuery = "SELECT * FROM \"customers\"";
+ m_composer.setQuery(simpleQuery);
+ assure("set/getQuery inconsistent", m_composer.getQuery().equals(simpleQuery));
+
+ checkAttributeAccess("Filter", "\"Name\" = 'oranges'");
+ checkAttributeAccess("Group", "\"City\"");
+ checkAttributeAccess("Order", "\"Address\"");
+ checkAttributeAccess("HavingClause", "\"ID\" <> 4");
+
+ final XIndexAccess orderColumns = m_composer.getOrderColumns();
+ assure("Order columns doesn't exist: \"Address\"",
+ orderColumns != null && orderColumns.getCount() == 1 && orderColumns.getByIndex(0) != null);
+
+ final XIndexAccess groupColumns = m_composer.getGroupColumns();
+ assure("Group columns doesn't exist: \"City\"",
+ groupColumns != null && groupColumns.getCount() == 1 && groupColumns.getByIndex(0) != null);
+
+ // XColumnsSupplier
+ final XColumnsSupplier xSelectColumns = (XColumnsSupplier) UnoRuntime.queryInterface(XColumnsSupplier.class, m_composer);
+ assure("no select columns, or wrong number of select columns",
+ xSelectColumns != null && xSelectColumns.getColumns() != null && xSelectColumns.getColumns().getElementNames().length == 6);
+
+ // structured filter
+ m_composer.setQuery("SELECT \"ID\", \"Postal\", \"Address\" FROM \"customers\"");
+ m_composer.setFilter(COMPLEXFILTER);
+ final PropertyValue[][] aStructuredFilter = m_composer.getStructuredFilter();
+ m_composer.setFilter("");
+ m_composer.setStructuredFilter(aStructuredFilter);
+ assure("Structured Filter not identical", m_composer.getFilter().equals(COMPLEXFILTER));
+
+ // structured having clause
+ m_composer.setHavingClause(COMPLEXFILTER);
+ final PropertyValue[][] aStructuredHaving = m_composer.getStructuredHavingClause();
+ m_composer.setHavingClause("");
+ m_composer.setStructuredHavingClause(aStructuredHaving);
+ assure("Structured Having Clause not identical", m_composer.getHavingClause().equals(COMPLEXFILTER));
+ }
+ catch (Exception e)
+ {
+ assure("Exception caught: " + e, false);
+ }
+ }
+
+ /** test various sub query related features ("queries in queries")
+ */
+ public void testSubQueries() throws Exception
+ {
+ m_composer.setQuery("SELECT * from \"" + INNERPRODUCTSQUERY + "\"");
+ final XTablesSupplier suppTables = (XTablesSupplier) UnoRuntime.queryInterface(
+ XTablesSupplier.class, m_composer);
+ final XNameAccess tables = suppTables.getTables();
+ assure("a simple SELECT * FROM <query> could not be parsed",
+ tables != null && tables.hasByName(INNERPRODUCTSQUERY));
+
+ final String sInnerCommand = m_database.getDatabase().getDataSource().getQueryDefinition(INNERPRODUCTSQUERY).getCommand();
+ final String sExecutableQuery = m_composer.getQueryWithSubstitution();
+ assure("simple query containing a sub query improperly parsed to SDBC level statement: \n1. " + sExecutableQuery + "\n2. " + "SELECT * FROM ( " + sInnerCommand + " ) AS \"" + INNERPRODUCTSQUERY + "\"",
+ sExecutableQuery.equals("SELECT * FROM ( " + sInnerCommand + " ) AS \"" + INNERPRODUCTSQUERY + "\""));
+ }
+
+ /** tests the XParametersSupplier functionality
+ */
+ public void testParameters()
+ {
+ try
+ {
+ // "orders for customers" is a query with a named parameter (based on another query)
+ m_database.getDatabase().getDataSource().createQuery("orders for customer", "SELECT * FROM \"all orders\" WHERE \"Customer Name\" LIKE :cname");
+ // "orders for customer and product" is query based on "orders for customers", adding an additional,
+ // anonymous parameter
+ m_database.getDatabase().getDataSource().createQuery("orders for customer and product", "SELECT * FROM \"orders for customer\" WHERE \"Product Name\" LIKE ?");
+
+ m_composer.setQuery(m_database.getDatabase().getDataSource().getQueryDefinition("orders for customer and product").getCommand());
+ final XParametersSupplier suppParams = (XParametersSupplier) UnoRuntime.queryInterface(
+ XParametersSupplier.class, m_composer);
+ final XIndexAccess parameters = suppParams.getParameters();
+
+ final String expectedParamNames[] =
+ {
+ "cname",
+ "Product Name"
+ };
+
+ final int paramCount = parameters.getCount();
+ assure("composer did find wrong number of parameters in the nested queries.",
+ paramCount == expectedParamNames.length);
+
+ for (int i = 0; i < paramCount; ++i)
+ {
+ final XPropertySet parameter = (XPropertySet) UnoRuntime.queryInterface(
+ XPropertySet.class, parameters.getByIndex(i));
+ final String paramName = (String) parameter.getPropertyValue("Name");
+ assure("wrong parameter name at position " + (i + 1) + " (expected: " + expectedParamNames[i] + ", found: " + paramName + ")",
+ paramName.equals(expectedParamNames[i]));
+
+ }
+ }
+ catch (Exception e)
+ {
+ assure("caught an exception: " + e, false);
+ }
+ }
+
+ public void testConditionByColumn()
+ {
+ try
+ {
+ m_composer.setQuery("SELECT * FROM \"customers\"");
+
+ final Object initArgs[] =
+ {
+ new NamedValue("AutomaticAddition", Boolean.valueOf(true))
+ };
+ final String serviceName = "com.sun.star.beans.PropertyBag";
+ final XPropertyContainer filter = (XPropertyContainer) UnoRuntime.queryInterface(XPropertyContainer.class,
+ getORB().createInstanceWithArguments(serviceName, initArgs));
+ filter.addProperty("Name", PropertyAttribute.MAYBEVOID, "Comment");
+ filter.addProperty("RealName", PropertyAttribute.MAYBEVOID, "Comment");
+ filter.addProperty("TableName", PropertyAttribute.MAYBEVOID, "customers");
+ filter.addProperty("Value", PropertyAttribute.MAYBEVOID, "Good one.");
+ filter.addProperty("Type", PropertyAttribute.MAYBEVOID, Integer.valueOf(DataType.LONGVARCHAR));
+ final XPropertySet column = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class,filter);
+
+ m_composer.appendFilterByColumn(column, true,SQLFilterOperator.LIKE);
+ assure("At least one row should exist",m_database.getConnection().createStatement().executeQuery(m_composer.getQuery()).next());
+
+ }
+ catch (Exception e)
+ {
+ // this is an error: the query is expected to be parseable
+ assure("caught an exception: " + e, false);
+ }
+ }
+
+ private void impl_testDisjunctiveNormalForm(String _query, PropertyValue[][] _expectedDNF)
+ {
+ try
+ {
+ m_composer.setQuery(_query);
+ }
+ catch (Exception e)
+ {
+ // this is an error: the query is expected to be parseable
+ assure("caught an exception: " + e, false);
+ }
+
+ final PropertyValue[][] disjunctiveNormalForm = m_composer.getStructuredFilter();
+
+ assureEquals("DNF: wrong number of rows", _expectedDNF.length, disjunctiveNormalForm.length);
+ for (int i = 0; i < _expectedDNF.length; ++i)
+ {
+ assureEquals("DNF: wrong number of columns in row " + i, _expectedDNF[i].length, disjunctiveNormalForm[i].length);
+ for (int j = 0; j < _expectedDNF[i].length; ++j)
+ {
+ assureEquals("DNF: wrong content in column " + j + ", row " + i,
+ _expectedDNF[i][j].Name, disjunctiveNormalForm[i][j].Name);
+ }
+ }
+ }
+
+ /** tests the disjunctive normal form functionality, aka the structured filter,
+ * of the composer
+ */
+ public void testDisjunctiveNormalForm()
+ {
+ // a simple case: WHERE clause simply is a combination of predicates knitted with AND
+ String query =
+ "SELECT \"customers\".\"Name\", " +
+ "\"customers\".\"Address\", " +
+ "\"customers\".\"City\", " +
+ "\"customers\".\"Postal\", " +
+ "\"products\".\"Name\" " +
+ "FROM \"orders\", \"customers\", \"orders_details\", \"products\" " +
+ "WHERE ( \"orders\".\"CustomerID\" = \"customers\".\"ID\" " +
+ "AND \"orders_details\".\"OrderID\" = \"orders\".\"ID\" " +
+ "AND \"orders_details\".\"ProductID\" = \"products\".\"ID\" " +
+ ") ";
+
+ impl_testDisjunctiveNormalForm(query, new PropertyValue[][]
+ {
+ new PropertyValue[]
+ {
+ new PropertyValue("CustomerID", SQLFilterOperator.EQUAL, "\"customers\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("OrderID", SQLFilterOperator.EQUAL, "\"orders\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("ProductID", SQLFilterOperator.EQUAL, "\"products\".\"ID\"", PropertyState.DIRECT_VALUE)
+ }
+ });
+
+ // somewhat more challenging: One of the conjunction terms is a disjunction itself
+ query =
+ "SELECT \"customers\".\"Name\", " +
+ "\"customers\".\"Address\", " +
+ "\"customers\".\"City\", " +
+ "\"customers\".\"Postal\", " +
+ "\"products\".\"Name\" " +
+ "FROM \"orders\", \"customers\", \"orders_details\", \"products\" " +
+ "WHERE ( \"orders\".\"CustomerID\" = \"customers\".\"ID\" " +
+ "AND \"orders_details\".\"OrderID\" = \"orders\".\"ID\" " +
+ "AND \"orders_details\".\"ProductID\" = \"products\".\"ID\" " +
+ ") " +
+ "AND " +
+ "( \"products\".\"Name\" = 'Apples' " +
+ "OR \"products\".\"ID\" = 2 " +
+ ")";
+
+ impl_testDisjunctiveNormalForm(query, new PropertyValue[][]
+ {
+ new PropertyValue[]
+ {
+ new PropertyValue("CustomerID", SQLFilterOperator.EQUAL, "\"customers\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("OrderID", SQLFilterOperator.EQUAL, "\"orders\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("ProductID", SQLFilterOperator.EQUAL, "\"products\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("Name", SQLFilterOperator.EQUAL, "Apples", PropertyState.DIRECT_VALUE)
+ },
+ new PropertyValue[]
+ {
+ new PropertyValue("CustomerID", SQLFilterOperator.EQUAL, "\"customers\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("OrderID", SQLFilterOperator.EQUAL, "\"orders\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("ProductID", SQLFilterOperator.EQUAL, "\"products\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("ID", SQLFilterOperator.EQUAL, Integer.valueOf(2), PropertyState.DIRECT_VALUE)
+ }
+ });
+
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/TestCase.java b/dbaccess/qa/complex/dbaccess/TestCase.java
new file mode 100644
index 000000000000..b8dae3f6f350
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/TestCase.java
@@ -0,0 +1,126 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.frame.XComponentLoader;
+import com.sun.star.frame.XModel;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+import helper.FileTools;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+public abstract class TestCase extends complexlib.ComplexTestCase
+{
+ // --------------------------------------------------------------------------------------------------------
+ protected final XMultiServiceFactory getORB()
+ {
+ return (XMultiServiceFactory)param.getMSF();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ protected final XComponentContext getComponentContext()
+ {
+ XComponentContext context = null;
+ try
+ {
+ final XPropertySet orbProps = UnoRuntime.queryInterface( XPropertySet.class, getORB() );
+ context = UnoRuntime.queryInterface( XComponentContext.class,
+ orbProps.getPropertyValue( "DefaultContext" ) );
+ }
+ catch ( Exception ex )
+ {
+ failed( "could not retrieve the ComponentContext" );
+ }
+ return context;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void before() throws java.lang.Exception
+ {
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void after() throws java.lang.Exception
+ {
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** 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
+ {
+ final File documentFile = java.io.File.createTempFile( getTestObjectName(), ".odb" ).getAbsoluteFile();
+ if ( documentFile.exists() )
+ documentFile.delete();
+ return FileHelper.getOOoCompatibleFileURL( documentFile.toURI().toURL().toString() );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /**
+ * copies the file given by URL to a temporary file
+ * @return
+ * the URL of the new file
+ */
+ protected final String copyToTempFile( String _sourceURL ) throws IOException
+ {
+ final String targetURL = createTempFileURL();
+ try
+ {
+ FileTools.copyFile( new File( new URI( _sourceURL ) ), new File( new URI( targetURL ) ) );
+ }
+ catch ( URISyntaxException e ) { }
+
+ return FileHelper.getOOoCompatibleFileURL( targetURL );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ protected final XModel loadDocument( final String _docURL ) throws Exception
+ {
+ final XComponentLoader loader = UnoRuntime.queryInterface( XComponentLoader.class,
+ getORB().createInstance( "com.sun.star.frame.Desktop" ) );
+ return UnoRuntime.queryInterface( XModel.class,
+ loader.loadComponentFromURL( _docURL, "_blank", 0, new PropertyValue[] {} ) );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ protected void assureException( Object _object, Class _unoInterfaceClass, String _methodName, Object[] _methodArgs,
+ Class _expectedExceptionClass )
+ {
+ assureException( UnoRuntime.queryInterface( _unoInterfaceClass, _object ), _methodName,
+ _methodArgs, _expectedExceptionClass );
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/UISettings.java b/dbaccess/qa/complex/dbaccess/UISettings.java
new file mode 100644
index 000000000000..fc772b158f5f
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/UISettings.java
@@ -0,0 +1,152 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.awt.FontSlant;
+import com.sun.star.awt.TextAlign;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.form.runtime.XFormController;
+import com.sun.star.frame.XController;
+import com.sun.star.frame.XModel;
+import com.sun.star.sdb.application.DatabaseObject;
+import com.sun.star.sdb.application.XDatabaseDocumentUI;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.util.XCloseable;
+import connectivity.tools.CRMDatabase;
+
+public class UISettings extends TestCase
+{
+ // --------------------------------------------------------------------------------------------------------
+ public String[] getTestMethodNames()
+ {
+ return new String[] {
+ "checkTableFormattingPersistence",
+ "checkTransparentQueryColumnSettings"
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public String getTestObjectName()
+ {
+ return "UISettings";
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** verifies that aliases for inner queries work as expected
+ */
+ public void checkTableFormattingPersistence() throws java.lang.Exception
+ {
+ // create, load, and connect a DB doc
+ CRMDatabase database = new CRMDatabase( getORB(), true );
+
+ // display a table
+ XFormController tableViewController = UnoRuntime.queryInterface( XFormController.class,
+ database.loadSubComponent( DatabaseObject.TABLE, "customers" ) );
+ XPropertySet tableControlModel = UnoRuntime.queryInterface( XPropertySet.class,
+ tableViewController.getCurrentControl().getModel() );
+
+ // change the table's formatting
+ tableControlModel.setPropertyValue( "FontName", "Andale Sans UI" );
+ tableControlModel.setPropertyValue( "FontHeight", Float.valueOf( 20 ) );
+ tableControlModel.setPropertyValue( "FontSlant", FontSlant.ITALIC );
+
+ String docURL = database.getDatabase().getModel().getURL();
+
+ // save close the database document
+ database.saveAndClose();
+
+ // load a copy of the document
+ // normally, it should be sufficient to load the same doc. However, there might be objects in the Java VM
+ // which are not yet freed, and which effectively hold the document alive. More precise: The document (|doc|)
+ // is certainly disposed, but other objects might hold a reference to one of the many other components
+ // around the database document, the data source, the connection, etc. As long as those objects are
+ // not cleaned up, the "database model impl" - the structure holding all document data - will
+ // stay alive, and subsequent requests to load the doc will just reuse it, without really loading it.
+ docURL = copyToTempFile( docURL );
+ loadDocument( docURL );
+ database = new CRMDatabase( getORB(), docURL );
+
+ // display the table, again
+ tableViewController = UnoRuntime.queryInterface( XFormController.class,
+ database.loadSubComponent( DatabaseObject.TABLE, "customers" ) );
+ tableControlModel = UnoRuntime.queryInterface( XPropertySet.class,
+ tableViewController.getCurrentControl().getModel() );
+
+ // verify the properties
+ assureEquals( "wrong font name", "Andale Sans UI", (String)tableControlModel.getPropertyValue( "FontName" ) );
+ assureEquals( "wrong font height", (float)20, ((Float)tableControlModel.getPropertyValue( "FontHeight" )).floatValue() );
+ assureEquals( "wrong font slant", FontSlant.ITALIC, (FontSlant)tableControlModel.getPropertyValue( "FontSlant" ) );
+
+ // close the doc
+ database.saveAndClose();
+ }
+
+ /**
+ * checks whether query columns use the settings of the underlying table column, if they do not (yet) have own
+ * settings
+ * @throws java.lang.Exception
+ */
+ public void checkTransparentQueryColumnSettings() throws java.lang.Exception
+ {
+ // create, load, and connect a DB doc
+ CRMDatabase database = new CRMDatabase( getORB(), true );
+
+ // display a table
+ XController tableView = database.loadSubComponent( DatabaseObject.TABLE, "customers" );
+ XFormController tableViewController = UnoRuntime.queryInterface( XFormController.class,
+ tableView );
+ XNameAccess tableControlModel = UnoRuntime.queryInterface( XNameAccess.class,
+ tableViewController.getCurrentControl().getModel() );
+
+ // change the formatting of a table column
+ XPropertySet idColumn = UnoRuntime.queryInterface( XPropertySet.class, tableControlModel.getByName( "ID" ) );
+ assure( "precondition not met: column already centered",
+ ((Short)idColumn.getPropertyValue( "Align" )).shortValue() != TextAlign.CENTER );
+ idColumn.setPropertyValue( "Align", TextAlign.CENTER );
+
+ // close the table data view
+ XCloseable closeSubComponent = UnoRuntime.queryInterface( XCloseable.class, tableView.getFrame() );
+ closeSubComponent.close( true );
+
+ // create a query based on that column
+ database.getDatabase().getDataSource().createQuery( "q_customers", "SELECT * FROM \"customers\"" );
+
+ // load this query, and verify the table column settings was propagated to the query column
+ XFormController queryViewController = UnoRuntime.queryInterface( XFormController.class,
+ database.loadSubComponent( DatabaseObject.QUERY, "q_customers" ) );
+ tableControlModel = UnoRuntime.queryInterface( XNameAccess.class,
+ queryViewController.getCurrentControl().getModel() );
+ idColumn = UnoRuntime.queryInterface( XPropertySet.class, tableControlModel.getByName( "ID" ) );
+
+ assure( "table column alignment was not propagated to the query column",
+ ((Short)idColumn.getPropertyValue( "Align" )).shortValue() == TextAlign.CENTER );
+
+ // save close the database document
+ database.saveAndClose();
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/dbaccess.sce b/dbaccess/qa/complex/dbaccess/dbaccess.sce
new file mode 100644
index 000000000000..c5fa408ff273
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/dbaccess.sce
@@ -0,0 +1,12 @@
+-o complex.dbaccess.SingleSelectQueryComposer
+-o complex.dbaccess.RowSet
+-o complex.dbaccess.PropertyBag
+-o complex.dbaccess.Query
+-o complex.dbaccess.QueryInQuery
+-o complex.dbaccess.DatabaseDocument
+-o complex.dbaccess.DataSource
+-o complex.dbaccess.Parser
+-o complex.dbaccess.ApplicationController
+-o complex.dbaccess.CopyTableWizard
+-o complex.dbaccess.UISettings
+-o complex.dbaccess.Beamer
diff --git a/dbaccess/qa/complex/dbaccess/makefile.mk b/dbaccess/qa/complex/dbaccess/makefile.mk
new file mode 100755
index 000000000000..56a24c0292fc
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/makefile.mk
@@ -0,0 +1,78 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# 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
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ = ..$/..$/..
+TARGET = DbaComplexTests
+PRJNAME = $(TARGET)
+PACKAGE = complex$/dbaccess
+
+# --- Settings -----------------------------------------------------
+.INCLUDE: settings.mk
+
+.IF "$(SOLAR_JAVA)" == ""
+all:
+ @echo "Java not available. Build skipped"
+
+.INCLUDE : target.mk
+.ELSE
+
+#----- compile .java files -----------------------------------------
+
+JARFILES = ridl.jar unoil.jar jurt.jar juh.jar java_uno.jar OOoRunner.jar ConnectivityTools.jar
+JAVAFILES := $(shell @$(FIND) ./*.java)
+JAVACLASSFILES = $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(PACKAGE)$/$(i:b).class)
+
+#----- make a jar from compiled files ------------------------------
+
+MAXLINELENGTH = 100000
+
+JARCLASSDIRS = $(PACKAGE)
+JARTARGET = $(TARGET).jar
+JARCOMPRESS = TRUE
+
+RUNNER_ARGS = -cp "$(CLASSPATH)$(PATH_SEPERATOR)$(SOLARBINDIR)$/OOoRunner.jar" org.openoffice.Runner -TestBase java_complex
+
+RUNNER_CALL = $(AUGMENT_LIBRARY_PATH) java
+
+# --- Targets ------------------------------------------------------
+
+.IF "$(depend)" == ""
+ALL : ALLTAR
+.ELSE
+ALL: ALLDEP
+.ENDIF
+
+.INCLUDE : target.mk
+
+
+run: $(CLASSDIR)$/$(JARTARGET)
+ +$(RUNNER_CALL) $(RUNNER_ARGS) -sce dbaccess.sce
+
+run_%: $(CLASSDIR)$/$(JARTARGET)
+ +$(RUNNER_CALL) $(RUNNER_ARGS) -o complex.dbaccess.$(@:s/run_//)
+
+.ENDIF # "$(SOLAR_JAVA)" == ""