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,v 1.6 2007/04/01 18:49:30 taqua Exp $
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 ClassLoader cl = ObjectUtilities.getClassLoader
110 (TypedPropertyReadHandler.class);
111 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 }