001 /* $Id: SetPropertyRule.java 568192 2007-08-21 16:41:16Z bayard $ 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 020 package org.apache.commons.digester; 021 022 023 import java.beans.PropertyDescriptor; 024 025 import org.apache.commons.beanutils.BeanUtils; 026 import org.apache.commons.beanutils.DynaBean; 027 import org.apache.commons.beanutils.DynaProperty; 028 import org.apache.commons.beanutils.PropertyUtils; 029 import org.xml.sax.Attributes; 030 031 032 /** 033 * Rule implementation that sets an individual property on the object at the 034 * top of the stack, based on attributes with specified names. 035 */ 036 037 public class SetPropertyRule extends Rule { 038 039 040 // ----------------------------------------------------------- Constructors 041 042 043 /** 044 * Construct a "set property" rule with the specified name and value 045 * attributes. 046 * 047 * @param digester The digester with which this rule is associated 048 * @param name Name of the attribute that will contain the name of the 049 * property to be set 050 * @param value Name of the attribute that will contain the value to which 051 * the property should be set 052 * 053 * @deprecated The digester instance is now set in the {@link Digester#addRule} method. 054 * Use {@link #SetPropertyRule(String name, String value)} instead. 055 */ 056 public SetPropertyRule(Digester digester, String name, String value) { 057 058 this(name, value); 059 060 } 061 062 /** 063 * Construct a "set property" rule with the specified name and value 064 * attributes. 065 * 066 * @param name Name of the attribute that will contain the name of the 067 * property to be set 068 * @param value Name of the attribute that will contain the value to which 069 * the property should be set 070 */ 071 public SetPropertyRule(String name, String value) { 072 073 this.name = name; 074 this.value = value; 075 076 } 077 078 // ----------------------------------------------------- Instance Variables 079 080 081 /** 082 * The attribute that will contain the property name. 083 */ 084 protected String name = null; 085 086 087 /** 088 * The attribute that will contain the property value. 089 */ 090 protected String value = null; 091 092 093 // --------------------------------------------------------- Public Methods 094 095 096 /** 097 * Process the beginning of this element. 098 * 099 * @param attributes The attribute list of this element 100 * 101 * @exception NoSuchMethodException if the bean does not 102 * have a writeable property of the specified name 103 */ 104 public void begin(Attributes attributes) throws Exception { 105 106 if (attributes.getLength() == 0 ) { 107 return; 108 } 109 110 // Identify the actual property name and value to be used 111 String actualName = null; 112 String actualValue = null; 113 for (int i = 0; i < attributes.getLength(); i++) { 114 String name = attributes.getLocalName(i); 115 if ("".equals(name)) { 116 name = attributes.getQName(i); 117 } 118 String value = attributes.getValue(i); 119 if (name.equals(this.name)) { 120 actualName = value; 121 } else if (name.equals(this.value)) { 122 actualValue = value; 123 } 124 } 125 126 // Get a reference to the top object 127 Object top = digester.peek(); 128 129 // Log some debugging information 130 if (digester.log.isDebugEnabled()) { 131 digester.log.debug("[SetPropertyRule]{" + digester.match + 132 "} Set " + top.getClass().getName() + " property " + 133 actualName + " to " + actualValue); 134 } 135 136 // Force an exception if the property does not exist 137 // (BeanUtils.setProperty() silently returns in this case) 138 // 139 // This code should probably use PropertyUtils.isWriteable(), 140 // like SetPropertiesRule does. 141 if (top instanceof DynaBean) { 142 DynaProperty desc = 143 ((DynaBean) top).getDynaClass().getDynaProperty(actualName); 144 if (desc == null) { 145 throw new NoSuchMethodException 146 ("Bean has no property named " + actualName); 147 } 148 } else /* this is a standard JavaBean */ { 149 PropertyDescriptor desc = 150 PropertyUtils.getPropertyDescriptor(top, actualName); 151 if (desc == null) { 152 throw new NoSuchMethodException 153 ("Bean has no property named " + actualName); 154 } 155 } 156 157 // Set the property (with conversion as necessary) 158 BeanUtils.setProperty(top, actualName, actualValue); 159 160 } 161 162 163 /** 164 * Render a printable version of this Rule. 165 */ 166 public String toString() { 167 168 StringBuffer sb = new StringBuffer("SetPropertyRule["); 169 sb.append("name="); 170 sb.append(name); 171 sb.append(", value="); 172 sb.append(value); 173 sb.append("]"); 174 return (sb.toString()); 175 176 } 177 178 179 }