001 /* $Id: SetPropertyRule.java 992060 2010-09-02 19:09:47Z simonetripodi $ 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 @Deprecated 057 public SetPropertyRule(Digester digester, String name, String value) { 058 059 this(name, value); 060 061 } 062 063 /** 064 * Construct a "set property" rule with the specified name and value 065 * attributes. 066 * 067 * @param name Name of the attribute that will contain the name of the 068 * property to be set 069 * @param value Name of the attribute that will contain the value to which 070 * the property should be set 071 */ 072 public SetPropertyRule(String name, String value) { 073 074 this.name = name; 075 this.value = value; 076 077 } 078 079 // ----------------------------------------------------- Instance Variables 080 081 082 /** 083 * The attribute that will contain the property name. 084 */ 085 protected String name = null; 086 087 088 /** 089 * The attribute that will contain the property value. 090 */ 091 protected String value = null; 092 093 094 // --------------------------------------------------------- Public Methods 095 096 097 /** 098 * Process the beginning of this element. 099 * 100 * @param attributes The attribute list of this element 101 * 102 * @exception NoSuchMethodException if the bean does not 103 * have a writeable property of the specified name 104 */ 105 @Override 106 public void begin(Attributes attributes) throws Exception { 107 108 if (attributes.getLength() == 0 ) { 109 return; 110 } 111 112 // Identify the actual property name and value to be used 113 String actualName = null; 114 String actualValue = null; 115 for (int i = 0; i < attributes.getLength(); i++) { 116 String name = attributes.getLocalName(i); 117 if ("".equals(name)) { 118 name = attributes.getQName(i); 119 } 120 String value = attributes.getValue(i); 121 if (name.equals(this.name)) { 122 actualName = value; 123 } else if (name.equals(this.value)) { 124 actualValue = value; 125 } 126 } 127 128 // Get a reference to the top object 129 Object top = digester.peek(); 130 131 // Log some debugging information 132 if (digester.log.isDebugEnabled()) { 133 digester.log.debug("[SetPropertyRule]{" + digester.match + 134 "} Set " + top.getClass().getName() + " property " + 135 actualName + " to " + actualValue); 136 } 137 138 // Force an exception if the property does not exist 139 // (BeanUtils.setProperty() silently returns in this case) 140 // 141 // This code should probably use PropertyUtils.isWriteable(), 142 // like SetPropertiesRule does. 143 if (top instanceof DynaBean) { 144 DynaProperty desc = 145 ((DynaBean) top).getDynaClass().getDynaProperty(actualName); 146 if (desc == null) { 147 throw new NoSuchMethodException 148 ("Bean has no property named " + actualName); 149 } 150 } else /* this is a standard JavaBean */ { 151 PropertyDescriptor desc = 152 PropertyUtils.getPropertyDescriptor(top, actualName); 153 if (desc == null) { 154 throw new NoSuchMethodException 155 ("Bean has no property named " + actualName); 156 } 157 } 158 159 // Set the property (with conversion as necessary) 160 BeanUtils.setProperty(top, actualName, actualValue); 161 162 } 163 164 165 /** 166 * Render a printable version of this Rule. 167 */ 168 @Override 169 public String toString() { 170 171 StringBuffer sb = new StringBuffer("SetPropertyRule["); 172 sb.append("name="); 173 sb.append(name); 174 sb.append(", value="); 175 sb.append(value); 176 sb.append("]"); 177 return (sb.toString()); 178 179 } 180 181 182 }