1 /*
   2  * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 /*
  26  * $Id: KeyInfoFactory.java,v 1.12 2005/05/10 16:35:35 mullan Exp $
  27  */
  28 package javax.xml.crypto.dsig.keyinfo;
  29 
  30 import java.math.BigInteger;
  31 import java.security.KeyException;
  32 import java.security.NoSuchAlgorithmException;
  33 import java.security.NoSuchProviderException;
  34 import java.security.Provider;
  35 import java.security.PublicKey;
  36 import java.security.Security;
  37 import java.security.cert.X509CRL;
  38 import java.util.List;
  39 import javax.xml.crypto.MarshalException;
  40 import javax.xml.crypto.NoSuchMechanismException;
  41 import javax.xml.crypto.URIDereferencer;
  42 import javax.xml.crypto.XMLStructure;
  43 import javax.xml.crypto.dom.DOMStructure;
  44 import javax.xml.crypto.dsig.*;
  45 
  46 import sun.security.jca.*;
  47 import sun.security.jca.GetInstance.Instance;
  48 
  49 /**
  50  * A factory for creating {@link KeyInfo} objects from scratch or for
  51  * unmarshalling a <code>KeyInfo</code> object from a corresponding XML
  52  * representation.
  53  *
  54  * <p>Each instance of <code>KeyInfoFactory</code> supports a specific
  55  * XML mechanism type. To create a <code>KeyInfoFactory</code>, call one of the
  56  * static {@link #getInstance getInstance} methods, passing in the XML
  57  * mechanism type desired, for example:
  58  *
  59  * <blockquote><code>
  60  *   KeyInfoFactory factory = KeyInfoFactory.getInstance("DOM");
  61  * </code></blockquote>
  62  *
  63  * <p>The objects that this factory produces will be based
  64  * on DOM and abide by the DOM interoperability requirements as defined in the
  65  * <a href="../../../../../../technotes/guides/security/xmldsig/overview.html#DOM%20Mechanism%20Requirements">
  66  * DOM Mechanism Requirements</a> section of the API overview. See the
  67  * <a href="../../../../../../technotes/guides/security/xmldsig/overview.html#Service%20Provider">
  68  * Service Providers</a> section of the API overview for a list of standard
  69  * mechanism types.
  70  *
  71  * <p><code>KeyInfoFactory</code> implementations are registered and loaded
  72  * using the {@link java.security.Provider} mechanism.
  73  * For example, a service provider that supports the
  74  * DOM mechanism would be specified in the <code>Provider</code> subclass as:
  75  * <pre>
  76  *     put("KeyInfoFactory.DOM", "org.example.DOMKeyInfoFactory");
  77  * </pre>
  78  *
  79  * <p>Also, the <code>XMLStructure</code>s that are created by this factory
  80  * may contain state specific to the <code>KeyInfo</code> and are not
  81  * intended to be reusable.
  82  *
  83  * <p>An implementation MUST minimally support the default mechanism type: DOM.
  84  *
  85  * <p>Note that a caller must use the same <code>KeyInfoFactory</code>
  86  * instance to create the <code>XMLStructure</code>s of a particular
  87  * <code>KeyInfo</code> object. The behavior is undefined if
  88  * <code>XMLStructure</code>s from different providers or different mechanism
  89  * types are used together.
  90  *
  91  * <p><b>Concurrent Access</b>
  92  * <p>The static methods of this class are guaranteed to be thread-safe.
  93  * Multiple threads may concurrently invoke the static methods defined in this
  94  * class with no ill effects.
  95  *
  96  * <p>However, this is not true for the non-static methods defined by this
  97  * class. Unless otherwise documented by a specific provider, threads that
  98  * need to access a single <code>KeyInfoFactory</code> instance concurrently
  99  * should synchronize amongst themselves and provide the necessary locking.
 100  * Multiple threads each manipulating a different <code>KeyInfoFactory</code>
 101  * instance need not synchronize.
 102  *
 103  * @author Sean Mullan
 104  * @author JSR 105 Expert Group
 105  * @since 1.6
 106  */
 107 public abstract class KeyInfoFactory {
 108 
 109     private String mechanismType;
 110     private Provider provider;
 111 
 112     /**
 113      * Default constructor, for invocation by subclasses.
 114      */
 115     protected KeyInfoFactory() {}
 116 
 117     /**
 118      * Returns a <code>KeyInfoFactory</code> that supports the
 119      * specified XML processing mechanism and representation type (ex: "DOM").
 120      *
 121      * <p>This method uses the standard JCA provider lookup mechanism to
 122      * locate and instantiate a <code>KeyInfoFactory</code> implementation of
 123      * the desired mechanism type. It traverses the list of registered security
 124      * <code>Provider</code>s, starting with the most preferred
 125      * <code>Provider</code>. A new <code>KeyInfoFactory</code> object
 126      * from the first <code>Provider</code> that supports the specified
 127      * mechanism is returned.
 128      *
 129      * <p> Note that the list of registered providers may be retrieved via
 130      * the {@link Security#getProviders() Security.getProviders()} method.
 131      *
 132      * @implNote
 133      * The JDK Reference Implementation additionally uses the
 134      * {@code jdk.security.provider.preferred}
 135      * {@link Security#getProperty(String) Security} property to determine
 136      * the preferred provider order for the specified algorithm. This
 137      * may be different than the order of providers returned by
 138      * {@link Security#getProviders() Security.getProviders()}.
 139      *
 140      * @param mechanismType the type of the XML processing mechanism and
 141      *    representation. See the <a
 142      *    href="../../../../../../technotes/guides/security/xmldsig/overview.html#Service%20Provider">
 143      *    Service Providers</a> section of the API overview for a list of
 144      *    standard mechanism types.
 145      * @return a new <code>KeyInfoFactory</code>
 146      * @throws NullPointerException if <code>mechanismType</code> is
 147      *    <code>null</code>
 148      * @throws NoSuchMechanismException if no <code>Provider</code> supports a
 149      *    <code>KeyInfoFactory</code> implementation for the specified mechanism
 150      * @see Provider
 151      */
 152     public static KeyInfoFactory getInstance(String mechanismType) {
 153         if (mechanismType == null) {
 154             throw new NullPointerException("mechanismType cannot be null");
 155         }
 156         Instance instance;
 157         try {
 158             instance = GetInstance.getInstance
 159                 ("KeyInfoFactory", null, mechanismType);
 160         } catch (NoSuchAlgorithmException nsae) {
 161             throw new NoSuchMechanismException(nsae);
 162         }
 163         KeyInfoFactory factory = (KeyInfoFactory) instance.impl;
 164         factory.mechanismType = mechanismType;
 165         factory.provider = instance.provider;
 166         return factory;
 167     }
 168 
 169     /**
 170      * Returns a <code>KeyInfoFactory</code> that supports the
 171      * requested XML processing mechanism and representation type (ex: "DOM"),
 172      * as supplied by the specified provider. Note that the specified
 173      * <code>Provider</code> object does not have to be registered in the
 174      * provider list.
 175      *
 176      * @param mechanismType the type of the XML processing mechanism and
 177      *    representation. See the <a
 178      *    href="../../../../../../technotes/guides/security/xmldsig/overview.html#Service%20Provider">
 179      *    Service Providers</a> section of the API overview for a list of
 180      *    standard mechanism types.
 181      * @param provider the <code>Provider</code> object
 182      * @return a new <code>KeyInfoFactory</code>
 183      * @throws NullPointerException if <code>mechanismType</code> or
 184      *    <code>provider</code> are <code>null</code>
 185      * @throws NoSuchMechanismException if a <code>KeyInfoFactory</code>
 186      *    implementation for the specified mechanism is not available from the
 187      *    specified <code>Provider</code> object
 188      * @see Provider
 189      */
 190     public static KeyInfoFactory getInstance(String mechanismType,
 191         Provider provider) {
 192         if (mechanismType == null) {
 193             throw new NullPointerException("mechanismType cannot be null");
 194         } else if (provider == null) {
 195             throw new NullPointerException("provider cannot be null");
 196         }
 197 
 198         Instance instance;
 199         try {
 200             instance = GetInstance.getInstance
 201                 ("KeyInfoFactory", null, mechanismType, provider);
 202         } catch (NoSuchAlgorithmException nsae) {
 203             throw new NoSuchMechanismException(nsae);
 204         }
 205         KeyInfoFactory factory = (KeyInfoFactory) instance.impl;
 206         factory.mechanismType = mechanismType;
 207         factory.provider = instance.provider;
 208         return factory;
 209     }
 210 
 211     /**
 212      * Returns a <code>KeyInfoFactory</code> that supports the
 213      * requested XML processing mechanism and representation type (ex: "DOM"),
 214      * as supplied by the specified provider. The specified provider must be
 215      * registered in the security provider list.
 216      *
 217      * <p>Note that the list of registered providers may be retrieved via
 218      * the {@link Security#getProviders() Security.getProviders()} method.
 219      *
 220      * @param mechanismType the type of the XML processing mechanism and
 221      *    representation. See the <a
 222      *    href="../../../../../../technotes/guides/security/xmldsig/overview.html#Service%20Provider">
 223      *    Service Providers</a> section of the API overview for a list of
 224      *    standard mechanism types.
 225      * @param provider the string name of the provider
 226      * @return a new <code>KeyInfoFactory</code>
 227      * @throws NoSuchProviderException if the specified provider is not
 228      *    registered in the security provider list
 229      * @throws NullPointerException if <code>mechanismType</code> or
 230      *    <code>provider</code> are <code>null</code>
 231      * @throws NoSuchMechanismException if a <code>KeyInfoFactory</code>
 232      *    implementation for the specified mechanism is not available from the
 233      *    specified provider
 234      * @see Provider
 235      */
 236     public static KeyInfoFactory getInstance(String mechanismType,
 237         String provider) throws NoSuchProviderException {
 238         if (mechanismType == null) {
 239             throw new NullPointerException("mechanismType cannot be null");
 240         } else if (provider == null) {
 241             throw new NullPointerException("provider cannot be null");
 242         } else if (provider.length() == 0) {
 243             throw new NoSuchProviderException();
 244         }
 245 
 246         Instance instance;
 247         try {
 248             instance = GetInstance.getInstance
 249                 ("KeyInfoFactory", null, mechanismType, provider);
 250         } catch (NoSuchAlgorithmException nsae) {
 251             throw new NoSuchMechanismException(nsae);
 252         }
 253         KeyInfoFactory factory = (KeyInfoFactory) instance.impl;
 254         factory.mechanismType = mechanismType;
 255         factory.provider = instance.provider;
 256         return factory;
 257     }
 258 
 259     /**
 260      * Returns a <code>KeyInfoFactory</code> that supports the
 261      * default XML processing mechanism and representation type ("DOM").
 262      *
 263      * <p>This method uses the standard JCA provider lookup mechanism to
 264      * locate and instantiate a <code>KeyInfoFactory</code> implementation of
 265      * the default mechanism type. It traverses the list of registered security
 266      * <code>Provider</code>s, starting with the most preferred
 267      * <code>Provider</code>.  A new <code>KeyInfoFactory</code> object
 268      * from the first <code>Provider</code> that supports the DOM mechanism is
 269      * returned.
 270      *
 271      * <p> Note that the list of registered providers may be retrieved via
 272      * the {@link Security#getProviders() Security.getProviders()} method.
 273      *
 274      * @implNote
 275      * The JDK Reference Implementation additionally uses the
 276      * {@code jdk.security.provider.preferred}
 277      * {@link Security#getProperty(String) Security} property to determine
 278      * the preferred provider order for the specified algorithm. This
 279      * may be different than the order of providers returned by
 280      * {@link Security#getProviders() Security.getProviders()}.
 281      *
 282      * @return a new <code>KeyInfoFactory</code>
 283      * @throws NoSuchMechanismException if no <code>Provider</code> supports a
 284      *    <code>KeyInfoFactory</code> implementation for the DOM mechanism
 285      * @see Provider
 286      */
 287     public static KeyInfoFactory getInstance() {
 288         return getInstance("DOM");
 289     }
 290 
 291     /**
 292      * Returns the type of the XML processing mechanism and representation
 293      * supported by this <code>KeyInfoFactory</code> (ex: "DOM")
 294      *
 295      * @return the XML processing mechanism type supported by this
 296      *    <code>KeyInfoFactory</code>
 297      */
 298     public final String getMechanismType() {
 299         return mechanismType;
 300     }
 301 
 302     /**
 303      * Returns the provider of this <code>KeyInfoFactory</code>.
 304      *
 305      * @return the provider of this <code>KeyInfoFactory</code>
 306      */
 307     public final Provider getProvider() {
 308         return provider;
 309     }
 310 
 311     /**
 312      * Creates a <code>KeyInfo</code> containing the specified list of
 313      * key information types.
 314      *
 315      * @param content a list of one or more {@link XMLStructure}s representing
 316      *    key information types. The list is defensively copied to protect
 317      *    against subsequent modification.
 318      * @return a <code>KeyInfo</code>
 319      * @throws NullPointerException if <code>content</code> is <code>null</code>
 320      * @throws IllegalArgumentException if <code>content</code> is empty
 321      * @throws ClassCastException if <code>content</code> contains any entries
 322      *    that are not of type {@link XMLStructure}
 323      */
 324     public abstract KeyInfo newKeyInfo(List<? extends XMLStructure> content);
 325 
 326     /**
 327      * Creates a <code>KeyInfo</code> containing the specified list of key
 328      * information types and optional id. The
 329      * <code>id</code> parameter represents the value of an XML
 330      * <code>ID</code> attribute and is useful for referencing
 331      * the <code>KeyInfo</code> from other XML structures.
 332      *
 333      * @param content a list of one or more {@link XMLStructure}s representing
 334      *    key information types. The list is defensively copied to protect
 335      *    against subsequent modification.
 336      * @param id the value of an XML <code>ID</code> (may be <code>null</code>)
 337      * @return a <code>KeyInfo</code>
 338      * @throws NullPointerException if <code>content</code> is <code>null</code>
 339      * @throws IllegalArgumentException if <code>content</code> is empty
 340      * @throws ClassCastException if <code>content</code> contains any entries
 341      *    that are not of type {@link XMLStructure}
 342      */
 343     public abstract KeyInfo newKeyInfo(List<? extends XMLStructure> content,
 344         String id);
 345 
 346     /**
 347      * Creates a <code>KeyName</code> from the specified name.
 348      *
 349      * @param name the name that identifies the key
 350      * @return a <code>KeyName</code>
 351      * @throws NullPointerException if <code>name</code> is <code>null</code>
 352      */
 353     public abstract KeyName newKeyName(String name);
 354 
 355     /**
 356      * Creates a <code>KeyValue</code> from the specified public key.
 357      *
 358      * @param key the public key
 359      * @return a <code>KeyValue</code>
 360      * @throws KeyException if the <code>key</code>'s algorithm is not
 361      *    recognized or supported by this <code>KeyInfoFactory</code>
 362      * @throws NullPointerException if <code>key</code> is <code>null</code>
 363      */
 364     public abstract KeyValue newKeyValue(PublicKey key) throws KeyException;
 365 
 366     /**
 367      * Creates a <code>PGPData</code> from the specified PGP public key
 368      * identifier.
 369      *
 370      * @param keyId a PGP public key identifier as defined in <a href=
 371      *    "http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>, section 11.2.
 372      *    The array is cloned to protect against subsequent modification.
 373      * @return a <code>PGPData</code>
 374      * @throws NullPointerException if <code>keyId</code> is <code>null</code>
 375      * @throws IllegalArgumentException if the key id is not in the correct
 376      *    format
 377      */
 378     public abstract PGPData newPGPData(byte[] keyId);
 379 
 380     /**
 381      * Creates a <code>PGPData</code> from the specified PGP public key
 382      * identifier, and optional key material packet and list of external
 383      * elements.
 384      *
 385      * @param keyId a PGP public key identifier as defined in <a href=
 386      *    "http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>, section 11.2.
 387      *    The array is cloned to protect against subsequent modification.
 388      * @param keyPacket a PGP key material packet as defined in <a href=
 389      *    "http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>, section 5.5.
 390      *    The array is cloned to protect against subsequent modification. May
 391      *    be <code>null</code>.
 392      * @param other a list of {@link XMLStructure}s representing elements from
 393      *    an external namespace. The list is defensively copied to protect
 394      *    against subsequent modification. May be <code>null</code> or empty.
 395      * @return a <code>PGPData</code>
 396      * @throws NullPointerException if <code>keyId</code> is <code>null</code>
 397      * @throws IllegalArgumentException if the <code>keyId</code> or
 398      *    <code>keyPacket</code> is not in the correct format. For
 399      *    <code>keyPacket</code>, the format of the packet header is
 400      *    checked and the tag is verified that it is of type key material. The
 401      *    contents and format of the packet body are not checked.
 402      * @throws ClassCastException if <code>other</code> contains any
 403      *    entries that are not of type {@link XMLStructure}
 404      */
 405     public abstract PGPData newPGPData(byte[] keyId, byte[] keyPacket,
 406         List<? extends XMLStructure> other);
 407 
 408     /**
 409      * Creates a <code>PGPData</code> from the specified PGP key material
 410      * packet and optional list of external elements.
 411      *
 412      * @param keyPacket a PGP key material packet as defined in <a href=
 413      *    "http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>, section 5.5.
 414      *    The array is cloned to protect against subsequent modification.
 415      * @param other a list of {@link XMLStructure}s representing elements from
 416      *    an external namespace. The list is defensively copied to protect
 417      *    against subsequent modification. May be <code>null</code> or empty.
 418      * @return a <code>PGPData</code>
 419      * @throws NullPointerException if <code>keyPacket</code> is
 420      *    <code>null</code>
 421      * @throws IllegalArgumentException if <code>keyPacket</code> is not in the
 422      *    correct format. For <code>keyPacket</code>, the format of the packet
 423      *    header is checked and the tag is verified that it is of type key
 424      *    material. The contents and format of the packet body are not checked.
 425      * @throws ClassCastException if <code>other</code> contains any
 426      *    entries that are not of type {@link XMLStructure}
 427      */
 428     public abstract PGPData newPGPData(byte[] keyPacket,
 429         List<? extends XMLStructure> other);
 430 
 431     /**
 432      * Creates a <code>RetrievalMethod</code> from the specified URI.
 433      *
 434      * @param uri the URI that identifies the <code>KeyInfo</code> information
 435      *    to be retrieved
 436      * @return a <code>RetrievalMethod</code>
 437      * @throws NullPointerException if <code>uri</code> is <code>null</code>
 438      * @throws IllegalArgumentException if <code>uri</code> is not RFC 2396
 439      *    compliant
 440      */
 441     public abstract RetrievalMethod newRetrievalMethod(String uri);
 442 
 443     /**
 444      * Creates a <code>RetrievalMethod</code> from the specified parameters.
 445      *
 446      * @param uri the URI that identifies the <code>KeyInfo</code> information
 447      *    to be retrieved
 448      * @param type a URI that identifies the type of <code>KeyInfo</code>
 449      *    information to be retrieved (may be <code>null</code>)
 450      * @param transforms a list of {@link Transform}s. The list is defensively
 451      *    copied to protect against subsequent modification. May be
 452      *    <code>null</code> or empty.
 453      * @return a <code>RetrievalMethod</code>
 454      * @throws NullPointerException if <code>uri</code> is <code>null</code>
 455      * @throws IllegalArgumentException if <code>uri</code> is not RFC 2396
 456      *    compliant
 457      * @throws ClassCastException if <code>transforms</code> contains any
 458      *    entries that are not of type {@link Transform}
 459      */
 460     public abstract RetrievalMethod newRetrievalMethod(String uri, String type,
 461         List<? extends Transform> transforms);
 462 
 463     /**
 464      * Creates a <code>X509Data</code> containing the specified list of
 465      * X.509 content.
 466      *
 467      * @param content a list of one or more X.509 content types. Valid types are
 468      *    {@link String} (subject names), <code>byte[]</code> (subject key ids),
 469      *    {@link java.security.cert.X509Certificate}, {@link X509CRL},
 470      *    or {@link XMLStructure} ({@link X509IssuerSerial}
 471      *    objects or elements from an external namespace). Subject names are
 472      *    distinguished names in RFC 2253 String format. Implementations MUST
 473      *    support the attribute type keywords defined in RFC 2253 (CN, L, ST,
 474      *    O, OU, C, STREET, DC and UID). Implementations MAY support additional
 475      *    keywords. The list is defensively copied to protect against
 476      *    subsequent modification.
 477      * @return a <code>X509Data</code>
 478      * @throws NullPointerException if <code>content</code> is <code>null</code>
 479      * @throws IllegalArgumentException if <code>content</code> is empty, or
 480      *    if a subject name is not RFC 2253 compliant or one of the attribute
 481      *    type keywords is not recognized.
 482      * @throws ClassCastException if <code>content</code> contains any entries
 483      *    that are not of one of the valid types mentioned above
 484      */
 485     public abstract X509Data newX509Data(List<?> content);
 486 
 487     /**
 488      * Creates an <code>X509IssuerSerial</code> from the specified X.500 issuer
 489      * distinguished name and serial number.
 490      *
 491      * @param issuerName the issuer's distinguished name in RFC 2253 String
 492      *    format. Implementations MUST support the attribute type keywords
 493      *    defined in RFC 2253 (CN, L, ST, O, OU, C, STREET, DC and UID).
 494      *    Implementations MAY support additional keywords.
 495      * @param serialNumber the serial number
 496      * @return an <code>X509IssuerSerial</code>
 497      * @throws NullPointerException if <code>issuerName</code> or
 498      *    <code>serialNumber</code> are <code>null</code>
 499      * @throws IllegalArgumentException if the issuer name is not RFC 2253
 500      *    compliant or one of the attribute type keywords is not recognized.
 501      */
 502     public abstract X509IssuerSerial newX509IssuerSerial
 503         (String issuerName, BigInteger serialNumber);
 504 
 505     /**
 506      * Indicates whether a specified feature is supported.
 507      *
 508      * @param feature the feature name (as an absolute URI)
 509      * @return <code>true</code> if the specified feature is supported,
 510      *    <code>false</code> otherwise
 511      * @throws NullPointerException if <code>feature</code> is <code>null</code>
 512      */
 513     public abstract boolean isFeatureSupported(String feature);
 514 
 515     /**
 516      * Returns a reference to the <code>URIDereferencer</code> that is used by
 517      * default to dereference URIs in {@link RetrievalMethod} objects.
 518      *
 519      * @return a reference to the default <code>URIDereferencer</code>
 520      */
 521     public abstract URIDereferencer getURIDereferencer();
 522 
 523     /**
 524      * Unmarshals a new <code>KeyInfo</code> instance from a
 525      * mechanism-specific <code>XMLStructure</code> (ex: {@link DOMStructure})
 526      * instance.
 527      *
 528      * @param xmlStructure a mechanism-specific XML structure from which to
 529      *   unmarshal the keyinfo from
 530      * @return the <code>KeyInfo</code>
 531      * @throws NullPointerException if <code>xmlStructure</code> is
 532      *   <code>null</code>
 533      * @throws ClassCastException if the type of <code>xmlStructure</code> is
 534      *   inappropriate for this factory
 535      * @throws MarshalException if an unrecoverable exception occurs during
 536      *   unmarshalling
 537      */
 538     public abstract KeyInfo unmarshalKeyInfo(XMLStructure xmlStructure)
 539         throws MarshalException;
 540 }