Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 341D3200CB6 for ; Thu, 25 May 2017 01:08:05 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 328D4160BDA; Wed, 24 May 2017 23:08:05 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id E07A5160BD0 for ; Thu, 25 May 2017 01:08:02 +0200 (CEST) Received: (qmail 69040 invoked by uid 500); 24 May 2017 23:08:02 -0000 Mailing-List: contact commits-help@juneau.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@juneau.incubator.apache.org Delivered-To: mailing list commits@juneau.incubator.apache.org Received: (qmail 69031 invoked by uid 99); 24 May 2017 23:08:02 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd3-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 24 May 2017 23:08:02 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd3-us-west.apache.org (ASF Mail Server at spamd3-us-west.apache.org) with ESMTP id 8836B190DC2 for ; Wed, 24 May 2017 23:08:01 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd3-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -4.222 X-Spam-Level: X-Spam-Status: No, score=-4.222 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.001, SPF_PASS=-0.001] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd3-us-west.apache.org [10.40.0.10]) (amavisd-new, port 10024) with ESMTP id tocbuSRm-G0g for ; Wed, 24 May 2017 23:07:48 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id 7157F5F19B for ; Wed, 24 May 2017 23:07:43 +0000 (UTC) Received: (qmail 67732 invoked by uid 99); 24 May 2017 23:07:42 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 24 May 2017 23:07:42 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 5F4A1DFB8A; Wed, 24 May 2017 23:07:42 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: jamesbognar@apache.org To: commits@juneau.incubator.apache.org Date: Wed, 24 May 2017 23:07:58 -0000 Message-Id: <4879eedda2e74742ab89f5f22d1d4705@git.apache.org> In-Reply-To: <0c63fc903d074ef2b66a7a76312ca5ae@git.apache.org> References: <0c63fc903d074ef2b66a7a76312ca5ae@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [18/32] incubator-juneau-website git commit: New @RequestBean annotation for remoteable interfaces. archived-at: Wed, 24 May 2017 23:08:05 -0000 http://git-wip-us.apache.org/repos/asf/incubator-juneau-website/blob/b852a3e8/content/site/apidocs/src-html/org/apache/juneau/PropertyStore.html ---------------------------------------------------------------------- diff --git a/content/site/apidocs/src-html/org/apache/juneau/PropertyStore.html b/content/site/apidocs/src-html/org/apache/juneau/PropertyStore.html index 405499c..9402a58 100644 --- a/content/site/apidocs/src-html/org/apache/juneau/PropertyStore.html +++ b/content/site/apidocs/src-html/org/apache/juneau/PropertyStore.html @@ -298,1098 +298,1100 @@ 290 * @return This object (for method chaining). 291 */ 292 public PropertyStore copyFrom(PropertyStore ps) { -293 // TODO - Needs more testing. -294 for (Map.Entry<String,PropertyMap> e : ps.properties.entrySet()) -295 this.properties.put(e.getKey(), new PropertyMap(this.properties.get(e.getKey()), e.getValue())); -296 this.classLoader = ps.classLoader; -297 this.defaultParser = ps.defaultParser; -298 return this; -299 } -300 -301 /** -302 * Creates a new store with the specified override properties applied to this store. -303 * -304 * @param overrideProperties The properties to apply to the copy of this store. -305 * @return Either this unmodified store, or a new store with override properties applied. -306 */ -307 public PropertyStore create(Map<String,Object> overrideProperties) { -308 return new PropertyStore(this).setProperties(overrideProperties); -309 } -310 -311 /** -312 * Sets a configuration property value on this object. -313 * <p> -314 * A typical usage is to set or overwrite configuration values like so... -315 * <p class='bcode'> -316 * PropertyStore ps = PropertyStore.<jsm>create</jsm>(); -317 * ps.setProperty(<jsf>BEAN_sortProperties</jsf>, <jk>true</jk>); -318 * </p> -319 * <p> -320 * The possible class types of the value depend on the property type: +293 if (ps != null) { +294 // TODO - Needs more testing. +295 for (Map.Entry<String,PropertyMap> e : ps.properties.entrySet()) +296 this.properties.put(e.getKey(), new PropertyMap(this.properties.get(e.getKey()), e.getValue())); +297 this.classLoader = ps.classLoader; +298 this.defaultParser = ps.defaultParser; +299 } +300 return this; +301 } +302 +303 /** +304 * Creates a new store with the specified override properties applied to this store. +305 * +306 * @param overrideProperties The properties to apply to the copy of this store. +307 * @return Either this unmodified store, or a new store with override properties applied. +308 */ +309 public PropertyStore create(Map<String,Object> overrideProperties) { +310 return new PropertyStore(this).setProperties(overrideProperties); +311 } +312 +313 /** +314 * Sets a configuration property value on this object. +315 * <p> +316 * A typical usage is to set or overwrite configuration values like so... +317 * <p class='bcode'> +318 * PropertyStore ps = PropertyStore.<jsm>create</jsm>(); +319 * ps.setProperty(<jsf>BEAN_sortProperties</jsf>, <jk>true</jk>); +320 * </p> 321 * <p> -322 * <table class='styled'> -323 * <tr> -324 * <th>Property type</th> -325 * <th>Example</th> -326 * <th>Allowed value type</th> -327 * </tr> -328 * <tr> -329 * <td>Set <l>SIMPLE</l></td> -330 * <td><js>"Foo.x"</js></td> -331 * <td>Any object type.</td> -332 * </tr> -333 * <tr> -334 * <td>Set <l>SET/LIST</l></td> -335 * <td><js>"Foo.x.set"</js></td> -336 * <td>Any collection or array of any objects, or a String containing a JSON array.</td> -337 * </tr> -338 * <tr> -339 * <td>Add/Remove <l>SET/LIST</l></td> -340 * <td><js>"Foo.x.set.add"</js></td> -341 * <td>If a collection, adds or removes the entries in the collection. Otherwise, adds/removes a single entry.</td> -342 * </tr> -343 * <tr> -344 * <td>Set <l>MAP</l></td> -345 * <td><js>"Foo.x.map"</js></td> -346 * <td>A map, or a String containing a JSON object. Entries overwrite existing map.</td> -347 * </tr> -348 * <tr> -349 * <td>Put <l>MAP</l></td> -350 * <td><js>"Foo.x.map.put"</js></td> -351 * <td>A map, or a String containing a JSON object. Entries are added to existing map.</td> -352 * </tr> -353 * </table> -354 * -355 * @param name The configuration property name.<br> -356 * If name ends with <l>.add</l>, then the specified value is added to the -357 * existing property value as an entry in a SET or LIST property.<br> -358 * If name ends with <l>.put</l>, then the specified value is added to the -359 * existing property value as a key/value pair in a MAP property.<br> -360 * If name ends with <l>.remove</l>, then the specified value is removed from the -361 * existing property property value in a SET or LIST property.<br> -362 * -363 * @param value The new value. -364 * If <jk>null</jk>, the property value is deleted.<br> -365 * In general, the value type can be anything.<br> -366 * -367 * @return This object (for method chaining). -368 */ -369 public PropertyStore setProperty(String name, Object value) { -370 String prefix = prefix(name); -371 -372 if (name.endsWith(".add")) -373 return addToProperty(name.substring(0, name.lastIndexOf('.')), value); -374 -375 if (name.endsWith(".put")) -376 return putToProperty(name.substring(0, name.lastIndexOf('.')), value); -377 -378 if (name.endsWith(".remove")) -379 return removeFromProperty(name.substring(0, name.lastIndexOf('.')), value); -380 -381 wl.lock(); -382 try { -383 contexts.clear(); -384 if (! properties.containsKey(prefix)) -385 properties.put(prefix, new PropertyMap(prefix)); -386 properties.get(prefix).set(name, value); -387 } finally { -388 wl.unlock(); -389 } -390 return this; -391 } -392 -393 /** -394 * Convenience method for setting multiple properties in one call. -395 * <p> -396 * This appends to any previous configuration properties set on this store. -397 * -398 * @param newProperties The new properties to set. -399 * @return This object (for method chaining). -400 */ -401 public PropertyStore setProperties(Map<String,Object> newProperties) { -402 if (newProperties == null || newProperties.isEmpty()) -403 return this; -404 wl.lock(); -405 try { -406 contexts.clear(); -407 for (Map.Entry<String,Object> e : newProperties.entrySet()) { -408 String name = e.getKey().toString(); -409 Object value = e.getValue(); -410 String prefix = prefix(name); -411 if (name.endsWith(".add")) -412 addToProperty(name.substring(0, name.lastIndexOf('.')), value); -413 else if (name.endsWith(".remove")) -414 removeFromProperty(name.substring(0, name.lastIndexOf('.')), value); -415 else { -416 if (! properties.containsKey(prefix)) -417 properties.put(prefix, new PropertyMap(prefix)); -418 properties.get(prefix).set(name, value); -419 } -420 } -421 -422 } finally { -423 wl.unlock(); -424 } -425 return this; -426 } -427 -428 /** -429 * Adds several properties to this store. -430 * -431 * @param properties The properties to add to this store. -432 * @return This object (for method chaining). -433 */ -434 @SuppressWarnings("hiding") -435 public PropertyStore addProperties(Map<String,Object> properties) { -436 if (properties != null) -437 for (Map.Entry<String,Object> e : properties.entrySet()) -438 setProperty(e.getKey(), e.getValue()); -439 return this; -440 } -441 -442 /** -443 * Adds a value to a SET property. -444 * -445 * @param name The property name. -446 * @param value The new value to add to the SET property. -447 * @return This object (for method chaining). -448 * @throws ConfigException If property is not a SET property. -449 */ -450 public PropertyStore addToProperty(String name, Object value) { -451 String prefix = prefix(name); -452 wl.lock(); -453 try { -454 contexts.clear(); -455 if (! properties.containsKey(prefix)) -456 properties.put(prefix, new PropertyMap(prefix)); -457 properties.get(prefix).addTo(name, value); -458 } finally { -459 wl.unlock(); -460 } -461 return this; -462 } -463 -464 /** -465 * Adds or overwrites a value to a MAP property. -466 * -467 * @param name The property name. -468 * @param key The property value map key. -469 * @param value The property value map value. -470 * @return This object (for method chaining). -471 * @throws ConfigException If property is not a MAP property. -472 */ -473 public PropertyStore putToProperty(String name, Object key, Object value) { -474 String prefix = prefix(name); -475 wl.lock(); -476 try { -477 contexts.clear(); -478 if (! properties.containsKey(prefix)) -479 properties.put(prefix, new PropertyMap(prefix)); -480 properties.get(prefix).putTo(name, key, value); -481 } finally { -482 wl.unlock(); -483 } -484 return this; -485 } -486 -487 /** -488 * Adds or overwrites a value to a MAP property. -489 * -490 * @param name The property value. -491 * @param value The property value map value. -492 * @return This object (for method chaining). -493 * @throws ConfigException If property is not a MAP property. -494 */ -495 public PropertyStore putToProperty(String name, Object value) { -496 String prefix = prefix(name); -497 wl.lock(); -498 try { -499 contexts.clear(); -500 if (! properties.containsKey(prefix)) -501 properties.put(prefix, new PropertyMap(prefix)); -502 properties.get(prefix).putTo(name, value); -503 } finally { -504 wl.unlock(); -505 } -506 return this; -507 } -508 -509 /** -510 * Removes a value from a SET property. -511 * -512 * @param name The property name. -513 * @param value The property value in the SET property. -514 * @return This object (for method chaining). -515 * @throws ConfigException If property is not a SET property. -516 */ -517 public PropertyStore removeFromProperty(String name, Object value) { -518 String prefix = prefix(name); -519 wl.lock(); -520 try { -521 contexts.clear(); -522 if (properties.containsKey(prefix)) -523 properties.get(prefix).removeFrom(name, value); -524 } finally { -525 wl.unlock(); -526 } -527 return this; -528 } -529 -530 /** -531 * Returns an instance of the specified context initialized with the properties -532 * in this store. -533 * <p> -534 * Multiple calls to this method for the same store class will return the same -535 * cached value as long as the properties on this store are not touched. -536 * <p> -537 * As soon as any properties are modified on this store, all cached entries -538 * are discarded and recreated as needed. -539 * -540 * @param c The context class to instantiate. -541 * @return The context instance. -542 */ -543 @SuppressWarnings("unchecked") -544 public <T extends Context> T getContext(Class<T> c) { -545 rl.lock(); -546 try { -547 try { -548 if (! contexts.containsKey(c)) { -549 -550 // Try to get it from the global cache. -551 Integer key = hashCode(); -552 if (! globalContextCache.containsKey(key)) -553 globalContextCache.putIfAbsent(key, new ConcurrentHashMap<Class<? extends Context>,Context>()); -554 ConcurrentHashMap<Class<? extends Context>, Context> cacheForThisConfig = globalContextCache.get(key); -555 -556 if (! cacheForThisConfig.containsKey(c)) -557 cacheForThisConfig.putIfAbsent(c, c.getConstructor(PropertyStore.class).newInstance(this)); -558 -559 contexts.put(c, cacheForThisConfig.get(c)); -560 } -561 return (T)contexts.get(c); -562 } catch (Exception e) { -563 throw new ConfigException("Could not instantiate context class ''{0}''", className(c)).initCause(e); -564 } -565 } finally { -566 rl.unlock(); -567 } -568 } -569 -570 /** -571 * Returns the configuration properties with the specified prefix. -572 * <p> -573 * For example, if <l>prefix</l> is <js>"BeanContext"</js>, then retrieves -574 * all configuration properties that are prefixed with <js>"BeanContext."</js>. -575 * -576 * @param prefix The prefix of properties to retrieve. -577 * @return The configuration properties with the specified prefix, never <jk>null</jk>. -578 */ -579 public PropertyMap getPropertyMap(String prefix) { -580 rl.lock(); -581 try { -582 PropertyMap m = properties.get(prefix); -583 return m == null ? new PropertyMap(prefix) : m; -584 } finally { -585 rl.unlock(); -586 } -587 } -588 -589 /** -590 * Specifies the classloader to use when resolving classes from strings. -591 * <p> -592 * Can be used for resolving class names when the classes being created are in a different -593 * classloader from the Juneau code. -594 * <p> -595 * If <jk>null</jk>, the system classloader will be used to resolve classes. -596 * -597 * @param classLoader The new classloader. -598 * @return This object (for method chaining). -599 */ -600 public PropertyStore setClassLoader(ClassLoader classLoader) { -601 this.classLoader = (classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader); -602 return this; -603 } -604 -605 /** -606 * Specifies the parser to use to convert Strings to POJOs. -607 * <p> -608 * If <jk>null</jk>, {@link JsonParser#DEFAULT} will be used. -609 * -610 * @param defaultParser The new defaultParser. -611 * @return This object (for method chaining). -612 */ -613 public PropertyStore setDefaultParser(ReaderParser defaultParser) { -614 this.defaultParser = defaultParser == null ? JsonParser.DEFAULT : defaultParser; -615 return this; -616 } -617 -618 /** -619 * Returns a property value converted to the specified type. -620 * -621 * @param name The full name of the property (e.g. <js>"BeanContext.sortProperties"</js>) -622 * @param type The class type to convert the property value to. -623 * @param def The default value if the property is not set. -624 * -625 * @return The property value. -626 * @throws ConfigException If property has a value that cannot be converted to a boolean. -627 */ -628 public <T> T getProperty(String name, Class<T> type, T def) { -629 rl.lock(); -630 try { -631 PropertyMap pm = getPropertyMap(prefix(name)); -632 if (pm != null) -633 return pm.get(name, type, def); -634 String s = System.getProperty(name); -635 if ((! StringUtils.isEmpty(s)) && isBeanSessionAvailable()) -636 return getBeanSession().convertToType(s, type); -637 return def; -638 } finally { -639 rl.unlock(); -640 } -641 } -642 -643 /** -644 * Returns a property value converted to a {@link LinkedHashMap} with the specified -645 * key and value types. -646 * -647 * @param name The full name of the property (e.g. <js>"BeanContext.sortProperties"</js>) -648 * @param keyType The class type of the keys in the map. -649 * @param valType The class type of the values in the map. -650 * @param def The default value if the property is not set. -651 * -652 * @return The property value. -653 * @throws ConfigException If property has a value that cannot be converted to a boolean. -654 */ -655 public <K,V> Map<K,V> getMap(String name, Class<K> keyType, Class<V> valType, Map<K,V> def) { -656 rl.lock(); -657 try { -658 PropertyMap pm = getPropertyMap(prefix(name)); -659 if (pm != null) -660 return pm.getMap(name, keyType, valType, def); -661 return def; -662 } finally { -663 rl.unlock(); -664 } -665 } -666 -667 -668 //------------------------------------------------------------------------------------- -669 // Convenience methods. +322 * The possible class types of the value depend on the property type: +323 * <p> +324 * <table class='styled'> +325 * <tr> +326 * <th>Property type</th> +327 * <th>Example</th> +328 * <th>Allowed value type</th> +329 * </tr> +330 * <tr> +331 * <td>Set <l>SIMPLE</l></td> +332 * <td><js>"Foo.x"</js></td> +333 * <td>Any object type.</td> +334 * </tr> +335 * <tr> +336 * <td>Set <l>SET/LIST</l></td> +337 * <td><js>"Foo.x.set"</js></td> +338 * <td>Any collection or array of any objects, or a String containing a JSON array.</td> +339 * </tr> +340 * <tr> +341 * <td>Add/Remove <l>SET/LIST</l></td> +342 * <td><js>"Foo.x.set.add"</js></td> +343 * <td>If a collection, adds or removes the entries in the collection. Otherwise, adds/removes a single entry.</td> +344 * </tr> +345 * <tr> +346 * <td>Set <l>MAP</l></td> +347 * <td><js>"Foo.x.map"</js></td> +348 * <td>A map, or a String containing a JSON object. Entries overwrite existing map.</td> +349 * </tr> +350 * <tr> +351 * <td>Put <l>MAP</l></td> +352 * <td><js>"Foo.x.map.put"</js></td> +353 * <td>A map, or a String containing a JSON object. Entries are added to existing map.</td> +354 * </tr> +355 * </table> +356 * +357 * @param name The configuration property name.<br> +358 * If name ends with <l>.add</l>, then the specified value is added to the +359 * existing property value as an entry in a SET or LIST property.<br> +360 * If name ends with <l>.put</l>, then the specified value is added to the +361 * existing property value as a key/value pair in a MAP property.<br> +362 * If name ends with <l>.remove</l>, then the specified value is removed from the +363 * existing property property value in a SET or LIST property.<br> +364 * +365 * @param value The new value. +366 * If <jk>null</jk>, the property value is deleted.<br> +367 * In general, the value type can be anything.<br> +368 * +369 * @return This object (for method chaining). +370 */ +371 public PropertyStore setProperty(String name, Object value) { +372 String prefix = prefix(name); +373 +374 if (name.endsWith(".add")) +375 return addToProperty(name.substring(0, name.lastIndexOf('.')), value); +376 +377 if (name.endsWith(".put")) +378 return putToProperty(name.substring(0, name.lastIndexOf('.')), value); +379 +380 if (name.endsWith(".remove")) +381 return removeFromProperty(name.substring(0, name.lastIndexOf('.')), value); +382 +383 wl.lock(); +384 try { +385 contexts.clear(); +386 if (! properties.containsKey(prefix)) +387 properties.put(prefix, new PropertyMap(prefix)); +388 properties.get(prefix).set(name, value); +389 } finally { +390 wl.unlock(); +391 } +392 return this; +393 } +394 +395 /** +396 * Convenience method for setting multiple properties in one call. +397 * <p> +398 * This appends to any previous configuration properties set on this store. +399 * +400 * @param newProperties The new properties to set. +401 * @return This object (for method chaining). +402 */ +403 public PropertyStore setProperties(Map<String,Object> newProperties) { +404 if (newProperties == null || newProperties.isEmpty()) +405 return this; +406 wl.lock(); +407 try { +408 contexts.clear(); +409 for (Map.Entry<String,Object> e : newProperties.entrySet()) { +410 String name = e.getKey().toString(); +411 Object value = e.getValue(); +412 String prefix = prefix(name); +413 if (name.endsWith(".add")) +414 addToProperty(name.substring(0, name.lastIndexOf('.')), value); +415 else if (name.endsWith(".remove")) +416 removeFromProperty(name.substring(0, name.lastIndexOf('.')), value); +417 else { +418 if (! properties.containsKey(prefix)) +419 properties.put(prefix, new PropertyMap(prefix)); +420 properties.get(prefix).set(name, value); +421 } +422 } +423 +424 } finally { +425 wl.unlock(); +426 } +427 return this; +428 } +429 +430 /** +431 * Adds several properties to this store. +432 * +433 * @param properties The properties to add to this store. +434 * @return This object (for method chaining). +435 */ +436 @SuppressWarnings("hiding") +437 public PropertyStore addProperties(Map<String,Object> properties) { +438 if (properties != null) +439 for (Map.Entry<String,Object> e : properties.entrySet()) +440 setProperty(e.getKey(), e.getValue()); +441 return this; +442 } +443 +444 /** +445 * Adds a value to a SET property. +446 * +447 * @param name The property name. +448 * @param value The new value to add to the SET property. +449 * @return This object (for method chaining). +450 * @throws ConfigException If property is not a SET property. +451 */ +452 public PropertyStore addToProperty(String name, Object value) { +453 String prefix = prefix(name); +454 wl.lock(); +455 try { +456 contexts.clear(); +457 if (! properties.containsKey(prefix)) +458 properties.put(prefix, new PropertyMap(prefix)); +459 properties.get(prefix).addTo(name, value); +460 } finally { +461 wl.unlock(); +462 } +463 return this; +464 } +465 +466 /** +467 * Adds or overwrites a value to a MAP property. +468 * +469 * @param name The property name. +470 * @param key The property value map key. +471 * @param value The property value map value. +472 * @return This object (for method chaining). +473 * @throws ConfigException If property is not a MAP property. +474 */ +475 public PropertyStore putToProperty(String name, Object key, Object value) { +476 String prefix = prefix(name); +477 wl.lock(); +478 try { +479 contexts.clear(); +480 if (! properties.containsKey(prefix)) +481 properties.put(prefix, new PropertyMap(prefix)); +482 properties.get(prefix).putTo(name, key, value); +483 } finally { +484 wl.unlock(); +485 } +486 return this; +487 } +488 +489 /** +490 * Adds or overwrites a value to a MAP property. +491 * +492 * @param name The property value. +493 * @param value The property value map value. +494 * @return This object (for method chaining). +495 * @throws ConfigException If property is not a MAP property. +496 */ +497 public PropertyStore putToProperty(String name, Object value) { +498 String prefix = prefix(name); +499 wl.lock(); +500 try { +501 contexts.clear(); +502 if (! properties.containsKey(prefix)) +503 properties.put(prefix, new PropertyMap(prefix)); +504 properties.get(prefix).putTo(name, value); +505 } finally { +506 wl.unlock(); +507 } +508 return this; +509 } +510 +511 /** +512 * Removes a value from a SET property. +513 * +514 * @param name The property name. +515 * @param value The property value in the SET property. +516 * @return This object (for method chaining). +517 * @throws ConfigException If property is not a SET property. +518 */ +519 public PropertyStore removeFromProperty(String name, Object value) { +520 String prefix = prefix(name); +521 wl.lock(); +522 try { +523 contexts.clear(); +524 if (properties.containsKey(prefix)) +525 properties.get(prefix).removeFrom(name, value); +526 } finally { +527 wl.unlock(); +528 } +529 return this; +530 } +531 +532 /** +533 * Returns an instance of the specified context initialized with the properties +534 * in this store. +535 * <p> +536 * Multiple calls to this method for the same store class will return the same +537 * cached value as long as the properties on this store are not touched. +538 * <p> +539 * As soon as any properties are modified on this store, all cached entries +540 * are discarded and recreated as needed. +541 * +542 * @param c The context class to instantiate. +543 * @return The context instance. +544 */ +545 @SuppressWarnings("unchecked") +546 public <T extends Context> T getContext(Class<T> c) { +547 rl.lock(); +548 try { +549 try { +550 if (! contexts.containsKey(c)) { +551 +552 // Try to get it from the global cache. +553 Integer key = hashCode(); +554 if (! globalContextCache.containsKey(key)) +555 globalContextCache.putIfAbsent(key, new ConcurrentHashMap<Class<? extends Context>,Context>()); +556 ConcurrentHashMap<Class<? extends Context>, Context> cacheForThisConfig = globalContextCache.get(key); +557 +558 if (! cacheForThisConfig.containsKey(c)) +559 cacheForThisConfig.putIfAbsent(c, c.getConstructor(PropertyStore.class).newInstance(this)); +560 +561 contexts.put(c, cacheForThisConfig.get(c)); +562 } +563 return (T)contexts.get(c); +564 } catch (Exception e) { +565 throw new ConfigException("Could not instantiate context class ''{0}''", className(c)).initCause(e); +566 } +567 } finally { +568 rl.unlock(); +569 } +570 } +571 +572 /** +573 * Returns the configuration properties with the specified prefix. +574 * <p> +575 * For example, if <l>prefix</l> is <js>"BeanContext"</js>, then retrieves +576 * all configuration properties that are prefixed with <js>"BeanContext."</js>. +577 * +578 * @param prefix The prefix of properties to retrieve. +579 * @return The configuration properties with the specified prefix, never <jk>null</jk>. +580 */ +581 public PropertyMap getPropertyMap(String prefix) { +582 rl.lock(); +583 try { +584 PropertyMap m = properties.get(prefix); +585 return m == null ? new PropertyMap(prefix) : m; +586 } finally { +587 rl.unlock(); +588 } +589 } +590 +591 /** +592 * Specifies the classloader to use when resolving classes from strings. +593 * <p> +594 * Can be used for resolving class names when the classes being created are in a different +595 * classloader from the Juneau code. +596 * <p> +597 * If <jk>null</jk>, the system classloader will be used to resolve classes. +598 * +599 * @param classLoader The new classloader. +600 * @return This object (for method chaining). +601 */ +602 public PropertyStore setClassLoader(ClassLoader classLoader) { +603 this.classLoader = (classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader); +604 return this; +605 } +606 +607 /** +608 * Specifies the parser to use to convert Strings to POJOs. +609 * <p> +610 * If <jk>null</jk>, {@link JsonParser#DEFAULT} will be used. +611 * +612 * @param defaultParser The new defaultParser. +613 * @return This object (for method chaining). +614 */ +615 public PropertyStore setDefaultParser(ReaderParser defaultParser) { +616 this.defaultParser = defaultParser == null ? JsonParser.DEFAULT : defaultParser; +617 return this; +618 } +619 +620 /** +621 * Returns a property value converted to the specified type. +622 * +623 * @param name The full name of the property (e.g. <js>"BeanContext.sortProperties"</js>) +624 * @param type The class type to convert the property value to. +625 * @param def The default value if the property is not set. +626 * +627 * @return The property value. +628 * @throws ConfigException If property has a value that cannot be converted to a boolean. +629 */ +630 public <T> T getProperty(String name, Class<T> type, T def) { +631 rl.lock(); +632 try { +633 PropertyMap pm = getPropertyMap(prefix(name)); +634 if (pm != null) +635 return pm.get(name, type, def); +636 String s = System.getProperty(name); +637 if ((! StringUtils.isEmpty(s)) && isBeanSessionAvailable()) +638 return getBeanSession().convertToType(s, type); +639 return def; +640 } finally { +641 rl.unlock(); +642 } +643 } +644 +645 /** +646 * Returns a property value converted to a {@link LinkedHashMap} with the specified +647 * key and value types. +648 * +649 * @param name The full name of the property (e.g. <js>"BeanContext.sortProperties"</js>) +650 * @param keyType The class type of the keys in the map. +651 * @param valType The class type of the values in the map. +652 * @param def The default value if the property is not set. +653 * +654 * @return The property value. +655 * @throws ConfigException If property has a value that cannot be converted to a boolean. +656 */ +657 public <K,V> Map<K,V> getMap(String name, Class<K> keyType, Class<V> valType, Map<K,V> def) { +658 rl.lock(); +659 try { +660 PropertyMap pm = getPropertyMap(prefix(name)); +661 if (pm != null) +662 return pm.getMap(name, keyType, valType, def); +663 return def; +664 } finally { +665 rl.unlock(); +666 } +667 } +668 +669 670 //------------------------------------------------------------------------------------- -671 -672 /** -673 * Shortcut for calling <code>getContext(BeanContext.<jk>class</jk>);</code>. -674 * -675 * @return The bean context instance. -676 */ -677 public BeanContext getBeanContext() { -678 return getContext(BeanContext.class); -679 } -680 -681 /** -682 * Shortcut for calling <code>setProperty(<jsf>BEAN_notBeanClasses</jsf>, <jf>classes</jf>)</code>. -683 * -684 * @param classes The new setting value for the bean context. -685 * @return This object (for method chaining). -686 * @see PropertyStore#setProperty(String, Object) -687 * @see BeanContext#BEAN_notBeanClasses -688 */ -689 public PropertyStore setNotBeanClasses(Class<?>...classes) { -690 setProperty(BEAN_notBeanClasses, classes); -691 return this; -692 } -693 -694 /** -695 * Shortcut for calling <code>addToProperty(<jsf>BEAN_notBeanClasses</jsf>, <jf>classes</jf>)</code>. -696 * -697 * @see PropertyStore#addToProperty(String,Object) -698 * @param classes The new setting value for the bean context. -699 * @return This object (for method chaining). -700 * @see PropertyStore#addToProperty(String, Object) -701 * @see BeanContext#BEAN_notBeanClasses -702 */ -703 public PropertyStore addNotBeanClasses(Class<?>...classes) { -704 addToProperty(BEAN_notBeanClasses, classes); -705 return this; -706 } -707 -708 /** -709 * Shortcut for calling <code>setProperty(<jsf>BEAN_beanFilters</jsf>, <jf>classes</jf>)</code>. -710 * -711 * @param classes The new setting value for the bean context. -712 * @return This object (for method chaining). -713 * @see PropertyStore#setProperty(String, Object) -714 * @see BeanContext#BEAN_beanFilters -715 */ -716 public PropertyStore setBeanFilters(Class<?>...classes) { -717 setProperty(BEAN_beanFilters, classes); -718 return this; -719 } -720 -721 /** -722 * Shortcut for calling <code>addToProperty(<jsf>BEAN_beanFilters</jsf>, <jf>classes</jf>)</code>. -723 * -724 * @param classes The new setting value for the bean context. -725 * @return This object (for method chaining). -726 * @see PropertyStore#addToProperty(String, Object) -727 * @see BeanContext#BEAN_beanFilters -728 */ -729 public PropertyStore addBeanFilters(Class<?>...classes) { -730 addToProperty(BEAN_beanFilters, classes); -731 return this; -732 } -733 -734 /** -735 * Shortcut for calling <code>setProperty(<jsf>BEAN_pojoSwaps</jsf>, <jf>classes</jf>)</code>. -736 * -737 * @param classes The new setting value for the bean context. -738 * @return This object (for method chaining). -739 * @see PropertyStore#setProperty(String, Object) -740 * @see BeanContext#BEAN_pojoSwaps -741 */ -742 public PropertyStore setPojoSwaps(Class<?>...classes) { -743 setProperty(BEAN_pojoSwaps, classes); -744 return this; -745 } -746 -747 /** -748 * Shortcut for calling <code>addToProperty(<jsf>BEAN_pojoSwaps</jsf>, <jf>classes</jf>)</code>. -749 * -750 * @param classes The new setting value for the bean context. -751 * @return This object (for method chaining). -752 * @see PropertyStore#addToProperty(String, Object) -753 * @see BeanContext#BEAN_pojoSwaps -754 */ -755 public PropertyStore addPojoSwaps(Class<?>...classes) { -756 addToProperty(BEAN_pojoSwaps, classes); -757 return this; -758 } -759 -760 /** -761 * Shortcut for calling <code>setProperty(<jsf>BEAN_beanDictionary</jsf>, <jf>classes</jf>)</code>. -762 * -763 * @param classes The new setting value for the bean context. -764 * @return This object (for method chaining). -765 * @see PropertyStore#setProperty(String, Object) -766 * @see BeanContext#BEAN_beanDictionary -767 */ -768 public PropertyStore setBeanDictionary(Class<?>...classes) { -769 addToProperty(BEAN_beanDictionary, classes); -770 return this; -771 } -772 -773 /** -774 * Shortcut for calling <code>addToProperty(<jsf>BEAN_beanDictionary</jsf>, <jf>classes</jf>)</code>. -775 * -776 * @param classes The new setting value for the bean context. -777 * @return This object (for method chaining). -778 * @see PropertyStore#addToProperty(String, Object) -779 * @see BeanContext#BEAN_beanDictionary -780 */ -781 public PropertyStore addToBeanDictionary(Class<?>...classes) { -782 addToProperty(BEAN_beanDictionary, classes); -783 return this; -784 } -785 -786 /** -787 * Shortcut for calling <code>putTo(<jsf>BEAN_implCLasses</jsf>, <jf>interfaceClass</jf>, <jf>implClass</jf>)</code>. -788 * -789 * @param interfaceClass The interface class. -790 * @param implClass The implementation class. -791 * @param <T> The class type of the interface. -792 * @return This object (for method chaining). -793 * @see PropertyStore#putToProperty(String, Object, Object) -794 * @see BeanContext#BEAN_implClasses -795 */ -796 public <T> PropertyStore addImplClass(Class<T> interfaceClass, Class<? extends T> implClass) { -797 putToProperty(BEAN_implClasses, interfaceClass, implClass); -798 return this; -799 } -800 -801 -802 //------------------------------------------------------------------------------------- -803 // Object methods. +671 // Convenience methods. +672 //------------------------------------------------------------------------------------- +673 +674 /** +675 * Shortcut for calling <code>getContext(BeanContext.<jk>class</jk>);</code>. +676 * +677 * @return The bean context instance. +678 */ +679 public Bea