001 /** 002 * ======================================== 003 * JFreeReport : a free Java report library 004 * ======================================== 005 * 006 * Project Info: http://reporting.pentaho.org/ 007 * 008 * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors. 009 * 010 * This library is free software; you can redistribute it and/or modify it under the terms 011 * of the GNU Lesser General Public License as published by the Free Software Foundation; 012 * either version 2.1 of the License, or (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 015 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 016 * See the GNU Lesser General Public License for more details. 017 * 018 * You should have received a copy of the GNU Lesser General Public License along with this 019 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, 020 * Boston, MA 02111-1307, USA. 021 * 022 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 023 * in the United States and other countries.] 024 * 025 * ------------ 026 * $Id: TypedPropertyReadHandler.java 3525 2007-10-16 11:43:48Z tmorgner $ 027 * ------------ 028 * (C) Copyright 2000-2005, by Object Refinery Limited. 029 * (C) Copyright 2005-2007, by Pentaho Corporation. 030 */ 031 package org.jfree.report.modules.factories.report.flow; 032 033 import java.beans.IntrospectionException; 034 import java.io.ByteArrayInputStream; 035 import java.io.IOException; 036 import java.io.ObjectInputStream; 037 038 import org.jfree.report.util.CharacterEntityParser; 039 import org.jfree.report.util.beans.BeanException; 040 import org.jfree.report.util.beans.BeanUtility; 041 import org.jfree.util.Log; 042 import org.jfree.util.ObjectUtilities; 043 import org.jfree.xmlns.parser.Base64; 044 import org.jfree.xmlns.parser.ParseException; 045 import org.jfree.xmlns.parser.PropertyReadHandler; 046 import org.jfree.xmlns.parser.XmlReadHandler; 047 import org.xml.sax.Attributes; 048 import org.xml.sax.SAXException; 049 050 /** 051 * Creation-Date: 09.04.2006, 12:58:24 052 * 053 * @author Thomas Morgner 054 */ 055 public class TypedPropertyReadHandler extends PropertyReadHandler 056 { 057 private boolean plainContent; 058 private String encoding; 059 private String className; 060 private BeanUtility beanUtility; 061 private String expressionName; 062 private CharacterEntityParser entityParser; 063 064 public TypedPropertyReadHandler(final BeanUtility beanDescription, 065 final String expressionName, 066 final CharacterEntityParser entityParser) 067 { 068 if (beanDescription == null) 069 { 070 throw new NullPointerException( 071 "Expression must not be null"); 072 } 073 if (entityParser == null) 074 { 075 throw new NullPointerException( 076 "EntityParser must not be null"); 077 } 078 this.expressionName = expressionName; 079 this.beanUtility = beanDescription; 080 this.entityParser = entityParser; 081 this.plainContent = true; 082 } 083 084 /** 085 * Done parsing. 086 * 087 * @throws SAXException if there is a parsing error. 088 */ 089 protected void doneParsing() throws SAXException 090 { 091 super.doneParsing(); 092 try 093 { 094 if (plainContent) 095 { 096 final String result = getResult(); 097 if ("base64".equals(encoding)) 098 { 099 final byte[] data = Base64.decode(result.trim().toCharArray()); 100 final ByteArrayInputStream bin = new ByteArrayInputStream(data); 101 final ObjectInputStream oin = new ObjectInputStream(bin); 102 final Object value = oin.readObject(); 103 beanUtility.setProperty(getName(), value); 104 } 105 else 106 { 107 if (className != null) 108 { 109 final ClassLoader cl = ObjectUtilities.getClassLoader 110 (TypedPropertyReadHandler.class); 111 final Class c = cl.loadClass(className); 112 beanUtility.setPropertyAsString 113 (getName(), c, entityParser.decodeEntities(result)); 114 } 115 else 116 { 117 beanUtility.setPropertyAsString 118 (getName(), entityParser.decodeEntities(result)); 119 } 120 } 121 } 122 } 123 catch (BeanException e) 124 { 125 e.printStackTrace(); 126 throw new ParseException("Unable to assign property '" + getName() 127 + "' to expression '" + expressionName + "'", e, getLocator()); 128 } 129 catch (ClassNotFoundException e) 130 { 131 throw new ParseException("Unable to assign property '" + getName() 132 + "' to expression '" + expressionName + "'", e, getLocator()); 133 } 134 catch (IOException e) 135 { 136 throw new ParseException("Unable to assign property '" + getName() 137 + "' to expression '" + expressionName + "'", e, getLocator()); 138 } 139 } 140 141 /** 142 * Starts parsing. 143 * 144 * @param attrs the attributes. 145 * @throws SAXException if there is a parsing error. 146 */ 147 protected void startParsing(final Attributes attrs) throws SAXException 148 { 149 super.startParsing(attrs); 150 className = attrs.getValue(getUri(), "class"); 151 encoding = attrs.getValue(getUri(), "encoding"); 152 if (encoding == null) 153 { 154 encoding = "text"; 155 } 156 else if (("text".equals(encoding) == false) && "base64".equals( 157 encoding) == false) 158 { 159 Log.warn("Invalid value for attribute 'encoding'. Defaulting to 'text'"); 160 encoding = "text"; 161 } 162 } 163 164 /** 165 * Returns the handler for a child element. 166 * 167 * @param tagName the tag name. 168 * @param atts the attributes. 169 * @return the handler or null, if the tagname is invalid. 170 * @throws SAXException if there is a parsing error. 171 */ 172 protected XmlReadHandler getHandlerForChild(final String uri, 173 final String tagName, 174 final Attributes atts) 175 throws SAXException 176 { 177 if (isSameNamespace(uri) == false) 178 { 179 return null; 180 } 181 182 if ("property".equals(tagName)) 183 { 184 plainContent = false; 185 final String name = atts.getValue(uri, "name"); 186 if (name == null) 187 { 188 throw new ParseException("Required attribute 'name' is missing", getLocator()); 189 } 190 try 191 { 192 final Class type = beanUtility.getPropertyType(name); 193 final Object property = type.newInstance(); 194 final BeanUtility propertyUtility = new BeanUtility(property); 195 return new TypedPropertyReadHandler 196 (propertyUtility, expressionName, entityParser); 197 } 198 catch (BeanException e) 199 { 200 throw new ParseException("Property '" + name + "' for expression '" + 201 className + "' is not valid. The specified class was not found.", 202 e, getRootHandler().getDocumentLocator()); 203 } 204 catch (IllegalAccessException e) 205 { 206 throw new ParseException( 207 "Property '" + name + "' for expression '" + className + 208 "' is not valid. The specified class was not found.", 209 e, getRootHandler().getDocumentLocator()); 210 } 211 catch (InstantiationException e) 212 { 213 throw new ParseException( 214 "Property '" + name + "' for expression '" + className + 215 "' is not valid. The specified class cannot be instantiated.", 216 e, getRootHandler().getDocumentLocator()); 217 } 218 catch (IntrospectionException e) 219 { 220 throw new ParseException( 221 "Property '" + name + "' for expression '" + className + 222 "' is not valid. Introspection failed for this expression.", 223 e, getRootHandler().getDocumentLocator()); 224 } 225 } 226 return null; 227 } 228 }