Hi Matthias,

>>>>> I created a little programm that removes a menu item from a menu and
>>>>> adds another instead. In case the user tries to access the menu while
>>>>> the menu update is performed my OO crashes and says:

[...]

> Usually this shouldn't happen. I'm afraid that without a test case or at
> least the relevant source code of your java program we can't do much. I
> assume that one of your API calls leaves the menu in an inconsistent
> state (that is resolved with one or more subsequent calls) or one of the
> API calls you are using is not synchronized correctly. In the first case
> we must check the involved API calls and see what can be done, in the
> latter case we definitely must fix our code.

I created a little sample application. You will find it at the end of
the mail. May be a little oversized, but that is how it works here.

One hint: in the main method the String args[] expects on Postition
args[0] the filename.

Please enter the file menu as soon as the application openes.

[...]

> Not really. Can you create and send a crash report (with your e-mail
> address in the report so that I can find it in our database)?

How can I do this? I use a Debian Sid OpenOffice (2.0.2) and no
crashreport screen is shown. How can I activate it?

Greetings, Tobias

-----%<-----
package de.twc.oocom;

import java.io.File;
import java.net.MalformedURLException;
import java.util.Vector;

import com.sun.star.beans.PropertyValue;
import com.sun.star.beans.XPropertySet;
import com.sun.star.comp.helper.Bootstrap;
import com.sun.star.comp.helper.BootstrapException;
import com.sun.star.container.XIndexAccess;
import com.sun.star.container.XIndexContainer;
import com.sun.star.frame.XComponentLoader;
import com.sun.star.frame.XDesktop;
import com.sun.star.frame.XFrame;
import com.sun.star.frame.XLayoutManager;
import com.sun.star.lang.EventObject;
import com.sun.star.lang.IllegalArgumentException;
import com.sun.star.lang.IndexOutOfBoundsException;
import com.sun.star.lang.WrappedTargetException;
import com.sun.star.lang.XComponent;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.ui.XUIElement;
import com.sun.star.ui.XUIElementSettings;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import com.sun.star.uri.ExternalUriReferenceTranslator;
import com.sun.star.util.CloseVetoException;
import com.sun.star.util.XCloseListener;
import com.sun.star.util.XCloseable;

public class MenuCrashTest {

    // You will need these Objects often...
    private Object desktop = null;
    private XComponentContext xRemoteContext = null;
    private XMultiComponentFactory xRemoteServiceManager = null;

    private XDesktop xDesktop = null;

    private XFrame xFrame = null;
    private XLayoutManager xLayoutManager = null;

    // The opened document itself
    private XComponent openDocument = null;

    private String openFilename = null;

    private MenuCrashTest(String newFilename) {
        openFilename = newFilename;
    }

    public static void main(String[] args){
        MenuCrashTest myCrashTest = new MenuCrashTest(args[0]);
        myCrashTest.bootstrapOpenOffice();
        myCrashTest.openDocument();
        // add a menu item after the menu item ".uno:Save"
        myCrashTest.changeMenus(".uno:Save",
                ".JudasSaveTo:",
                "Sicherheitskopie");
        // remove menu item ".uno:SaveAs"
        myCrashTest.changeMenus(".uno:SaveAs", null, null);
        // remove toolbar item ".uno:SaveAs"
        myCrashTest.changeToolbars(".uno:SaveAs", "remove");
        myCrashTest.addCloseListener();
    }

