001// SECTION-START[License Header]
002// <editor-fold defaultstate="collapsed" desc=" Generated License ">
003/*
004 *   Java Object Management and Configuration
005 *   Copyright (C) Christian Schulte, 2011-313
006 *   All rights reserved.
007 *
008 *   Redistribution and use in source and binary forms, with or without
009 *   modification, are permitted provided that the following conditions
010 *   are met:
011 *
012 *     o Redistributions of source code must retain the above copyright
013 *       notice, this list of conditions and the following disclaimer.
014 *
015 *     o Redistributions in binary form must reproduce the above copyright
016 *       notice, this list of conditions and the following disclaimer in
017 *       the documentation and/or other materials provided with the
018 *       distribution.
019 *
020 *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
021 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
022 *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
023 *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
024 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
025 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
026 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
027 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
028 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
029 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
030 *
031 *   $JOMC: RuntimeImplementation.java 4588 2012-06-03 06:01:30Z schulte2005 $
032 *
033 */
034// </editor-fold>
035// SECTION-END
036package org.jomc.ri.model;
037
038import java.lang.ref.Reference;
039import java.lang.ref.WeakReference;
040import java.net.URI;
041import java.util.Map;
042import org.jomc.model.Implementation;
043import static org.jomc.ri.model.RuntimeModelObjects.BOOTSTRAP_CLASSLOADER_KEY;
044import static org.jomc.ri.model.RuntimeModelObjects.classesByClassLoaderAndNameCache;
045import static org.jomc.ri.model.RuntimeModelObjects.createMap;
046
047// SECTION-START[Documentation]
048// <editor-fold defaultstate="collapsed" desc=" Generated Documentation ">
049/**
050 * Runtime {@code Implementation}.
051 *
052 * <dl>
053 *   <dt><b>Identifier:</b></dt><dd>org.jomc.ri.model.RuntimeImplementation</dd>
054 *   <dt><b>Name:</b></dt><dd>JOMC RI RuntimeImplementation</dd>
055 *   <dt><b>Specifications:</b></dt>
056 *     <dd>org.jomc.ri.model.RuntimeModelObject @ 1.2</dd>
057 *   <dt><b>Abstract:</b></dt><dd>No</dd>
058 *   <dt><b>Final:</b></dt><dd>No</dd>
059 *   <dt><b>Stateless:</b></dt><dd>No</dd>
060 * </dl>
061 *
062 * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a> 1.2
063 * @version 1.2
064 */
065// </editor-fold>
066// SECTION-END
067// SECTION-START[Annotations]
068// <editor-fold defaultstate="collapsed" desc=" Generated Annotations ">
069@javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.3", comments = "See http://jomc.sourceforge.net/jomc/1.3/jomc-tools-1.3" )
070// </editor-fold>
071// SECTION-END
072public class RuntimeImplementation extends Implementation implements RuntimeModelObject
073{
074    // SECTION-START[RuntimeImplementation]
075
076    /** Cached location URI. */
077    private volatile URI locationUri;
078
079    /**
080     * Creates a new {@code RuntimeImplementation} instance by deeply copying a given {@code Implementation} instance.
081     *
082     * @param implementation The instance to copy.
083     *
084     * @throws NullPointerException if {@code implementation} is {@code null}.
085     */
086    public RuntimeImplementation( final Implementation implementation )
087    {
088        super( implementation );
089
090        if ( this.getAuthors() != null )
091        {
092            this.setAuthors( RuntimeModelObjects.getInstance().copyOf( this.getAuthors() ) );
093        }
094        if ( this.getDependencies() != null )
095        {
096            this.setDependencies( RuntimeModelObjects.getInstance().copyOf( this.getDependencies() ) );
097        }
098        if ( this.getDocumentation() != null )
099        {
100            this.setDocumentation( RuntimeModelObjects.getInstance().copyOf( this.getDocumentation() ) );
101        }
102        if ( this.getImplementations() != null )
103        {
104            this.setImplementations( RuntimeModelObjects.getInstance().copyOf( this.getImplementations() ) );
105        }
106        if ( this.getMessages() != null )
107        {
108            this.setMessages( RuntimeModelObjects.getInstance().copyOf( this.getMessages() ) );
109        }
110        if ( this.getProperties() != null )
111        {
112            this.setProperties( RuntimeModelObjects.getInstance().copyOf( this.getProperties() ) );
113        }
114        if ( this.getSpecifications() != null )
115        {
116            this.setSpecifications( RuntimeModelObjects.getInstance().copyOf( this.getSpecifications() ) );
117        }
118    }
119
120    /**
121     * Gets the location URI used for locating instances of this implementation.
122     * <p>This method queries an internal cache for a result object to return. If no cached result object is available,
123     * this method queries the super-class for a result object to return and caches the outcome of that query for use on
124     * successive calls.</p>
125     * <p><b>Note:</b><br/>Method {@code clear()} must be used to synchronize the state of the internal cache with the
126     * state of the instance, should the state of the instance change.</p>
127     *
128     * @return The location URI used for locating instances of this implementation or {@code null}, if instances of this
129     * implementation do not need to be located.
130     *
131     * @see #getLocation()
132     * @see #clear()
133     */
134    @Override
135    public URI getLocationUri()
136    {
137        if ( this.locationUri == null )
138        {
139            this.locationUri = super.getLocationUri();
140        }
141
142        return this.locationUri;
143    }
144
145    /**
146     * Gets the Java class of the implementation for a given class loader.
147     * <p>This method queries an internal cache for a result object to return for the given argument values. If no
148     * cached result object is available, this method queries the super-class for a result object to return and caches
149     * the outcome of that query for use on successive calls.</p>
150     * <p><b>Note:</b><br/>Method {@code RuntimeModelObjects.clear()} must be used to synchronize the state of the
151     * internal cache with the state of the class loader, should the state of the class loader change.</p>
152     *
153     * @param classLoader The class loader to get the Java class from or {@code null}, to get the Java class from the
154     * platform's bootstrap class loader.
155     *
156     * @return The Java class of the implementation or {@code null}, if the implementation does not declare a class.
157     *
158     * @throws ClassNotFoundException if the Java class is not found.
159     *
160     * @see #getClazz()
161     * @see RuntimeModelObjects#clear()
162     */
163    @Override
164    public Class<?> getJavaClass( final ClassLoader classLoader ) throws ClassNotFoundException
165    {
166        Class<?> javaClass = null;
167
168        if ( this.getClazz() != null )
169        {
170            ClassLoader classLoaderKey = classLoader;
171            if ( classLoaderKey == null )
172            {
173                classLoaderKey = BOOTSTRAP_CLASSLOADER_KEY;
174            }
175
176            synchronized ( classesByClassLoaderAndNameCache )
177            {
178                Map<String, Reference<Class<?>>> map = classesByClassLoaderAndNameCache.get( classLoaderKey );
179
180                if ( map == null )
181                {
182                    map = createMap();
183                    classesByClassLoaderAndNameCache.put( classLoaderKey, map );
184                }
185
186                final Reference<Class<?>> reference = map.get( this.getClazz() );
187
188                if ( reference != null )
189                {
190                    javaClass = reference.get();
191                }
192
193                if ( javaClass == null )
194                {
195                    javaClass = super.getJavaClass( classLoader );
196                    map.put( this.getClazz(), new WeakReference<Class<?>>( javaClass ) );
197                }
198            }
199        }
200
201        return javaClass;
202    }
203
204    // SECTION-END
205    // SECTION-START[RuntimeModelObject]
206    public void gc()
207    {
208        this.gcOrClear( true, false );
209    }
210
211    public void clear()
212    {
213        this.locationUri = null;
214        this.gcOrClear( false, true );
215    }
216
217    private void gcOrClear( final boolean gc, final boolean clear )
218    {
219        if ( this.getAuthors() instanceof RuntimeModelObject )
220        {
221            if ( gc )
222            {
223                ( (RuntimeModelObject) this.getAuthors() ).gc();
224            }
225            if ( clear )
226            {
227                ( (RuntimeModelObject) this.getAuthors() ).clear();
228            }
229        }
230        if ( this.getDependencies() instanceof RuntimeModelObject )
231        {
232            if ( gc )
233            {
234                ( (RuntimeModelObject) this.getDependencies() ).gc();
235            }
236            if ( clear )
237            {
238                ( (RuntimeModelObject) this.getDependencies() ).clear();
239            }
240        }
241        if ( this.getDocumentation() instanceof RuntimeModelObject )
242        {
243            if ( gc )
244            {
245                ( (RuntimeModelObject) this.getDocumentation() ).gc();
246            }
247            if ( clear )
248            {
249                ( (RuntimeModelObject) this.getDocumentation() ).clear();
250            }
251        }
252        if ( this.getImplementations() instanceof RuntimeModelObject )
253        {
254            if ( gc )
255            {
256                ( (RuntimeModelObject) this.getImplementations() ).gc();
257            }
258            if ( clear )
259            {
260                ( (RuntimeModelObject) this.getImplementations() ).clear();
261            }
262        }
263        if ( this.getMessages() instanceof RuntimeModelObject )
264        {
265            if ( gc )
266            {
267                ( (RuntimeModelObject) this.getMessages() ).gc();
268            }
269            if ( clear )
270            {
271                ( (RuntimeModelObject) this.getMessages() ).clear();
272            }
273        }
274        if ( this.getProperties() instanceof RuntimeModelObject )
275        {
276            if ( gc )
277            {
278                ( (RuntimeModelObject) this.getProperties() ).gc();
279            }
280            if ( clear )
281            {
282                ( (RuntimeModelObject) this.getProperties() ).clear();
283            }
284        }
285        if ( this.getSpecifications() instanceof RuntimeModelObject )
286        {
287            if ( gc )
288            {
289                ( (RuntimeModelObject) this.getSpecifications() ).gc();
290            }
291            if ( clear )
292            {
293                ( (RuntimeModelObject) this.getSpecifications() ).clear();
294            }
295        }
296    }
297
298    // SECTION-END
299    // SECTION-START[Constructors]
300    // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
301    /** Creates a new {@code RuntimeImplementation} instance. */
302    @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.3", comments = "See http://jomc.sourceforge.net/jomc/1.3/jomc-tools-1.3" )
303    public RuntimeImplementation()
304    {
305        // SECTION-START[Default Constructor]
306        super();
307        // SECTION-END
308    }
309    // </editor-fold>
310    // SECTION-END
311    // SECTION-START[Dependencies]
312    // SECTION-END
313    // SECTION-START[Properties]
314    // SECTION-END
315    // SECTION-START[Messages]
316    // SECTION-END
317}