1a5b190bfSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3a5b190bfSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4a5b190bfSAndrew Rist * or more contributor license agreements. See the NOTICE file 5a5b190bfSAndrew Rist * distributed with this work for additional information 6a5b190bfSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7a5b190bfSAndrew Rist * to you under the Apache License, Version 2.0 (the 8a5b190bfSAndrew Rist * "License"); you may not use this file except in compliance 9a5b190bfSAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11a5b190bfSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13a5b190bfSAndrew Rist * Unless required by applicable law or agreed to in writing, 14a5b190bfSAndrew Rist * software distributed under the License is distributed on an 15a5b190bfSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16a5b190bfSAndrew Rist * KIND, either express or implied. See the License for the 17a5b190bfSAndrew Rist * specific language governing permissions and limitations 18a5b190bfSAndrew Rist * under the License. 19cdf0e10cSrcweir * 20a5b190bfSAndrew Rist *************************************************************/ 21a5b190bfSAndrew Rist 22a5b190bfSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir package com.sun.star.lib.uno.helper; 25cdf0e10cSrcweir 26cdf0e10cSrcweir import com.sun.star.beans.Property; 27cdf0e10cSrcweir import com.sun.star.beans.PropertyAttribute; 28cdf0e10cSrcweir import com.sun.star.beans.PropertyChangeEvent; 29cdf0e10cSrcweir import com.sun.star.beans.PropertyState; 30cdf0e10cSrcweir import com.sun.star.beans.PropertyValue; 31cdf0e10cSrcweir import com.sun.star.beans.PropertyVetoException; 32cdf0e10cSrcweir import com.sun.star.beans.UnknownPropertyException; 33cdf0e10cSrcweir import com.sun.star.beans.XPropertyChangeListener; 34cdf0e10cSrcweir import com.sun.star.beans.XPropertySetInfo; 35cdf0e10cSrcweir import com.sun.star.beans.XVetoableChangeListener; 36cdf0e10cSrcweir import com.sun.star.container.NoSuchElementException; 37cdf0e10cSrcweir import com.sun.star.container.XHierarchicalNameAccess; 38cdf0e10cSrcweir import com.sun.star.lang.DisposedException; 39cdf0e10cSrcweir import com.sun.star.lang.EventObject; 40cdf0e10cSrcweir import com.sun.star.lang.WrappedTargetException; 41cdf0e10cSrcweir import com.sun.star.lang.WrappedTargetRuntimeException; 42cdf0e10cSrcweir import com.sun.star.lang.XComponent; 43cdf0e10cSrcweir import com.sun.star.reflection.XCompoundTypeDescription; 44cdf0e10cSrcweir import com.sun.star.reflection.XIdlClass; 45cdf0e10cSrcweir import com.sun.star.reflection.XIdlField2; 46cdf0e10cSrcweir import com.sun.star.reflection.XIdlReflection; 47cdf0e10cSrcweir import com.sun.star.reflection.XIndirectTypeDescription; 48cdf0e10cSrcweir import com.sun.star.reflection.XInterfaceAttributeTypeDescription2; 49cdf0e10cSrcweir import com.sun.star.reflection.XInterfaceMemberTypeDescription; 50cdf0e10cSrcweir import com.sun.star.reflection.XInterfaceTypeDescription2; 51cdf0e10cSrcweir import com.sun.star.reflection.XStructTypeDescription; 52cdf0e10cSrcweir import com.sun.star.reflection.XTypeDescription; 53cdf0e10cSrcweir import com.sun.star.uno.Any; 54cdf0e10cSrcweir import com.sun.star.uno.AnyConverter; 55cdf0e10cSrcweir import com.sun.star.uno.DeploymentException; 56cdf0e10cSrcweir import com.sun.star.uno.Type; 57cdf0e10cSrcweir import com.sun.star.uno.TypeClass; 58cdf0e10cSrcweir import com.sun.star.uno.UnoRuntime; 59cdf0e10cSrcweir import com.sun.star.uno.XComponentContext; 60cdf0e10cSrcweir import com.sun.star.uno.XInterface; 61cdf0e10cSrcweir import java.util.ArrayList; 62cdf0e10cSrcweir import java.util.HashMap; 63cdf0e10cSrcweir import java.util.HashSet; 64cdf0e10cSrcweir import java.util.Iterator; 65cdf0e10cSrcweir import java.util.Map; 66cdf0e10cSrcweir import java.util.Vector; 67cdf0e10cSrcweir 68cdf0e10cSrcweir /** 69cdf0e10cSrcweir A helper mixin to implement certain UNO interfaces related to property set 70cdf0e10cSrcweir handling on top of the attributes of a given UNO interface type. 71cdf0e10cSrcweir 72cdf0e10cSrcweir <p>A client will mix in this class by keeping a reference to an instance of 73cdf0e10cSrcweir this class, and forwarding all methods of (a subset of the interfaces) 74cdf0e10cSrcweir <code>com.sun.star.beans.XPropertySet</code>, 75cdf0e10cSrcweir <code>com.sun.star.beans.XFastPropertySet</code>, and 76cdf0e10cSrcweir <code>com.sun.star.beans.XPropertyAccess</code> to it.</p> 77cdf0e10cSrcweir 78cdf0e10cSrcweir <p>Client code should not use the monitors associated with instances of this 79cdf0e10cSrcweir class, as they are used for internal purposes.</p> 80cdf0e10cSrcweir 81cdf0e10cSrcweir @since UDK 3.2 82cdf0e10cSrcweir */ 83cdf0e10cSrcweir public final class PropertySetMixin { 84cdf0e10cSrcweir /** 85cdf0e10cSrcweir The constructor. 86cdf0e10cSrcweir 87cdf0e10cSrcweir @param context the component context used by this instance; must not be 88cdf0e10cSrcweir null, and must supply the service 89cdf0e10cSrcweir <code>com.sun.star.reflection.CoreReflection</code> and the singleton 90cdf0e10cSrcweir <code>com.sun.star.reflection.theTypeDescriptionManager</code> 91cdf0e10cSrcweir 92cdf0e10cSrcweir @param object the client UNO object into which this instance is mixed in; 93cdf0e10cSrcweir must not be null, and must support the given <code>type</code> 94cdf0e10cSrcweir 95cdf0e10cSrcweir @param type the UNO interface type whose attributes are mapped to 96cdf0e10cSrcweir properties; must not be null, and must represent a UNO interface type 97cdf0e10cSrcweir 98cdf0e10cSrcweir @param absentOptional a list of optional properties that are not present, 99cdf0e10cSrcweir and should thus not be visible via 100cdf0e10cSrcweir <code>com.sun.star.beans.XPropertySet.getPropertySetInfo</code>, 101cdf0e10cSrcweir <code>com.sun.star.beans.XPropertySet.addPropertyChangeListener</code>, 102cdf0e10cSrcweir <code>com.sun.star.beans.XPropertySet.removePropertyChangeListener<!-- 103cdf0e10cSrcweir --></code>, 104cdf0e10cSrcweir <code>com.sun.star.beans.XPropertySet.addVetoableChangeListener</code>, 105cdf0e10cSrcweir and <code>com.sun.star.beans.XPropertySet.<!-- 106cdf0e10cSrcweir -->removeVetoableChangeListener</code>; null is treated the same as an 107cdf0e10cSrcweir empty list; if non-null, the given array must not be modified after it is 108cdf0e10cSrcweir passed to this constructor. For consistency reasons, the given 109cdf0e10cSrcweir <code>absentOptional</code> should only contain the names of attributes 110cdf0e10cSrcweir that represent optional properties that are not present (that is, the 111cdf0e10cSrcweir attribute getters and setters always throw a 112cdf0e10cSrcweir <code>com.sun.star.beans.UnknownPropertyException</code>), and should 113cdf0e10cSrcweir contain each such name only once. If an optional property is not present 114cdf0e10cSrcweir (that is, the corresponding attribute getter and setter always throw a 115cdf0e10cSrcweir <code>com.sun.star.beans.UnknownPropertyException</code>) but is not 116cdf0e10cSrcweir contained in the given <code>absentOptional</code>, then it will be 117cdf0e10cSrcweir visible via 118cdf0e10cSrcweir <code>com.sun.star.beans.XPropertySet.getPropertySetInfo</code> as a 119cdf0e10cSrcweir <code>com.sun.star.beans.Property</code> with a set 120cdf0e10cSrcweir <code>com.sun.star.beans.PropertyAttribute.OPTIONAL</code>. If the given 121cdf0e10cSrcweir <code>object</code> does not implement 122cdf0e10cSrcweir <code>com.sun.star.beans.XPropertySet</code>, then the given 123cdf0e10cSrcweir <code>absentOptional</code> is effectively ignored and can be null or 124cdf0e10cSrcweir empty. 125cdf0e10cSrcweir */ PropertySetMixin( XComponentContext context, XInterface object, Type type, String[] absentOptional)126cdf0e10cSrcweir public PropertySetMixin( 127cdf0e10cSrcweir XComponentContext context, XInterface object, Type type, 128cdf0e10cSrcweir String[] absentOptional) 129cdf0e10cSrcweir { 130cdf0e10cSrcweir // assert context != null && object != null && type != null 131cdf0e10cSrcweir // && type.getTypeClass() == TypeClass.INTERFACE; 132cdf0e10cSrcweir this.context = context; 133cdf0e10cSrcweir this.object = object; 134cdf0e10cSrcweir this.type = type; 135cdf0e10cSrcweir this.absentOptional = absentOptional; 136cdf0e10cSrcweir idlClass = getReflection(type.getTypeName()); 137cdf0e10cSrcweir XTypeDescription ifc; 138cdf0e10cSrcweir try { 139cdf0e10cSrcweir ifc = UnoRuntime.queryInterface( 140cdf0e10cSrcweir XTypeDescription.class, 141cdf0e10cSrcweir (UnoRuntime.queryInterface( 142cdf0e10cSrcweir XHierarchicalNameAccess.class, 143cdf0e10cSrcweir context.getValueByName( 144cdf0e10cSrcweir "/singletons/com.sun.star.reflection." 145cdf0e10cSrcweir + "theTypeDescriptionManager")). 146cdf0e10cSrcweir getByHierarchicalName(type.getTypeName()))); 147cdf0e10cSrcweir } catch (NoSuchElementException e) { 148cdf0e10cSrcweir throw new RuntimeException( 149cdf0e10cSrcweir "unexpected com.sun.star.container.NoSuchElementException: " 150cdf0e10cSrcweir + e.getMessage()); 151cdf0e10cSrcweir } 152cdf0e10cSrcweir HashMap map = new HashMap(); 153cdf0e10cSrcweir ArrayList handleNames = new ArrayList(); 154cdf0e10cSrcweir initProperties(ifc, map, handleNames, new HashSet()); 155cdf0e10cSrcweir properties = map; 156cdf0e10cSrcweir handleMap = (String[]) handleNames.toArray( 157cdf0e10cSrcweir new String[handleNames.size()]); 158cdf0e10cSrcweir } 159cdf0e10cSrcweir 160cdf0e10cSrcweir /** 161cdf0e10cSrcweir A method used by clients when implementing UNO interface type attribute 162cdf0e10cSrcweir setter functions. 163cdf0e10cSrcweir 164cdf0e10cSrcweir <p>First, this method checks whether this instance has already been 165cdf0e10cSrcweir disposed (see {@link #dispose}), and throws a 166cdf0e10cSrcweir <code>com.sun.star.beans.DisposedException</code> if applicable. For a 167cdf0e10cSrcweir constrained attribute (whose setter can explicitly raise 168cdf0e10cSrcweir <code>com.sun.star.beans.PropertyVetoException</code>), this method 169cdf0e10cSrcweir notifies any <code>com.sun.star.beans.XVetoableChangeListener</code>s. 170cdf0e10cSrcweir For a bound attribute, this method modifies the passed-in 171cdf0e10cSrcweir <code>bound</code> so that it can afterwards be used to notify any 172cdf0e10cSrcweir <code>com.sun.star.beans.XPropertyChangeListener</code>s. This method 173cdf0e10cSrcweir should be called before storing the new attribute value, and 174cdf0e10cSrcweir <code>bound.notifyListeners()</code> should be called exactly once after 175cdf0e10cSrcweir storing the new attribute value (in case the attribute is bound; 176cdf0e10cSrcweir otherwise, calling <code>bound.notifyListeners()</code> is ignored). 177cdf0e10cSrcweir Furthermore, <code>bound.notifyListeners()</code> and this method have to 178cdf0e10cSrcweir be called from the same thread.</p> 179cdf0e10cSrcweir 180cdf0e10cSrcweir @param propertyName the name of the property (which is the same as the 181cdf0e10cSrcweir name of the attribute that is going to be set) 182cdf0e10cSrcweir 183cdf0e10cSrcweir @param oldValue the property value corresponding to the old attribute 184cdf0e10cSrcweir value. This is only used as 185cdf0e10cSrcweir <code>com.sun.star.beans.PropertyChangeEvent.OldValue</code>, which is 186cdf0e10cSrcweir rather useless, anyway (see “Using the Observer Pattern” in 187cdf0e10cSrcweir <a href="http://tools.openoffice.org/CodingGuidelines.sxw"> 188cdf0e10cSrcweir <cite>OpenOffice.org Coding Guidelines</cite></a>). If the attribute 189cdf0e10cSrcweir that is going to be set is neither bound nor constrained, or if 190cdf0e10cSrcweir <code>com.sun.star.beans.PropertyChangeEvent.OldValue</code> should not 191cdf0e10cSrcweir be set, {@link Any#VOID} can be used instead. 192cdf0e10cSrcweir 193cdf0e10cSrcweir @param newValue the property value corresponding to the new 194cdf0e10cSrcweir attribute value. This is only used as 195cdf0e10cSrcweir <code>com.sun.star.beans.PropertyChangeEvent.NewValue</code>, which is 196*9ad05808SDamjan Jovanovic rather useless, anyway (see “Using the Observer Pattern” in 197cdf0e10cSrcweir <a href="http://tools.openoffice.org/CodingGuidelines.sxw"> 198cdf0e10cSrcweir <cite>OpenOffice.org Coding Guidelines</cite></a>), <em>unless</em> the 199cdf0e10cSrcweir attribute that is going to be set is constrained. If the attribute 200cdf0e10cSrcweir that is going to be set is neither bound nor constrained, or if it is 201cdf0e10cSrcweir only bound but 202cdf0e10cSrcweir <code>com.sun.star.beans.PropertyChangeEvent.NewValue</code> should not 203cdf0e10cSrcweir be set, {@link Any#VOID} can be used instead. 204cdf0e10cSrcweir 205cdf0e10cSrcweir @param bound a reference to a fresh {@link BoundListeners} instance 206cdf0e10cSrcweir (which has not been passed to this method before, and on which 207cdf0e10cSrcweir {@link BoundListeners#notifyListeners} has not yet been called); may only 208cdf0e10cSrcweir be null if the attribute that is going to be set is not bound 209cdf0e10cSrcweir */ prepareSet( String propertyName, Object oldValue, Object newValue, BoundListeners bound)210cdf0e10cSrcweir public void prepareSet( 211cdf0e10cSrcweir String propertyName, Object oldValue, Object newValue, 212cdf0e10cSrcweir BoundListeners bound) 213cdf0e10cSrcweir throws PropertyVetoException 214cdf0e10cSrcweir { 215cdf0e10cSrcweir // assert properties.get(propertyName) != null; 216cdf0e10cSrcweir Property p = ((PropertyData) properties.get(propertyName)).property; 217cdf0e10cSrcweir Vector specificVeto = null; 218cdf0e10cSrcweir Vector unspecificVeto = null; 219cdf0e10cSrcweir synchronized (this) { 220cdf0e10cSrcweir if (disposed) { 221cdf0e10cSrcweir throw new DisposedException("disposed", object); 222cdf0e10cSrcweir } 223cdf0e10cSrcweir if ((p.Attributes & PropertyAttribute.CONSTRAINED) != 0) { 224cdf0e10cSrcweir Object o = vetoListeners.get(propertyName); 225cdf0e10cSrcweir if (o != null) { 226cdf0e10cSrcweir specificVeto = (Vector) ((Vector) o).clone(); 227cdf0e10cSrcweir } 228cdf0e10cSrcweir o = vetoListeners.get(""); 229cdf0e10cSrcweir if (o != null) { 230cdf0e10cSrcweir unspecificVeto = (Vector) ((Vector) o).clone(); 231cdf0e10cSrcweir } 232cdf0e10cSrcweir } 233cdf0e10cSrcweir if ((p.Attributes & PropertyAttribute.BOUND) != 0) { 234cdf0e10cSrcweir // assert bound != null; 235cdf0e10cSrcweir Object o = boundListeners.get(propertyName); 236cdf0e10cSrcweir if (o != null) { 237cdf0e10cSrcweir bound.specificListeners = (Vector) ((Vector) o).clone(); 238cdf0e10cSrcweir } 239cdf0e10cSrcweir o = boundListeners.get(""); 240cdf0e10cSrcweir if (o != null) { 241cdf0e10cSrcweir bound.unspecificListeners = (Vector) ((Vector) o).clone(); 242cdf0e10cSrcweir } 243cdf0e10cSrcweir } 244cdf0e10cSrcweir } 245cdf0e10cSrcweir if ((p.Attributes & PropertyAttribute.CONSTRAINED) != 0) { 246cdf0e10cSrcweir PropertyChangeEvent event = new PropertyChangeEvent( 247cdf0e10cSrcweir object, propertyName, false, p.Handle, oldValue, newValue); 248cdf0e10cSrcweir if (specificVeto != null) { 249cdf0e10cSrcweir for (Iterator i = specificVeto.iterator(); i.hasNext();) { 250cdf0e10cSrcweir try { 251cdf0e10cSrcweir ((XVetoableChangeListener) i.next()).vetoableChange( 252cdf0e10cSrcweir event); 253cdf0e10cSrcweir } catch (DisposedException e) {} 254cdf0e10cSrcweir } 255cdf0e10cSrcweir } 256cdf0e10cSrcweir if (unspecificVeto != null) { 257cdf0e10cSrcweir for (Iterator i = unspecificVeto.iterator(); i.hasNext();) { 258cdf0e10cSrcweir try { 259cdf0e10cSrcweir ((XVetoableChangeListener) i.next()).vetoableChange( 260cdf0e10cSrcweir event); 261cdf0e10cSrcweir } catch (DisposedException e) {} 262cdf0e10cSrcweir } 263cdf0e10cSrcweir } 264cdf0e10cSrcweir } 265cdf0e10cSrcweir if ((p.Attributes & PropertyAttribute.BOUND) != 0) { 266cdf0e10cSrcweir // assert bound != null; 267cdf0e10cSrcweir bound.event = new PropertyChangeEvent( 268cdf0e10cSrcweir object, propertyName, false, p.Handle, oldValue, newValue); 269cdf0e10cSrcweir } 270cdf0e10cSrcweir } 271cdf0e10cSrcweir 272cdf0e10cSrcweir /** 273cdf0e10cSrcweir A simplified version of {@link #prepareSet(String, Object, Object, 274cdf0e10cSrcweir PropertySetMixin.BoundListeners)}. 275cdf0e10cSrcweir 276cdf0e10cSrcweir <p>This method is useful for attributes that are not constrained.</p> 277cdf0e10cSrcweir 278cdf0e10cSrcweir @param propertyName the name of the property (which is the same as the 279cdf0e10cSrcweir name of the attribute that is going to be set) 280cdf0e10cSrcweir 281cdf0e10cSrcweir @param bound a reference to a fresh {@link BoundListeners} instance 282cdf0e10cSrcweir (which has not been passed to this method before, and on which 283cdf0e10cSrcweir {@link BoundListeners#notifyListeners} has not yet been called); may only 284cdf0e10cSrcweir be null if the attribute that is going to be set is not bound 285cdf0e10cSrcweir */ prepareSet(String propertyName, BoundListeners bound)286cdf0e10cSrcweir public void prepareSet(String propertyName, BoundListeners bound) { 287cdf0e10cSrcweir try { 288cdf0e10cSrcweir prepareSet(propertyName, Any.VOID, Any.VOID, bound); 289cdf0e10cSrcweir } catch (PropertyVetoException e) { 290cdf0e10cSrcweir throw new RuntimeException("unexpected " + e); 291cdf0e10cSrcweir } 292cdf0e10cSrcweir } 293cdf0e10cSrcweir 294cdf0e10cSrcweir /** 295cdf0e10cSrcweir Marks this instance as being disposed. 296cdf0e10cSrcweir 297cdf0e10cSrcweir <p>See <code>com.sun.star.lang.XComponent</code> for the general concept 298cdf0e10cSrcweir of disposing UNO objects. On the first call to this method, all 299cdf0e10cSrcweir registered listeners 300cdf0e10cSrcweir (<code>com.sun.star.beans.XPropertyChangeListener</code>s and 301cdf0e10cSrcweir <code>com.sun.star.beans.XVetoableChangeListener</code>s) are notified of 302cdf0e10cSrcweir the disposing source. Any subsequent calls to this method are 303cdf0e10cSrcweir ignored.</p> 304cdf0e10cSrcweir */ dispose()305cdf0e10cSrcweir public void dispose() { 306cdf0e10cSrcweir HashMap bound; 307cdf0e10cSrcweir HashMap veto; 308cdf0e10cSrcweir synchronized (this) { 309cdf0e10cSrcweir bound = boundListeners; 310cdf0e10cSrcweir boundListeners = null; 311cdf0e10cSrcweir veto = vetoListeners; 312cdf0e10cSrcweir vetoListeners = null; 313cdf0e10cSrcweir disposed = true; 314cdf0e10cSrcweir } 315cdf0e10cSrcweir EventObject event = new EventObject(object); 316cdf0e10cSrcweir if (bound != null) { 317cdf0e10cSrcweir for (Iterator i = bound.values().iterator(); i.hasNext();) { 318cdf0e10cSrcweir for (Iterator j = ((Vector) i.next()).iterator(); j.hasNext();) 319cdf0e10cSrcweir { 320cdf0e10cSrcweir ((XPropertyChangeListener) j.next()).disposing(event); 321cdf0e10cSrcweir } 322cdf0e10cSrcweir } 323cdf0e10cSrcweir } 324cdf0e10cSrcweir if (veto != null) { 325cdf0e10cSrcweir for (Iterator i = veto.values().iterator(); i.hasNext();) { 326cdf0e10cSrcweir for (Iterator j = ((Vector) i.next()).iterator(); j.hasNext();) 327cdf0e10cSrcweir { 328cdf0e10cSrcweir ((XVetoableChangeListener) j.next()).disposing(event); 329cdf0e10cSrcweir } 330cdf0e10cSrcweir } 331cdf0e10cSrcweir } 332cdf0e10cSrcweir } 333cdf0e10cSrcweir 334cdf0e10cSrcweir /** 335cdf0e10cSrcweir Implements 336cdf0e10cSrcweir <code>com.sun.star.beans.XPropertySet.getPropertySetInfo</code>. 337cdf0e10cSrcweir */ getPropertySetInfo()338cdf0e10cSrcweir public XPropertySetInfo getPropertySetInfo() { 339cdf0e10cSrcweir return new Info(properties); 340cdf0e10cSrcweir } 341cdf0e10cSrcweir 342cdf0e10cSrcweir /** 343cdf0e10cSrcweir Implements <code>com.sun.star.beans.XPropertySet.setPropertyValue</code>. 344cdf0e10cSrcweir */ setPropertyValue(String propertyName, Object value)345cdf0e10cSrcweir public void setPropertyValue(String propertyName, Object value) 346cdf0e10cSrcweir throws UnknownPropertyException, PropertyVetoException, 347cdf0e10cSrcweir com.sun.star.lang.IllegalArgumentException, WrappedTargetException 348cdf0e10cSrcweir { 349cdf0e10cSrcweir setProperty(propertyName, value, false, false, (short) 1); 350cdf0e10cSrcweir } 351cdf0e10cSrcweir 352cdf0e10cSrcweir /** 353cdf0e10cSrcweir Implements <code>com.sun.star.beans.XPropertySet.getPropertyValue</code>. 354cdf0e10cSrcweir */ getPropertyValue(String propertyName)355cdf0e10cSrcweir public Object getPropertyValue(String propertyName) 356cdf0e10cSrcweir throws UnknownPropertyException, WrappedTargetException 357cdf0e10cSrcweir { 358cdf0e10cSrcweir return getProperty(propertyName, null); 359cdf0e10cSrcweir } 360cdf0e10cSrcweir 361cdf0e10cSrcweir /** 362cdf0e10cSrcweir Implements 363cdf0e10cSrcweir <code>com.sun.star.beans.XPropertySet.addPropertyChangeListener</code>. 364cdf0e10cSrcweir 365cdf0e10cSrcweir <p>If a listener is added more than once, it will receive all relevant 366cdf0e10cSrcweir notifications multiple times.</p> 367cdf0e10cSrcweir */ addPropertyChangeListener( String propertyName, XPropertyChangeListener listener)368cdf0e10cSrcweir public void addPropertyChangeListener( 369cdf0e10cSrcweir String propertyName, XPropertyChangeListener listener) 370cdf0e10cSrcweir throws UnknownPropertyException, WrappedTargetException 371cdf0e10cSrcweir { 372cdf0e10cSrcweir // assert listener != null; 373cdf0e10cSrcweir checkUnknown(propertyName); 374cdf0e10cSrcweir boolean disp; 375cdf0e10cSrcweir synchronized (this) { 376cdf0e10cSrcweir disp = disposed; 377cdf0e10cSrcweir if (!disp) { 378cdf0e10cSrcweir Vector v = (Vector) boundListeners.get(propertyName); 379cdf0e10cSrcweir if (v == null) { 380cdf0e10cSrcweir v = new Vector(); 381cdf0e10cSrcweir boundListeners.put(propertyName, v); 382cdf0e10cSrcweir } 383cdf0e10cSrcweir v.add(listener); 384cdf0e10cSrcweir } 385cdf0e10cSrcweir } 386cdf0e10cSrcweir if (disp) { 387cdf0e10cSrcweir listener.disposing(new EventObject(object)); 388cdf0e10cSrcweir } 389cdf0e10cSrcweir } 390cdf0e10cSrcweir 391cdf0e10cSrcweir /** 392cdf0e10cSrcweir Implements <code> 393cdf0e10cSrcweir com.sun.star.beans.XPropertySet.removePropertyChangeListener</code>. 394cdf0e10cSrcweir */ removePropertyChangeListener( String propertyName, XPropertyChangeListener listener)395cdf0e10cSrcweir public void removePropertyChangeListener( 396cdf0e10cSrcweir String propertyName, XPropertyChangeListener listener) 397cdf0e10cSrcweir throws UnknownPropertyException, WrappedTargetException 398cdf0e10cSrcweir { 399cdf0e10cSrcweir // assert listener != null; 400cdf0e10cSrcweir checkUnknown(propertyName); 401cdf0e10cSrcweir synchronized (this) { 402cdf0e10cSrcweir if (boundListeners != null) { 403cdf0e10cSrcweir Vector v = (Vector) boundListeners.get(propertyName); 404cdf0e10cSrcweir if (v != null) { 405cdf0e10cSrcweir v.remove(listener); 406cdf0e10cSrcweir } 407cdf0e10cSrcweir } 408cdf0e10cSrcweir } 409cdf0e10cSrcweir } 410cdf0e10cSrcweir 411cdf0e10cSrcweir /** 412cdf0e10cSrcweir Implements 413cdf0e10cSrcweir <code>com.sun.star.beans.XPropertySet.addVetoableChangeListener</code>. 414cdf0e10cSrcweir 415cdf0e10cSrcweir <p>If a listener is added more than once, it will receive all relevant 416cdf0e10cSrcweir notifications multiple times.</p> 417cdf0e10cSrcweir */ addVetoableChangeListener( String propertyName, XVetoableChangeListener listener)418cdf0e10cSrcweir public void addVetoableChangeListener( 419cdf0e10cSrcweir String propertyName, XVetoableChangeListener listener) 420cdf0e10cSrcweir throws UnknownPropertyException, WrappedTargetException 421cdf0e10cSrcweir { 422cdf0e10cSrcweir // assert listener != null; 423cdf0e10cSrcweir checkUnknown(propertyName); 424cdf0e10cSrcweir boolean disp; 425cdf0e10cSrcweir synchronized (this) { 426cdf0e10cSrcweir disp = disposed; 427cdf0e10cSrcweir if (!disp) { 428cdf0e10cSrcweir Vector v = (Vector) vetoListeners.get(propertyName); 429cdf0e10cSrcweir if (v == null) { 430cdf0e10cSrcweir v = new Vector(); 431cdf0e10cSrcweir vetoListeners.put(propertyName, v); 432cdf0e10cSrcweir } 433cdf0e10cSrcweir v.add(listener); 434cdf0e10cSrcweir } 435cdf0e10cSrcweir } 436cdf0e10cSrcweir if (disp) { 437cdf0e10cSrcweir listener.disposing(new EventObject(object)); 438cdf0e10cSrcweir } 439cdf0e10cSrcweir } 440cdf0e10cSrcweir 441cdf0e10cSrcweir /** 442cdf0e10cSrcweir Implements <code> 443cdf0e10cSrcweir com.sun.star.beans.XPropertySet.removeVetoableChangeListener</code>. 444cdf0e10cSrcweir */ removeVetoableChangeListener( String propertyName, XVetoableChangeListener listener)445cdf0e10cSrcweir public void removeVetoableChangeListener( 446cdf0e10cSrcweir String propertyName, XVetoableChangeListener listener) 447cdf0e10cSrcweir throws UnknownPropertyException, WrappedTargetException 448cdf0e10cSrcweir { 449cdf0e10cSrcweir // assert listener != null; 450cdf0e10cSrcweir checkUnknown(propertyName); 451cdf0e10cSrcweir synchronized (this) { 452cdf0e10cSrcweir if (vetoListeners != null) { 453cdf0e10cSrcweir Vector v = (Vector) vetoListeners.get(propertyName); 454cdf0e10cSrcweir if (v != null) { 455cdf0e10cSrcweir v.remove(listener); 456cdf0e10cSrcweir } 457cdf0e10cSrcweir } 458cdf0e10cSrcweir } 459cdf0e10cSrcweir } 460cdf0e10cSrcweir 461cdf0e10cSrcweir /** 462cdf0e10cSrcweir Implements 463cdf0e10cSrcweir <code>com.sun.star.beans.XFastPropertySet.setFastPropertyValue</code>. 464cdf0e10cSrcweir */ setFastPropertyValue(int handle, Object value)465cdf0e10cSrcweir public void setFastPropertyValue(int handle, Object value) 466cdf0e10cSrcweir throws UnknownPropertyException, PropertyVetoException, 467cdf0e10cSrcweir com.sun.star.lang.IllegalArgumentException, WrappedTargetException 468cdf0e10cSrcweir { 469cdf0e10cSrcweir setProperty(translateHandle(handle), value, false, false, (short) 1); 470cdf0e10cSrcweir } 471cdf0e10cSrcweir 472cdf0e10cSrcweir /** 473cdf0e10cSrcweir Implements 474cdf0e10cSrcweir <code>com.sun.star.beans.XFastPropertySet.getFastPropertyValue</code>. 475cdf0e10cSrcweir */ getFastPropertyValue(int handle)476cdf0e10cSrcweir public Object getFastPropertyValue(int handle) 477cdf0e10cSrcweir throws UnknownPropertyException, WrappedTargetException 478cdf0e10cSrcweir { 479cdf0e10cSrcweir return getProperty(translateHandle(handle), null); 480cdf0e10cSrcweir } 481cdf0e10cSrcweir 482cdf0e10cSrcweir /** 483cdf0e10cSrcweir Implements 484cdf0e10cSrcweir <code>com.sun.star.beans.XPropertyAccess.getPropertyValues</code>. 485cdf0e10cSrcweir */ getPropertyValues()486cdf0e10cSrcweir public PropertyValue[] getPropertyValues() { 487cdf0e10cSrcweir PropertyValue[] s = new PropertyValue[handleMap.length]; 488cdf0e10cSrcweir int n = 0; 489cdf0e10cSrcweir for (int i = 0; i < handleMap.length; ++i) { 490cdf0e10cSrcweir PropertyState[] state = new PropertyState[1]; 491cdf0e10cSrcweir Object value; 492cdf0e10cSrcweir try { 493cdf0e10cSrcweir value = getProperty(handleMap[i], state); 494cdf0e10cSrcweir } catch (UnknownPropertyException e) { 495cdf0e10cSrcweir continue; 496cdf0e10cSrcweir } catch (WrappedTargetException e) { 497cdf0e10cSrcweir throw new WrappedTargetRuntimeException( 498cdf0e10cSrcweir e.getMessage(), object, e.TargetException); 499cdf0e10cSrcweir } 500cdf0e10cSrcweir s[n++] = new PropertyValue(handleMap[i], i, value, state[0]); 501cdf0e10cSrcweir } 502cdf0e10cSrcweir if (n < handleMap.length) { 503cdf0e10cSrcweir PropertyValue[] s2 = new PropertyValue[n]; 504cdf0e10cSrcweir System.arraycopy(s, 0, s2, 0, n); 505cdf0e10cSrcweir s = s2; 506cdf0e10cSrcweir } 507cdf0e10cSrcweir return s; 508cdf0e10cSrcweir } 509cdf0e10cSrcweir 510cdf0e10cSrcweir /** 511cdf0e10cSrcweir Implements 512cdf0e10cSrcweir <code>com.sun.star.beans.XPropertyAccess.setPropertyValues</code>. 513cdf0e10cSrcweir */ setPropertyValues(PropertyValue[] props)514cdf0e10cSrcweir public void setPropertyValues(PropertyValue[] props) 515cdf0e10cSrcweir throws UnknownPropertyException, PropertyVetoException, 516cdf0e10cSrcweir com.sun.star.lang.IllegalArgumentException, WrappedTargetException 517cdf0e10cSrcweir { 518cdf0e10cSrcweir for (int i = 0; i < props.length; ++i) { 519cdf0e10cSrcweir if (props[i].Handle != -1 520cdf0e10cSrcweir && !props[i].Name.equals(translateHandle(props[i].Handle))) 521cdf0e10cSrcweir { 522cdf0e10cSrcweir throw new UnknownPropertyException( 523cdf0e10cSrcweir ("name " + props[i].Name + " does not match handle " 524cdf0e10cSrcweir + props[i].Handle), 525cdf0e10cSrcweir object); 526cdf0e10cSrcweir } 527cdf0e10cSrcweir setProperty( 528cdf0e10cSrcweir props[i].Name, props[i].Value, 529cdf0e10cSrcweir props[i].State == PropertyState.AMBIGUOUS_VALUE, 530cdf0e10cSrcweir props[i].State == PropertyState.DEFAULT_VALUE, (short) 0); 531cdf0e10cSrcweir } 532cdf0e10cSrcweir } 533cdf0e10cSrcweir 534cdf0e10cSrcweir /** 535cdf0e10cSrcweir A class used by clients of {@link PropertySetMixin} when implementing UNO 536cdf0e10cSrcweir interface type attribute setter functions. 537cdf0e10cSrcweir 538cdf0e10cSrcweir @see #prepareSet(String, Object, Object, PropertySetMixin.BoundListeners) 539cdf0e10cSrcweir */ 540cdf0e10cSrcweir public static final class BoundListeners { 541cdf0e10cSrcweir /** 542cdf0e10cSrcweir The constructor. 543cdf0e10cSrcweir */ BoundListeners()544cdf0e10cSrcweir public BoundListeners() {} 545cdf0e10cSrcweir 546cdf0e10cSrcweir /** 547cdf0e10cSrcweir Notifies any 548cdf0e10cSrcweir <code>com.sun.star.beans.XPropertyChangeListener</code>s. 549cdf0e10cSrcweir 550cdf0e10cSrcweir @see #prepareSet(String, Object, Object, 551cdf0e10cSrcweir PropertySetMixin.BoundListeners) 552cdf0e10cSrcweir */ notifyListeners()553cdf0e10cSrcweir public void notifyListeners() { 554cdf0e10cSrcweir if (specificListeners != null) { 555cdf0e10cSrcweir for (Iterator i = specificListeners.iterator(); i.hasNext();) { 556cdf0e10cSrcweir try { 557cdf0e10cSrcweir ((XPropertyChangeListener) i.next()).propertyChange( 558cdf0e10cSrcweir event); 559cdf0e10cSrcweir } catch (DisposedException e) {} 560cdf0e10cSrcweir } 561cdf0e10cSrcweir } 562cdf0e10cSrcweir if (unspecificListeners != null) { 563cdf0e10cSrcweir for (Iterator i = unspecificListeners.iterator(); i.hasNext();) 564cdf0e10cSrcweir { 565cdf0e10cSrcweir try { 566cdf0e10cSrcweir ((XPropertyChangeListener) i.next()).propertyChange( 567cdf0e10cSrcweir event); 568cdf0e10cSrcweir } catch (DisposedException e) {} 569cdf0e10cSrcweir } 570cdf0e10cSrcweir } 571cdf0e10cSrcweir } 572cdf0e10cSrcweir 573cdf0e10cSrcweir private Vector specificListeners = null; 574cdf0e10cSrcweir private Vector unspecificListeners = null; 575cdf0e10cSrcweir private PropertyChangeEvent event = null; 576cdf0e10cSrcweir } 577cdf0e10cSrcweir getReflection(String typeName)578cdf0e10cSrcweir private XIdlClass getReflection(String typeName) { 579cdf0e10cSrcweir XIdlReflection refl; 580cdf0e10cSrcweir try { 581cdf0e10cSrcweir refl = UnoRuntime.queryInterface( 582cdf0e10cSrcweir XIdlReflection.class, 583cdf0e10cSrcweir context.getServiceManager().createInstanceWithContext( 584cdf0e10cSrcweir "com.sun.star.reflection.CoreReflection", context)); 585cdf0e10cSrcweir } catch (com.sun.star.uno.Exception e) { 586cdf0e10cSrcweir throw new DeploymentException( 587cdf0e10cSrcweir ("component context fails to supply service" 588cdf0e10cSrcweir + " com.sun.star.reflection.CoreReflection: " 589cdf0e10cSrcweir + e.getMessage()), 590cdf0e10cSrcweir context); 591cdf0e10cSrcweir } 592cdf0e10cSrcweir try { 593cdf0e10cSrcweir return refl.forName(typeName); 594cdf0e10cSrcweir } finally { 595cdf0e10cSrcweir XComponent comp = UnoRuntime.queryInterface(XComponent.class, refl); 596cdf0e10cSrcweir if (comp != null) { 597cdf0e10cSrcweir comp.dispose(); 598cdf0e10cSrcweir } 599cdf0e10cSrcweir } 600cdf0e10cSrcweir } 601cdf0e10cSrcweir initProperties( XTypeDescription type, HashMap map, ArrayList handleNames, HashSet seen)602cdf0e10cSrcweir private void initProperties( 603cdf0e10cSrcweir XTypeDescription type, HashMap map, ArrayList handleNames, HashSet seen) 604cdf0e10cSrcweir { 605cdf0e10cSrcweir XInterfaceTypeDescription2 ifc = UnoRuntime.queryInterface( 606cdf0e10cSrcweir XInterfaceTypeDescription2.class, resolveTypedefs(type)); 607cdf0e10cSrcweir if (seen.add(ifc.getName())) { 608cdf0e10cSrcweir XTypeDescription[] bases = ifc.getBaseTypes(); 609cdf0e10cSrcweir for (int i = 0; i < bases.length; ++i) { 610cdf0e10cSrcweir initProperties(bases[i], map, handleNames, seen); 611cdf0e10cSrcweir } 612cdf0e10cSrcweir XInterfaceMemberTypeDescription[] members = ifc.getMembers(); 613cdf0e10cSrcweir for (int i = 0; i < members.length; ++i) { 614cdf0e10cSrcweir if (members[i].getTypeClass() == TypeClass.INTERFACE_ATTRIBUTE) 615cdf0e10cSrcweir { 616cdf0e10cSrcweir XInterfaceAttributeTypeDescription2 attr = 617cdf0e10cSrcweir UnoRuntime.queryInterface( 618cdf0e10cSrcweir XInterfaceAttributeTypeDescription2.class, 619cdf0e10cSrcweir members[i]); 620cdf0e10cSrcweir short attrAttribs = 0; 621cdf0e10cSrcweir if (attr.isBound()) { 622cdf0e10cSrcweir attrAttribs |= PropertyAttribute.BOUND; 623cdf0e10cSrcweir } 624cdf0e10cSrcweir boolean setUnknown = false; 625cdf0e10cSrcweir if (attr.isReadOnly()) { 626cdf0e10cSrcweir attrAttribs |= PropertyAttribute.READONLY; 627cdf0e10cSrcweir setUnknown = true; 628cdf0e10cSrcweir } 629cdf0e10cSrcweir XCompoundTypeDescription[] excs = attr.getGetExceptions(); 630cdf0e10cSrcweir boolean getUnknown = false; 631cdf0e10cSrcweir //XXX Special interpretation of getter/setter exceptions 632cdf0e10cSrcweir // only works if the specified exceptions are of the exact 633cdf0e10cSrcweir // type, not of a supertype: 634cdf0e10cSrcweir for (int j = 0; j < excs.length; ++j) { 635cdf0e10cSrcweir if (excs[j].getName().equals( 636cdf0e10cSrcweir "com.sun.star.beans.UnknownPropertyException")) 637cdf0e10cSrcweir { 638cdf0e10cSrcweir getUnknown = true; 639cdf0e10cSrcweir break; 640cdf0e10cSrcweir } 641cdf0e10cSrcweir } 642cdf0e10cSrcweir excs = attr.getSetExceptions(); 643cdf0e10cSrcweir for (int j = 0; j < excs.length; ++j) { 644cdf0e10cSrcweir if (excs[j].getName().equals( 645cdf0e10cSrcweir "com.sun.star.beans.UnknownPropertyException")) 646cdf0e10cSrcweir { 647cdf0e10cSrcweir setUnknown = true; 648cdf0e10cSrcweir } else if (excs[j].getName().equals( 649cdf0e10cSrcweir "com.sun.star.beans." 650cdf0e10cSrcweir + "PropertyVetoException")) 651cdf0e10cSrcweir { 652cdf0e10cSrcweir attrAttribs |= PropertyAttribute.CONSTRAINED; 653cdf0e10cSrcweir } 654cdf0e10cSrcweir } 655cdf0e10cSrcweir if (getUnknown && setUnknown) { 656cdf0e10cSrcweir attrAttribs |= PropertyAttribute.OPTIONAL; 657cdf0e10cSrcweir } 658cdf0e10cSrcweir XTypeDescription t = attr.getType(); 659cdf0e10cSrcweir for (;;) { 660cdf0e10cSrcweir t = resolveTypedefs(t); 661cdf0e10cSrcweir short n; 662cdf0e10cSrcweir if (t.getName().startsWith( 663cdf0e10cSrcweir "com.sun.star.beans.Ambiguous<")) 664cdf0e10cSrcweir { 665cdf0e10cSrcweir n = PropertyAttribute.MAYBEAMBIGUOUS; 666cdf0e10cSrcweir } else if (t.getName().startsWith( 667cdf0e10cSrcweir "com.sun.star.beans.Defaulted<")) 668cdf0e10cSrcweir { 669cdf0e10cSrcweir n = PropertyAttribute.MAYBEDEFAULT; 670cdf0e10cSrcweir } else if (t.getName().startsWith( 671cdf0e10cSrcweir "com.sun.star.beans.Optional<")) 672cdf0e10cSrcweir { 673cdf0e10cSrcweir n = PropertyAttribute.MAYBEVOID; 674cdf0e10cSrcweir } else { 675cdf0e10cSrcweir break; 676cdf0e10cSrcweir } 677cdf0e10cSrcweir attrAttribs |= n; 678cdf0e10cSrcweir t = (UnoRuntime.queryInterface( 679cdf0e10cSrcweir XStructTypeDescription.class, t)). 680cdf0e10cSrcweir getTypeArguments()[0]; 681cdf0e10cSrcweir } 682cdf0e10cSrcweir String name = members[i].getMemberName(); 683cdf0e10cSrcweir boolean present = true; 684cdf0e10cSrcweir if (absentOptional != null) { 685cdf0e10cSrcweir for (int j = 0; j < absentOptional.length; ++j) { 686cdf0e10cSrcweir if (name.equals(absentOptional[j])) { 687cdf0e10cSrcweir present = false; 688cdf0e10cSrcweir break; 689cdf0e10cSrcweir } 690cdf0e10cSrcweir } 691cdf0e10cSrcweir } 692cdf0e10cSrcweir if (map.put( 693cdf0e10cSrcweir name, 694cdf0e10cSrcweir new PropertyData( 695cdf0e10cSrcweir new Property( 696cdf0e10cSrcweir name, handleNames.size(), 697cdf0e10cSrcweir new Type(t.getName(), t.getTypeClass()), 698cdf0e10cSrcweir attrAttribs), 699cdf0e10cSrcweir present)) 700cdf0e10cSrcweir != null) 701cdf0e10cSrcweir { 702cdf0e10cSrcweir throw new RuntimeException( 703cdf0e10cSrcweir "inconsistent UNO type registry"); 704cdf0e10cSrcweir } 705cdf0e10cSrcweir handleNames.add(name); 706cdf0e10cSrcweir } 707cdf0e10cSrcweir } 708cdf0e10cSrcweir } 709cdf0e10cSrcweir } 710cdf0e10cSrcweir translateHandle(int handle)711cdf0e10cSrcweir private String translateHandle(int handle) throws UnknownPropertyException { 712cdf0e10cSrcweir if (handle < 0 || handle >= handleMap.length) { 713cdf0e10cSrcweir throw new UnknownPropertyException("bad handle " + handle, object); 714cdf0e10cSrcweir } 715cdf0e10cSrcweir return handleMap[handle]; 716cdf0e10cSrcweir } 717cdf0e10cSrcweir setProperty( String name, Object value, boolean isAmbiguous, boolean isDefaulted, short illegalArgumentPosition)718cdf0e10cSrcweir private void setProperty( 719cdf0e10cSrcweir String name, Object value, boolean isAmbiguous, boolean isDefaulted, 720cdf0e10cSrcweir short illegalArgumentPosition) 721cdf0e10cSrcweir throws UnknownPropertyException, PropertyVetoException, 722cdf0e10cSrcweir com.sun.star.lang.IllegalArgumentException, WrappedTargetException 723cdf0e10cSrcweir { 724cdf0e10cSrcweir PropertyData p = (PropertyData) properties.get(name); 725cdf0e10cSrcweir if (p == null) { 726cdf0e10cSrcweir throw new UnknownPropertyException(name, object); 727cdf0e10cSrcweir } 728cdf0e10cSrcweir if ((isAmbiguous 729cdf0e10cSrcweir && (p.property.Attributes & PropertyAttribute.MAYBEAMBIGUOUS) == 0) 730cdf0e10cSrcweir || (isDefaulted 731cdf0e10cSrcweir && ((p.property.Attributes & PropertyAttribute.MAYBEDEFAULT) 732cdf0e10cSrcweir == 0))) 733cdf0e10cSrcweir { 734cdf0e10cSrcweir throw new com.sun.star.lang.IllegalArgumentException( 735cdf0e10cSrcweir ("flagging as ambiguous/defaulted non-ambiguous/defaulted" 736cdf0e10cSrcweir + " property " + name), 737cdf0e10cSrcweir object, illegalArgumentPosition); 738cdf0e10cSrcweir 739cdf0e10cSrcweir } 740cdf0e10cSrcweir XIdlField2 f = UnoRuntime.queryInterface( 741cdf0e10cSrcweir XIdlField2.class, idlClass.getField(name)); 742cdf0e10cSrcweir Object[] o = new Object[] { 743cdf0e10cSrcweir new Any(type, UnoRuntime.queryInterface(type, object)) }; 744cdf0e10cSrcweir Object v = wrapValue( 745cdf0e10cSrcweir value, 746cdf0e10cSrcweir UnoRuntime.queryInterface( 747cdf0e10cSrcweir XIdlField2.class, idlClass.getField(name)).getType(), 748cdf0e10cSrcweir (p.property.Attributes & PropertyAttribute.MAYBEAMBIGUOUS) != 0, 749cdf0e10cSrcweir isAmbiguous, 750cdf0e10cSrcweir (p.property.Attributes & PropertyAttribute.MAYBEDEFAULT) != 0, 751cdf0e10cSrcweir isDefaulted, 752cdf0e10cSrcweir (p.property.Attributes & PropertyAttribute.MAYBEVOID) != 0); 753cdf0e10cSrcweir try { 754cdf0e10cSrcweir f.set(o, v); 755cdf0e10cSrcweir } catch (com.sun.star.lang.IllegalArgumentException e) { 756cdf0e10cSrcweir if (e.ArgumentPosition == 1) { 757cdf0e10cSrcweir throw new com.sun.star.lang.IllegalArgumentException( 758cdf0e10cSrcweir e.getMessage(), object, illegalArgumentPosition); 759cdf0e10cSrcweir } else { 760cdf0e10cSrcweir throw new RuntimeException( 761cdf0e10cSrcweir "unexpected com.sun.star.lang.IllegalArgumentException: " 762cdf0e10cSrcweir + e.getMessage()); 763cdf0e10cSrcweir } 764cdf0e10cSrcweir } catch (com.sun.star.lang.IllegalAccessException e) { 765cdf0e10cSrcweir //TODO Clarify whether PropertyVetoException is the correct 766cdf0e10cSrcweir // exception to throw when trying to set a read-only property: 767cdf0e10cSrcweir throw new PropertyVetoException( 768cdf0e10cSrcweir "cannot set read-only property " + name, object); 769cdf0e10cSrcweir } catch (WrappedTargetRuntimeException e) { 770cdf0e10cSrcweir //FIXME A WrappedTargetRuntimeException from XIdlField2.get is not 771cdf0e10cSrcweir // guaranteed to originate directly within XIdlField2.get (and thus 772cdf0e10cSrcweir // have the expected semantics); it might also be passed through 773cdf0e10cSrcweir // from lower layers. 774cdf0e10cSrcweir if (new Type(UnknownPropertyException.class).isSupertypeOf( 775cdf0e10cSrcweir AnyConverter.getType(e.TargetException)) 776cdf0e10cSrcweir && (p.property.Attributes & PropertyAttribute.OPTIONAL) != 0) 777cdf0e10cSrcweir { 778cdf0e10cSrcweir throw new UnknownPropertyException(name, object); 779cdf0e10cSrcweir } else if (new Type(PropertyVetoException.class).isSupertypeOf( 780cdf0e10cSrcweir AnyConverter.getType(e.TargetException)) 781cdf0e10cSrcweir && ((p.property.Attributes 782cdf0e10cSrcweir & PropertyAttribute.CONSTRAINED) 783cdf0e10cSrcweir != 0)) 784cdf0e10cSrcweir { 785cdf0e10cSrcweir throw new PropertyVetoException(name, object); 786cdf0e10cSrcweir } else { 787cdf0e10cSrcweir throw new WrappedTargetException( 788cdf0e10cSrcweir e.getMessage(), object, e.TargetException); 789cdf0e10cSrcweir } 790cdf0e10cSrcweir } 791cdf0e10cSrcweir } 792cdf0e10cSrcweir getProperty(String name, PropertyState[] state)793cdf0e10cSrcweir Object getProperty(String name, PropertyState[] state) 794cdf0e10cSrcweir throws UnknownPropertyException, WrappedTargetException 795cdf0e10cSrcweir { 796cdf0e10cSrcweir PropertyData p = (PropertyData) properties.get(name); 797cdf0e10cSrcweir if (p == null) { 798cdf0e10cSrcweir throw new UnknownPropertyException(name, object); 799cdf0e10cSrcweir } 800cdf0e10cSrcweir XIdlField2 field = UnoRuntime.queryInterface( 801cdf0e10cSrcweir XIdlField2.class, idlClass.getField(name)); 802cdf0e10cSrcweir Object value; 803cdf0e10cSrcweir try { 804cdf0e10cSrcweir value = field.get( 805cdf0e10cSrcweir new Any(type, UnoRuntime.queryInterface(type, object))); 806cdf0e10cSrcweir } catch (com.sun.star.lang.IllegalArgumentException e) { 807cdf0e10cSrcweir throw new RuntimeException( 808cdf0e10cSrcweir "unexpected com.sun.star.lang.IllegalArgumentException: " 809cdf0e10cSrcweir + e.getMessage()); 810cdf0e10cSrcweir } catch (WrappedTargetRuntimeException e) { 811cdf0e10cSrcweir //FIXME A WrappedTargetRuntimeException from XIdlField2.get is not 812cdf0e10cSrcweir // guaranteed to originate directly within XIdlField2.get (and thus 813cdf0e10cSrcweir // have the expected semantics); it might also be passed through 814cdf0e10cSrcweir // from lower layers. 815cdf0e10cSrcweir if (new Type(UnknownPropertyException.class).isSupertypeOf( 816cdf0e10cSrcweir AnyConverter.getType(e.TargetException)) 817cdf0e10cSrcweir && (p.property.Attributes & PropertyAttribute.OPTIONAL) != 0) 818cdf0e10cSrcweir { 819cdf0e10cSrcweir throw new UnknownPropertyException(name, object); 820cdf0e10cSrcweir } else { 821cdf0e10cSrcweir throw new WrappedTargetException( 822cdf0e10cSrcweir e.getMessage(), object, e.TargetException); 823cdf0e10cSrcweir } 824cdf0e10cSrcweir } 825cdf0e10cSrcweir boolean undoAmbiguous 826cdf0e10cSrcweir = (p.property.Attributes & PropertyAttribute.MAYBEAMBIGUOUS) != 0; 827cdf0e10cSrcweir boolean undoDefaulted 828cdf0e10cSrcweir = (p.property.Attributes & PropertyAttribute.MAYBEDEFAULT) != 0; 829cdf0e10cSrcweir boolean undoOptional 830cdf0e10cSrcweir = (p.property.Attributes & PropertyAttribute.MAYBEVOID) != 0; 831cdf0e10cSrcweir boolean isAmbiguous = false; 832cdf0e10cSrcweir boolean isDefaulted = false; 833cdf0e10cSrcweir while (undoAmbiguous || undoDefaulted || undoOptional) { 834cdf0e10cSrcweir String typeName = AnyConverter.getType(value).getTypeName(); 835cdf0e10cSrcweir if (undoAmbiguous 836cdf0e10cSrcweir && typeName.startsWith("com.sun.star.beans.Ambiguous<")) 837cdf0e10cSrcweir { 838cdf0e10cSrcweir XIdlClass ambiguous = getReflection(typeName); 839cdf0e10cSrcweir try { 840cdf0e10cSrcweir isAmbiguous = AnyConverter.toBoolean( 841cdf0e10cSrcweir UnoRuntime.queryInterface( 842cdf0e10cSrcweir XIdlField2.class, 843cdf0e10cSrcweir ambiguous.getField("IsAmbiguous")).get(value)); 844cdf0e10cSrcweir value = UnoRuntime.queryInterface( 845cdf0e10cSrcweir XIdlField2.class, 846cdf0e10cSrcweir ambiguous.getField("Value")).get(value); 847cdf0e10cSrcweir } catch (com.sun.star.lang.IllegalArgumentException e) { 848cdf0e10cSrcweir throw new RuntimeException( 849cdf0e10cSrcweir "unexpected" 850cdf0e10cSrcweir + " com.sun.star.lang.IllegalArgumentException: " 851cdf0e10cSrcweir + e.getMessage()); 852cdf0e10cSrcweir } 853cdf0e10cSrcweir undoAmbiguous = false; 854cdf0e10cSrcweir } else if (undoDefaulted 855cdf0e10cSrcweir && typeName.startsWith("com.sun.star.beans.Defaulted<")) 856cdf0e10cSrcweir { 857cdf0e10cSrcweir XIdlClass defaulted = getReflection(typeName); 858cdf0e10cSrcweir try { 859cdf0e10cSrcweir isDefaulted = AnyConverter.toBoolean( 860cdf0e10cSrcweir UnoRuntime.queryInterface( 861cdf0e10cSrcweir XIdlField2.class, 862cdf0e10cSrcweir defaulted.getField("IsDefaulted")).get(value)); 863cdf0e10cSrcweir value = UnoRuntime.queryInterface( 864cdf0e10cSrcweir XIdlField2.class, 865cdf0e10cSrcweir defaulted.getField("Value")).get(value); 866cdf0e10cSrcweir } catch (com.sun.star.lang.IllegalArgumentException e) { 867cdf0e10cSrcweir throw new RuntimeException( 868cdf0e10cSrcweir "unexpected" 869cdf0e10cSrcweir + " com.sun.star.lang.IllegalArgumentException: " 870cdf0e10cSrcweir + e.getMessage()); 871cdf0e10cSrcweir } 872cdf0e10cSrcweir undoDefaulted = false; 873cdf0e10cSrcweir } else if (undoOptional 874cdf0e10cSrcweir && typeName.startsWith("com.sun.star.beans.Optional<")) 875cdf0e10cSrcweir { 876cdf0e10cSrcweir XIdlClass optional = getReflection(typeName); 877cdf0e10cSrcweir try { 878cdf0e10cSrcweir boolean present = AnyConverter.toBoolean( 879cdf0e10cSrcweir UnoRuntime.queryInterface( 880cdf0e10cSrcweir XIdlField2.class, 881cdf0e10cSrcweir optional.getField("IsPresent")).get(value)); 882cdf0e10cSrcweir if (!present) { 883cdf0e10cSrcweir value = Any.VOID; 884cdf0e10cSrcweir break; 885cdf0e10cSrcweir } 886cdf0e10cSrcweir value = UnoRuntime.queryInterface( 887cdf0e10cSrcweir XIdlField2.class, 888cdf0e10cSrcweir optional.getField("Value")).get(value); 889cdf0e10cSrcweir } catch (com.sun.star.lang.IllegalArgumentException e) { 890cdf0e10cSrcweir throw new RuntimeException( 891cdf0e10cSrcweir "unexpected" 892cdf0e10cSrcweir + " com.sun.star.lang.IllegalArgumentException: " 893cdf0e10cSrcweir + e.getMessage()); 894cdf0e10cSrcweir } 895cdf0e10cSrcweir undoOptional = false; 896cdf0e10cSrcweir } else { 897cdf0e10cSrcweir throw new RuntimeException( 898cdf0e10cSrcweir "unexpected type of attribute " + name); 899cdf0e10cSrcweir } 900cdf0e10cSrcweir } 901cdf0e10cSrcweir if (state != null) { 902cdf0e10cSrcweir //XXX If isAmbiguous && isDefaulted, arbitrarily choose 903cdf0e10cSrcweir // AMBIGUOUS_VALUE over DEFAULT_VALUE: 904cdf0e10cSrcweir state[0] = isAmbiguous 905cdf0e10cSrcweir ? PropertyState.AMBIGUOUS_VALUE 906cdf0e10cSrcweir : isDefaulted 907cdf0e10cSrcweir ? PropertyState.DEFAULT_VALUE : PropertyState.DIRECT_VALUE; 908cdf0e10cSrcweir } 909cdf0e10cSrcweir return value; 910cdf0e10cSrcweir } 911cdf0e10cSrcweir wrapValue( Object value, XIdlClass type, boolean wrapAmbiguous, boolean isAmbiguous, boolean wrapDefaulted, boolean isDefaulted, boolean wrapOptional)912cdf0e10cSrcweir private Object wrapValue( 913cdf0e10cSrcweir Object value, XIdlClass type, boolean wrapAmbiguous, 914cdf0e10cSrcweir boolean isAmbiguous, boolean wrapDefaulted, boolean isDefaulted, 915cdf0e10cSrcweir boolean wrapOptional) 916cdf0e10cSrcweir { 917cdf0e10cSrcweir // assert (wrapAmbiguous || !isAmbiguous) 918cdf0e10cSrcweir // && (wrapDefaulted || !isDefaulted); 919cdf0e10cSrcweir if (wrapAmbiguous 920cdf0e10cSrcweir && type.getName().startsWith("com.sun.star.beans.Ambiguous<")) 921cdf0e10cSrcweir { 922cdf0e10cSrcweir Object[] strct = new Object[1]; 923cdf0e10cSrcweir type.createObject(strct); 924cdf0e10cSrcweir try { 925cdf0e10cSrcweir XIdlField2 field = UnoRuntime.queryInterface( 926cdf0e10cSrcweir XIdlField2.class, type.getField("Value")); 927cdf0e10cSrcweir field.set( 928cdf0e10cSrcweir strct, 929cdf0e10cSrcweir wrapValue( 930cdf0e10cSrcweir value, field.getType(), false, false, wrapDefaulted, 931cdf0e10cSrcweir isDefaulted, wrapOptional)); 932cdf0e10cSrcweir UnoRuntime.queryInterface( 933cdf0e10cSrcweir XIdlField2.class, type.getField("IsAmbiguous")).set( 934cdf0e10cSrcweir strct, new Boolean(isAmbiguous)); 935cdf0e10cSrcweir } catch (com.sun.star.lang.IllegalArgumentException e) { 936cdf0e10cSrcweir throw new RuntimeException( 937cdf0e10cSrcweir "unexpected com.sun.star.lang.IllegalArgumentException: " 938cdf0e10cSrcweir + e.getMessage()); 939cdf0e10cSrcweir } catch (com.sun.star.lang.IllegalAccessException e) { 940cdf0e10cSrcweir throw new RuntimeException( 941cdf0e10cSrcweir "unexpected com.sun.star.lang.IllegalAccessException: " 942cdf0e10cSrcweir + e.getMessage()); 943cdf0e10cSrcweir } 944cdf0e10cSrcweir return strct[0]; 945cdf0e10cSrcweir } else if (wrapDefaulted 946cdf0e10cSrcweir && type.getName().startsWith( 947cdf0e10cSrcweir "com.sun.star.beans.Defaulted<")) 948cdf0e10cSrcweir { 949cdf0e10cSrcweir Object[] strct = new Object[1]; 950cdf0e10cSrcweir type.createObject(strct); 951cdf0e10cSrcweir try { 952cdf0e10cSrcweir XIdlField2 field = UnoRuntime.queryInterface( 953cdf0e10cSrcweir XIdlField2.class, type.getField("Value")); 954cdf0e10cSrcweir field.set( 955cdf0e10cSrcweir strct, 956cdf0e10cSrcweir wrapValue( 957cdf0e10cSrcweir value, field.getType(), wrapAmbiguous, isAmbiguous, 958cdf0e10cSrcweir false, false, wrapOptional)); 959cdf0e10cSrcweir UnoRuntime.queryInterface( 960cdf0e10cSrcweir XIdlField2.class, type.getField("IsDefaulted")).set( 961cdf0e10cSrcweir strct, new Boolean(isDefaulted)); 962cdf0e10cSrcweir } catch (com.sun.star.lang.IllegalArgumentException e) { 963cdf0e10cSrcweir throw new RuntimeException( 964cdf0e10cSrcweir "unexpected com.sun.star.lang.IllegalArgumentException: " 965cdf0e10cSrcweir + e.getMessage()); 966cdf0e10cSrcweir } catch (com.sun.star.lang.IllegalAccessException e) { 967cdf0e10cSrcweir throw new RuntimeException( 968cdf0e10cSrcweir "unexpected com.sun.star.lang.IllegalAccessException: " 969cdf0e10cSrcweir + e.getMessage()); 970cdf0e10cSrcweir } 971cdf0e10cSrcweir return strct[0]; 972cdf0e10cSrcweir } else if (wrapOptional 973cdf0e10cSrcweir && type.getName().startsWith("com.sun.star.beans.Optional<")) 974cdf0e10cSrcweir { 975cdf0e10cSrcweir Object[] strct = new Object[1]; 976cdf0e10cSrcweir type.createObject(strct); 977cdf0e10cSrcweir boolean present = !AnyConverter.isVoid(value); 978cdf0e10cSrcweir try { 979cdf0e10cSrcweir UnoRuntime.queryInterface( 980cdf0e10cSrcweir XIdlField2.class, type.getField("IsPresent")).set( 981cdf0e10cSrcweir strct, new Boolean(present)); 982cdf0e10cSrcweir if (present) { 983cdf0e10cSrcweir XIdlField2 field = UnoRuntime.queryInterface( 984cdf0e10cSrcweir XIdlField2.class, type.getField("Value")); 985cdf0e10cSrcweir field.set( 986cdf0e10cSrcweir strct, 987cdf0e10cSrcweir wrapValue( 988cdf0e10cSrcweir value, field.getType(), wrapAmbiguous, isAmbiguous, 989cdf0e10cSrcweir wrapDefaulted, isDefaulted, false)); 990cdf0e10cSrcweir } 991cdf0e10cSrcweir } catch (com.sun.star.lang.IllegalArgumentException e) { 992cdf0e10cSrcweir throw new RuntimeException( 993cdf0e10cSrcweir "unexpected com.sun.star.lang.IllegalArgumentException: " 994cdf0e10cSrcweir + e.getMessage()); 995cdf0e10cSrcweir } catch (com.sun.star.lang.IllegalAccessException e) { 996cdf0e10cSrcweir throw new RuntimeException( 997cdf0e10cSrcweir "unexpected com.sun.star.lang.IllegalAccessException: " 998cdf0e10cSrcweir + e.getMessage()); 999cdf0e10cSrcweir } 1000cdf0e10cSrcweir return strct[0]; 1001cdf0e10cSrcweir } else { 1002cdf0e10cSrcweir if (wrapAmbiguous || wrapDefaulted || wrapOptional) { 1003cdf0e10cSrcweir throw new RuntimeException("unexpected type of attribute"); 1004cdf0e10cSrcweir } 1005cdf0e10cSrcweir return value; 1006cdf0e10cSrcweir } 1007cdf0e10cSrcweir } 1008cdf0e10cSrcweir resolveTypedefs(XTypeDescription type)1009cdf0e10cSrcweir private static XTypeDescription resolveTypedefs(XTypeDescription type) { 1010cdf0e10cSrcweir while (type.getTypeClass() == TypeClass.TYPEDEF) { 1011cdf0e10cSrcweir type = UnoRuntime.queryInterface( 1012cdf0e10cSrcweir XIndirectTypeDescription.class, type).getReferencedType(); 1013cdf0e10cSrcweir } 1014cdf0e10cSrcweir return type; 1015cdf0e10cSrcweir } 1016cdf0e10cSrcweir get(Object object, String propertyName)1017cdf0e10cSrcweir private PropertyData get(Object object, String propertyName) 1018cdf0e10cSrcweir throws UnknownPropertyException 1019cdf0e10cSrcweir { 1020cdf0e10cSrcweir PropertyData p = (PropertyData) properties.get(propertyName); 1021cdf0e10cSrcweir if (p == null || !p.present) { 1022cdf0e10cSrcweir throw new UnknownPropertyException(propertyName, object); 1023cdf0e10cSrcweir } 1024cdf0e10cSrcweir return p; 1025cdf0e10cSrcweir } 1026cdf0e10cSrcweir checkUnknown(String propertyName)1027cdf0e10cSrcweir private void checkUnknown(String propertyName) 1028cdf0e10cSrcweir throws UnknownPropertyException 1029cdf0e10cSrcweir { 1030cdf0e10cSrcweir if (!propertyName.equals("")) { 1031cdf0e10cSrcweir get(this, propertyName); 1032cdf0e10cSrcweir } 1033cdf0e10cSrcweir } 1034cdf0e10cSrcweir 1035cdf0e10cSrcweir private static final class PropertyData { PropertyData(Property property, boolean present)1036cdf0e10cSrcweir public PropertyData(Property property, boolean present) { 1037cdf0e10cSrcweir this.property = property; 1038cdf0e10cSrcweir this.present = present; 1039cdf0e10cSrcweir } 1040cdf0e10cSrcweir 1041cdf0e10cSrcweir public final Property property; 1042cdf0e10cSrcweir public final boolean present; 1043cdf0e10cSrcweir } 1044cdf0e10cSrcweir 1045cdf0e10cSrcweir private final class Info extends WeakBase implements XPropertySetInfo 1046cdf0e10cSrcweir { Info(Map properties)1047cdf0e10cSrcweir public Info(Map properties) { 1048cdf0e10cSrcweir this.properties = properties; 1049cdf0e10cSrcweir } 1050cdf0e10cSrcweir getProperties()1051cdf0e10cSrcweir public Property[] getProperties() { 1052cdf0e10cSrcweir ArrayList al = new ArrayList(properties.size()); 1053cdf0e10cSrcweir for (Iterator i = properties.values().iterator(); i.hasNext();) { 1054cdf0e10cSrcweir PropertyData p = (PropertyData) i.next(); 1055cdf0e10cSrcweir if (p.present) { 1056cdf0e10cSrcweir al.add(p.property); 1057cdf0e10cSrcweir } 1058cdf0e10cSrcweir } 1059cdf0e10cSrcweir return (Property[]) al.toArray(new Property[al.size()]); 1060cdf0e10cSrcweir } 1061cdf0e10cSrcweir getPropertyByName(String name)1062cdf0e10cSrcweir public Property getPropertyByName(String name) 1063cdf0e10cSrcweir throws UnknownPropertyException 1064cdf0e10cSrcweir { 1065cdf0e10cSrcweir return get(this, name).property; 1066cdf0e10cSrcweir } 1067cdf0e10cSrcweir hasPropertyByName(String name)1068cdf0e10cSrcweir public boolean hasPropertyByName(String name) { 1069cdf0e10cSrcweir PropertyData p = (PropertyData) properties.get(name); 1070cdf0e10cSrcweir return p != null && p.present; 1071cdf0e10cSrcweir } 1072cdf0e10cSrcweir 1073cdf0e10cSrcweir private final Map properties; // from String to Property 1074cdf0e10cSrcweir } 1075cdf0e10cSrcweir 1076cdf0e10cSrcweir private final XComponentContext context; 1077cdf0e10cSrcweir private final XInterface object; 1078cdf0e10cSrcweir private final Type type; 1079cdf0e10cSrcweir private final String[] absentOptional; 1080cdf0e10cSrcweir private final XIdlClass idlClass; 1081cdf0e10cSrcweir private final Map properties; // from String to Property 1082cdf0e10cSrcweir private final String[] handleMap; 1083cdf0e10cSrcweir 1084cdf0e10cSrcweir private HashMap boundListeners = new HashMap(); 1085cdf0e10cSrcweir // from String to Vector of XPropertyChangeListener 1086cdf0e10cSrcweir private HashMap vetoListeners = new HashMap(); 1087cdf0e10cSrcweir // from String to Vector of XVetoableChangeListener 1088cdf0e10cSrcweir private boolean disposed = false; 1089cdf0e10cSrcweir } 1090