    /**
     * This method bootstraps a OpenOffice and returns it's Desktop.
     *
     * @return
     */
    private void bootstrapOpenOffice()
    {
        try
        {
            // Connect or start a OpenOffice instance
            xRemoteContext = Bootstrap.bootstrap();
        }
        catch (BootstrapException e)
        {
            System.out.println("Unable to start OpenOffice. Starter says:");
            System.out.println(e.getLocalizedMessage());
        }
        // get OO desktop
        xRemoteServiceManager = xRemoteContext.getServiceManager();
        try
        {
            desktop = xRemoteServiceManager.createInstanceWithContext(
                    "com.sun.star.frame.Desktop", xRemoteContext
            );
        }
        catch (com.sun.star.uno.Exception e)
        {
            System.out.println("OpenOffice started, but can't get
Desktop:");
            System.out.println(e.getLocalizedMessage());
        }
        // Get the XDesktop so you can close Openoffice correctly
        xDesktop = (XDesktop)
                UnoRuntime.queryInterface(XDesktop.class, desktop);
        System.out.println("OpenOffice successfully started.");
    }

    /**
     * This method connects to a running OpenOffice or, if none found
starts it.
     * Afterwards a specified document is loaded.
     *
     * @param documentProperties
     * @param source_File
     * @return
     */
    public XComponent openDocument()
    {
        // Query the XComponentLoader interface from the desktop
        XComponentLoader xComponentLoader = (XComponentLoader)
                UnoRuntime.queryInterface(XComponentLoader.class,
this.desktop);

        PropertyValue[] myProperties = new PropertyValue[1];
        myProperties[0] = new PropertyValue();
        // open document read only
        myProperties[0].Name = "ReadOnly";
        myProperties[0].Value = new Boolean(false);

        // Load a given document
        try
        {
            this.openDocument = xComponentLoader.loadComponentFromURL(
                    createUNOFileURL(this.openFilename),  // File folder
and name
                    "_blank",                             // New windos
                    0,                                    // Is ignored
                    myProperties);             // Special properties
        }
        catch(com.sun.star.uno.Exception e)
        {
            System.out.println("OpenOffice runs, but error opening
document:");
            System.out.println(e.getLocalizedMessage());
        }

        if (openDocument == null) {
            System.err.println("I cannot open the document. Is the
filename " +
                    "correct?");
            System.exit(-1);
        }
        System.out.println("Document successfully opened.");
        return this.openDocument;
    }

    /**
     * Creating a correct File URL that OpenOffice can handle. This is
     * necessary to be platform independent.
     *
     * @param filelocation
     * @return
     */
    protected String createUNOFileURL(String filelocation)
    {
        java.io.File newfile = new java.io.File(filelocation);
        java.net.URL before = null;
        try
        {
            before = newfile.toURL();
        }
        catch (MalformedURLException e) {
            System.out.println(e);
        }
        // Create a URL, which can be used by UNO
        String myUNOFileURL =  ExternalUriReferenceTranslator

.create(xRemoteContext).translateToInternal(before.toExternalForm());

        if (myUNOFileURL.length() == 0 && filelocation.length() > 0)
        {
            System.out.println("File URL conversion faild. Filelocation " +
                    "contains illegal characters: " + filelocation);
        }
        return myUNOFileURL;
    }

    /**
     * This method either removes the item specified in the CommandURL from
     * OpenOffice menubar or adds the menu item specified in the
     * addItemCommandURL after myCommandURL to the menu. Changes are
transient.
     *
     * @param myCommandURL
     * @param addItemCommandURL
     * @param addItemLabel
     */
    public void changeMenus(String myCommandURL,
            String addItemCommandURL,
            String addItemLabel)
    {
        // Init menu elements
        // 1. Getting the menubar
        com.sun.star.ui.XUIElement myMenubar
            =
this.getLayoutManager().getElement("private:resource/menubar/menubar");

        // 2. Getting the menubar settings
        XUIElementSettings myMenuBarSettings = (XUIElementSettings)
                UnoRuntime.queryInterface(XUIElementSettings.class,
myMenubar);

        // 3. Casting the settings into a container to be able to get the
        // properties
        XIndexContainer myMenuBarContainer = (XIndexContainer)
                UnoRuntime.queryInterface(XIndexContainer.class,
                        myMenuBarSettings.getSettings(true));

        try
        {
            // Creating a Vector containing all menus with a "Save" item
            Vector foundSaveMenuItems = this.searchXIndexContainerForItem(
                    myCommandURL,
                    myMenuBarContainer,
                    new Vector());
            if(addItemCommandURL != null)
            {
                this.addItemToMenu(addItemCommandURL,
                        addItemLabel,
                        foundSaveMenuItems);
            }
            else
            {
                // Remove the menu items
                this.removeXIndexContainerItems(foundSaveMenuItems);
            }

            // Make changes only transient (temporary).
            com.sun.star.beans.XPropertySet xPropSet = (XPropertySet)
            UnoRuntime.queryInterface(XPropertySet.class, myMenubar);
            xPropSet.setPropertyValue("Persistent", new Boolean(false));

            // Apply settings to the root container (includes all
subcontainers)
            myMenuBarSettings.setSettings(myMenuBarContainer);
        }
        catch (Exception e)
        {
            System.out.println("Cannot modify menubar. Reason: " + e);
        }
    }

    /**
     * This method return a Layout Manager of an opened OpenOffice.
     *
     * @return
     */
    protected XLayoutManager getLayoutManager()
    {
        this.xFrame = this.xDesktop.getCurrentFrame();

        XPropertySet xps = (XPropertySet)
                UnoRuntime.queryInterface(XPropertySet.class, this.xFrame);

        try
        {
            this.xLayoutManager = (XLayoutManager)
                    UnoRuntime.queryInterface(XLayoutManager.class,
                    xps.getPropertyValue("LayoutManager"));
        }
        catch (com.sun.star.uno.Exception e)
        {
            System.out.println("Cannot get Layout Manager:");
            System.out.println(e.getLocalizedMessage());
        }
        return this.xLayoutManager;
    }

    /**
     * Method that searches menus and its submenus for the "CommandURL"
     * property. The returned Vector consists of Vectors. Each contained
Vector
     * has two values. The first gives the XIndexContainer where the
searched
     * menu item was found, the second is an Integer that tells the position
     * where the menu item was found.
     *
     * @param myCommandURL
     * @param myMenuContainer
     * @param foundMenuItems
     * @return
     * @throws IllegalArgumentException
     * @throws IndexOutOfBoundsException
     * @throws WrappedTargetException
     */
    private Vector searchXIndexContainerForItem(String myCommandURL,
            XIndexContainer myMenuContainer, Vector foundMenuItems)
            throws IllegalArgumentException,
                IndexOutOfBoundsException,
                WrappedTargetException  {

        if(myMenuContainer != null) {
            for(int g = 0; g < myMenuContainer.getCount(); g++) {
                // Getting the properties of the given container
                PropertyValue[] gMenuItem = (PropertyValue[])
                        com.sun.star.uno.AnyConverter.toObject(
                        PropertyValue[].class,
                        myMenuContainer.getByIndex(g));
                for(int h = 0; h < gMenuItem.length; h++)
                {
                    if(gMenuItem[h].Name.equals("CommandURL"))
                    {
                        if(gMenuItem[h].Value.equals(myCommandURL))
                        {
                            Vector thisMenuItem = new Vector();
                                thisMenuItem.addElement(myMenuContainer);
                                thisMenuItem.addElement(new Integer(g));
                            foundMenuItems.addElement(thisMenuItem);
                            break;
                        }
                    }
                    else
if(gMenuItem[h].Name.equals("ItemDescriptorContainer"))
                    {
                        XIndexAccess subMenuAccess = (XIndexAccess)
                                com.sun.star.uno.AnyConverter.toObject(
                                XIndexAccess.class,
                                gMenuItem[h].Value);
                        XIndexContainer subMenuContainer = (XIndexContainer)
                                UnoRuntime.queryInterface(
                                XIndexContainer.class, subMenuAccess);
                        if(subMenuAccess != null)
                        {
                            searchXIndexContainerForItem(myCommandURL,
                                    subMenuContainer,
                                    foundMenuItems);
                        }
                    }
                }
            }
        }
        return foundMenuItems;
    }

    /**
     * This method adds the specified myCommandURL with the itemLabel to the
     * menu / toolbar after the specified menu item in foundMenuItems.
     *
     * @param myCommandURL
     * @param itemLabel
     * @param foundMenuItems
     */
    private void addItemToMenu(String myCommandURL,
            String itemLabel,
            Vector foundMenuItems)
    {
        try
        {
            // Starting with the last Element, because removing changes
item index
            for (int i = foundMenuItems.size() -1; i >= 0; i--)
            {
                Vector thisVectorItem = (Vector)foundMenuItems.elementAt(i);
                XIndexContainer thisMenuContainer = (XIndexContainer)
                    thisVectorItem.elementAt(0);
                Integer menuPosition = (Integer)thisVectorItem.elementAt(1);

                // add the menu item
                thisMenuContainer.insertByIndex(menuPosition.intValue() + 1,
                        createMenuItem(myCommandURL, itemLabel));
            }
        }
        catch(IndexOutOfBoundsException e)
        {
            System.out.println("Can't add this item. Reason: " + e);
        }
        catch(WrappedTargetException e)
        {
            System.out.println("Can't add this item. Reason: " + e);
        }
        catch(IllegalArgumentException e)
        {
            System.out.println("Can't add this item. Reason: " + e);
        }
    }

    /**
     * Method that removes the given menu items. The given Vector contains a
     * XIndexContainer at first position (the menu containing the Item
to remove)
     * and an Integer at second position (the item number of the item to
remove.
     * The changes are transient (temporary).
     *
     * @param itemsToRemove
     * @throws IndexOutOfBoundsException
     * @throws WrappedTargetException
     */
    private void removeXIndexContainerItems(Vector itemsToRemove) throws
            IndexOutOfBoundsException,
            WrappedTargetException
    {
        // Starting with the last Element, because removing changes item
index
        for (int i = itemsToRemove.size() -1; i >= 0; i--)
        {
            Vector thisVectorItem = (Vector)itemsToRemove.elementAt(i);
            XIndexContainer thisMenuContainer = (XIndexContainer)
                thisVectorItem.elementAt(0);
            Integer menuPosition = (Integer)thisVectorItem.elementAt(1);

            // remove the item, but settings must be set to make it visible
            thisMenuContainer.removeByIndex(menuPosition.intValue());
        }
    }

    /**
     * Creating the properties for a new menu item.
     *
     * @param sMyCommand
     * @param label
     * @return
     */
    private PropertyValue[] createMenuItem(String sMyCommand, String
label) {
        PropertyValue[] menuItemProperties = new PropertyValue[3];

        menuItemProperties[0] = new PropertyValue();
        menuItemProperties[0].Name = "CommandURL";
        menuItemProperties[0].Value = sMyCommand;

        menuItemProperties[1] = new PropertyValue();
        menuItemProperties[1].Name = "Label";
        menuItemProperties[1].Value = label;

        menuItemProperties[2] = new PropertyValue();
        menuItemProperties[2].Name = "Type";
        menuItemProperties[2].Value = new Short((short)0);

        return menuItemProperties;
    }

    /**
     * This method removes the in the CommandURL specified items from
OpenOffice
     * toolbars. Changes are transient.
     *
     * @param xLayoutManager
     * @param CommandURL
     * @param action
     * @throws Exception
     */
    public void changeToolbars(String myCommandURL, String action)
    {
        final String[] toolbars = { "private:resource/toolbar/alignmentbar",
                "private:resource/toolbar/arrowshapes",
                "private:resource/toolbar/basicshapes",
                "private:resource/toolbar/calloutshapes",
                "private:resource/toolbar/colorbar",
                "private:resource/toolbar/drawbar",
                "private:resource/toolbar/drawobjectbar",
                "private:resource/toolbar/extrusionobjectbar",
                "private:resource/toolbar/fontworkobjectbar",
                "private:resource/toolbar/fontworkshapetypes",
                "private:resource/toolbar/formatobjectbar",
                "private:resource/toolbar/formcontrols",
                "private:resource/toolbar/formdesign",
                "private:resource/toolbar/formsfilterbar",
                "private:resource/toolbar/formsnavigationbar",
                "private:resource/toolbar/formsobjectbar",
                "private:resource/toolbar/formtextobjectbar",
                "private:resource/toolbar/fullscreenbar",
                "private:resource/toolbar/graphicobjectbar",
                "private:resource/toolbar/insertbar",
                "private:resource/toolbar/insertcellsbar",
                "private:resource/toolbar/insertobjectbar",
                "private:resource/toolbar/mediaobjectbar",
                "private:resource/toolbar/moreformcontrols",
                "private:resource/toolbar/previewbar",
                "private:resource/toolbar/standardbar",
                "private:resource/toolbar/starshapes",
                "private:resource/toolbar/symbolshapes",
                "private:resource/toolbar/textobjectbar",
                "private:resource/toolbar/toolbar",
                "private:resource/toolbar/viewerbar"};

        for (int i = 0; i < toolbars.length; i++)
        {
            if (this.getLayoutManager().getElement(toolbars[i]) != null)
            {
                // Getting the toolbar
                XUIElement myToolbar
                    = this.getLayoutManager().getElement(toolbars[i]);

                // Getting the toolbar settings
                XUIElementSettings myToolBarSettings = (XUIElementSettings)
                        UnoRuntime.queryInterface(XUIElementSettings.class,
                        myToolbar);
                // Casting the settings into a container to be able to
get the
                // properties
                XIndexContainer myToolBarSettingsContainer =
(XIndexContainer)
                        UnoRuntime.queryInterface(
                        XIndexContainer.class,
                        myToolBarSettings.getSettings(true));

                try
                {
                    // Creating a Vector containing all toolbars containing
                    // the CommanURL
                    Vector foundSaveToolbarItems =
this.searchXIndexContainerForItem(
                            myCommandURL,
                            myToolBarSettingsContainer,
                            new Vector());
                    if(action.equals("remove"))
                    {
                        // Remove the toolbar items

this.removeXIndexContainerItems(foundSaveToolbarItems);
                    }
                    else
                    {
                        System.out.println("Unknown action: '" + action
+ "'");
                    }

                    // Make changes only transient (temporary).
                    com.sun.star.beans.XPropertySet xPropSet =
(XPropertySet)
                            UnoRuntime.queryInterface(XPropertySet.class,
                                    myToolbar);
                    xPropSet.setPropertyValue("Persistent", new
Boolean(false));

                    // Apply changes

myToolBarSettings.setSettings(myToolBarSettingsContainer);
                }
                catch (Exception e)
                {
                    System.out.println("Cannot modify toolbars. Reason:
" + e);
                }
            }
        }
    }

    /**
     * This method adds a CloseListener to the opened document.
     */
    public void addCloseListener()
    {
        // initial close listener
        XCloseable close = (XCloseable)UnoRuntime.queryInterface(
                com.sun.star.util.XCloseable.class, this.openDocument);

        final File openFile = new File(this.openFilename);
        final long last_modified_old = openFile.lastModified();

        close.addCloseListener(new XCloseListener() {
            public void queryClosing(EventObject arg0, boolean arg1)
                    throws CloseVetoException {
                // TODO Auto-generated method stub
                long last_modified = openFile.lastModified();
                if (last_modified != last_modified_old) {
                    System.exit(0);
                } else {
                    // XModifiable modi =
openDocument.interfaces.getXModifiable();
                    // System.out.println(modi.isModified());
                    System.exit(1);
                }
            }

            public void notifyClosing(EventObject arg0) {
                // TODO Auto-generated method stub
            }

            public void disposing(EventObject arg0) {
                // TODO Auto-generated method stub
            }
        });

        // wait for closing document
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println(e);
            }
        }
    }
}

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to