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