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: RuntimeImplementation.java 4795 2013-04-21 09:09:02Z 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.net.URI;
41  import java.util.Map;
42  import javax.xml.bind.annotation.XmlTransient;
43  import org.jomc.model.Implementation;
44  import org.jomc.model.JavaTypeName;
45  import org.jomc.model.ModelObjectException;
46  import static org.jomc.ri.model.RuntimeModelObjects.BOOTSTRAP_CLASSLOADER_KEY;
47  import static org.jomc.ri.model.RuntimeModelObjects.classesByClassLoaderAndNameCache;
48  import static org.jomc.ri.model.RuntimeModelObjects.createMap;
49  
50  // SECTION-START[Documentation]
51  // <editor-fold defaultstate="collapsed" desc=" Generated Documentation ">
52  /**
53   * Runtime {@code Implementation}.
54   *
55   * <dl>
56   *   <dt><b>Identifier:</b></dt><dd>org.jomc.ri.model.RuntimeImplementation</dd>
57   *   <dt><b>Name:</b></dt><dd>JOMC ⁑ RI ⁑ RuntimeImplementation</dd>
58   *   <dt><b>Specifications:</b></dt>
59   *     <dd>org.jomc.ri.model.RuntimeModelObject @ 1.2</dd>
60   *   <dt><b>Abstract:</b></dt><dd>No</dd>
61   *   <dt><b>Final:</b></dt><dd>No</dd>
62   *   <dt><b>Stateless:</b></dt><dd>No</dd>
63   * </dl>
64   *
65   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 1.2
66   * @version 1.2
67   */
68  // </editor-fold>
69  // SECTION-END
70  // SECTION-START[Annotations]
71  // <editor-fold defaultstate="collapsed" desc=" Generated Annotations ">
72  @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.5", comments = "See http://www.jomc.org/jomc/1.5/jomc-tools-1.5" )
73  // </editor-fold>
74  // SECTION-END
75  public class RuntimeImplementation extends Implementation implements RuntimeModelObject
76  {
77      // SECTION-START[RuntimeImplementation]
78  
79      /** Cached location URI. */
80      private volatile URI locationUri;
81  
82      /** Java type name. */
83      @XmlTransient
84      private volatile JavaTypeName javaTypeName;
85  
86      /**
87       * Creates a new {@code RuntimeImplementation} instance by deeply copying a given {@code Implementation} instance.
88       *
89       * @param implementation The instance to copy.
90       *
91       * @throws NullPointerException if {@code implementation} is {@code null}.
92       */
93      public RuntimeImplementation( final Implementation implementation )
94      {
95          super( implementation );
96  
97          if ( this.getAuthors() != null )
98          {
99              this.setAuthors( RuntimeModelObjects.getInstance().copyOf( this.getAuthors() ) );
100         }
101         if ( this.getDependencies() != null )
102         {
103             this.setDependencies( RuntimeModelObjects.getInstance().copyOf( this.getDependencies() ) );
104         }
105         if ( this.getDocumentation() != null )
106         {
107             this.setDocumentation( RuntimeModelObjects.getInstance().copyOf( this.getDocumentation() ) );
108         }
109         if ( this.getImplementations() != null )
110         {
111             this.setImplementations( RuntimeModelObjects.getInstance().copyOf( this.getImplementations() ) );
112         }
113         if ( this.getMessages() != null )
114         {
115             this.setMessages( RuntimeModelObjects.getInstance().copyOf( this.getMessages() ) );
116         }
117         if ( this.getProperties() != null )
118         {
119             this.setProperties( RuntimeModelObjects.getInstance().copyOf( this.getProperties() ) );
120         }
121         if ( this.getSpecifications() != null )
122         {
123             this.setSpecifications( RuntimeModelObjects.getInstance().copyOf( this.getSpecifications() ) );
124         }
125     }
126 
127     /**
128      * Gets the location URI used for locating instances of this implementation.
129      * <p>This method queries an internal cache for a result object to return. If no cached result object is available,
130      * this method queries the super-class for a result object to return and caches the outcome of that query for use on
131      * successive calls.</p>
132      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
133      * state of the instance, should the state of the instance change.</p>
134      *
135      * @return The location URI used for locating instances of this implementation or {@code null}, if instances of this
136      * implementation do not need to be located.
137      *
138      * @throws ModelObjectException if parsing the location to an {@code URI} object fails.
139      *
140      * @see #getLocation()
141      * @see #clear()
142      */
143     @Override
144     public URI getLocationUri() throws ModelObjectException
145     {
146         if ( this.locationUri == null )
147         {
148             this.locationUri = super.getLocationUri();
149         }
150 
151         return this.locationUri;
152     }
153 
154     /**
155      * Gets the Java class of the implementation for a given class loader.
156      * <p>This method queries an internal cache for a result object to return for the given argument values. If no
157      * cached result object is available, this method queries the super-class for a result object to return and caches
158      * the outcome of that query for use on successive calls.</p>
159      * <p><b>Note:</b><br/>Method {@code RuntimeModelObjects.clear()} must be used to synchronize the state of the
160      * internal cache with the state of the class loader, should the state of the class loader change.</p>
161      *
162      * @param classLoader The class loader to get the Java class from or {@code null}, to get the Java class from the
163      * platform's bootstrap class loader.
164      *
165      * @return The Java class of the implementation or {@code null}, if the implementation does not declare a class.
166      *
167      * @throws ClassNotFoundException if the Java class is not found.
168      * @throws ModelObjectException if parsing the name of the referenced type fails.
169      *
170      * @see #getClazz()
171      * @see RuntimeModelObjects#clear()
172      */
173     @Override
174     public Class<?> getJavaClass( final ClassLoader classLoader )
175         throws ModelObjectException, ClassNotFoundException
176     {
177         Class<?> javaClass = null;
178 
179         if ( this.getJavaTypeName() != null )
180         {
181             ClassLoader classLoaderKey = classLoader;
182             if ( classLoaderKey == null )
183             {
184                 classLoaderKey = BOOTSTRAP_CLASSLOADER_KEY;
185             }
186 
187             synchronized ( classesByClassLoaderAndNameCache )
188             {
189                 Map<String, Reference<Class<?>>> map = classesByClassLoaderAndNameCache.get( classLoaderKey );
190 
191                 if ( map == null )
192                 {
193                     map = createMap();
194                     classesByClassLoaderAndNameCache.put( classLoaderKey, map );
195                 }
196 
197                 final Reference<Class<?>> reference = map.get( this.getJavaTypeName().getClassName() );
198 
199                 if ( reference != null )
200                 {
201                     javaClass = reference.get();
202                 }
203 
204                 if ( javaClass == null )
205                 {
206                     javaClass = super.getJavaClass( classLoader );
207                     map.put( this.getJavaTypeName().getClassName(), new WeakReference<Class<?>>( javaClass ) );
208                 }
209             }
210         }
211 
212         return javaClass;
213     }
214 
215     /**
216      * Gets the Java type name of the type referenced by the implementation.
217      * <p>This method queries an internal cache for a result object to return. If no cached result object is available,
218      * this method queries the super-class for a result object to return and caches the outcome of that query for use on
219      * successive calls.</p>
220      * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
221      * state of the instance, should the state of the instance change.</p>
222      *
223      * @return The Java type name of the type referenced by the implementation or {@code null}, if the implementation
224      * does not reference a type.
225      *
226      * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails.
227      *
228      * @since 1.4
229      *
230      * @see #getJavaTypeName()
231      * @see #clear()
232      */
233     @Override
234     public JavaTypeName getJavaTypeName() throws ModelObjectException
235     {
236         if ( this.javaTypeName == null )
237         {
238             this.javaTypeName = super.getJavaTypeName();
239         }
240 
241         return this.javaTypeName;
242     }
243 
244     // SECTION-END
245     // SECTION-START[RuntimeModelObject]
246     public void gc()
247     {
248         this.gcOrClear( true, false );
249     }
250 
251     public void clear()
252     {
253         this.locationUri = null;
254         this.javaTypeName = null;
255         this.gcOrClear( false, true );
256     }
257 
258     private void gcOrClear( final boolean gc, final boolean clear )
259     {
260         if ( this.getAuthors() instanceof RuntimeModelObject )
261         {
262             if ( gc )
263             {
264                 ( (RuntimeModelObject) this.getAuthors() ).gc();
265             }
266             if ( clear )
267             {
268                 ( (RuntimeModelObject) this.getAuthors() ).clear();
269             }
270         }
271         if ( this.getDependencies() instanceof RuntimeModelObject )
272         {
273             if ( gc )
274             {
275                 ( (RuntimeModelObject) this.getDependencies() ).gc();
276             }
277             if ( clear )
278             {
279                 ( (RuntimeModelObject) this.getDependencies() ).clear();
280             }
281         }
282         if ( this.getDocumentation() instanceof RuntimeModelObject )
283         {
284             if ( gc )
285             {
286                 ( (RuntimeModelObject) this.getDocumentation() ).gc();
287             }
288             if ( clear )
289             {
290                 ( (RuntimeModelObject) this.getDocumentation() ).clear();
291             }
292         }
293         if ( this.getImplementations() instanceof RuntimeModelObject )
294         {
295             if ( gc )
296             {
297                 ( (RuntimeModelObject) this.getImplementations() ).gc();
298             }
299             if ( clear )
300             {
301                 ( (RuntimeModelObject) this.getImplementations() ).clear();
302             }
303         }
304         if ( this.getMessages() instanceof RuntimeModelObject )
305         {
306             if ( gc )
307             {
308                 ( (RuntimeModelObject) this.getMessages() ).gc();
309             }
310             if ( clear )
311             {
312                 ( (RuntimeModelObject) this.getMessages() ).clear();
313             }
314         }
315         if ( this.getProperties() instanceof RuntimeModelObject )
316         {
317             if ( gc )
318             {
319                 ( (RuntimeModelObject) this.getProperties() ).gc();
320             }
321             if ( clear )
322             {
323                 ( (RuntimeModelObject) this.getProperties() ).clear();
324             }
325         }
326         if ( this.getSpecifications() instanceof RuntimeModelObject )
327         {
328             if ( gc )
329             {
330                 ( (RuntimeModelObject) this.getSpecifications() ).gc();
331             }
332             if ( clear )
333             {
334                 ( (RuntimeModelObject) this.getSpecifications() ).clear();
335             }
336         }
337     }
338 
339     // SECTION-END
340     // SECTION-START[Constructors]
341     // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
342     /** Creates a new {@code RuntimeImplementation} instance. */
343     @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.5", comments = "See http://www.jomc.org/jomc/1.5/jomc-tools-1.5" )
344     public RuntimeImplementation()
345     {
346         // SECTION-START[Default Constructor]
347         super();
348         // SECTION-END
349     }
350     // </editor-fold>
351     // SECTION-END
352     // SECTION-START[Dependencies]
353     // SECTION-END
354     // SECTION-START[Properties]
355     // SECTION-END
356     // SECTION-START[Messages]
357     // SECTION-END
358 }