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: RuntimeSpecification.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.util.Map;
041import org.jomc.model.Specification;
042import static org.jomc.ri.model.RuntimeModelObjects.BOOTSTRAP_CLASSLOADER_KEY;
043import static org.jomc.ri.model.RuntimeModelObjects.classesByClassLoaderAndNameCache;
044import static org.jomc.ri.model.RuntimeModelObjects.createMap;
045
046// SECTION-START[Documentation]
047// <editor-fold defaultstate="collapsed" desc=" Generated Documentation ">
048/**
049 * Runtime {@code Specification}.
050 *
051 * <dl>
052 *   <dt><b>Identifier:</b></dt><dd>org.jomc.ri.model.RuntimeSpecification</dd>
053 *   <dt><b>Name:</b></dt><dd>JOMC RI RuntimeSpecification</dd>
054 *   <dt><b>Specifications:</b></dt>
055 *     <dd>org.jomc.ri.model.RuntimeModelObject @ 1.2</dd>
056 *   <dt><b>Abstract:</b></dt><dd>No</dd>
057 *   <dt><b>Final:</b></dt><dd>No</dd>
058 *   <dt><b>Stateless:</b></dt><dd>No</dd>
059 * </dl>
060 *
061 * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a> 1.2
062 * @version 1.2
063 */
064// </editor-fold>
065// SECTION-END
066// SECTION-START[Annotations]
067// <editor-fold defaultstate="collapsed" desc=" Generated Annotations ">
068@javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.3", comments = "See http://jomc.sourceforge.net/jomc/1.3/jomc-tools-1.3" )
069// </editor-fold>
070// SECTION-END
071public class RuntimeSpecification extends Specification implements RuntimeModelObject
072{
073    // SECTION-START[RuntimeSpecification]
074
075    /**
076     * Creates a new {@code RuntimeSpecification} instance by deeply copying a given {@code Specification} instance.
077     *
078     * @param specification The instance to copy.
079     *
080     * @throws NullPointerException if {@code specification} is {@code null}.
081     */
082    public RuntimeSpecification( final Specification specification )
083    {
084        super( specification );
085
086        if ( this.getAuthors() != null )
087        {
088            this.setAuthors( RuntimeModelObjects.getInstance().copyOf( this.getAuthors() ) );
089        }
090        if ( this.getDocumentation() != null )
091        {
092            this.setDocumentation( RuntimeModelObjects.getInstance().copyOf( this.getDocumentation() ) );
093        }
094        if ( this.getProperties() != null )
095        {
096            this.setProperties( RuntimeModelObjects.getInstance().copyOf( this.getProperties() ) );
097        }
098    }
099
100    /**
101     * Gets the Java class of the specification for a given class loader.
102     * <p>This method queries an internal cache for a result object to return for the given argument values. If no
103     * cached result object is available, this method queries the super-class for a result object to return and caches
104     * the outcome of that query for use on successive calls.</p>
105     * <p><b>Note:</b><br/>Method {@code RuntimeModelObjects.clear()} must be used to synchronize the state of the
106     * internal cache with the state of the class loader, should the state of the class loader change.</p>
107     *
108     * @param classLoader The class loader to get the Java class from or {@code null}, to get the Java class from the
109     * platform's bootstrap class loader.
110     *
111     * @return The Java class of the specification or {@code null}, if the specification does not declare a class.
112     *
113     * @throws ClassNotFoundException if the Java class is not found.
114     *
115     * @see #getClazz()
116     * @see RuntimeModelObjects#clear()
117     */
118    @Override
119    public Class<?> getJavaClass( final ClassLoader classLoader ) throws ClassNotFoundException
120    {
121        Class<?> javaClass = null;
122
123        if ( this.getClazz() != null )
124        {
125            synchronized ( classesByClassLoaderAndNameCache )
126            {
127                ClassLoader classLoaderKey = classLoader;
128                if ( classLoaderKey == null )
129                {
130                    classLoaderKey = BOOTSTRAP_CLASSLOADER_KEY;
131                }
132
133                Map<String, Reference<Class<?>>> map = classesByClassLoaderAndNameCache.get( classLoaderKey );
134
135                if ( map == null )
136                {
137                    map = createMap();
138                    classesByClassLoaderAndNameCache.put( classLoaderKey, map );
139                }
140
141                final Reference<Class<?>> reference = map.get( this.getClazz() );
142
143                if ( reference != null )
144                {
145                    javaClass = reference.get();
146                }
147
148                if ( javaClass == null )
149                {
150                    javaClass = super.getJavaClass( classLoader );
151                    map.put( this.getClazz(), new WeakReference<Class<?>>( javaClass ) );
152                }
153            }
154        }
155
156        return javaClass;
157    }
158
159    // SECTION-END
160    // SECTION-START[RuntimeModelObject]
161    public void gc()
162    {
163        this.gcOrClear( true, false );
164    }
165
166    public void clear()
167    {
168        this.gcOrClear( false, true );
169    }
170
171    private void gcOrClear( final boolean gc, final boolean clear )
172    {
173        if ( this.getAuthors() instanceof RuntimeModelObject )
174        {
175            if ( gc )
176            {
177                ( (RuntimeModelObject) this.getAuthors() ).gc();
178            }
179            if ( clear )
180            {
181                ( (RuntimeModelObject) this.getAuthors() ).clear();
182            }
183        }
184        if ( this.getDocumentation() instanceof RuntimeModelObject )
185        {
186            if ( gc )
187            {
188                ( (RuntimeModelObject) this.getDocumentation() ).gc();
189            }
190            if ( clear )
191            {
192                ( (RuntimeModelObject) this.getDocumentation() ).clear();
193            }
194        }
195        if ( this.getProperties() instanceof RuntimeModelObject )
196        {
197            if ( gc )
198            {
199                ( (RuntimeModelObject) this.getProperties() ).gc();
200            }
201            if ( clear )
202            {
203                ( (RuntimeModelObject) this.getProperties() ).clear();
204            }
205        }
206    }
207
208    // SECTION-END
209    // SECTION-START[Constructors]
210    // <editor-fold defaultstate="collapsed" desc=" Generated Constructors ">
211    /** Creates a new {@code RuntimeSpecification} instance. */
212    @javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.3", comments = "See http://jomc.sourceforge.net/jomc/1.3/jomc-tools-1.3" )
213    public RuntimeSpecification()
214    {
215        // SECTION-START[Default Constructor]
216        super();
217        // SECTION-END
218    }
219    // </editor-fold>
220    // SECTION-END
221    // SECTION-START[Dependencies]
222    // SECTION-END
223    // SECTION-START[Properties]
224    // SECTION-END
225    // SECTION-START[Messages]
226    // SECTION-END
227}