View Javadoc

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, 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: RuntimeSpecification.java 4881 2014-02-20 22:55:53Z schulte $
32   *
33   */
34  // </editor-fold>
35  // SECTION-END
36  package org.jomc.ri.model;
37  
38  import java.lang.ref.Reference;
39  import java.lang.ref.WeakReference;
40  import java.util.Map;
41  import javax.xml.bind.annotation.XmlTransient;
42  import org.jomc.model.JavaTypeName;
43  import org.jomc.model.ModelObjectException;
44  import org.jomc.model.Specification;
45  import static org.jomc.ri.model.RuntimeModelObjects.BOOTSTRAP_CLASSLOADER_KEY;
46  import static org.jomc.ri.model.RuntimeModelObjects.classesByClassLoaderAndNameCache;
47  import static org.jomc.ri.model.RuntimeModelObjects.createMap;
48  
49  // SECTION-START[Documentation]
50  // <editor-fold defaultstate="collapsed" desc=" Generated Documentation ">
51  /**
52   * Runtime {@code Specification}.
53   *
54   * <dl>
55   *   <dt><b>Identifier:</b></dt><dd>org.jomc.ri.model.RuntimeSpecification</dd>
56   *   <dt><b>Name:</b></dt><dd>JOMC ⁑ RI ⁑ RuntimeSpecification</dd>
57   *   <dt><b>Specifications:</b></dt>
58   *     <dd>org.jomc.ri.model.RuntimeModelObject @ 1.2</dd>
59   *   <dt><b>Abstract:</b></dt><dd>No</dd>
60   *   <dt><b>Final:</b></dt><dd>No</dd>
61   *   <dt><b>Stateless:</b></dt><dd>No</dd>
62   * </dl>
63   *
64   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 1.2
65   * @version 1.2
66   */
67  // </editor-fold>
68  // SECTION-END
69  // SECTION-START[Annotations]
70  // <editor-fold defaultstate="collapsed" desc=" Generated Annotations ">
71  @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.6", comments = "See http://www.jomc.org/jomc/1.6/jomc-tools-1.6" )
72  // </editor-fold>
73  // SECTION-END
74  public class RuntimeSpecification extends Specification implements RuntimeModelObject
75  {
76      // SECTION-START[RuntimeSpecification]
77  
78      /** Java type name. */
79      @XmlTransient
80      private volatile JavaTypeName javaTypeName;
81  
82      /**
83       * Creates a new {@code RuntimeSpecification} instance by deeply copying a given {@code Specification} instance.
84       *
85       * @param specification The instance to copy.
86       *
87       * @throws NullPointerException if {@code specification} is {@code null}.
88       */
89      public RuntimeSpecification( final Specification specification )
90      {
91          super( specification );
92  
93          if ( this.getAuthors() != null )
94          {
95              this.setAuthors( RuntimeModelObjects.getInstance().copyOf( this.getAuthors() ) );
96          }
97          if ( this.getDocumentation() != null )
98          {
99              this.setDocumentation( RuntimeModelObjects.getInstance().copyOf( this.getDocumentation() ) );
100         }
101         if ( this.getProperties() != null )
102         {
103             this.setProperties( RuntimeModelObjects.getInstance().copyOf( this.getProperties() ) );
104         }
105     }
106 
107     /**
108      * Gets the Java class of the specification for a given class loader.
109      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
110      * cached result object is available, this method queries the super-class for a result object to return and caches
111      * the outcome of that query for use on successive calls.</p>
112      * <p><b>Note:</b><br/>Method {@code RuntimeModelObjects.clear()} must be used to synchronize the state of the
113      * internal cache with the state of the class loader, should the state of the class loader change.</p>
114      *
115      * @param classLoader The class loader to get the Java class from or {@code null}, to get the Java class from the
116      * platform's bootstrap class loader.
117      *
118      * @return The Java class of the specification or {@code null}, if the specification does not declare a class.
119      *
120      * @throws ClassNotFoundException if the Java class is not found.
121      * @throws ModelObjectException if parsing the name of the referenced type fails.
122      *
123      * @see #getClazz()
124      * @see RuntimeModelObjects#clear()
125      */
126     @Override
127     public Class<?> getJavaClass( final ClassLoader classLoader )
128         throws ModelObjectException, ClassNotFoundException
129     {
130         Class<?> javaClass = null;
131 
132         if ( this.getJavaTypeName() != null )
133         {
134             synchronized ( classesByClassLoaderAndNameCache )
135             {
136                 ClassLoader classLoaderKey = classLoader;
137                 if ( classLoaderKey == null )
138                 {
139                     classLoaderKey = BOOTSTRAP_CLASSLOADER_KEY;
140                 }
141 
142                 Map<String, Reference<Class<?>>> map = classesByClassLoaderAndNameCache.get( classLoaderKey );
143 
144                 if ( map == null )
145                 {
146                     map = createMap();
147                     classesByClassLoaderAndNameCache.put( classLoaderKey, map );
148                 }
149 
150                 final Reference<Class<?>> reference = map.get( this.getJavaTypeName().getClassName() );
151 
152                 if ( reference != null )
153                 {
154                     javaClass = reference.get();
155                 }
156 
157                 if ( javaClass == null )
158                 {
159                     javaClass = super.getJavaClass( classLoader );
160                     map.put( this.getJavaTypeName().getClassName(), new WeakReference<Class<?>>( javaClass ) );
161                 }
162             }
163         }
164 
165         return javaClass;
166     }
167 
168     /**
169      * Gets the Java type name of the type referenced by the specification.
170      * <p>This method queries an internal cache for a result object to return. If no cached result object is available,
171      * this method queries the super-class for a result object to return and caches the outcome of that query for use on
172      * successive calls.</p>
173      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
174      * state of the instance, should the state of the instance change.</p>
175      *
176      * @return The Java type name of the type referenced by the specification or {@code null}, if the specification does
177      * not reference a type.
178      *
179      * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails.
180      *
181      * @since 1.4
182      *
183      * @see #getJavaTypeName()
184      * @see #clear()
185      */
186     @Override
187     public JavaTypeName getJavaTypeName() throws ModelObjectException
188     {
189         if ( this.javaTypeName == null )
190         {
191             this.javaTypeName = super.getJavaTypeName();
192         }
193 
194         return this.javaTypeName;
195     }
196 
197     // SECTION-END
198     // SECTION-START[RuntimeModelObject]
199     public void gc()
200     {
201         this.gcOrClear( true, false );
202     }
203 
204     public void clear()
205     {
206         this.javaTypeName = null;
207         this.gcOrClear( false, true );
208     }
209 
210     private void gcOrClear( final boolean gc, final boolean clear )
211     {
212         if ( this.getAuthors() instanceof RuntimeModelObject )
213         {
214             if ( gc )
215             {
216                 ( (RuntimeModelObject) this.getAuthors() ).gc();
217             }
218             if ( clear )
219             {
220                 ( (RuntimeModelObject) this.getAuthors() ).clear();
221             }
222         }
223         if ( this.getDocumentation() instanceof RuntimeModelObject )
224         {
225             if ( gc )
226             {
227                 ( (RuntimeModelObject) this.getDocumentation() ).gc();
228             }
229             if ( clear )
230             {
231                 ( (RuntimeModelObject) this.getDocumentation() ).clear();
232             }
233         }
234         if ( this.getProperties() instanceof RuntimeModelObject )
235         {
236             if ( gc )
237             {
238                 ( (RuntimeModelObject) this.getProperties() ).gc();
239             }
240             if ( clear )
241             {
242                 ( (RuntimeModelObject) this.getProperties() ).clear();
243             }
244         }
245     }
246 
247     // SECTION-END
248     // SECTION-START[Constructors]
249     // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
250     /** Creates a new {@code RuntimeSpecification} instance. */
251     @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.6", comments = "See http://www.jomc.org/jomc/1.6/jomc-tools-1.6" )
252     public RuntimeSpecification()
253     {
254         // SECTION-START[Default Constructor]
255         super();
256         // SECTION-END
257     }
258     // </editor-fold>
259     // SECTION-END
260     // SECTION-START[Dependencies]
261     // SECTION-END
262     // SECTION-START[Properties]
263     // SECTION-END
264     // SECTION-START[Messages]
265     // SECTION-END
266 }