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]