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 <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: RuntimeSpecification.java 5061 2015-05-31 13:20:40Z 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.9", comments = "See http://www.jomc.org/jomc/1.9/jomc-tools-1.9" )
72  // </editor-fold>
73  // SECTION-END
74  public class RuntimeSpecification extends Specification implements RuntimeModelObject
75  {
76      // SECTION-START[RuntimeSpecification]
77  
78      /**
79       * Java type name.
80       */
81      @XmlTransient
82      private volatile JavaTypeName javaTypeName;
83  
84      /**
85       * Creates a new {@code RuntimeSpecification} instance by deeply copying a given {@code Specification} instance.
86       *
87       * @param specification The instance to copy.
88       *
89       * @throws NullPointerException if {@code specification} is {@code null}.
90       */
91      public RuntimeSpecification( final Specification specification )
92      {
93          super( specification );
94  
95          if ( this.getAuthors() != null )
96          {
97              this.setAuthors( RuntimeModelObjects.getInstance().copyOf( this.getAuthors() ) );
98          }
99          if ( this.getDocumentation() != null )
100         {
101             this.setDocumentation( RuntimeModelObjects.getInstance().copyOf( this.getDocumentation() ) );
102         }
103         if ( this.getProperties() != null )
104         {
105             this.setProperties( RuntimeModelObjects.getInstance().copyOf( this.getProperties() ) );
106         }
107     }
108 
109     /**
110      * Gets the Java class of the specification for a given class loader.
111      * <p>
112      * This method queries an internal cache for a result object to return for the given argument values. If no
113      * cached result object is available, this method queries the super-class for a result object to return and caches
114      * the outcome of that query for use on successive calls.
115      * </p>
116      * <p>
117      * <b>Note:</b><br/>Method {@code RuntimeModelObjects.clear()} must be used to synchronize the state of the
118      * internal cache with the state of the class loader, should the state of the class loader change.
119      * </p>
120      *
121      * @param classLoader The class loader to get the Java class from or {@code null}, to get the Java class from the
122      * platform's bootstrap class loader.
123      *
124      * @return The Java class of the specification or {@code null}, if the specification does not declare a class.
125      *
126      * @throws ClassNotFoundException if the Java class is not found.
127      * @throws ModelObjectException if parsing the name of the referenced type fails.
128      *
129      * @see #getClazz()
130      * @see RuntimeModelObjects#clear()
131      */
132     @Override
133     public Class<?> getJavaClass( final ClassLoader classLoader )
134         throws ModelObjectException, ClassNotFoundException
135     {
136         Class<?> javaClass = null;
137 
138         if ( this.getJavaTypeName() != null )
139         {
140             synchronized ( classesByClassLoaderAndNameCache )
141             {
142                 ClassLoader classLoaderKey = classLoader;
143                 if ( classLoaderKey == null )
144                 {
145                     classLoaderKey = BOOTSTRAP_CLASSLOADER_KEY;
146                 }
147 
148                 Map<String, Reference<Class<?>>> map = classesByClassLoaderAndNameCache.get( classLoaderKey );
149 
150                 if ( map == null )
151                 {
152                     map = createMap();
153                     classesByClassLoaderAndNameCache.put( classLoaderKey, map );
154                 }
155 
156                 final Reference<Class<?>> reference = map.get( this.getJavaTypeName().getClassName() );
157 
158                 if ( reference != null )
159                 {
160                     javaClass = reference.get();
161                 }
162 
163                 if ( javaClass == null )
164                 {
165                     javaClass = super.getJavaClass( classLoader );
166                     map.put( this.getJavaTypeName().getClassName(), new WeakReference<Class<?>>( javaClass ) );
167                 }
168             }
169         }
170 
171         return javaClass;
172     }
173 
174     /**
175      * Gets the Java type name of the type referenced by the specification.
176      * <p>
177      * This method queries an internal cache for a result object to return. If no cached result object is available,
178      * this method queries the super-class for a result object to return and caches the outcome of that query for use on
179      * successive calls.
180      * </p>
181      * <p>
182      * <b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
183      * state of the instance, should the state of the instance change.
184      * </p>
185      *
186      * @return The Java type name of the type referenced by the specification or {@code null}, if the specification does
187      * not reference a type.
188      *
189      * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails.
190      *
191      * @since 1.4
192      *
193      * @see #getJavaTypeName()
194      * @see #clear()
195      */
196     @Override
197     public JavaTypeName getJavaTypeName() throws ModelObjectException
198     {
199         if ( this.javaTypeName == null )
200         {
201             this.javaTypeName = super.getJavaTypeName();
202         }
203 
204         return this.javaTypeName;
205     }
206 
207     // SECTION-END
208     // SECTION-START[RuntimeModelObject]
209     public void gc()
210     {
211         this.gcOrClear( true, false );
212     }
213 
214     public void clear()
215     {
216         this.javaTypeName = null;
217         this.gcOrClear( false, true );
218     }
219 
220     private void gcOrClear( final boolean gc, final boolean clear )
221     {
222         if ( this.getAuthors() instanceof RuntimeModelObject )
223         {
224             if ( gc )
225             {
226                 ( (RuntimeModelObject) this.getAuthors() ).gc();
227             }
228             if ( clear )
229             {
230                 ( (RuntimeModelObject) this.getAuthors() ).clear();
231             }
232         }
233         if ( this.getDocumentation() instanceof RuntimeModelObject )
234         {
235             if ( gc )
236             {
237                 ( (RuntimeModelObject) this.getDocumentation() ).gc();
238             }
239             if ( clear )
240             {
241                 ( (RuntimeModelObject) this.getDocumentation() ).clear();
242             }
243         }
244         if ( this.getProperties() instanceof RuntimeModelObject )
245         {
246             if ( gc )
247             {
248                 ( (RuntimeModelObject) this.getProperties() ).gc();
249             }
250             if ( clear )
251             {
252                 ( (RuntimeModelObject) this.getProperties() ).clear();
253             }
254         }
255     }
256 
257     // SECTION-END
258     // SECTION-START[Constructors]
259     // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
260     /** Creates a new {@code RuntimeSpecification} instance. */
261     @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.9", comments = "See http://www.jomc.org/jomc/1.9/jomc-tools-1.9" )
262     public RuntimeSpecification()
263     {
264         // SECTION-START[Default Constructor]
265         super();
266         // SECTION-END
267     }
268     // </editor-fold>
269     // SECTION-END
270     // SECTION-START[Dependencies]
271     // SECTION-END
272     // SECTION-START[Properties]
273     // SECTION-END
274     // SECTION-START[Messages]
275     // SECTION-END
276 
277 }