RuntimeInstance.java

  1. // SECTION-START[License Header]
  2. // <editor-fold defaultstate="collapsed" desc=" Generated License ">
  3. /*
  4.  * Java Object Management and Configuration
  5.  * Copyright (C) Christian Schulte <cs@schulte.it>, 2011-313
  6.  * All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  *
  12.  *   o Redistributions of source code must retain the above copyright
  13.  *     notice, this list of conditions and the following disclaimer.
  14.  *
  15.  *   o Redistributions in binary form must reproduce the above copyright
  16.  *     notice, this list of conditions and the following disclaimer in
  17.  *     the documentation and/or other materials provided with the
  18.  *     distribution.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  21.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  22.  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  23.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  29.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30.  *
  31.  * $JOMC: RuntimeInstance.java 5061 2015-05-31 13:20:40Z schulte $
  32.  *
  33.  */
  34. // </editor-fold>
  35. // SECTION-END
  36. package org.jomc.ri.model;

  37. import java.lang.ref.Reference;
  38. import java.lang.ref.WeakReference;
  39. import java.lang.reflect.Constructor;
  40. import java.lang.reflect.Method;
  41. import java.util.Map;
  42. import javax.xml.bind.annotation.XmlTransient;
  43. import org.jomc.model.Instance;
  44. import org.jomc.model.JavaTypeName;
  45. import org.jomc.model.ModelObjectException;
  46. import org.jomc.model.Specification;
  47. import org.jomc.util.WeakIdentityHashMap;
  48. import static org.jomc.ri.model.RuntimeModelObjects.BOOTSTRAP_CLASSLOADER_KEY;
  49. import static org.jomc.ri.model.RuntimeModelObjects.classesByClassLoaderAndNameCache;
  50. import static org.jomc.ri.model.RuntimeModelObjects.createMap;

  51. // SECTION-START[Documentation]
  52. // <editor-fold defaultstate="collapsed" desc=" Generated Documentation ">
  53. /**
  54.  * Runtime {@code Instance}.
  55.  *
  56.  * <dl>
  57.  *   <dt><b>Identifier:</b></dt><dd>org.jomc.ri.model.RuntimeInstance</dd>
  58.  *   <dt><b>Name:</b></dt><dd>JOMC ⁑ RI ⁑ RuntimeInstance</dd>
  59.  *   <dt><b>Specifications:</b></dt>
  60.  *     <dd>org.jomc.ri.model.RuntimeModelObject @ 1.2</dd>
  61.  *   <dt><b>Abstract:</b></dt><dd>No</dd>
  62.  *   <dt><b>Final:</b></dt><dd>No</dd>
  63.  *   <dt><b>Stateless:</b></dt><dd>No</dd>
  64.  * </dl>
  65.  *
  66.  * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 1.2
  67.  * @version 1.2
  68.  */
  69. // </editor-fold>
  70. // SECTION-END
  71. // SECTION-START[Annotations]
  72. // <editor-fold defaultstate="collapsed" desc=" Generated Annotations ">
  73. @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.9", comments = "See http://www.jomc.org/jomc/1.9/jomc-tools-1.9" )
  74. // </editor-fold>
  75. // SECTION-END
  76. public class RuntimeInstance extends Instance implements RuntimeModelObject
  77. {
  78.     // SECTION-START[RuntimeInstance]

  79.     /**
  80.      * Classes by class loader any instance cache.
  81.      */
  82.     @XmlTransient
  83.     static final Map<ClassLoader, Map<String, Reference<Class<?>[]>>> classesByClassLoaderAndInstanceCache =
  84.         new WeakIdentityHashMap<ClassLoader, Map<String, Reference<Class<?>[]>>>();

  85.     /**
  86.      * Constructors by class loader any instance cache.
  87.      */
  88.     @XmlTransient
  89.     static final Map<ClassLoader, Map<String, Reference<Constructor<?>>>> constructorsByClassLoaderAndInstanceCache =
  90.         new WeakIdentityHashMap<ClassLoader, Map<String, Reference<Constructor<?>>>>();

  91.     /**
  92.      * Methods by class loader any instance cache.
  93.      */
  94.     @XmlTransient
  95.     static final Map<ClassLoader, Map<String, Reference<Method>>> methodsByClassLoaderAndInstanceCache =
  96.         new WeakIdentityHashMap<ClassLoader, Map<String, Reference<Method>>>();

  97.     /**
  98.      * Assignable flags by class loader any instance cache.
  99.      */
  100.     @XmlTransient
  101.     static final Map<ClassLoader, Map<String, Boolean>> assignableFlagsByClassLoaderAndInstanceCache =
  102.         new WeakIdentityHashMap<ClassLoader, Map<String, Boolean>>();

  103.     /**
  104.      * Proxy classes by class loader any instance cache.
  105.      */
  106.     @XmlTransient
  107.     static final Map<ClassLoader, Map<String, Reference<Class<?>>>> proxyClassesByClassLoaderAndInstanceCache =
  108.         new WeakIdentityHashMap<ClassLoader, Map<String, Reference<Class<?>>>>();

  109.     /**
  110.      * Method name.
  111.      */
  112.     @XmlTransient
  113.     private volatile String javaClassFactoryMethodName;

  114.     /**
  115.      * Java type name.
  116.      */
  117.     @XmlTransient
  118.     private volatile JavaTypeName javaTypeName;

  119.     /**
  120.      * Creates a new {@code RuntimeInstance} instance by deeply copying a given {@code Instance} instance.
  121.      *
  122.      * @param instance The instance to copy.
  123.      *
  124.      * @throws NullPointerException if {@code instance} is {@code null}.
  125.      */
  126.     public RuntimeInstance( final Instance instance )
  127.     {
  128.         super( instance );

  129.         if ( this.getAuthors() != null )
  130.         {
  131.             this.setAuthors( RuntimeModelObjects.getInstance().copyOf( this.getAuthors() ) );
  132.         }
  133.         if ( this.getDependencies() != null )
  134.         {
  135.             this.setDependencies( RuntimeModelObjects.getInstance().copyOf( this.getDependencies() ) );
  136.         }
  137.         if ( this.getDocumentation() != null )
  138.         {
  139.             this.setDocumentation( RuntimeModelObjects.getInstance().copyOf( this.getDocumentation() ) );
  140.         }
  141.         if ( this.getMessages() != null )
  142.         {
  143.             this.setMessages( RuntimeModelObjects.getInstance().copyOf( this.getMessages() ) );
  144.         }
  145.         if ( this.getProperties() != null )
  146.         {
  147.             this.setProperties( RuntimeModelObjects.getInstance().copyOf( this.getProperties() ) );
  148.         }
  149.         if ( this.getSpecifications() != null )
  150.         {
  151.             this.setSpecifications( RuntimeModelObjects.getInstance().copyOf( this.getSpecifications() ) );
  152.         }
  153.     }

  154.     /**
  155.      * Gets the Java class of the instance for a given class loader.
  156.      * <p>
  157.      * This method queries an internal cache for a result object to return for the given argument values. If no
  158.      * cached result object is available, this method queries the super-class for a result object to return and caches
  159.      * the outcome of that query for use on successive calls.
  160.      * </p>
  161.      * <p>
  162.      * <b>Note:</b><br/>Method {@code RuntimeModelObjects.clear()} must be used to synchronize the state of the
  163.      * internal cache with the state of the class loader, should the state of the class loader change.
  164.      * </p>
  165.      *
  166.      * @param classLoader The class loader to get the Java class from or {@code null}, to get the Java class from the
  167.      * platform's bootstrap class loader.
  168.      *
  169.      * @return The Java class of the instance.
  170.      *
  171.      * @throws ClassNotFoundException if the Java class is not found.
  172.      * @throws ModelObjectException if parsing the name of the referenced type fails.
  173.      *
  174.      * @see #getClazz()
  175.      * @see RuntimeModelObjects#clear()
  176.      */
  177.     @Override
  178.     public Class<?> getJavaClass( final ClassLoader classLoader )
  179.         throws ModelObjectException, ClassNotFoundException
  180.     {
  181.         Class<?> javaClass = null;

  182.         if ( this.getJavaTypeName() != null )
  183.         {
  184.             ClassLoader classLoaderKey = classLoader;
  185.             if ( classLoaderKey == null )
  186.             {
  187.                 classLoaderKey = BOOTSTRAP_CLASSLOADER_KEY;
  188.             }

  189.             synchronized ( classesByClassLoaderAndNameCache )
  190.             {
  191.                 Map<String, Reference<Class<?>>> map = classesByClassLoaderAndNameCache.get( classLoaderKey );

  192.                 if ( map == null )
  193.                 {
  194.                     map = createMap();
  195.                     classesByClassLoaderAndNameCache.put( classLoaderKey, map );
  196.                 }

  197.                 final Reference<Class<?>> reference = map.get( this.getJavaTypeName().getClassName() );

  198.                 if ( reference != null )
  199.                 {
  200.                     javaClass = reference.get();
  201.                 }

  202.                 if ( javaClass == null )
  203.                 {
  204.                     javaClass = super.getJavaClass( classLoader );
  205.                     map.put( this.getJavaTypeName().getClassName(), new WeakReference<Class<?>>( javaClass ) );
  206.                 }
  207.             }
  208.         }

  209.         return javaClass;
  210.     }

  211.     /**
  212.      * Gets the Java classes of all specifications of the instance for a given class loader.
  213.      * <p>
  214.      * This method queries an internal cache for a result object to return for the given argument values. If no
  215.      * cached result object is available, this method queries the super-class for a result object to return and caches
  216.      * the outcome of that query for use on successive calls.
  217.      * </p>
  218.      * <p>
  219.      * <b>Note:</b><br/>Method {@code RuntimeModelObjects.clear()} must be used to synchronize the state of the
  220.      * internal cache with the state of the instance and class loader, should the state of the instance or class loader
  221.      * change.
  222.      * </p>
  223.      *
  224.      * @param classLoader The class loader to get the Java classes from or {@code null}, to get the Java classes from
  225.      * the platform's bootstrap class loader.
  226.      *
  227.      * @return The Java classes of all specifications of the instance.
  228.      *
  229.      * @throws ClassNotFoundException if a Java class is not found.
  230.      * @throws ModelObjectException if parsing a name of a referenced type fails.
  231.      *
  232.      * @see #getSpecifications()
  233.      * @see Specification#getClazz()
  234.      * @see RuntimeModelObjects#clear()
  235.      */
  236.     @Override
  237.     public Class<?>[] getJavaClasses( final ClassLoader classLoader )
  238.         throws ModelObjectException, ClassNotFoundException
  239.     {
  240.         ClassLoader classLoaderKey = classLoader;
  241.         if ( classLoaderKey == null )
  242.         {
  243.             classLoaderKey = BOOTSTRAP_CLASSLOADER_KEY;
  244.         }

  245.         synchronized ( classesByClassLoaderAndInstanceCache )
  246.         {
  247.             Class<?>[] javaClasses = null;
  248.             Map<String, Reference<Class<?>[]>> map = classesByClassLoaderAndInstanceCache.get( classLoaderKey );

  249.             if ( map == null )
  250.             {
  251.                 map = createMap();
  252.                 classesByClassLoaderAndInstanceCache.put( classLoaderKey, map );
  253.             }

  254.             final Reference<Class<?>[]> reference = map.get( this.getIdentifier() );

  255.             if ( reference != null )
  256.             {
  257.                 javaClasses = reference.get();
  258.             }

  259.             if ( javaClasses == null && ( reference != null || !map.containsKey( this.getIdentifier() ) ) )
  260.             {
  261.                 javaClasses = super.getJavaClasses( classLoader );
  262.                 map.put( this.getIdentifier(), new WeakReference<Class<?>[]>( javaClasses ) );
  263.             }

  264.             return javaClasses;
  265.         }
  266.     }

  267.     /**
  268.      * Gets the Java constructor to use for creating objects of the instance.
  269.      * <p>
  270.      * This method queries an internal cache for a result object to return for the given argument values. If no
  271.      * cached result object is available, this method queries the super-class for a result object to return and caches
  272.      * the outcome of that query for use on successive calls.
  273.      * </p>
  274.      * <p>
  275.      * <b>Note:</b><br/>Method {@code RuntimeModelObjects.clear()} must be used to synchronize the state of the
  276.      * internal cache with the state of the instance and class loader, should the state of the instance or class loader
  277.      * change.
  278.      * </p>
  279.      *
  280.      * @param classLoader The class loader to get the Java class from or {@code null}, to get the Java class from the
  281.      * platform's bootstrap class loader.
  282.      *
  283.      * @return The public default Java constructor of the Java class of the instance or {@code null}, if that class
  284.      * does not declare such a constructor, is abstract or is not public.
  285.      *
  286.      * @throws ClassNotFoundException if the Java class is not found.
  287.      * @throws ModelObjectException if parsing the name of the type referenced by the instance fails.
  288.      *
  289.      * @see #getJavaClass(java.lang.ClassLoader)
  290.      * @see RuntimeModelObjects#clear()
  291.      */
  292.     @Override
  293.     public Constructor<?> getJavaConstructor( final ClassLoader classLoader )
  294.         throws ModelObjectException, ClassNotFoundException
  295.     {
  296.         ClassLoader classLoaderKey = classLoader;
  297.         if ( classLoaderKey == null )
  298.         {
  299.             classLoaderKey = BOOTSTRAP_CLASSLOADER_KEY;
  300.         }

  301.         synchronized ( constructorsByClassLoaderAndInstanceCache )
  302.         {
  303.             Constructor<?> javaClassConstructor = null;
  304.             Map<String, Reference<Constructor<?>>> map = constructorsByClassLoaderAndInstanceCache.get( classLoaderKey );

  305.             if ( map == null )
  306.             {
  307.                 map = createMap();
  308.                 constructorsByClassLoaderAndInstanceCache.put( classLoaderKey, map );
  309.             }

  310.             final Reference<Constructor<?>> reference = map.get( this.getIdentifier() );

  311.             if ( reference != null )
  312.             {
  313.                 javaClassConstructor = reference.get();
  314.             }

  315.             if ( javaClassConstructor == null && ( reference != null || !map.containsKey( this.getIdentifier() ) ) )
  316.             {
  317.                 javaClassConstructor = super.getJavaConstructor( classLoader );
  318.                 map.put( this.getIdentifier(), new WeakReference<Constructor<?>>( javaClassConstructor ) );
  319.             }

  320.             return javaClassConstructor;
  321.         }
  322.     }

  323.     /**
  324.      * Gets the name of the Java method to use for creating objects of the instance.
  325.      * <p>
  326.      * This method queries an internal cache for a result object to return. If no cached result object is available,
  327.      * this method queries the super-class for a result object to return and caches the outcome of that query for use on
  328.      * successive calls.
  329.      * </p>
  330.      * <p>
  331.      * <b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
  332.      * state of the instance, should the state of the instance change.
  333.      * </p>
  334.      *
  335.      * @return The name of the Java method to use for creating objects of the instance or {@code null}, if no such
  336.      * method name is supported.
  337.      *
  338.      * @throws ModelObjectException if compiling the name of the instance to a {@code JavaIdentifier} fails.
  339.      *
  340.      * @see #getName()
  341.      * @see #clear()
  342.      */
  343.     @Override
  344.     public String getJavaFactoryMethodName() throws ModelObjectException
  345.     {
  346.         if ( this.javaClassFactoryMethodName == null )
  347.         {
  348.             this.javaClassFactoryMethodName = super.getJavaFactoryMethodName();
  349.         }

  350.         return this.javaClassFactoryMethodName;
  351.     }

  352.     /**
  353.      * Gets the Java method to use for creating objects of the instance.
  354.      * <p>
  355.      * This method queries an internal cache for a result object to return for the given argument values. If no
  356.      * cached result object is available, this method queries the super-class for a result object to return and caches
  357.      * the outcome of that query for use on successive calls.
  358.      * </p>
  359.      * <p>
  360.      * <b>Note:</b><br/>Method {@code RuntimeModelObjects.clear()} must be used to synchronize the state of the
  361.      * internal cache with the state of the instance and class loader, should the state of the instance or class loader
  362.      * change.
  363.      * </p>
  364.      *
  365.      * @param classLoader The class loader to get the Java class from or {@code null}, to get the Java class from the
  366.      * platform's bootstrap class loader.
  367.      *
  368.      * @return The public Java method of the Java class of the instance to use for creating objects of the instance or
  369.      * {@code null}, if that class does not declare such a method.
  370.      *
  371.      * @throws ClassNotFoundException if the Java class is not found.
  372.      * @throws ModelObjectException if parsing the name of the type referenced by the instance fails.
  373.      *
  374.      * @see #getJavaClass(java.lang.ClassLoader)
  375.      * @see #getJavaFactoryMethodName()
  376.      * @see RuntimeModelObjects#clear()
  377.      */
  378.     @Override
  379.     public Method getJavaFactoryMethod( final ClassLoader classLoader )
  380.         throws ModelObjectException, ClassNotFoundException
  381.     {
  382.         ClassLoader classLoaderKey = classLoader;
  383.         if ( classLoaderKey == null )
  384.         {
  385.             classLoaderKey = BOOTSTRAP_CLASSLOADER_KEY;
  386.         }

  387.         synchronized ( methodsByClassLoaderAndInstanceCache )
  388.         {
  389.             Method javaClassFactoryMethod = null;
  390.             Map<String, Reference<Method>> map = methodsByClassLoaderAndInstanceCache.get( classLoaderKey );

  391.             if ( map == null )
  392.             {
  393.                 map = createMap();
  394.                 methodsByClassLoaderAndInstanceCache.put( classLoaderKey, map );
  395.             }

  396.             final Reference<Method> reference = map.get( this.getIdentifier() );

  397.             if ( reference != null )
  398.             {
  399.                 javaClassFactoryMethod = reference.get();
  400.             }

  401.             if ( javaClassFactoryMethod == null && ( reference != null || !map.containsKey( this.getIdentifier() ) ) )
  402.             {
  403.                 javaClassFactoryMethod = super.getJavaFactoryMethod( classLoader );
  404.                 map.put( this.getIdentifier(), new WeakReference<Method>( javaClassFactoryMethod ) );
  405.             }

  406.             return javaClassFactoryMethod;
  407.         }
  408.     }

  409.     /**
  410.      * Gets a flag indicating the Java class of the instance is assignable to all Java classes of all specifications of
  411.      * the instance.
  412.      * <p>
  413.      * This method queries an internal cache for a result object to return for the given argument values. If no
  414.      * cached result object is available, this method queries the super-class for a result object to return and caches
  415.      * the outcome of that query for use on successive calls.
  416.      * </p>
  417.      * <p>
  418.      * <b>Note:</b><br/>Method {@code RuntimeModelObjects.clear()} must be used to synchronize the state of the
  419.      * internal cache with the state of the instance and class loader, should the state of the instance or class loader
  420.      * change.
  421.      * </p>
  422.      *
  423.      * @param classLoader The class loader to get the Java classes from or {@code null}, to get the Java classes from
  424.      * the platform's bootstrap class loader.
  425.      *
  426.      * @return {@code true}, if the Java class of the instance is assignable to all Java classes of all specifications
  427.      * of the instance; {@code false}, if the Java class of the instance is not assignable to all Java classes of all
  428.      * specifications of the instance.
  429.      *
  430.      * @throws ClassNotFoundException if a Java class is not found.
  431.      * @throws ModelObjectException if parsing a name of a referenced type fails.
  432.      *
  433.      * @see #getJavaClass(java.lang.ClassLoader)
  434.      * @see #getJavaClasses(java.lang.ClassLoader)
  435.      * @see RuntimeModelObjects#clear()
  436.      */
  437.     @Override
  438.     public boolean isJavaClassAssignable( final ClassLoader classLoader )
  439.         throws ModelObjectException, ClassNotFoundException
  440.     {
  441.         ClassLoader classLoaderKey = classLoader;
  442.         if ( classLoaderKey == null )
  443.         {
  444.             classLoaderKey = BOOTSTRAP_CLASSLOADER_KEY;
  445.         }

  446.         synchronized ( assignableFlagsByClassLoaderAndInstanceCache )
  447.         {
  448.             Map<String, Boolean> map = assignableFlagsByClassLoaderAndInstanceCache.get( classLoaderKey );

  449.             if ( map == null )
  450.             {
  451.                 map = createMap();
  452.                 assignableFlagsByClassLoaderAndInstanceCache.put( classLoaderKey, map );
  453.             }

  454.             Boolean javaClassAssignable = map.get( this.getIdentifier() );

  455.             if ( javaClassAssignable == null && !map.containsKey( this.getIdentifier() ) )
  456.             {
  457.                 javaClassAssignable = super.isJavaClassAssignable( classLoader );
  458.                 map.put( this.getIdentifier(), javaClassAssignable );
  459.             }

  460.             return javaClassAssignable == null ? false : javaClassAssignable;
  461.         }
  462.     }

  463.     /**
  464.      * Gets the Java proxy class for a given class loader.
  465.      * <p>
  466.      * This method queries an internal cache for a result object to return for the given argument values. If no
  467.      * cached result object is available, this method queries the super-class for a result object to return and caches
  468.      * the outcome of that query for use on successive calls.
  469.      * </p>
  470.      * <p>
  471.      * <b>Note:</b><br/>Method {@code RuntimeModelObjects.clear()} must be used to synchronize the state of the
  472.      * internal cache with the state of the instance and class loader, should the state of the instance or class loader
  473.      * change.
  474.      * </p>
  475.      *
  476.      * @param classLoader The class loader to get the Java proxy class for.
  477.      *
  478.      * @return The Java proxy class for {@code classLoader} or {@code null}, if the instance does not support a Java
  479.      * proxy class.
  480.      *
  481.      * @throws ClassNotFoundException if a Java class is not found.
  482.      * @throws ModelObjectException if parsing a name of a referenced type fails.
  483.      *
  484.      * @see #getJavaClasses(java.lang.ClassLoader)
  485.      * @see RuntimeModelObjects#clear()
  486.      */
  487.     @Override
  488.     public Class<?> getJavaProxyClass( final ClassLoader classLoader )
  489.         throws ModelObjectException, ClassNotFoundException
  490.     {
  491.         ClassLoader classLoaderKey = classLoader;
  492.         if ( classLoaderKey == null )
  493.         {
  494.             classLoaderKey = BOOTSTRAP_CLASSLOADER_KEY;
  495.         }

  496.         synchronized ( proxyClassesByClassLoaderAndInstanceCache )
  497.         {
  498.             Class<?> javaProxyClass = null;
  499.             Map<String, Reference<Class<?>>> map = proxyClassesByClassLoaderAndInstanceCache.get( classLoaderKey );

  500.             if ( map == null )
  501.             {
  502.                 map = createMap();
  503.                 proxyClassesByClassLoaderAndInstanceCache.put( classLoaderKey, map );
  504.             }

  505.             final Reference<Class<?>> reference = map.get( this.getIdentifier() );

  506.             if ( reference != null )
  507.             {
  508.                 javaProxyClass = reference.get();
  509.             }

  510.             if ( javaProxyClass == null && ( reference != null || !map.containsKey( this.getIdentifier() ) ) )
  511.             {
  512.                 javaProxyClass = super.getJavaProxyClass( classLoader );
  513.                 map.put( this.getIdentifier(), new WeakReference<Class<?>>( javaProxyClass ) );
  514.             }

  515.             return javaProxyClass;
  516.         }
  517.     }

  518.     /**
  519.      * Gets the Java type name of the type referenced by the instance.
  520.      * <p>
  521.      * This method queries an internal cache for a result object to return. If no cached result object is available,
  522.      * this method queries the super-class for a result object to return and caches the outcome of that query for use on
  523.      * successive calls.
  524.      * </p>
  525.      * <p>
  526.      * <b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
  527.      * state of the instance, should the state of the instance change.
  528.      * </p>
  529.      *
  530.      * @return The Java type name of the type referenced by the instance or {@code null}, if the instance does not
  531.      * reference a type.
  532.      *
  533.      * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails.
  534.      *
  535.      * @since 1.4
  536.      *
  537.      * @see Instance#getJavaTypeName()
  538.      * @see #clear()
  539.      */
  540.     @Override
  541.     public JavaTypeName getJavaTypeName() throws ModelObjectException
  542.     {
  543.         if ( this.javaTypeName == null )
  544.         {
  545.             this.javaTypeName = super.getJavaTypeName();
  546.         }

  547.         return this.javaTypeName;
  548.     }

  549.     // SECTION-END
  550.     // SECTION-START[RuntimeModelObject]
  551.     public void gc()
  552.     {
  553.         this.gcOrClear( true, false );
  554.     }

  555.     public void clear()
  556.     {
  557.         this.javaClassFactoryMethodName = null;
  558.         this.javaTypeName = null;
  559.         this.gcOrClear( false, true );
  560.     }

  561.     private void gcOrClear( final boolean gc, final boolean clear )
  562.     {
  563.         if ( this.getAuthors() instanceof RuntimeModelObject )
  564.         {
  565.             if ( gc )
  566.             {
  567.                 ( (RuntimeModelObject) this.getAuthors() ).gc();
  568.             }
  569.             if ( clear )
  570.             {
  571.                 ( (RuntimeModelObject) this.getAuthors() ).clear();
  572.             }
  573.         }
  574.         if ( this.getDependencies() instanceof RuntimeModelObject )
  575.         {
  576.             if ( gc )
  577.             {
  578.                 ( (RuntimeModelObject) this.getDependencies() ).gc();
  579.             }
  580.             if ( clear )
  581.             {
  582.                 ( (RuntimeModelObject) this.getDependencies() ).clear();
  583.             }
  584.         }
  585.         if ( this.getDocumentation() instanceof RuntimeModelObject )
  586.         {
  587.             if ( gc )
  588.             {
  589.                 ( (RuntimeModelObject) this.getDocumentation() ).gc();
  590.             }
  591.             if ( clear )
  592.             {
  593.                 ( (RuntimeModelObject) this.getDocumentation() ).clear();
  594.             }
  595.         }
  596.         if ( this.getMessages() instanceof RuntimeModelObject )
  597.         {
  598.             if ( gc )
  599.             {
  600.                 ( (RuntimeModelObject) this.getMessages() ).gc();
  601.             }
  602.             if ( clear )
  603.             {
  604.                 ( (RuntimeModelObject) this.getMessages() ).clear();
  605.             }
  606.         }
  607.         if ( this.getProperties() instanceof RuntimeModelObject )
  608.         {
  609.             if ( gc )
  610.             {
  611.                 ( (RuntimeModelObject) this.getProperties() ).gc();
  612.             }
  613.             if ( clear )
  614.             {
  615.                 ( (RuntimeModelObject) this.getProperties() ).clear();
  616.             }
  617.         }
  618.         if ( this.getSpecifications() instanceof RuntimeModelObject )
  619.         {
  620.             if ( gc )
  621.             {
  622.                 ( (RuntimeModelObject) this.getSpecifications() ).gc();
  623.             }
  624.             if ( clear )
  625.             {
  626.                 ( (RuntimeModelObject) this.getSpecifications() ).clear();
  627.             }
  628.         }
  629.     }

  630.     // SECTION-END
  631.     // SECTION-START[Constructors]
  632.     // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
  633.     /** Creates a new {@code RuntimeInstance} instance. */
  634.     @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.9", comments = "See http://www.jomc.org/jomc/1.9/jomc-tools-1.9" )
  635.     public RuntimeInstance()
  636.     {
  637.         // SECTION-START[Default Constructor]
  638.         super();
  639.         // SECTION-END
  640.     }
  641.     // </editor-fold>
  642.     // SECTION-END
  643.     // SECTION-START[Dependencies]
  644.     // SECTION-END
  645.     // SECTION-START[Properties]
  646.     // SECTION-END
  647.     // SECTION-START[Messages]
  648.     // SECTION-END

  649. }