1 16 17 package org.springframework.beans.factory.support; 18 19 import java.io.IOException ; 20 import java.io.InputStream ; 21 import java.io.InputStreamReader ; 22 import java.util.Enumeration ; 23 import java.util.HashMap ; 24 import java.util.Iterator ; 25 import java.util.Map ; 26 import java.util.Properties ; 27 import java.util.ResourceBundle ; 28 29 import org.springframework.beans.BeansException; 30 import org.springframework.beans.MutablePropertyValues; 31 import org.springframework.beans.PropertyAccessor; 32 import org.springframework.beans.factory.BeanDefinitionStoreException; 33 import org.springframework.beans.factory.CannotLoadBeanClassException; 34 import org.springframework.beans.factory.config.ConstructorArgumentValues; 35 import org.springframework.beans.factory.config.RuntimeBeanReference; 36 import org.springframework.core.io.Resource; 37 import org.springframework.core.io.support.EncodedResource; 38 import org.springframework.util.DefaultPropertiesPersister; 39 import org.springframework.util.PropertiesPersister; 40 import org.springframework.util.StringUtils; 41 42 82 public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader { 83 84 88 public static final String TRUE_VALUE = "true"; 89 90 94 public static final String SEPARATOR = "."; 95 96 99 public static final String CLASS_KEY = "(class)"; 100 101 105 private static final String DEPRECATED_CLASS_KEY = "class"; 106 107 110 public static final String PARENT_KEY = "(parent)"; 111 112 116 public static final String ABSTRACT_KEY = "(abstract)"; 117 118 122 public static final String SINGLETON_KEY = "(singleton)"; 123 124 128 public static final String LAZY_INIT_KEY = "(lazy-init)"; 129 130 136 public static final String REF_SUFFIX = "(ref)"; 137 138 141 public static final String REF_PREFIX = "*"; 142 143 146 public static final String CONSTRUCTOR_ARG_PREFIX = "$"; 147 148 149 private String defaultParentBean; 150 151 private PropertiesPersister propertiesPersister = new DefaultPropertiesPersister(); 152 153 154 157 public PropertiesBeanDefinitionReader(BeanDefinitionRegistry beanFactory) { 158 super(beanFactory); 159 } 160 161 173 public void setDefaultParentBean(String defaultParentBean) { 174 this.defaultParentBean = defaultParentBean; 175 } 176 177 180 public String getDefaultParentBean() { 181 return defaultParentBean; 182 } 183 184 189 public void setPropertiesPersister(PropertiesPersister propertiesPersister) { 190 this.propertiesPersister = 191 (propertiesPersister != null ? propertiesPersister : new DefaultPropertiesPersister()); 192 } 193 194 197 public PropertiesPersister getPropertiesPersister() { 198 return propertiesPersister; 199 } 200 201 202 210 public int loadBeanDefinitions(Resource resource) throws BeansException { 211 return loadBeanDefinitions(new EncodedResource(resource), null); 212 } 213 214 222 public int loadBeanDefinitions(Resource resource, String prefix) throws BeansException { 223 return loadBeanDefinitions(new EncodedResource(resource), prefix); 224 } 225 226 233 public int loadBeanDefinitions(EncodedResource encodedResource) throws BeansException { 234 return loadBeanDefinitions(encodedResource, null); 235 } 236 237 244 public int loadBeanDefinitions(EncodedResource encodedResource, String prefix) throws BeansException { 245 Properties props = new Properties (); 246 try { 247 InputStream is = encodedResource.getResource().getInputStream(); 248 try { 249 if (encodedResource.getEncoding() != null) { 250 getPropertiesPersister().load(props, new InputStreamReader (is, encodedResource.getEncoding())); 251 } 252 else { 253 getPropertiesPersister().load(props, is); 254 } 255 } 256 finally { 257 is.close(); 258 } 259 return registerBeanDefinitions(props, prefix, encodedResource.getResource().getDescription()); 260 } 261 catch (IOException ex) { 262 throw new BeanDefinitionStoreException("Could not parse properties from " + encodedResource.getResource(), ex); 263 } 264 } 265 266 274 public int registerBeanDefinitions(ResourceBundle rb) throws BeanDefinitionStoreException { 275 return registerBeanDefinitions(rb, null); 276 } 277 278 288 public int registerBeanDefinitions(ResourceBundle rb, String prefix) throws BeanDefinitionStoreException { 289 Map map = new HashMap (); 291 Enumeration keys = rb.getKeys(); 292 while (keys.hasMoreElements()) { 293 String key = (String ) keys.nextElement(); 294 map.put(key, rb.getObject(key)); 295 } 296 return registerBeanDefinitions(map, prefix); 297 } 298 299 300 310 public int registerBeanDefinitions(Map map) throws BeansException { 311 return registerBeanDefinitions(map, null); 312 } 313 314 324 public int registerBeanDefinitions(Map map, String prefix) throws BeansException { 325 return registerBeanDefinitions(map, prefix, "Map " + map); 326 } 327 328 342 public int registerBeanDefinitions(Map map, String prefix, String resourceDescription) 343 throws BeansException { 344 345 if (prefix == null) { 346 prefix = ""; 347 } 348 int beanCount = 0; 349 350 for (Iterator it = map.keySet().iterator(); it.hasNext();) { 351 Object key = it.next(); 352 if (!(key instanceof String )) { 353 throw new IllegalArgumentException ("Illegal key [" + key + "]: only Strings allowed"); 354 } 355 String keyString = (String ) key; 356 if (keyString.startsWith(prefix)) { 357 String nameAndProperty = keyString.substring(prefix.length()); 359 int sepIdx = -1; 361 int propKeyIdx = nameAndProperty.indexOf(PropertyAccessor.PROPERTY_KEY_PREFIX); 362 if (propKeyIdx != -1) { 363 sepIdx = nameAndProperty.lastIndexOf(SEPARATOR, propKeyIdx); 364 } 365 else { 366 sepIdx = nameAndProperty.lastIndexOf(SEPARATOR); 367 } 368 if (sepIdx != -1) { 369 String beanName = nameAndProperty.substring(0, sepIdx); 370 if (logger.isDebugEnabled()) { 371 logger.debug("Found bean name '" + beanName + "'"); 372 } 373 if (!getBeanFactory().containsBeanDefinition(beanName)) { 374 registerBeanDefinition(beanName, map, prefix + beanName, resourceDescription); 376 ++beanCount; 377 } 378 } 379 else { 380 if (logger.isDebugEnabled()) { 383 logger.debug("Invalid bean name and property [" + nameAndProperty + "]"); 384 } 385 } 386 } 387 } 388 389 return beanCount; 390 } 391 392 402 protected void registerBeanDefinition(String beanName, Map map, String prefix, String resourceDescription) 403 throws BeansException { 404 405 String className = null; 406 String parent = null; 407 boolean isAbstract = false; 408 boolean singleton = true; 409 boolean lazyInit = false; 410 411 ConstructorArgumentValues cas = new ConstructorArgumentValues(); 412 MutablePropertyValues pvs = new MutablePropertyValues(); 413 414 for (Iterator it = map.entrySet().iterator(); it.hasNext();) { 415 Map.Entry entry = (Map.Entry ) it.next(); 416 String key = StringUtils.trimWhitespace((String ) entry.getKey()); 417 if (key.startsWith(prefix + SEPARATOR)) { 418 String property = key.substring(prefix.length() + SEPARATOR.length()); 419 if (isClassKey(property)) { 420 className = StringUtils.trimWhitespace((String ) entry.getValue()); 421 } 422 else if (PARENT_KEY.equals(property)) { 423 parent = StringUtils.trimWhitespace((String ) entry.getValue()); 424 } 425 else if (ABSTRACT_KEY.equals(property)) { 426 String val = StringUtils.trimWhitespace((String ) entry.getValue()); 427 isAbstract = TRUE_VALUE.equals(val); 428 } 429 else if (SINGLETON_KEY.equals(property)) { 430 String val = StringUtils.trimWhitespace((String ) entry.getValue()); 431 singleton = (val == null) || TRUE_VALUE.equals(val); 432 } 433 else if (LAZY_INIT_KEY.equals(property)) { 434 String val = StringUtils.trimWhitespace((String ) entry.getValue()); 435 lazyInit = TRUE_VALUE.equals(val); 436 } 437 else if (property.startsWith(CONSTRUCTOR_ARG_PREFIX)) { 438 if (property.endsWith(REF_SUFFIX)) { 439 int index = Integer.parseInt(property.substring(1, property.length() - REF_SUFFIX.length())); 440 cas.addIndexedArgumentValue(index, new RuntimeBeanReference(entry.getValue().toString())); 441 } 442 else { 443 int index = Integer.parseInt(property.substring(1)); 444 cas.addIndexedArgumentValue(index, readValue(entry)); 445 } 446 } 447 else if (property.endsWith(REF_SUFFIX)) { 448 property = property.substring(0, property.length() - REF_SUFFIX.length()); 451 String ref = StringUtils.trimWhitespace((String ) entry.getValue()); 452 453 Object val = new RuntimeBeanReference(ref); 456 pvs.addPropertyValue(property, val); 457 } 458 else{ 459 pvs.addPropertyValue(property, readValue(entry)); 461 } 462 } 463 } 464 465 if (logger.isDebugEnabled()) { 466 logger.debug("Registering bean definition for bean name '" + beanName + "' with " + pvs); 467 } 468 469 if (parent == null && className == null && !beanName.equals(this.defaultParentBean)) { 473 parent = this.defaultParentBean; 474 } 475 476 try { 477 AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition( 478 parent, className, getBeanClassLoader()); 479 bd.setAbstract(isAbstract); 480 bd.setSingleton(singleton); 481 bd.setLazyInit(lazyInit); 482 bd.setConstructorArgumentValues(cas); 483 bd.setPropertyValues(pvs); 484 getBeanFactory().registerBeanDefinition(beanName, bd); 485 } 486 catch (ClassNotFoundException ex) { 487 throw new CannotLoadBeanClassException(resourceDescription, beanName, className, ex); 488 } 489 catch (LinkageError err) { 490 throw new CannotLoadBeanClassException(resourceDescription, beanName, className, err); 491 } 492 } 493 494 498 private boolean isClassKey(String property) { 499 if (CLASS_KEY.equals(property)) { 500 return true; 501 } 502 else if (DEPRECATED_CLASS_KEY.equals(property)) { 503 if (logger.isWarnEnabled()) { 504 logger.warn("Use of 'class' property in [" + getClass().getName() + "] is deprecated in favor of '(class)'"); 505 } 506 return true; 507 } 508 return false; 509 } 510 511 515 private Object readValue(Map.Entry entry) { 516 Object val = entry.getValue(); 517 if (val instanceof String ) { 518 String strVal = (String ) val; 519 if (strVal.startsWith(REF_PREFIX)) { 521 String targetName = strVal.substring(1); 523 if (targetName.startsWith(REF_PREFIX)) { 524 val = targetName; 526 } 527 else { 528 val = new RuntimeBeanReference(targetName); 529 } 530 } 531 } 532 return val; 533 } 534 535 } 536 | Popular Tags |