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 4795 2013-04-21 09:09:02Z schulte $ 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 javax.xml.bind.annotation.XmlTransient; 043import org.jomc.model.Implementation; 044import org.jomc.model.JavaTypeName; 045import org.jomc.model.ModelObjectException; 046import static org.jomc.ri.model.RuntimeModelObjects.BOOTSTRAP_CLASSLOADER_KEY; 047import static org.jomc.ri.model.RuntimeModelObjects.classesByClassLoaderAndNameCache; 048import static org.jomc.ri.model.RuntimeModelObjects.createMap; 049 050// SECTION-START[Documentation] 051// <editor-fold defaultstate="collapsed" desc=" Generated Documentation "> 052/** 053 * Runtime {@code Implementation}. 054 * 055 * <dl> 056 * <dt><b>Identifier:</b></dt><dd>org.jomc.ri.model.RuntimeImplementation</dd> 057 * <dt><b>Name:</b></dt><dd>JOMC ⁑ RI ⁑ RuntimeImplementation</dd> 058 * <dt><b>Specifications:</b></dt> 059 * <dd>org.jomc.ri.model.RuntimeModelObject @ 1.2</dd> 060 * <dt><b>Abstract:</b></dt><dd>No</dd> 061 * <dt><b>Final:</b></dt><dd>No</dd> 062 * <dt><b>Stateless:</b></dt><dd>No</dd> 063 * </dl> 064 * 065 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 1.2 066 * @version 1.2 067 */ 068// </editor-fold> 069// SECTION-END 070// SECTION-START[Annotations] 071// <editor-fold defaultstate="collapsed" desc=" Generated Annotations "> 072@javax.annotation.Generated( value = "org.jomc.tools.SourceFileProcessor 1.5", comments = "See http://www.jomc.org/jomc/1.5/jomc-tools-1.5" ) 073// </editor-fold> 074// SECTION-END 075public class RuntimeImplementation extends Implementation implements RuntimeModelObject 076{ 077 // SECTION-START[RuntimeImplementation] 078 079 /** Cached location URI. */ 080 private volatile URI locationUri; 081 082 /** Java type name. */ 083 @XmlTransient 084 private volatile JavaTypeName javaTypeName; 085 086 /** 087 * Creates a new {@code RuntimeImplementation} instance by deeply copying a given {@code Implementation} instance. 088 * 089 * @param implementation The instance to copy. 090 * 091 * @throws NullPointerException if {@code implementation} is {@code null}. 092 */ 093 public RuntimeImplementation( final Implementation implementation ) 094 { 095 super( implementation ); 096 097 if ( this.getAuthors() != null ) 098 { 099 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}