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 <cs@schulte.it>, 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 5061 2015-05-31 13:20:40Z 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.9", comments = "See http://www.jomc.org/jomc/1.9/jomc-tools-1.9" ) 073// </editor-fold> 074// SECTION-END 075public class RuntimeImplementation extends Implementation implements RuntimeModelObject 076{ 077 // SECTION-START[RuntimeImplementation] 078 079 /** 080 * Cached location URI. 081 */ 082 private volatile URI locationUri; 083 084 /** 085 * Java type name. 086 */ 087 @XmlTransient 088 private volatile JavaTypeName javaTypeName; 089 090 /** 091 * Creates a new {@code RuntimeImplementation} instance by deeply copying a given {@code Implementation} instance. 092 * 093 * @param implementation The instance to copy. 094 * 095 * @throws NullPointerException if {@code implementation} is {@code null}. 096 */ 097 public RuntimeImplementation( final Implementation implementation ) 098 { 099 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}